diff --git a/.bazelversion b/.bazelversion index a3fcc7121bba..815da58b7a9e 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -7.1.0 +7.4.1 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b9816ce5aff2..85fca8ff990f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,6 +10,7 @@ in review. 4. Note that PRs updating dependencies and new Go versions are not accepted. Please file an issue instead. +5. A changelog entry is required for user facing issues. --> **What type of PR is this?** @@ -28,3 +29,9 @@ Fixes # **Other notes for review** + +**Acknowledgements** + +- [ ] I have read [CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md). +- [ ] I have included a uniquely named [changelog fragment file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd). +- [ ] I have added a description to this PR with sufficient context for reviewers to understand this PR. diff --git a/.github/actions/gomodtidy/Dockerfile b/.github/actions/gomodtidy/Dockerfile index c9e1e740857d..570585ef8748 100644 --- a/.github/actions/gomodtidy/Dockerfile +++ b/.github/actions/gomodtidy/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22-alpine +FROM golang:1.23-alpine COPY entrypoint.sh /entrypoint.sh diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 000000000000..7bd10135ab60 --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,34 @@ +# This workflow will build a golang project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go + +name: changelog + +on: + pull_request: + branches: [ "develop" ] + +jobs: + run-changelog-check: + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Download unclog binary + uses: dsaltares/fetch-gh-release-asset@aa2ab1243d6e0d5b405b973c89fa4d06a2d0fff7 # 1.1.2 + with: + repo: OffchainLabs/unclog + version: "tags/v0.1.3" + file: "unclog" + + - name: Get new changelog files + id: new-changelog-files + uses: tj-actions/changed-files@v45 + with: + files: | + changelog/**.md + + - name: Run lint command + env: + ALL_ADDED_MARKDOWN: ${{ steps.new-changelog-files.outputs.added_files }} + run: chmod +x unclog && ./unclog check -fragment-env=ALL_ADDED_MARKDOWN diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 000000000000..9810545c0c76 --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,21 @@ +name: Protobuf Format + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + merge_group: + types: [checks_requested] + +jobs: + clang-format-checking: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # Is this step failing for you? + # Run: clang-format -i proto/**/*.proto + # See: https://clang.llvm.org/docs/ClangFormat.html + - uses: RafikFarhad/clang-format-github-action@v3 + with: + sources: "proto/**/*.proto" diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 07677c1c73e3..b547eec08ebd 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '1.22.3' + go-version: '1.23.5' - id: list uses: shogo82148/actions-go-fuzz/list@v0 with: @@ -36,7 +36,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 with: - go-version: '1.22.3' + go-version: '1.23.5' - uses: shogo82148/actions-go-fuzz/run@v0 with: packages: ${{ matrix.package }} diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 02f828499c25..202782263f7a 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Go mod tidy checker id: gomodtidy @@ -27,11 +27,11 @@ jobs: GO111MODULE: on steps: - name: Checkout - uses: actions/checkout@v2 - - name: Set up Go 1.22 - uses: actions/setup-go@v3 + uses: actions/checkout@v4 + - name: Set up Go 1.23 + uses: actions/setup-go@v4 with: - go-version: '1.22.3' + go-version: '1.23.5' - name: Run Gosec Security Scanner run: | # https://github.com/securego/gosec/issues/469 export PATH=$PATH:$(go env GOPATH)/bin @@ -43,18 +43,18 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - name: Set up Go 1.22 - uses: actions/setup-go@v3 + - name: Set up Go 1.23 + uses: actions/setup-go@v4 with: - go-version: '1.22.3' + go-version: '1.23.5' id: go - name: Golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v5 with: - version: v1.55.2 + version: v1.63.4 args: --config=.golangci.yml --out-${NO_FUTURE}format colored-line-number build: @@ -62,13 +62,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: - go-version: '1.22.3' + go-version: '1.23.5' id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Get dependencies run: | diff --git a/.golangci.yml b/.golangci.yml index 2a5b771b78d4..5dbb659483ef 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,28 +1,20 @@ run: - skip-files: + timeout: 10m + go: '1.23.5' + +issues: + exclude-files: - validator/web/site_data.go - .*_test.go - skip-dirs: + exclude-dirs: - proto - tools/analyzers - timeout: 10m - go: '1.22.3' linters: enable-all: true disable: # Deprecated linters: - - deadcode - - exhaustivestruct - - golint - govet - - ifshort - - interfacer - - maligned - - nosnakecase - - scopelint - - structcheck - - varcheck # Disabled for now: - asasalint @@ -34,6 +26,8 @@ linters: - dogsled - dupl - durationcheck + - errname + - err113 - exhaustive - exhaustruct - forbidigo @@ -47,17 +41,17 @@ linters: - gocyclo - godot - godox - - goerr113 - gofumpt - - gomnd - gomoddirectives - gosec - inamedparam - interfacebloat + - intrange - ireturn - lll - maintidx - makezero + - mnd - musttag - nakedret - nestif @@ -72,7 +66,9 @@ linters: - predeclared - promlinter - protogetter + - recvcheck - revive + - spancheck - staticcheck - stylecheck - tagalign diff --git a/.policy.yml b/.policy.yml index 4f76e4865d5a..5fed6dc23393 100644 --- a/.policy.yml +++ b/.policy.yml @@ -26,7 +26,6 @@ approval_rules: only_changed_files: paths: - "*pb.go" - - "*pb.gw.go" - "*.bazel" options: ignore_commits_by: @@ -69,7 +68,6 @@ approval_rules: changed_files: ignore: - "*pb.go" - - "*pb.gw.go" - "*.bazel" options: ignore_commits_by: diff --git a/BUILD.bazel b/BUILD.bazel index cfe2ee4863af..4020dcac406b 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -55,13 +55,6 @@ alias( visibility = ["//visibility:public"], ) -# Protobuf gRPC gateway compiler -alias( - name = "grpc_gateway_proto_compiler", - actual = "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway", - visibility = ["//visibility:public"], -) - gometalinter( name = "gometalinter", config = "//:.gometalinter.json", diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000000..5417108dbf34 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3125 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on Keep a Changelog, and this project adheres to Semantic Versioning. + +## [v5.3.0](https://github.com/prysmaticlabs/prysm/compare/v5.2.0...v5.3.0) - 2025-02-12 + +This release includes support for Pectra activation in the [Holesky](https://github.com/eth-clients/holesky) and [Sepolia](https://github.com/eth-clients/sepolia) testnets! The release contains many fixes for Electra that have been found in rigorous testing through devnets in the last few months. + +For mainnet, we have a few nice features for you to try: + +- [PR #14023](https://github.com/prysmaticlabs/prysm/pull/14023) introduces a new file layout structure for storing blobs. Rather than storing all blob root directories in one parent directory, blob root directories are organized in subdirectories by epoch. This should vastly decrease the blob cache warmup time when Prysm is starting. Try this feature with `--blob-storage-layout=by-epoch`. + +Updating to this release is **required** for Holesky and Sepolia operators and it is **recommended** for mainnet users as there are a few bug fixes that apply to deneb logic. + +### Added + +- Added an error field to log `Finished building block`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14696) +- Implemented a new `EmptyExecutionPayloadHeader` function. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14713) +- Added proper gas limit check for header from the builder. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14707) +- `Finished building block`: Display error only if not nil. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14722) +- Added light client feature flag check to RPC handlers. [PR](https://github.com/prysmaticlabs/prysm/pull/14736). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14782) +- Added support to update target and max blob count to different values per hard fork config. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14678) +- Log before blob filesystem cache warm-up. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14735) +- New design for the attestation pool. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14324) +- Add field param placeholder for Electra blob target and max to pass spec tests. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14733) +- Light client: Add better error handling. [PR](https://github.com/prysmaticlabs/prysm/pull/14749). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14782) +- Add EIP-7691: Blob throughput increase. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14750) +- Trace IDONTWANT Messages in Pubsub. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14778) +- Add Fulu fork boilerplate. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14771) +- DB optimization for saving light client bootstraps (save unique sync committees only). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14782) +- Separate type for unaggregated network attestations. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14659) +- Remote signer electra fork support. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14477) +- Add Electra test case to rewards API. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14816) +- Update `proto_test.go` to Electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14817) +- Update slasher service to Electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14812) +- Builder API endpoint to support Electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14344) +- Added protoc toolchains with a version of v25.3. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14818) +- Add test cases for the eth_lightclient_bootstrap API SSZ support. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14824) +- Handle `AttesterSlashingElectra` everywhere in the codebase. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14823) +- Add Beacon DB pruning service to prune historical data older than MIN_EPOCHS_FOR_BLOCK_REQUESTS (roughly equivalent to the weak subjectivity period). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14687) +- Nil consolidation request check for core processing. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14851) +- Updated blob sidecar api endpoint for Electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14852) +- Slashing pool service to convert slashings from Phase0 to Electra at the fork. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14844) +- check to stop eth1 voting after electra and eth1 deposits stop. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14835) +- WARN log message on node startup advising of the upcoming deprecation of the --enable-historical-state-representation feature flag. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14856) +- Beacon API event support for `SingleAttestation` and `SignedAggregateAttestationAndProofElectra`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14855) +- Added Electra tests for `TestLightClient_NewLightClientOptimisticUpdateFromBeaconState` and `TestLightClient_NewLightClientFinalityUpdateFromBeaconState`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14783) +- New option to select an alternate blob storage layout. Rather than a flat directory with a subdir for each block root, a multi-level scheme is used to organize blobs by epoch/slot/root, enabling leaner syscalls, indexing and pruning. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14023) +- Send pending att queue's attestations through the notification feed. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14862) +- Prune all pending deposits and proofs in post-Electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14829) +- Add Pectra testnet dates. (Sepolia and Holesky). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14884) + +### Changed + +- Process light client finality updates only for new finalized epochs instead of doing it for every block. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14713) +- Refactor subnets subscriptions. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14711) +- Refactor RPC handlers subscriptions. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14732) +- Go deps upgrade, from `ioutil` to `io`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14737) +- Move successfully registered validator(s) on builder log to debug. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14735) +- Update some test files to use `crypto/rand` instead of `math/rand`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14747) +- Re-organize the content of the `*.proto` files (No functional change). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14755) +- SSZ files generation: Remove the `// Hash: ...` header.[[PR]](https://github.com/prysmaticlabs/prysm/pull/14760) +- Updated Electra spec definition for `process_epoch`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14768) +- Update our `go-libp2p-pubsub` dependency. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14770) +- Re-organize the content of files to ease the creation of a new fork boilerplate. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14761) +- Updated spec definition electra `process_registry_updates`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14767) +- Fixed Metadata errors for peers connected via QUIC. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14776) +- Updated spec definitions for `process_slashings` in godocs. Simplified `ProcessSlashings` API. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14766) +- Update spec tests to v1.5.0-beta.0. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14788) +- Process light client finality updates only for new finalized epochs instead of doing it for every block. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14718) +- Update blobs by rpc topics from V2 to V1. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14785) +- Updated geth to 1.14~. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14351) +- E2e tests start from bellatrix. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14351) +- Version pinning unclog after making some ux improvements. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14802) +- Remove helpers to check for execution/compounding withdrawal credentials and expose them as methods. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14808) +- Refactor `2006-01-02 15:04:05` to `time.DateTime`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14792) +- Updated Prysm to Go v1.23.5. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14818) +- Updated Bazel version to v7.4.1. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14818) +- Updated rules_go to v0.46.0. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14818) +- Updated golang.org/x/tools to be compatible with v1.23.5. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14818) +- CI now requires proto files to be properly formatted with clang-format. [[PR](https://github.com/prysmaticlabs/prysm/pull/14831)]. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14831) +- Improved test coverage of beacon-chain/core/electra/churn.go. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14837) +- Update electra spec test to beta1. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14841) +- Move deposit request nil check to apply all. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14849) +- Do not mark blocks as invalid on context deadlines during state transition. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14838) +- Update electra core processing to not mark block bad if execution request error. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14826) +- Dependency: Updated go-ethereum to v1.14.13. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14872) +- improving readability on proposer settings loader. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14868) +- Removes existing validator.processSlot span and adds validator.processSlot span to slotCtx. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14874) +- DownloadFinalizedData has moved from the api/client package to beacon-chain/sync/checkpoint. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14871) +- Updated Blob-Batch-Limit to increase to 192 for electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14883) +- Updated Blob-Batch-Limit-Burst-Factor to increase to 3. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14883) +- Changed the derived batch limit when serving blobs. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14883) +- Updated go-libp2p-pubsub to v0.13.0. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14890) +- Rename light client flag from `enable-lightclient` to `enable-light-client`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14887) +- Update electra spec test to beta2. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14901) + +### Removed + +- Cleanup ProcessSlashings method to remove unnecessary argument. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14762) +- Remove `/proto/eth/v2` directory. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14765) +- Remove `/memsize/` pprof endpoint as it will no longer be supported in go 1.23. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14351) +- Clean `TestCanUpgrade*` tests. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14791) +- Remove `Copy()` from the `ReadOnlyBeaconBlock` interface. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14811) +- Removed a tracing span on signature requests. These requests usually took less than 5 nanoseconds and are generally not worth tracing. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14864) + +### Fixed + +- Added check to prevent nil pointer deference or out of bounds array access when validating the BLSToExecutionChange on an impossibly nil validator. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14705) +- EIP-7691: Ensure new blobs subnets are subscribed on epoch in advance. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14759) +- Fix kzg commitment inclusion proof depth minimal value. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14787) +- Replace exampleIP to `96.7.129.13`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14795) +- Fixed a p2p test to reliably return a static IP through DNS resolution. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14800) +- `ToBlinded`: Use Fulu struct for Fulu (instead of Electra). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14797) +- fix panic with type cast on pbgenericblock(). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14801) +- Prysmctl generate genesis state: fix truncation of ExtraData to 32 bytes to satisfy SSZ marshaling. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14803) +- added conditional evaluators to fix scenario e2e tests. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14798) +- Use `SingleAttestation` for Fulu in p2p attestation map. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14809) +- `UpgradeToFulu`: Respect the specification. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14821) +- `nodeFilter`: Implement `filterPeerForBlobSubnet` to avoid error logs. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14822) +- Fixed deposit packing for post-Electra: early return if EIP-6110 is applied. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14697) +- Fix batch process new pending deposits by getting validators from state. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14827) +- Fix handling unfound block at slot. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14852) +- Fixed incorrect attester slashing length check. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14833) +- Fix monitor service for Electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14853) +- add more nil checks on ToConsensus functions for added safety. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14867) +- Fix electra state to safe share references on pending fields when append. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14895) +- Add missing config values from the spec. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14903) +- We remove the unused `rebuildTrie` assignments for fields which do not use them. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14906) +- fix block api endpoint to handle blocks with the same structure but on different forks (i.e. fulu and electra). [[PR]](https://github.com/prysmaticlabs/prysm/pull/14897) +- We change how we track blob indexes during their reconstruction from the EL to prevent. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14909) +- We now use the correct maximum value when serving blobs for electra blocks. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14910) + +### Security + +- go version upgrade to 1.22.10 for CVE CVE-2024-34156. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14729) +- Update golang.org/x/crypto to v0.31.0 to address CVE-2024-45337. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14777) +- Update golang.org/x/net to v0.33.0 to address CVE-2024-45338. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14780) + +## [v5.2.0](https://github.com/prysmaticlabs/prysm/compare/v5.1.2...v5.2.0) + +Updating to this release is highly recommended, especially for users running v5.1.1 or v5.1.2. +This release is **mandatory** for all validator clients using mev-boost with a gas limit increase. +Without upgrading to this release, validator clients will default to using local execution blocks +when the gas limit starts to increase. + +This release has several fixes and new features. In this release, we have enabled QUIC protocol by +default, which uses port 13000 for `--p2p-quic-port`. This may be a [breaking change](https://github.com/prysmaticlabs/prysm/pull/14688#issuecomment-2516713826) +if you're using port 13000 already. This release has some improvements for raising the gas limit, +but there are [known issues](https://hackmd.io/@ttsao/prysm-gas-limit) with the proposer settings +file provided gas limit not being respected for mev-boost outsourced blocks. Signalling an increase +for the gas limit works perfectly for local block production as of this release. See [pumpthegas.org](https://pumpthegas.org) for more info on raising the gas limit on L1. + +Notable features: +- Prysm can reuse blobs from the EL via engine_getBlobsV1, [potentially saving bandwidth](https://hackmd.io/@ttsao/get-blobs-early-results). +- QUIC is enabled by default. This is a UDP based networking protocol with default port 13000. + +### Added + +- Electra EIP6110: Queue deposit [pr](https://github.com/prysmaticlabs/prysm/pull/14430). +- Add Bellatrix tests for light client functions. +- Add Discovery Rebooter Feature. +- Added GetBlockAttestationsV2 endpoint. +- Light client support: Consensus types for Electra. +- Added SubmitPoolAttesterSlashingV2 endpoint. +- Added SubmitAggregateAndProofsRequestV2 endpoint. +- Updated the `beacon-chain/monitor` package to Electra. [PR](https://github.com/prysmaticlabs/prysm/pull/14562) +- Added ListAttestationsV2 endpoint. +- Add ability to rollback node's internal state during processing. +- Change how unsafe protobuf state is created to prevent unnecessary copies. +- Added benchmarks for process slots for Capella, Deneb, Electra. +- Add helper to cast bytes to string without allocating memory. +- Added GetAggregatedAttestationV2 endpoint. +- Added SubmitAttestationsV2 endpoint. +- Validator REST mode Electra block support. +- Added validator index label to `validator_statuses` metric. +- Added Validator REST mode use of Attestation V2 endpoints and Electra attestations. +- PeerDAS: Added proto for `DataColumnIdentifier`, `DataColumnSidecar`, `DataColumnSidecarsByRangeRequest` and `MetadataV2`. +- Better attestation packing for Electra. [PR](https://github.com/prysmaticlabs/prysm/pull/14534) +- P2P: Add logs when a peer is (dis)connected. Add the reason of the disconnection when we initiate it. +- Added a Prometheus error counter metric for HTTP requests to track beacon node requests. +- Added a Prometheus error counter metric for SSE requests. +- Save light client updates and bootstraps in DB. +- Added more comprehensive tests for `BlockToLightClientHeader`. [PR](https://github.com/prysmaticlabs/prysm/pull/14699) +- Added light client feature flag check to RPC handlers. [PR](https://github.com/prysmaticlabs/prysm/pull/14736) +- Light client: Add better error handling. [PR](https://github.com/prysmaticlabs/prysm/pull/14749) + +### Changed + +- Electra EIP6110: Queue deposit requests changes from consensus spec pr #3818 +- reversed the boolean return on `BatchVerifyDepositsSignatures`, from need verification, to all keys successfully verified +- Fix `engine_exchangeCapabilities` implementation. +- Updated the default `scrape-interval` in `Client-stats` to 2 minutes to accommodate Beaconcha.in API rate limits. +- Switch to compounding when consolidating with source==target. +- Revert block db save when saving state fails. +- Return false from HasBlock if the block is being synced. +- Cleanup forkchoice on failed insertions. +- Use read only validator for core processing to avoid unnecessary copying. +- Use ROBlock across block processing pipeline. +- Added missing Eth-Consensus-Version headers to GetBlockAttestationsV2 and GetAttesterSlashingsV2 endpoints. +- When instantiating new validators, explicit set `Slashed` to false and move `EffectiveBalance` to match struct definition. +- Updated pgo profile for beacon chain with holesky data. This improves the profile guided + optimizations in the go compiler. +- Use read only state when computing the active validator list. +- Simplified `ExitedValidatorIndices`. +- Simplified `EjectedValidatorIndices`. +- `engine_newPayloadV4`,`engine_getPayloadV4` are changes due to new execution request serialization decisions, [PR](https://github.com/prysmaticlabs/prysm/pull/14580) +- Fixed various small things in state-native code. +- Use ROBlock earlier in block syncing pipeline. +- Changed the signature of `ProcessPayload`. +- Only Build the Protobuf state once during serialization. +- Capella blocks are execution. +- Fixed panic when http request to subscribe to event stream fails. +- Return early for blob reconstructor during capella fork. +- Updated block endpoint from V1 to V2. +- Rename instances of "deposit receipts" to "deposit requests". +- Non-blocking payload attribute event handling in beacon api [pr](https://github.com/prysmaticlabs/prysm/pull/14644). +- Updated light client protobufs. [PR](https://github.com/prysmaticlabs/prysm/pull/14650) +- Added `Eth-Consensus-Version` header to `ListAttestationsV2` and `GetAggregateAttestationV2` endpoints. +- Updated light client consensus types. [PR](https://github.com/prysmaticlabs/prysm/pull/14652) +- Update earliest exit epoch for upgrade to electra +- Add missed exit checks to consolidation processing +- Fixed pending deposits processing on Electra. +- Modified `ListAttestationsV2`, `GetAttesterSlashingsV2` and `GetAggregateAttestationV2` endpoints to use slot to determine fork version. +- Improvements to HTTP response handling. [pr](https://github.com/prysmaticlabs/prysm/pull/14673) +- Updated `Blobs` endpoint to return additional metadata fields. +- Made QUIC the default method to connect with peers. +- Check kzg commitments align with blobs and proofs for beacon api end point. +- Revert "Proposer checks gas limit before accepting builder's bid". +- Updated quic-go to v0.48.2 . + +### Deprecated + +- `/eth/v1alpha1/validator/activation/stream` grpc wait for activation stream is deprecated. [pr](https://github.com/prysmaticlabs/prysm/pull/14514) +- `--interop-genesis-time` and `--interop-num-validators` have been deprecated in the beacon node as the functionality has been removed. These flags have no effect. + +### Removed + +- Removed finalized validator index cache, no longer needed. +- Removed validator queue position log on key reload and wait for activation. +- Removed outdated spectest exclusions for EIP-6110. +- Removed support for starting a beacon node with a deterministic interop genesis state via interop flags. Alternatively, create a genesis state with prysmctl and use `--genesis-state`. This removes about 9Mb (~11%) of unnecessary code and dependencies from the final production binary. +- Removed kzg proof check from blob reconstructor. + +### Fixed + +- Fixed mesh size by appending `gParams.Dhi = gossipSubDhi` +- Fix skipping partial withdrawals count. +- wait for the async StreamEvent writer to exit before leaving the http handler, avoiding race condition panics [pr](https://github.com/prysmaticlabs/prysm/pull/14557) +- Certain deb files were returning a 404 which made building new docker images without an existing + cache impossible. This has been fixed with updates to rules_oci and bazel-lib. +- Fixed an issue where the length check between block body KZG commitments and the existing cache from the database was incompatible. +- Fix `--backfill-oldest-slot` handling - this flag was totally broken, the code would always backfill to the default slot [pr](https://github.com/prysmaticlabs/prysm/pull/14584) +- Fix keymanager API should return corrected error format for malformed tokens +- Fix keymanager API so that get keys returns an empty response instead of a 500 error when using an unsupported keystore. +- Small log improvement, removing some redundant or duplicate logs +- EIP7521 - Fixes withdrawal bug by accounting for pending partial withdrawals and deducting already withdrawn amounts from the sweep balance. [PR](https://github.com/prysmaticlabs/prysm/pull/14578) +- unskip electra merkle spec test +- Fix panic in validator REST mode when checking status after removing all keys +- Fix panic on attestation interface since we call data before validation +- corrects nil check on some interface attestation types +- temporary solution to handling electra attesation and attester_slashing events. [pr](14655) +- Diverse log improvements and comment additions. +- Validate that each committee bitfield in an aggregate contains at least one non-zero bit +- P2P: Avoid infinite loop when looking for peers in small networks. +- Fixed another rollback bug due to a context deadline. +- Fix checkpoint sync bug on holesky. [pr](https://github.com/prysmaticlabs/prysm/pull/14689) +- Fix proposer boost spec tests being flakey by adjusting start time from 3 to 2s into slot. +- Fix segmentation fault in E2E when light-client feature flag is enabled. [PR](https://github.com/prysmaticlabs/prysm/pull/14699) +- Fix `searchForPeers` infinite loop in small networks. +- Fix slashing pool behavior to enforce MaxAttesterSlashings limit in Electra version. + +### Security + +## [v5.1.2](https://github.com/prysmaticlabs/prysm/compare/v5.1.1...v5.1.2) - 2024-10-16 + +This is a hotfix release with one change. + +Prysm v5.1.1 contains an updated implementation of the beacon api streaming events endpoint. This +new implementation contains a bug that can cause a panic in certain conditions. The issue is +difficult to reproduce reliably and we are still trying to determine the root cause, but in the +meantime we are issuing a patch that recovers from the panic to prevent the node from crashing. + +This only impacts the v5.1.1 release beacon api event stream endpoints. This endpoint is used by the +prysm REST mode validator (a feature which requires the validator to be configured to use the beacon +api instead of prysm's stock grpc endpoints) or accessory software that connects to the events api, +like https://github.com/ethpandaops/ethereum-metrics-exporter + +### Fixed + +- Recover from panics when writing the event stream [#14545](https://github.com/prysmaticlabs/prysm/pull/14545) + +## [v5.1.1](https://github.com/prysmaticlabs/prysm/compare/v5.1.0...v5.1.1) - 2024-10-15 + +This release has a number of features and improvements. Most notably, the feature flag +`--enable-experimental-state` has been flipped to "opt out" via `--disable-experimental-state`. +The experimental state management design has shown significant improvements in memory usage at +runtime. Updates to libp2p's gossipsub have some bandwidith stability improvements with support for +IDONTWANT control messages. + +The gRPC gateway has been deprecated from Prysm in this release. If you need JSON data, consider the +standardized beacon-APIs. + +Updating to this release is recommended at your convenience. + +### Added + +- Aggregate and proof committee validation for Electra. +- More tests for electra field generation. +- Light client support: Implement `ComputeFieldRootsForBlockBody`. +- Light client support: Add light client database changes. +- Light client support: Implement capella and deneb changes. +- Light client support: Implement `BlockToLightClientHeader` function. +- Light client support: Consensus types. +- GetBeaconStateV2: add Electra case. +- Implement [consensus-specs/3875](https://github.com/ethereum/consensus-specs/pull/3875). +- Tests to ensure sepolia config matches the official upstream yaml. +- `engine_newPayloadV4`,`engine_getPayloadV4` used for electra payload communication with execution client. [pr](https://github.com/prysmaticlabs/prysm/pull/14492) +- HTTP endpoint for PublishBlobs. +- GetBlockV2, GetBlindedBlock, ProduceBlockV2, ProduceBlockV3: add Electra case. +- Add Electra support and tests for light client functions. +- fastssz version bump (better error messages). +- SSE implementation that sheds stuck clients. [pr](https://github.com/prysmaticlabs/prysm/pull/14413) +- Added GetPoolAttesterSlashingsV2 endpoint. +- Use engine API get-blobs for block subscriber to reduce block import latency and potentially reduce bandwidth. + +### Changed + +- Electra: Updated interop genesis generator to support Electra. +- `getLocalPayload` has been refactored to enable work in ePBS branch. +- `TestNodeServer_GetPeer` and `TestNodeServer_ListPeers` test flakes resolved by iterating the whole peer list to find + a match rather than taking the first peer in the map. +- Passing spectests v1.5.0-alpha.4 and v1.5.0-alpha.5. +- Beacon chain now asserts that the external builder block uses the expected gas limit. +- Electra: Add electra objects to beacon API. +- Electra: Updated block publishing beacon APIs to support Electra. +- "Submitted builder validator registration settings for custom builders" log message moved to debug level. +- config: Genesis validator root is now hardcoded in params.BeaconConfig() +- `grpc-gateway-host` is renamed to http-host. The old name can still be used as an alias. +- `grpc-gateway-port` is renamed to http-port. The old name can still be used as an alias. +- `grpc-gateway-corsdomain` is renamed to http-cors-domain. The old name can still be used as an alias. +- `api-timeout` is changed from int flag to duration flag, default value updated. +- Light client support: abstracted out the light client headers with different versions. +- `ApplyToEveryValidator` has been changed to prevent misuse bugs, it takes a closure that takes a `ReadOnlyValidator` and returns a raw pointer to a `Validator`. +- Removed gorilla mux library and replaced it with net/http updates in go 1.22. +- Clean up `ProposeBlock` for validator client to reduce cognitive scoring and enable further changes. +- Updated k8s-io/client-go to v0.30.4 and k8s-io/apimachinery to v0.30.4 +- Migrated tracing library from opencensus to opentelemetry for both the beacon node and validator. +- Refactored light client code to make it more readable and make future PRs easier. +- Update light client helper functions to reference `dev` branch of CL specs +- Updated Libp2p Dependencies to allow prysm to use gossipsub v1.2 . +- Updated Sepolia bootnodes. +- Make committee aware packing the default by deprecating `--enable-committee-aware-packing`. +- Moved `ConvertKzgCommitmentToVersionedHash` to the `primitives` package. +- Updated correlation penalty for EIP-7251. + +### Deprecated +- `--disable-grpc-gateway` flag is deprecated due to grpc gateway removal. +- `--enable-experimental-state` flag is deprecated. This feature is now on by default. Opt-out with `--disable-experimental-state`. + +### Removed + +- Removed gRPC Gateway. +- Removed unused blobs bundle cache. +- Removed consolidation signing domain from params. The Electra design changed such that EL handles consolidation signature verification. +- Remove engine_getPayloadBodiesBy{Hash|Range}V2 + +### Fixed + +- Fixed early release of read lock in BeaconState.getValidatorIndex. +- Electra: resolve inconsistencies with validator committee index validation. +- Electra: build blocks with blobs. +- E2E: fixed gas limit at genesis +- Light client support: use LightClientHeader instead of BeaconBlockHeader. +- validator registration log changed to debug, and the frequency of validator registration calls are reduced +- Core: Fix process effective balance update to safe copy validator for Electra. +- `== nil` checks before calling `IsNil()` on interfaces to prevent panics. +- Core: Fixed slash processing causing extra hashing. +- Core: Fixed extra allocations when processing slashings. +- remove unneeded container in blob sidecar ssz response +- Light client support: create finalized header based on finalizedBlock's version, not attestedBlock. +- Light client support: fix light client attested header execution fields' wrong version bug. +- Testing: added custom matcher for better push settings testing. +- Registered `GetDepositSnapshot` Beacon API endpoint. +- Fix rolling back of a block due to a context deadline. + +### Security + +No notable security updates. + +## [v5.1.0](https://github.com/prysmaticlabs/prysm/compare/v5.0.4...v5.1.0) - 2024-08-20 + +This release contains 171 new changes and many of these are related to Electra! Along side the Electra changes, there +are nearly 100 changes related to bug fixes, feature additions, and other improvements to Prysm. Updating to this +release is recommended at your convenience. + +⚠️ Deprecation Notice: Removal of gRPC Gateway and Gateway Flag Renaming ⚠️ + +In an upcoming release, we will be deprecating the gRPC gateway and renaming several associated flags. This change will +result in the removal of access to several internal APIs via REST, though the gRPC endpoints will remain unaffected. We +strongly encourage systems to transition to using the beacon API endpoints moving forward. Please refer to PR for more +details. + +### Added + +- Electra work +- Fork-specific consensus-types interfaces +- Fuzz ssz roundtrip marshalling, cloner fuzzing +- Add support for multiple beacon nodes in the REST API +- Add middleware for Content-Type and Accept headers +- Add debug logs for proposer settings +- Add tracing to beacon api package +- Add support for persistent validator keys when using remote signer. --validators-external-signer-public-keys and + --validators-external-signer-key-file See the docs page for more info. +- Add AggregateKeyFromIndices to beacon state to reduce memory usage when processing attestations +- Add GetIndividualVotes endpoint +- Implement is_better_update for light client +- HTTP endpoint for GetValidatorParticipation +- HTTP endpoint for GetChainHead +- HTTP endpoint for GetValidatorActiveSetChanges +- Check locally for min-bid and min-bid-difference + +### Changed + +- Refactored slasher operations to their logical order +- Refactored Gwei and Wei types from math to primitives package. +- Unwrap payload bid from ExecutionData +- Change ZeroWei to a func to avoid shared ptr +- Updated go-libp2p to v0.35.2 and go-libp2p-pubsub to v0.11.0 +- Use genesis block root in epoch 1 for attester duties +- Cleanup validator client code +- Old attestations log moved to debug. "Attestation is too old to broadcast, discarding it" +- Modify ProcessEpoch not to return the state as a returned value +- Updated go-bitfield to latest release +- Use go ticker instead of timer +- process_registry_updates no longer makes a full copy of the validator set +- Validator client processes sync committee roll separately +- Use vote pointers in forkchoice to reduce memory churn +- Avoid Cloning When Creating a New Gossip Message +- Proposer filters invalid attestation signatures +- Validator now pushes proposer settings every slot +- Get all beacon committees at once +- Committee-aware attestation packing + +### Deprecated + +- `--enable-debug-rpc-endpoints` is deprecated and debug rpc points are on by default. + +### Removed + +- Removed fork specific getter functions (i.e. PbCapellaBlock, PbDenebBlock, etc) + +### Fixed + +- Fixed debug log "upgraded stake to $fork" to only log on upgrades instead of every state transition +- Fixed nil block panic in API +- Fixed mockgen script +- Do not fail to build block when block value is unknown +- Fix prysmctl TUI when more than 20 validators were listed +- Revert peer backoff changes from. This was causing some sync committee performance issues. +- Increased attestation seen cache expiration to two epochs +- Fixed slasher db disk usage leak +- fix: Multiple network flags should prevent the BN to start +- Correctly handle empty payload from GetValidatorPerformance requests +- Fix Event stream with carriage return support +- Fix panic on empty block result in REST API +- engine_getPayloadBodiesByRangeV1 - fix, adding hexutil encoding on request parameters +- Use sync committee period instead of epoch in `createLightClientUpdate` + +### Security + +- Go version updated to 1.22 + +## [v5.0.4](https://github.com/prysmaticlabs/prysm/compare/v5.0.3...v5.0.4) - 2024-07-21 + +This release has many wonderful bug fixes and improvements. Some highlights include p2p peer fix for windows users, +beacon API fix for retrieving blobs older than the minimum blob retention period, and improvements to initial sync by +avoiding redundant blob downloads. + +Updating to this release is recommended at your earliest convenience, especially for windows users. + +### Added + +- Beacon-api: broadcast blobs in the event of seen block +- P2P: Add QUIC support + +### Changed + +- Use slices package for various slice operations +- Initsync skip local blobs +- Use read only validators in Beacon API +- Return syncing status when node is optimistic +- Upgrade the Beacon API e2e evaluator +- Don't return error that can be internally handled +- Allow consistent auth token for validator apis +- Change example.org DNS record +- Simplify prune invalid by reusing existing fork choice store call +- use [32]byte keys in the filesystem cache +- Update Libp2p Dependencies +- Parallelize Broadcasting And Processing Each Blob +- Substantial VC cleanup +- Only log error when aggregator check fails +- Update Libp2p Dependencies +- Change Attestation Log To Debug +- update codegen dep and cleanup organization + +### Deprecated + +- Remove eip4881 flag (--disable-eip-4881) + +### Removed + +- Remove the Goerli/Prater support +- Remove unused IsViableForCheckpoint +- Remove unused validator map copy method + +### Fixed + +- Various typos and other cosmetic fixes +- Send correct state root with finalized event stream +- Extend Broadcast Window For Attestations +- Beacon API: Use retention period when fetching blobs +- Backfill throttling +- Use correct port for health check in Beacon API e2e evaluator +- Do not remove blobs DB in slasher. +- use time.NewTimer() to avoid possible memory leaks +- paranoid underflow protection without error handling +- Fix CommitteeAssignments to not return every validator +- Fix dependent root retrieval genesis case +- Restrict Dials From Discovery +- Always close cache warm chan to prevent blocking +- Keep only the latest value in the health channel + +### Security + +- Bump golang.org/x/net from 0.21.0 to 0.23.0 + +## [v5.0.3](https://github.com/prysmaticlabs/prysm/compare/v5.0.2...v5.0.3) - 2024-04-04 + +Prysm v5.0.3 is a small patch release with some nice additions and bug fixes. Updating to this release is recommended +for users on v5.0.0 or v5.0.1. There aren't many changes since last week's v5.0.2 so upgrading is not strictly required, +but there are still improvements in this release so update if you can! + +### Added + +- Testing: spec test coverage tool +- Add bid value metrics +- prysmctl: Command-line interface for visualizing min/max span bucket +- Explicit Peering Agreement implementation + +### Changed + +- Utilize next slot cache in block rewards rpc +- validator: Call GetGenesis only once when using beacon API +- Simplify ValidateAttestationTime +- Various typo / commentary improvements +- Change goodbye message from rate limited peer to debug verbosity +- Bump libp2p to v0.33.1 +- Fill in missing debug logs for blob p2p IGNORE/REJECT + +### Fixed + +- Remove check for duplicates in pending attestation queue +- Repair finalized index issue +- Maximize Peer Capacity When Syncing +- Reject Empty Bundles + +### Security + +No security updates in this release. + +## [v5.0.2](https://github.com/prysmaticlabs/prysm/compare/v5.0.1...v5.0.2) - 2024-03-27 + +This release has many optimizations, UX improvements, and bug fixes. Due to the number of important bug fixes and +optimizations, we encourage all operators to update to v5.0.2 at their earliest convenience. + +In this release, there is a notable change to the default value of --local-block-value-boost from 0 to 10. This means +that the default behavior of using the builder API / mev-boost requires the builder bid to be 10% better than your local +block profit. If you want to preserve the existing behavior, set --local-block-value-boost=0. + +### Added + +- API: Add support for sync committee selections +- blobs: call fsync between part file write and rename (feature flag --blob-save-fsync) +- Implement EIP-3076 minimal slashing protection, using a filesystem database (feature flag + --enable-minimal-slashing-protection) +- Save invalid block to temp --save-invalid-block-temp +- Compute unrealized checkpoints with pcli +- Add gossip blob sidecar verification ms metric +- Backfill min slot flag (feature flag --backfill-oldest-slot) +- adds a metric to track blob sig cache lookups +- Keymanager APIs - get,post,delete graffiti +- Set default LocalBlockValueBoost to 10 +- Add bid value metrics +- REST VC metrics +- `startDB`: Add log when checkpoint sync. + +### Changed + +- Normalized checkpoint logs +- Normalize filesystem/blob logs +- Updated gomock libraries +- Use Max Request Limit in Initial Sync +- Do not Persist Startup State +- Normalize backfill logs/errors +- Unify log fields +- Do Not Compute Block Root Again +- Optimize Adding Dirty Indices +- Use a Validator Reader When Computing Unrealized Balances +- Copy Validator Field Trie +- Do not log zero sync committee messages +- small cleanup on functions: use slots.PrevSlot +- Set the log level for running on as INFO. +- Employ Dynamic Cache Sizes +- VC: Improve logging in case of fatal error +- refactoring how proposer settings load into validator client +- Spectest: Unskip Merkle Proof test +- Improve logging. +- Check Unrealized Justification Balances In Spectests +- Optimize SubscribeCommitteeSubnets VC action +- Clean up unreachable code; use new(big.Int) instead of big.NewInt(0) +- Update bazel, rules_go, gazelle, and go versions +- replace receive slot with event stream +- New gossip cache size +- Use headstate for recent checkpoints +- Update spec test to official 1.4.0 +- Additional tests for KZG commitments +- Enable Configurable Mplex Timeouts +- Optimize SubmitAggregateSelectionProof VC action +- Re-design TestStartDiscV5_DiscoverPeersWithSubnets test +- Add da waited time to sync block log +- add log message if in da check at slot end +- Log da block root in hex +- Log the slot and blockroot when we deadline waiting for blobs +- Modify the algorithm of updateFinalizedBlockRoots +- Rename payloadattribute Timestamps to Timestamp +- Optimize GetDuties VC action +- docker: Add bazel target for building docker tarball +- Utilize next slot cache in block rewards rpc +- Spec test coverage report +- Refactor batch verifier for sharing across packages + +### Removed + +- Remove unused bolt buckets +- config: Remove DOMAIN_BLOB_SIDECAR. +- Remove unused deneb code +- Clean up: remove some unused beacon state protos +- Cleaned up code in the sync package +- P2P: Simplify code + +### Fixed + +- Slasher: Reduce surrounding/surrounded attestations processing time +- Fix blob batch verifier pointer receiver +- db/blobs: Check non-zero data is written to disk +- avoid part path collisions with mem addr entropy +- Download checkpoint sync origin blobs in init-sync +- bazel: Update aspect-build/bazel-lib to v2.5.0 +- move setting route handlers to registration from start +- Downgrade Level DB to Stable Version +- Fix failed reorg log +- Fix Data Race in Epoch Boundary +- exit blob fetching for cp block if outside retention +- Do not check parent weight on early FCU +- Fix VC DB conversion when no proposer settings is defined and add Experimental flag in the + --enable-minimal-slashing-protection help. +- keymanager api: lowercase statuses +- Fix unrealized justification +- fix race condition when pinging peers +- Fix/race receive block +- Blob verification spectest +- Ignore Pubsub Messages Hitting Context Deadlines +- Use justified checkpoint from head state to build attestation +- only update head at 10 seconds when validating +- Use correct gossip validation time +- fix 1-worker underflow; lower default batch size +- handle special case of batch size=1 +- Always Set Inprogress Boolean In Cache +- Builder APIs: adding headers to post endpoint +- Rename misspelled variable +- allow blob by root within da period +- Rewrite Pruning Implementation To Handle EIP 7045 +- Set default fee recipient if tracked val fails +- validator client on rest mode has an inappropriate context deadline for events +- validator client should set beacon API endpoint in configurations +- Fix get validator endpoint for empty query parameters +- Expand Our TTL for our Message ID Cache +- fix some typos +- fix handling of goodbye messages for limited peers +- create the log file along with its parent directory if not present +- Call GetGenesis only once + +### Security + +- Go version has been updated from 1.21.6 to 1.21.8. + +## [v5.0.1](https://github.com/prysmaticlabs/prysm/compare/v5.0.0...v5.0.1) - 2024-03-08 + +This minor patch release has some nice improvements over the recent v5.0.0 for Deneb. We have minimized this patch +release to include only low risk and valuable fixes or features ahead of the upcoming network upgrade on March 13th. + +Deneb is scheduled for mainnet epoch 269568 on March 13, 2024 at 01:55:35pm UTC. All operators MUST update their Prysm +software to v5.0.0 or later before the upgrade in order to continue following the blockchain. + +### Added + +- A new flag to ensure that blobs are flushed to disk via fsync immediately after write. --blob-save-fsync + +### Changed + +- Enforce a lower maximum batch limit value to prevent annoying peers +- Download blobs for checkpoint sync block before starting sync +- Set justified epoch to the finalized epoch in Goerli to unstuck some Prysm nodes on Goerli + +### Fixed + +- Data race in epoch boundary cache +- "Failed reorg" log was misplaced +- Do not check parent weights on early fork choice update calls +- Compute unrealized justification with slashed validators +- Missing libxml dependency + +### Security + +Prysm version v5.0.0 or later is required to maintain participation in the network after the Deneb upgrade. + +## [v5.0.0](https://github.com/prysmaticlabs/prysm/compare/v4.2.1...v5.0.0) + +Behold the Prysm v5 release with official support for Deneb on Ethereum mainnet! + +Deneb is scheduled for mainnet epoch 269568 on March 13, 2024 at 01:55:35pm UTC. All operators MUST update their Prysm +software to v5.0.0 or later before the upgrade in order to continue following the blockchain. + +This release brings improvements to the backfill functionality of the beacon node to support backfilling blobs. If +running a beacon node with checkpoint sync, we encourage you to test the backfilling functionality and share your +feedback. Run with backfill enabled using the flag --enable-experimental-backfill. + +Known Issues + +- --backfill-batch-size with a value of 1 or less breaks backfill. +- Validator client on v4.2.0 or older uses some API methods that are incompatible with beacon node v5. Ensure that you + have updated the beacon node and validator client to v4.2.1 and then upgrade to v5 or update both processes at the + same time to minimize downtime. + +### Added + +- Support beacon_committee_selections +- /eth/v1/beacon/deposit_snapshot +- Docker images now have coreutils pre-installed +- da_waited_time_milliseconds tracks total time waiting for data availability check in ReceiveBlock +- blob_written, blob_disk_count, blob_disk_bytes new metrics for tracking blobs on disk +- Backfill supports blob backfilling +- Add mainnet deneb fork epoch config + +### Changed + +- --clear-db and --force-clear-db flags now remove blobs as well as beaconchain.db +- EIP-4881 is now on by default. +- Updates filtering logic to match spec +- Verbose signature verification is now on by default +- gossip_block_arrival_milliseconds and gossip_block_verification_milliseconds measure in +- milliseconds instead of nanoseconds +- aggregate_attestations_t1 histogram buckets have been updated +- Reduce lookahead period from 8 to 4. This reduces block batch sizes during sync to account for +- larger blocks in deneb. +- Update gohashtree to v0.0.4-beta +- Various logging improvements +- Improved operations during syncing +- Backfill starts after initial-sync is complete + +### Deprecated + +The following flags have been removed entirely: + +- --enable-reorg-late-blocks +- --disable-vectorized-htr +- --aggregate-parallel +- --build-block-parallel +- --enable-registration-cache, disable-gossip-batch-aggregation +- --safe-slots-to-import-optimistically +- --show-deposit-data + +### Removed + +- Prysm gRPC slasher endpoints are removed +- Remove /eth/v1/debug/beacon/states/{state_id} +- Prysm gRPC endpoints that were marked as deprecated in v4 have been removed +- Remove /eth/v1/beacon/blocks/{block_id} + +### Fixed + +- Return unaggregated if no aggregated attestations available in GetAggregateAttestation +- Fix JWT auth checks in certain API endpoints used by the web UI +- Return consensus block value in wei units +- Minor fixes in protobuf files +- Fix 500 error when requesting blobs from a block without blobs +- Handle cases were EL client is syncing and unable to provide payloads +- /eth/v1/beacon/blob_sidecars/{block_id} correctly returns an error when invalid indices are requested +- Fix head state fetch when proposing a failed reorg +- Fix data race in background forkchoice update call +- Correctly return "unavailable" response to peers requesting batches before the node completes +- backfill. +- Many significant improvements and fixes to the prysm slasher +- Fixed slashing gossip checks, improves peer scores for slasher peers +- Log warning if attempting to exit more than 5 validators at a time +- Do not cache inactive public keys +- Validator exits prints testnet URLs +- Fix pending block/blob zero peer edge case +- Check non-zero blob data is written to disk +- Avoid blob partial filepath collisions with mem addr entropy + +### Security + +v5.0.0 of Prysm is required to maintain participation in the network after the Deneb upgrade. + +## [v4.2.1](https://github.com/prysmaticlabs/prysm/compare/v4.2.0...v4.2.1) - 2024-01-29 + +Welcome to Prysm Release v4.2.1! This release is highly recommended for stakers and node operators, possibly being the +final update before V5. + +⚠️ This release will cause failures on Goerli, Sepolia and Holeski testnets, when running on certain older CPUs without +AVX support (eg Celeron) after the Deneb fork. This is not an issue for mainnet. + +### Added + +- Linter: Wastedassign linter enabled to improve code quality. +- API Enhancements: + - Added payload return in Wei for /eth/v3/validator/blocks. + - Added Holesky Deneb Epoch for better epoch management. +- Testing Enhancements: + - Clear cache in tests of core helpers to ensure test reliability. + - Added Debug State Transition Method for improved debugging. + - Backfilling test: Enabled backfill in E2E tests for more comprehensive coverage. +- API Updates: Re-enabled jwt on keymanager API for enhanced security. +- Logging Improvements: Enhanced block by root log for better traceability. +- Validator Client Improvements: + - Added Spans to Core Validator Methods for enhanced monitoring. + - Improved readability in validator client code for better maintenance (various commits). + +### Changed + +- Optimizations and Refinements: + - Lowered resource usage in certain processes for efficiency. + - Moved blob rpc validation closer to peer read for optimized processing. + - Cleaned up validate beacon block code for clarity and efficiency. + - Updated Sepolia Deneb fork epoch for alignment with network changes. + - Changed blob latency metrics to milliseconds for more precise measurement. + - Altered getLegacyDatabaseLocation message for better clarity. + - Improved wait for activation method for enhanced performance. + - Capitalized Aggregated Unaggregated Attestations Log for consistency. + - Modified HistoricalRoots usage for accuracy. + - Adjusted checking of attribute emptiness for efficiency. +- Database Management: + - Moved --db-backup-output-dir as a deprecated flag for database management simplification. + - Added the Ability to Defragment the Beacon State for improved database performance. +- Dependency Update: Bumped quic-go version from 0.39.3 to 0.39.4 for up-to-date dependencies. + +### Removed + +- Removed debug setting highest slot log to clean up the logging process. +- Deleted invalid blob at block processing for data integrity. + +### Fixed + +- Bug Fixes: + - Fixed off by one error for improved accuracy. + - Resolved small typo in error messages for clarity. + - Addressed minor issue in blsToExecChange validator for better validation. + - Corrected blobsidecar json tag for commitment inclusion proof. + - Fixed ssz post-requests content type check. + - Resolved issue with port logging in bootnode. +- Test Fixes: Re-enabled Slasher E2E Test for more comprehensive testing. + +### Security + +No security issues in this release. + +## [v4.2.0](https://github.com/prysmaticlabs/prysm/compare/v4.1.1...v4.2.0) - 2024-01-11 + +Happy new year! We have an incredibly exciting release to kick off the new year. This release is **strongly recommended +** for all operators to update as it has many bug fixes, security patches, and features that will improve the Prysm +experience on mainnet. This release has so many wonderful changes that we've deviated from our normal release notes +format to aptly categorize the changes. + +### Highlights + +#### Upgrading / Downgrading Validators + +There are some API changes bundled in this release that require you to upgrade or downgrade in particular order. If the +validator is updated before the beacon node, it will see repeated 404 errors at start up until the beacon node is +updated as it uses a new API endpoint introduced in v4.2.0. + +:arrow_up_small: **Upgrading**: Upgrade the beacon node, then the validator. +:arrow_down_small: **Downgrading**: Downgrade the validator to v4.1.1 then downgrade the beacon node. + +#### Deneb Goerli Support + +This release adds in full support for the upcoming deneb hard fork on goerli next week on January 17th. + +#### Networking Parameter Changes + +This release increases the default peer count to 70 from 45. The reason this is done is so that node's running +with default peer counts can perform their validator duties as expected. Users who want to use the old peer count +can add in `--p2p-max-peers=45` as a flag. + +#### Profile Guided Optimization + +This release has binaries built using PGO, for more information on how it works feel free to look +here: https://tip.golang.org/doc/pgo . +This allows the go compiler to build more optimized Prysm binaries using production profiles and workloads. + +#### ARM Supported Docker Images + +Our docker images now support amd64 and arm64 architecture! This long awaited feature is finally here for Apple Silicon +and Raspberry Pi users. + +### Deneb + +#### Core + +- Use ROForkchoice in blob verifier +- Add Goerli Deneb Fork Epoch +- Use deneb key for deneb state in saveStatesEfficientInternal +- Initialize Inactivity Scores Correctly +- Excludes DA wait time for chain processing time +- Initialize sig cache for verification.Initializer +- Verify roblobs +- KZG Commitment inclusion proof verifier +- Merkle Proofs of KZG commitments +- Add RO blob sidecar +- Check blob index duplication for blob notifier +- Remove sidecars with invalid proofs +- Proposer: better handling of blobs bundle +- Update proposer RPC to new blob sidecar format +- Implement Slot-Dependent Caching for Blobs Bundle +- Verified roblobs + +#### Networking + +- Check sidecar index in BlobSidecarsByRoot response +- Use proposer index cache for blob verification +- VerifiedROBlobs in initial-sync +- Reordered blob validation +- Initialize blob storage for initial sync service +- Use verified blob for gossip checks +- Update broadcast method to use `BlobSidecar` instead of `SingedBlobSidecar` +- Remove pending blobs queue +- Reject Blob Sidecar Incorrect Index +- Check return and request lengths for blob sidecar by root +- Fix blob sidecar subnet check +- Add pending blobs queue for missing parent block +- Verify blobs that arrived from by root request +- Reject blobs with invalid parent +- Add more blob and block checks for by range +- Exit early if blob by root request is empty +- Request missing blobs while processing pending queue +- Check blob exists before requesting from peer +- Passing block as argument for sidecar validation + +#### Blob Management + +- Remove old blob types +- minimize syscalls in pruning routine +- Prune dangling blob +- Use Afero Walk for Pruning Blob +- Initialize blob storage without pruning +- Fix batch pruning errors +- Blob filesystem add pruning during blob write +- Blob filesystem add pruning at startup +- Ensure partial blob is deleted if there's an error +- Split blob pruning into two funcs +- Use functional options for `--blob-retention-epochs` +- Blob filesystem: delete blobs +- Fix Blob Storage Path +- Add blob getters +- Blob filesystem: Save Blobs +- Blob filesystem: prune blobs +- blobstorage: Improve mkdirall error + +#### Beacon-API + +- Add rpc trigger for blob sidecar event +- Do not skip mev boost in `v3` block production endpoint +- Beacon APIs: re enabling blob events +- Beacon API: update Deneb endpoints after removing blob signing +- Beacon API: fix get blob returns 500 instead of empty +- Fix bug in Beacon API getBlobs +- Fix blob_sidecar SSE payload +- fix(beacon-chain/rpc): blob_sidecar event stream handler +- Improvements to `produceBlockV3` +- Deneb: Produce Block V3 - adding consensus block value + +#### Validator Client + +- Validator client: remove blob signing +- Deneb - web3signer + +#### Testing + +- Enable Deneb For E2E Scenario Tests +- Activate deneb in E2E +- Deneb E2E + +#### Miscellaneous + +- Update blob pruning log +- Fix total pruned metric + add to logging +- Check kzg commitment count from builder +- Add error wrapping to blob initialization errors +- Blob filesystem metrics +- Check builder header kzg commitment +- Add more color to sending blob by range req log +- Move pruning log to after retention check +- Enhance Pruning Logs +- Rename Blob retention epoch flag +- Check that blobs count is correct when unblinding +- Log blob's kzg commmitment at sync +- Replace MAX_BLOB_EPOCHS usages with more accurate terms +- Fix comment of `BlobSidecarsBySlot` + +### Core Prysm Work(Non-Deneb) + +#### Core Protocol + +- Only process blocks which haven't been processed +- Initialize exec payload fields and enforce order +- Add nil check for head in IsOptimistic +- Unlock forkchoice store if attribute is empty +- Make Aggregating In Parallel The Permanent Default +- Break out several helpers from `postBlockProcess` +- Don't hardcode 4 seconds in forkchoice +- Simplify fcu 4 +- Remove the getPayloadAttribute call from updateForkchoiceWithExecution +- Simplify fcu 2 +- Remove getPayloadAttributes from FCU call +- Simplify fcu 1 +- Remove unsafe proposer indices cache +- Rewrite `ProposeBlock` endpoint +- Remove blind field from block type +- update shuffling caches before calling FCU on epoch boundaries +- Return SignedBeaconBlock from ReadOnlySignedBeaconBlock.Copy +- Use advanced epoch cache when preparing proposals +- refactor Payload Id caches +- Use block value correctly when proposing a block +- use different keys for the proposer indices cache +- Use a cache of one entry to build attestation +- Remove signed block requirement from no-verify functions +- Allow requests for old target roots +- Remove Redundant Hash Computation in Cache +- Fix FFG LMD Consistency Check (Option 2) +- Verify lmd without ancestor +- Track target in forkchoice +- Return early from ReceiveBlock if already sycned + +#### Builder + +- Adding builder boost factor to get block v3 +- Builder API: Fix max field check on toProto function +- Add sanity checks for bundle from builder +- Update Prysm Proposer end points for Builder API +- Builder API: remove blinded blob sidecar +- Allow validators registration batching on Builder API `/eth/v1/builder/validators` + +#### State-Management + +- Add Detailed Multi Value Metrics +- Optimize Multivalue Slice For Trie Recomputation +- Fix Multivalue Slice Deadlock +- Set Better Slice Capacities in the State + +#### Networking + +- Refactor Network Config Into Main Config +- Handle potential error from newBlockRangeBatcher +- Clean Up Goodbye Stream Errors +- Support New Subnet Backbone +- Increase Networking Defaults +- Bump Up Gossip Queue Size +- Improve Gossipsub Rejection Metric +- Add Gossipsub Queue Flag +- Fix Deadlock With Subscriber Checker +- Add Additional Pubsub Metrics +- Verify Block Signatures On Insertion Into Pending Queue +- Enhance Validation for Block by Root RPC Requests +- Add a helper for max request block +- Fix Pending Queue Deadline Bug +- Add context deadline for pending queue's receive block +- Fix Pending Queue Expiration Bug +- sync only up to previous epoch on phase 1 +- Use correct context for sendBatchRootRequest +- Refactor Pending Block Queue Logic in Sync Package +- Check block exists in pending queue before requesting from peer +- Set Verbosity of Goodbye Logs to Trace +- use read only head state + +#### Beacon-API + +_Most of the PRs here involve shifting our http endpoints to using vanilla http handlers(without the API middleware)._ + +- http endpoint cleanup +- Revert "REST VC: Subscribe to Beacon API events " +- proposer and attester slashing sse +- REST VC: Subscribe to Beacon API events +- Simplify error handling for JsonRestHandler +- Update block publishing to 2.4.2 spec +- Use `SkipMevBoost` properly during block production +- Handle HTTP 404 Not Found in `SubmitAggregateAndProof` +- beacon-chain/rpc: use BalanceAtIndex instead of Balances to reduce memory copy +- HTTP endpoints cleanup +- APIs: reusing grpc cors middleware for rest +- Beacon API: routes unit test +- Remove API Middleware +- HTTP validator API: beacon and account endpoints +- REST VC: Use POST to fetch validators +- HTTP handler for Beacon API events +- Move weak subjectivity endpoint to HTTP +- Handle non-JSON responses from Beacon API +- POST version of GetValidators and GetValidatorBalances +- [2/5] light client http api +- HTTP validator API: wallet endpoints +- HTTP Validator API: slashing protection import and export +- Config HTTP endpoints +- Return 404 from `eth/v1/beacon/headers` when there are no blocks +- Pool slashings HTTP endpoints +- Validator HTTP endpoints +- Debug HTTP endpoints +- HTTP validator API: health endpoints +- HTTP Validator API: `/eth/v1/keystores` +- Allow unknown fields in Beacon API responses +- HTTP state endpoints +- HTTP Validator API: `/eth/v1/validator/{pubkey}/feerecipient` +- HTTP Validator API: `/eth/v1/validator/{pubkey}/gas_limit` +- HTTP VALIDATOR API: remote keymanager api `/eth/v1/remotekeys` +- rpc/apimiddleware: Test all paths can be created +- HTTP Beacon APIs for blocks +- HTTP VALIDATOR API: `/eth/v1/validator/{pubkey}/voluntary_exit` +- HTTP Beacon APIs: 3 state endpoints +- HTTP Beacon APIs for node +- HTTP API: `/eth/v1/beacon/pool/bls_to_execution_changes` +- Register sync subnet when fetching sync committee duties through Beacon API + +#### Validator Client + +- Refactor validator client help. +- `--validatorS-registration-batch-size` (add `s`) +- Validator client: Always use the `--datadir` value. +- Hook to slot stream instead of block stream on the VC +- CLI: fixing account import ux bugs +- `filterAndCacheActiveKeys`: Stop filtering out exiting validators +- Gracefully handle unknown validator index in the REST VC +- Don't fetch duties for unknown keys +- Fix Domain Data Caching +- Add `--jwt-id` flag +- Make Prysm VC compatible with the version `v5.3.0` of the slashing protections interchange tests. +- Fix handling POST requests in the REST VC +- Better error handling in REST VC +- Fix block proposals in the REST validator client +- CLEANUP: validator exit prompt +- integrate validator count endpoint in validator client + +#### Build/CI Work + +- Bazel 7.0.0 +- Sort static analyzers, add more, fix violations +- For golangci-lint, enable all by default +- Enable mirror linter and fix findings +- Enable usestdlibvars linter and fix findings +- Fix docker image version strings in CI +- fixing sa4006 +- Enable errname linter and fix findings +- Remove rules_docker, make multiarch images canonical +- Fix staticcheck violations +- Add staticchecks to bazel builds +- CI: Add merge queue events trigger for github workflows +- Update bazel and other CI improvements +- bazel: Run buildifier, general cleanup +- pgo: Enable pgo behind release flag +- pgo: remove default pprof profile +- zig: Update zig to recent main branch commit +- Enable profile guided optimization for beacon-chain +- Refactor Exported Names to Follow Golang Best Practices +- Update rules_go and gazelle to 0.42 & 0.33 (latest releases) +- Fix image deps + +#### Dependency Updates + +- Update go to 1.21.6 +- Update Our Golang Crypto Library +- Update libp2p/go-libp2p-asn-util to v0.4.1 +- Update Libp2p To v0.32.1 and Go to v1.21.5 +- Bump google.golang.org/grpc from 1.53.0 to 1.56.3 +- Update go to 1.20.10 + +#### Testing + +- Enable Profiling for Long Running E2E Runs +- Fetch Goroutine Traces in E2E +- Fix Up Builder Evaluator +- Increase Blob Batch Parameters in E2E +- Uncomment e2e flakiness +- Update spectests to 1.4.0-beta.5 +- Test improvement TestValidateVoluntaryExit_ValidExit +- Simplify post-evaluation in Beacon API evaluator +- Run Evaluator In the Middle Of An Epoch +- Simplify Beacon API evaluator +- Fix Optimistic Sync Evaluator +- Add test helpers to produce commitments and proofs +- Redesign of Beacon API evaluator +- Drop Transaction Count for Transaction Generator +- Add concurrency test for getting attestation state +- Add `construct_generic_block_test` to build file +- Implement Merkle proof spectests +- Remove `/node/peers/{peer_id}` from Beacon API evaluator +- Update spectest and changed minimal preset for field elements +- Better Beacon API evaluator part 1 +- beacon-chain/blockchain: fix some datarace in go test +- beacon-node/rpc: fix go test datarace +- Fix Builder Testing For Multiclient Runs +- Fill state attestations +- beacon-chain/sync: fix some datarace in go test +- beacon-chain/execution: fix a data race in testcase +- Add state not found test case + +#### Feature Updates + +- Make New Engine Methods The Permanent Default +- Make Reorging Of Late Blocks The Permanent Default + +#### Miscellaneous + +- Update teku's bootnode +- fix metric for exited validator +- Fix typos +- Replace validator count with validator indices in update fee recipient log +- Log value of local payload when proposing +- Small encoding fixes on logs and http error code change +- typo fix +- Fix error string generation for missing commitments +- Increase buffer of events channel +- Fix missing testnet versions. Issue +- Update README.md +- Only run metrics for canonical blocks +- Relax file permissions check on existing directories +- forkchoice.Getter wrapper with locking wrappers +- Initialize cancellable root context in main.go +- Fix forkchoice pkg's comments grammar +- lock RecentBlockSlot +- Comment typo +- Optimize `ReplayBlocks` for Zero Diff +- Remove default value of circuit breaker flags +- Fix Withdrawals +- Remove no-op cancel func +- Update Terms of Service +- fix head slot in log +- DEPRECATION: Remove exchange transition configuration call +- fix segmentation fork when Capella for epoch is MaxUint64 +- Return Error Gracefully When Removing 4881 Flag +- Add zero length check on indices during NextSyncCommitteeIndices +- Replace Empty Slice Literals with Nil Slices +- Refactor Error String Formatting According to Go Best Practices +- Fix redundant type conversion +- docs: fix typo +- Add Clarification To Sync Committee Cache +- Fix typos +- remove bad comment +- Remove confusing comment +- Log when sending FCU with payload attributes +- Fix Withdrawals Marshalling +- beacon-chain/execution: no need to reread and unmarshal the eth1Data twice + +## [v4.1.1](https://github.com/prysmaticlabs/prysm/compare/v4.1.0...v4.1.1) - 2023-10-24 + +This patch release includes two cherry-picked changes from the develop branch to resolve critical issues that affect a +small set of users. + +### Fixed + +- Fix improperly registered REST API endpoint for validators using Prysm's REST API with an external builder +- Fix deadlock when using --enable-experimental-state feature + +### Security + +No security issues in this release. + +## [v4.1.0](https://github.com/prysmaticlabs/prysm/compare/v4.0.8...v4.1.0) - 2023-08-22 + +- **Fundamental Deneb Support**: This release lays the foundation for Deneb support, although features like backwards + syncing and filesystem-based blob storage are planned for Q4 2024. +- **Multi-Value Slices for Beacon State**: Implemented multi-value slices to reduce the memory footprint and optimize + certain processing paths. This data structure allows for storing values shared between state instances more + efficiently. This feature is controller by the `--enable-experimental-state` flag. +- **EIP-4881 Deposit Tree**: Integrated the EIP-4881 Deposit Tree into Prysm to optimize runtime block processing and + production. This feature is controlled by a flag: `--enable-eip-4881` +- **BLST version 0.3.11**: Introduced a significant improvement to the portable build's performance. The portable build + now features runtime detection, automatically enabling optimized code paths if your CPU supports it. +- **Multiarch Containers Preview Available**: multiarch (:wave: arm64 support :wave:) containers will be offered for + preview at the following locations: + - Beacon Chain: [gcr.io/prylabs-dev/prysm/beacon-chain:v4.1.0](gcr.io/prylabs-dev/prysm/beacon-chain:v4.1.0) + - Validator: [gcr.io/prylabs-dev/prysm/validator:v4.1.0](gcr.io/prylabs-dev/prysm/validator:v4.1.0) + - Please note that in the next cycle, we will exclusively use these containers at the canonical URLs. + +### Added + +#### EIP-4844: + +##### Core: + +- **Deneb State & Block Types**: New state and block types added specifically for Deneb. +- **Deneb Protobufs**: Protocol Buffers designed exclusively for Deneb. +- **Deneb Engine API**: Specialized API endpoints for Deneb. +- **Deneb Config/Params**: Deneb-specific configurations and parameters from the deneb-integration branch. + +##### Blob Management: + +- **Blob Retention Epoch Period**: Configurable retention periods for blobs. +- **Blob Arrival Gossip Metric**: Metrics for blob arrivals via gossip protocol. +- **Blob Merge Function**: Functionality to merge and validate saved/new blobs. +- **Blob Channel**: A channel dedicated to blob processing. +- **Save Blobs to DB**: Feature to save blobs to the database for subscribers. + +##### Logging and Validation: + +- **Logging for Blob Sidecar**: Improved logging functionalities for Blob Sidecar. +- **Blob Commitment Count Logging**: Introduced logging for blob commitment counts. +- **Blob Validation**: A feature to validate blobs. + +##### Additional Features and Tests: + +- **Deneb Changes & Blobs to Builder**: Deneb-specific changes and blob functionality added to the builder. +- **Deneb Blob Sidecar Events**: Blob sidecar events added as part of the Deneb release. +- **KZG Commitments**: Functionality to copy KZG commitments when using the builder block. +- **Deneb Validator Beacon APIs**: New REST APIs specifically for the Deneb release. +- **Deneb Tests**: Test cases specific to the Deneb version. +- **PublishBlockV2 for Deneb**: The `publishblockv2` endpoint implemented specifically for Deneb. +- **Builder Override & Builder Flow for Deneb**: An override for the builder and a new RPC to handle the builder flow in + Deneb. +- **SSZ Detection for Deneb**: SSZ detection capabilities added for Deneb. +- **Validator Signing for Deneb**: Validators can now sign Deneb blocks. +- **Deneb Upgrade Function**: A function to handle the upgrade to Deneb. + +#### Rest of EIPs + +- **EIP-4788**: Added support for Beacon block root in the EVM. +- **EIP-7044** and **EIP-7045**: Implemented support for Perpetually Valid Signed Voluntary Exits and increased the max + attestation inclusion slot. + +#### Beacon API: + +*Note: All Beacon API work is related with moving endpoints into pure HTTP handlers. This is NOT new functionality.* + +##### Endpoints moved to HTTP: + +- `/eth/v1/beacon/blocks` and `/eth/v1/beacon/blinded_blocks`. +- `/eth/v1/beacon/states/{state_id}/committees`. +- `/eth/v1/config/deposit_contract`. +- `/eth/v1/beacon/pool/sync_committees`. +- `/eth/v1/beacon/states/{state_id}/validators`, `/eth/v1/beacon/states/{state_id}/validators/{validator_id}` + and `/eth/v1/beacon/states/{state_id}/validator_balances`. +- `/eth/v1/validator/duties/attester/{epoch}`, `/eth/v1/validator/duties/proposer/{epoch}` + and `/eth/v1/validator/duties/sync/{epoch}`. +- `/eth/v1/validator/register_validator`. +- `/eth/v1/validator/prepare_beacon_proposer`. +- `/eth/v1/beacon/headers`. +- `/eth/v1/beacon/blocks/{block_id}/root`. +- `/eth/v1/validator/attestation_data`. +- `/eth/v1/validator/sync_committee_contribution`. +- `/eth/v1/beacon/genesis` and `/eth/v1/beacon/states/{state_id}/finality_checkpoints`. +- `/eth/v1/node/syncing`. +- `/eth/v1/beacon/pool/voluntary_exits`. +- `/eth/v1/beacon/headers/{block_id}` and `/eth/v1/validator/liveness/{epoch}`. + +##### Miscellaneous: + +- **Comma-Separated Query Params**: Support for comma-separated query parameters added to Beacon API. +- **Middleware for Query Params**: Middleware introduced for handling comma-separated query parameters. +- **Content-Type Header**: Compliance improved by adding Content-Type header to VC POST requests. +- **Node Version**: REST-based node version endpoint implemented. + +#### Other additions + +##### Protocol: + +- **Multi-Value Slice for Beacon State**: Enhanced the beacon state by utilizing a multi-value slice. +- **EIP-4881 Deposit Tree**: EIP-4881 Deposit Tree integrated into Prysm, controlled by a feature flag. +- **New Engine Methods**: New engine methods set as the default. +- **Light Client Sync Protocol**: Initiation of a 5-part light client sync protocol. +- **Block Commitment Checks**: Functionality to reject blocks with excessive commitments added. + +##### State Management: + +- **Alloc More Items**: Modified beacon-node/state to allocate an additional item during appends. +- **GetParentBlockHash Helper**: Refactoring of `getLocalPayloadAndBlobs` with a new helper function for fetching parent + block hashes. +- **RW Lock for Duties**: Read-Write lock mechanism introduced for managing validator duties. + +##### Build and CI/CD Improvements: + +- **Manual Build Tag**: A "manual" build tag introduced to expedite CI build times. +- **Multiarch Docker Containers**: Support for multiple architectures in Docker containers added. + +##### Testing: + +- **Init-Sync DA Tests**: Tests for initial sync Data Availability (DA) included. +- **Fuzz List Timeout**: Github workflow for fuzz testing now includes a timeout setting. +- **Go Fuzzing Workflow**: New Github workflow for Go fuzzing on a cron schedule. + +##### Logging and Monitoring: + +- **FFG-LMD Consistency Logging**: Enhanced logging for Finality Gadget LMD (FFG-LMD) consistency. +- **Validator Count Endpoint**: New endpoint to count the number of validators. + +##### User Interface and Web: + +- **Web UI Release**: Prysm Web UI v2.0.4 released with unspecified updates and improvements. + +##### Testnet support: + +- **Holesky Support**: Support for Holesky decompositions integrated into the codebase. + +##### Error Handling and Responses: + +- **Validation Error in ForkchoiceUpdatedResponse**: Included validation errors in fork choice update responses. +- **Wrapped Invalid Block Error**: Improved error handling for cases where an invalid block error is wrapped.. + +### Changed + +#### General: + +- **Skip MEV-Boost Flag**: Updated `GetBlock` RPC to utilize `skip mev-boost` flag. +- **Portable Version of BLST**: Transitioned to portable BLST version as default. +- **Teku Mainnet Bootnodes**: Refreshed Teku mainnet bootnodes ENRs. +- **Geth Version Updates**: Elevated geth to version v1.13.1 for additional stability and features. +- **Parallel Block Building**: Deprecated sequential block building path + +#### Deneb-Specific Changes: + +- **Deneb Spectests Release**: Upgraded to Deneb spectests v1.4.0-beta.2-hotfix. +- **Deneb API and Builder Cleanup**: Conducted clean-up activities for Deneb-specific API and builder. +- **Deneb Block Versioning**: Introduced changes related to Deneb produce block version 3. +- **Deneb Database Methods**: Adapted database methods to accommodate Deneb. +- **Unused Code Removal**: Eliminated an unused function and pending blobs queue. +- **Blob Sidecar Syncing**: Altered behavior when value is 0. + +#### Code Cleanup and Refactor: + +- **API Types Cleanup**: Reorganized API types for improved readability. +- **Geth Client Headers**: Simplified code for setting geth client headers. +- **Bug Report Template**: Revised requirements for more clarity. + +#### Flags and Configuration: + +- **Safe Slots to Import Flag**: Deprecated this flag for standard alignment. +- **Holesky Config**: Revised the Holesky configuration for new genesis. + +#### Logging: + +- **Genesis State Warning**: Will log a warning if the genesis state size is under 1KB. +- **Debug Log Removal**: Excised debug logs for cleaner output. + +#### Miscellaneous: + +- **First Aggregation Timing**: Default setting for first aggregation is 7 seconds post-genesis. +- **Pointer Usage**: Modified execution chain to use pointers, reducing copy operations. + +#### Dependency Updates: + +- **Go Version Update**: Updated to Go version 1.20.7. +- **Go Version Update**: Updated to Go version 1.20.9 for better security. +- **Various Dependencies**: Updated multiple dependencies including Geth, Bazel, rules_go, Gazelle, BLST, and go-libp2p. + +### Removed + +- **Remote Slashing Protection**: Eliminated the remote slashing protection feature. +- **Go-Playground/Validator**: Removed the go-playground/validator dependency from the Beacon API. +- **Revert Cache Proposer ID**: Reverted the caching of proposer ID on GetProposerDuties. +- **Go-Playground/Validator**: Removed go-playground/validator from Beacon API. +- **Reverted Cache Proposer ID**: Reversed the change that cached proposer ID on GetProposerDuties. +- **Cache Proposer ID**: Reversed the functionality that cached proposer ID on GetProposerDuties. +- **Quadratic Loops in Exiting**: Eliminated quadratic loops that occurred during voluntary exits, improving + performance. +- **Deprecated Go Embed Rules**: Removed deprecated `go_embed` rules from rules_go, to stay up-to-date with best + practices. +- **Alpine Images**: Removed Alpine images from the Prysm project. + +### Fixed + +#### Deneb-Specific Bug Fixes: + +- **Deneb Builder Bid HTR**: Fixed an issue related to HashTreeRoot (HTR) in Deneb builder bid. +- **PBV2 Condition**: Corrected conditions related to PBV2. +- **Route Handler and Cleanup**: Updated the route handler and performed minor cleanups. +- **Devnet6 Interop Issues**: Resolved interoperability issues specific to Devnet6. +- **Sepolia Version**: Updated the version information for the Sepolia testnet. +- **No Blob Bundle Handling**: Rectified the handling when no blob bundle exists. +- **Blob Sidecar Prefix**: Corrected the database prefix used for blob sidecars. +- **Blob Retrieval Error**: Added specific error handling for blob retrieval from the database. +- **Blob Sidecar Count**: Adjusted metrics for accurate blob sidecar count. +- **Sync/RPC Blob Usage**: Rectified blob usage when requesting a block by root in Sync/RPC. + +#### Cache Fixes: + +- **Don't Prune Proposer ID Cache**: Fixed a loop erroneously pruning the proposer ID cache. +- **LastRoot Adjustment**: Altered `LastRoot` to return the head root. +- **Last Canonical Root**: Modified forkchoice to return the last canonical root of the epoch. + +#### Block Processing fixes: + +- **Block Validation**: Fixed an issue where blocks were incorrectly marked as bad during validation. +- **Churn Limit Helpers**: Improved churn limit calculations through refactoring. +- **Churn with 0 Exits**: Rectified a bug that calculated churn even when there were 0 exits. +- **Proposer Duties Sorting**: Resolved sorting issues in proposer duties. +- **Duplicate Block Processing**: Eliminated redundant block processing. + +#### Error Handling and Logging: + +- **RpcError from Core Service**: Ensured that `RpcError` is returned from core services. +- **Unhandled Error**: Enhanced error management by handling previously unhandled errors. +- **Error Handling**: Wrapped `ctx.Err` for improved error handling. +- **Attestation Error**: Optimized error management in attestation processing. + +#### Test and Build Fixes: + +- **Racy Tests in Blockchain**: Resolved race conditions in blockchain tests. +- **TestService_ReceiveBlock**: Modified `TestService_ReceiveBlock` to work as expected. +- **Build Issue with @com_github_ethereum_c_kzg_4844**: Resolved build issues related to this specific library. +- **Fuzz Testing**: Addressed fuzz testing issues in the `origin/deneb-integration` +- **Long-Running E2E Tests**: Fixed issues that were causing the end-to-end tests to run for an extended period. + +#### Additional Fixes: + +- **Public Key Copies During Aggregation**: Optimized to avoid unnecessary public key copies during aggregation. +- **Epoch Participations**: Fixed the setting of current and previous epoch participations. +- **Verify Attestations**: Resolved an attestation verification issue in proposer logic. +- **Empty JSON/YAML Files**: Fixed an issue where `prysmctl` was writing empty configuration files. +- **Generic Fixes**: Addressed various unspecified issues. +- **Phase0 Block Parsing**: Resolved parsing issues in phase0 blocks on submit. +- **Hex Handling**: Upgraded the hex handling in various modules. +- **Initial Sync PreProcessing**: Resolved an issue affecting the initial sync preprocessing. + +### Security + +No security updates in this release. + +## [v4.0.8](https://github.com/prysmaticlabs/prysm/compare/v4.0.7...v4.0.8) - 2023-08-22 + +Welcome to Prysm Release v4.0.8! This release is recommended. Highlights: + +- Parallel hashing of validator entries in the beacon state. This results in a faster hash tree root. ~3x reduction +- Parallel validations of consensus and execution checks. This results in a faster block verification +- Aggregate parallel is now the default. This results in faster attestation aggregation time if a node is subscribed to + multiple beacon attestation subnets. ~3x reduction +- Better process block epoch boundary cache usages and bug fixes +- Beacon-API endpoints optimizations and bug fixes + +### Added + +- Optimization: parallelize hashing for validator entries in beacon state +- Optimization: parallelize consensus & execution validation when processing beacon block +- Optimization: integrate LRU cache (above) for validator public keys +- Cache: threadsafe LRU with non-blocking reads for concurrent readers +- PCLI: add deserialization time in benchmark +- PCLI: add allocation data To benchmark +- Beacon-API: GetSyncCommitteeRewards endpoint +- Beacon-API: SSZ responses for the Publishblockv2 +- Beacon-API client: use GetValidatorPerformance +- Spec tests: mainnet withdrawals and bls spec tests +- Spec tests: random and fork transition spec tests +- Spec tests execution payload operation tests +- Metric: block gossip arrival time +- Metric: state regen duration +- Metric: validator is in the next sync committee +- New data structure: multi-value slice + +### Changed + +- Build: update Go version to 1.20.6 +- Build: update hermetic_cc_toolchain +- Optimization: aggregate parallel is now default +- Optimization: do not perform full copies for metrics reporting +- Optimization: use GetPayloadBodies in Execution Engine Client +- Optimization: better nil check for reading validator +- Optimization: better cache update at epoch boundary +- Optimization: improve InnerShuffleList for shuffling +- Optimization: remove span for converting to indexed attestation` +- Beacon-API: optimize GetValidatorPerformance as POST +- Beacon-API: optimize /eth/v1/validator/aggregate_attestation +- Beacon-API: optimize /eth/v1/validator/contribution_and_proofs +- Beacon-API: optimize /eth/v1/validator/aggregate_and_proofs +- Beacon-API: use struct in beacon-chain/rpc/core to store dependencies +- Beacon-API: set CoreService in beaconv1alpha1.Server +- Beacon-API: use BlockProcessed event in certain endpoints +- Syncing: exit sync early with 0 peers to sync +- Cache: only call epoch boundary processing on canonical blocks +- Build: update server-side events dependency +- Refactor: slot tickers with intervals +- Logging: shift Error Logs To Debug +- Logging: clean up attestation routine logs + +### Fixed + +- Cache: update shuffling caches at epoch boundary +- Cache: committee cache correctly for epoch + 1 +- Cache: use the correct context for UpdateCommitteeCache +- Cache: proposer-settings edge case for activating validators +- Cache: prevent the public key cache from overwhelming runtime +- Sync: correctly set optimistic status in the head when syncing +- Sync: use last optimistic status on batch +- Flag: adds local boost flag to main/usage +- Beacon-API: correct header for get block and get blinded block calls +- Beacon-API: GetValidatorPerformance endpoint +- Beacon-API: return correct historical roots in Capella state +- Beacon-API: use the correct root in consensus validation +- Prysm API: size of SyncCommitteeBits +- Mev-boost: builder gas limit fix default to 0 in some cases +- PCLI: benchmark deserialize without clone and init trie +- PCLI: state trie for HTR duration +- Metric: adding fix pending validators balance +- Metric: effective balance for unknown/pending validators +- Comment: comments when receiving block +- Comment: cleanups to blockchain pkg + +### Security + +No security updates in this release. + +## [v4.0.7](https://github.com/prysmaticlabs/prysm/compare/v4.0.6...v4.0.7) - 2023-07-13 + +Welcome to the v4.0.7 release of Prysm! This recommended release contains many essential optimizations since v4.0.6. + +Highlights: + +- The validator proposal time for slot 0 has been reduced by 800ms. Writeup and PR +- The attestation aggregation time has been reduced by 400ms—roughly 75% with all subnets subscribed. Flag + --aggregate-parallel. PR. This is only useful if running more than a dozen validator keys. The more subnets your node + subscribe to, the more useful. +- The usage of fork choice lock has been reduced and optimized, significantly reducing block processing time. This + results in a higher proposal and attest rate. PR +- The block proposal path has been optimized with more efficient copies and a better pruning algorithm for pending + deposits. PR and PR +- Validator Registration cache is enabled by default, this affects users who have used webui along with mevboost. Please + review PR for details. + +Note: We remind our users that there are two versions of the cryptographic library BLST, one is "portable" and less +performant, and another is "non-portable" or "modern" and more performant. Most users would want to use the second one. +You can set the environment variable USE_PRYSM_MODERN=true when using prysm.sh. The released docker images are using the +non-portable version by default. + +### Added + +- Optimize multiple validator status query +- Track optimistic status on head +- Get attestation rewards API end point +- Expected withdrawals API +- Validator voluntary exit endpoint +- Aggregate atts using fixed pool of go routines +- Use the incoming payload status instead of calling forkchoice +- Add hermetic_cc_toolchain for a hermetic cc toolchain +- Cache next epoch proposers at epoch boundary +- Optimize Validator Roots Computation +- Log Finalized Deposit Insertion +- Move consensus and execution validation outside of onBlock +- Add metric for ReceiveBlock +- Prune Pending Deposits on Finalization +- GetValidatorPerformance http endpoint +- Block proposal copy Bytes Alternatively +- Append Dynamic Adding Trusted Peer Apis + +### Changed + +- Do not validate merge transition block after Capella +- Metric for balance displayed for public keys without validator indexes +- Set blst_modern=true to be the bazel default build +- Rename payloadHash to lastValidHash in setOptimisticToInvalid +- Clarify sync committee message validation +- Checkpoint sync ux +- Registration Cache by default + +### Removed + +- Disable nil payloadid log on relayers flags +- Remove unneeded helper +- Remove forkchoice call from notify new payload + +### Fixed + +- Late block task wait for initial sync +- Log the right block number +- Fix for keystore field name to align with EIP2335 +- Fix epoch participation parsing for API +- Spec checker, ensure file does not exit or error +- Uint256 parsing for builder API +- Fuzz target for execution payload +- Contribution doc typo +- Unit test TestFieldTrie_NativeState_fieldConvertersNative +- Typo on beacon-chain/node/node.go +- Remove single bit aggregation for aggregator +- Deflake cloners_test.go +- Use diff context to update proposer cache background +- Update protobuf and protobuf deps +- Run ineffassign for all code +- Increase validator client startup proposer settings deadline +- Correct log level for 'Could not send a chunked response' +- Rrune invalid blocks during initial sync +- Handle Epoch Boundary Misses +- Bump google.golang.org/grpc from 1.40.0 to 1.53.0 +- Fix bls signature batch unit test +- Fix Context Cancellation for insertFinalizedDeposits +- Lock before saving the poststate to db + +### Security + +No security updates in this release. + +## [v4.0.6](https://github.com/prysmaticlabs/prysm/compare/v4.0.5...v4.0.6) - 2023-07-15 + +Welcome to v4.0.6 release of Prysm! This recommended release contains many essential optimizations since v4.0.5. Notable +highlights: + +Better handling of state field trie under late block scenario. This improves the next slot proposer's proposed time +Better utilization of next slot cache under various conditions + +**Important read:** + +1.) We use this opportunity to remind you that two different implementations of the underlying cryptographic library +BLST exist. + +- portable: supports every CPU made in the modern era +- non-portable: more performant but requires your CPU to support special instructions + +Most users will want to use the "non-portable" version since most CPUs support these instructions. Our docker builds are +now non-portable by default. Most users will benefit from the performance improvements. You can run with the "portable" +versions if your CPU is old or unsupported. For binary distributions and to maintain backward compatibility with older +versions of prysm.sh or prysm.bat, users that want to benefit from the non-portable performance improvements need to add +an environment variable, like so: USE_PRYSM_MODERN=true prysm.sh beacon-chain prefix, or download the "non-portable" +version of the binaries from the github repo. + +2.) A peering bug that led to nodes losing peers gradually and eventually needing a restart has been patched. Nodes +previously affected by it can remove the --disable-resource-manager flag from v4.0.6 onwards. + +### Added + +- Copy state field tries for late block +- Utilize next slot cache correctly under late block scenario +- Epoch boundary uses next slot cache +- Beacon API broadcast_validation to block publishing +- Appropriate Size for the P2P Attestation Queue +- Flag --disable-resource-manager to disable resource manager for libp2p +- Beacon RPC start and end block building time logs +- Prysmctl: output proposer settings +- Libp2p patch +- Handle trusted peers for libp2p +- Spec test v1.4.0-alpha.1 + +### Changed + +- Use fork-choice store to validate sync message faster +- Proposer RPc unblind block workflow +- Restore flag disable-peer-scorer +- Validator import logs improvement +- Optimize zero hash comparisons in forkchoice +- Check peer threshold is met before giving up on context deadline +- Cleanup of proposer payload ID cache +- Clean up set execution data for proposer RPC +- Update Libp2p to v0.27.5 +- Always Favour Yamux for Multiplexing +- Ignore Phase0 Blocks For Monitor +- Move hash tree root to after block broadcast +- Use next slot cache for sync committee +- Log validation time for blocks +- Change update duties to handle all validators exited check +- Ignore late message log + +### Removed + +- SubmitblindBlock context timeout +- Defer state feed In propose block + +### Fixed + +- Sandwich attack on honest reorgs +- Missing config yamls for specific domains +- Release lock before panic for feed +- Return 500 in `/eth/v1/node/peers` interface +- Checkpoint sync uses correct slot + +### Security + +No security updates in this release. + +## [v4.0.5](https://github.com/prysmaticlabs/prysm/compare/v4.0.4...v4.0.5) - 2023-05-22 + +Welcome to v4.0.5 release of Prysm! This release contains many important improvements and bug fixes since v4.0.4, +including significant improvements to attestation aggregation. See @potuz's +notes [here](https://hackmd.io/TtyFurRJRKuklG3n8lMO9Q). This release is **strongly** recommended for all users. + +Note: The released docker images are using the portable version of the blst cryptography library. The Prysm team will +release docker images with the non-portable blst library as the default image. In the meantime, you can compile docker +images with blst non-portable locally with the `--define=blst_modern=true` bazel flag, use the "-modern-" assets +attached to releases, or set environment variable USE_PRYSM_MODERN=true when using prysm.sh. + +### Added + +- Added epoch and root to "not a checkpt in forkchoice" log message +- Added cappella support for eth1voting tool +- Persist validator proposer settings in the validator db. +- Add flag to disable p2p resource management. This flag is for debugging purposes and should not be used in production + for extended periods of time. Use this flag if you are experiencing significant peering issues. + --disable-resource-manager + +### Changed + +- Improved slot ticker for attestation aggregation +- Parallel block production enabled by default. Opt out with --disable-build-block-parallel if issues are suspected with + this feature. +- Improve attestation aggregation by not using max cover on unaggregated attestations and not checking subgroup of + previously validated signatures. +- Improve sync message processing by using forkchoice + +### Fixed + +- Fixed --slasher flag. +- Fixed state migration for capella / bellatrix +- Fix deadlock when using --monitor-indices + +### Security + +No security updates in this release. + +## [v4.0.4](https://github.com/prysmaticlabs/prysm/compare/v4.0.3...v4.0.4) - 2023-05-15 + +Welcome to v4.0.4 release of Prysm! This is the first full release following the recent mainnet issues and it is very +important that all stakers update to this release as soon as possible. + +Aside from the critical fixes for mainnet, this release contains a number of new features and other fixes since v4.0.3. + +### Added + +- Feature to build consensus and execution blocks in parallel. This feature has shown a noticeable reduction (~200ms) in + block proposal times. Enable with --build-block-parallel +- An in memory cache for validator registration can be enabled with --enable-registration-cache. See PR description + before enabling. +- Added new linters +- Improved tracing data for builder pipeline +- Improved withdrawal phrasing in validator withdrawal tooling +- Improved blinded block error message +- Added test for future slot tolerance +- Pre-populate bls pubkey cache +- Builder API support in E2E tests + +### Changed + +- Updated spectests to v1.3 +- Cleanup duplicated code +- Updated method signature for UnrealizedJustifiedPayloadBlockHash() +- Updated k8s.io/client-go to 0.20.0 +- Removed unused method argument +- Refactored / moved some errors to different package +- Update next slot cache at an earlier point in block processing +- Use next slot cache for payload attribute +- Cleanup keymanager mock +- Update to go 1.20 +- Modify InsertFinalizedDeposits signature to return an error +- Improved statefeed initialization +- Use v1alpha1 server in block production +- Updated go generated files +- Typo corrections + +### Fixed + +- Fixed e2e tx fuzzer nilerr lint issue +- Fixed status for pending validators with multiple deposits +- Use gwei in builder value evaluation +- Return correct error when failing to unmarshal genesis state +- Avoid double state copy in latestAncestor call +- Fix mock v1alpha1 server +- Fix committee race test +- Fix flaky validator tests +- Log correctly when the forkchoice head changed +- Filter inactive keys from mev-boost / builder API validator registration +- Save attestation to cache when calling SubmitAttestation in beacon API +- Avoid panic on nil broadcast object +- Fix initialization race +- Properly close subnet iterator +- ⚠️ Ignore untimely attestations +- Fix inverted metric +- ⚠️ Save to checkpoint cache if next state cache hits + +### Security + +This release contains some important fixes that improve the resiliency of Ethereum Consensus Layer. +See https://github.com/prysmaticlabs/prysm/pull/12387 and https://github.com/prysmaticlabs/prysm/pull/12398. + +## [v4.0.3](https://github.com/prysmaticlabs/prysm/compare/v4.0.2...v4.0.3) - 2023-04-20 + +### Added + +- Add REST API endpoint for beacon chain client's GetChainHead +- Add prepare-all-payloads flag +- support modifying genesis.json for capella +- Add support for engine_exchangeCapabilities +- prysmctl: Add support for writing signed validator exits to disk + +### Changed + +- Enable misspell linter & fix findings + +### Fixed + +- Fix Panic In Builder Service +- prysmctl using the same genesis func as e2e +- Check that Builder Is Configured +- Correctly use Gwei to compare builder bid value +- Fix Broken Dependency +- Deflake TestWaitForActivation_AccountsChanged +- Fix Attester Slashing Validation In Gossip +- Keymanager fixes for bad file writes +- windows: Fix build after PR 12293 + +### Security + +No security updates in this release. + +## [v4.0.2](https://github.com/prysmaticlabs/prysm/compare/v4.0.1...v4.0.2) - 2023-04-12 + +This release fixes a critical bug on Prysm interacting with mev-boost / relayer. You MUST upgrade to this release if you +run Prysm with mev boost and relayer, or you will be missing block proposals during the first days after the Shapella +fork while the block has bls-to-exec changes. +Post-mortem that describes this incident will be provided by the end of the week. + +One of this release's main optimizations is revamping the next slot cache. It has been upgraded to be more performant +across edge case re-org scenarios. This can help with the bad head attestation vote. + +Minor fixes in this release address a bug that affected certain large operators querying RPC endpoints. This bug caused +unexpected behavior and may have impacted the performance of affected operators. To resolve this issue, we have included +a patch that ensures proper functionality when querying RPC endpoints. + +### Added + +- CLI: New beacon node flag local-block-value-boost that allows the local block value to be multiplied by the boost + value +- Smart caching for square root computation +- Beacon-API: Implemented Block rewards endpoint +- Beacon-API client: Implemented GetSyncStatus endpoint +- Beacon-API client: Implemented GetGenesis endpoint +- Beacon-API client: Implemented ListValidators endpoint + +### Changed + +- Block processing: Optimize next slot cache +- Execution-API: Used unrealized justified block hash for FCU call +- CLI: Improved voluntary exit confirmation prompt +- Unit test: Unskip API tests +- End to end test: Misc improvements +- Build: Build tag to exclude mainnet genesis from prysmctl +- Dependency: Update go-ethereum to v1.11.3 +- Dependency: Update lighthouse to v4.0.1 + +### Fixed + +- Builder: Unblind beacon block correctly with bls-to-exec changes +- Block construction: Default to local payload on error correctly +- Block construction: Default to local payload on nil value correctly +- Block processing: Fallback in update head on error +- Block processing: Add orphaned operations to the appropriate pool +- Prysm-API: Fix Deadlock in StreamChainHead +- Beacon-API: Get header error, nil summary returned from the DB +- Beacon-API: Broadcast correct slashing object + +### Security + +No security updates in this release. + +## [v4.0.1](https://github.com/prysmaticlabs/prysm/compare/v4.0.0...v4.0.1) + +This is a reissue of v4.0.0. See https://github.com/prysmaticlabs/prysm/issues/12201 for more information. + +## [v4.0.0](https://github.com/prysmaticlabs/prysm/compare/v3.2.2...v4.0.0) + +### Added + +- Config: set mainnet capella epoch +- Validator: enable proposer to reorg late block +- Metric: bls-to-exec count in the operation pool +- Metric: pubsub metrics racer +- Metric: add late block metric +- Engine-API: Implement GetPayloadBodies +- Beacon-API: Implement GetPayloadAttribute SSE +- Prysm CLI: add experimental flags to dev mode +- Prysmctl utility: add eth1data to genesis state +- Spec test: EIP4881 spec compliance tests +- Spec test: forkchoice lock to fix flaskyness + +### Changed + +- Prysm: upgrade v3 to v4 +- Prysm: apply goimports to generated files +- Validator: lower builder circuit breaker thresholds to 5 missed slots per epoch and updates off by 1 +- Validator: reorg late block by default +- Forkchoice: cleanups +- Forkchoice: remove bouncing attack fix and strength equivocation discarding +- Forkchoice: call FCU at 4s mark if there's no new head +- Forkchoice: better locking on calls to retrieving ancestor root +- Forkchoice: stricker visibility for blockchain package access +- Block processing: optimizing validator balance retrieval by using epoch boundary cache +- Block processing: reduce FCU calls +- Block processing: increase attempted reorgs at the correct spot +- Block processing: remove duplicated bls to exec message pruning +- Block processing: skip hash tree root state when checking optimistic mode +- Prysm-API: mark GetChainHead deprecated +- Logging: add late block logs +- Logging: enhancements and clean ups +- Build: fix bazel remote cache upload +- Build: update cross compile toolchains +- Build: only build non-test targets in hack/update-go-pbs.sh +- Build: update rules_go to v0.38.1 and go_version to 1.19.7 +- Build: replace bazel pkg_tar rule with canonical @rules_pkg pkg_tar +- Build: update bazel to 6.1.0 +- Libp2p: updated to latest version +- Libp2p: make peer scorer permanent default +- Test: disable e2e slasher test +- CLI: derecate the following flags + +### Deprecated + +The following flags have been deprecated. + +- disable-peer-scorer +- disable-vectorized-htr +- disable-gossip-batch-aggregation + +### Removed + +- Prsym remote signer +- CLI: Prater feature flag +- CLI: Deprecated flags +- Unit test: unused beacon chain altair mocks +- Validator REST API: unused endpoints + +The following flags have been removed. + +- http-web3provider +- enable-db-backup-webhook +- bolt-mmap-initial-size +- disable-discv5 +- enable-reorg-late-blocks +- disable-attesting-history-db-cache +- enable-vectorized-htr +- enable-peer-scorer +- enable-forkchoice-doubly-linked-tree +- enable-back-pull +- enable-duty-count-down +- head-sync +- enable-gossip-batch-aggregation +- enable-larger-gossip-history +- fallback-web3provider +- disable-native-state +- enable-only-blinded-beacon-blocks +- ropsten +- interop-genesis-state +- experimental-enable-boundary-checks +- disable-back-pull +- disable-forkchoice-doubly-linked-tree + +### Fixed + +- Validator: startup deadline +- Prysmctl: withdrawals fork checking logic +- End-to-end test: fix flakes +- End-to-end test: fix altair transition +- Unit test: fix error message in + +### Security + +This release is required to participate in the Capella upgrade. + +## [v3.2.2](https://github.com/prysmaticlabs/prysm/compare/v3.2.2...v3.2.1) - 2023-05-10 + +Gm! ☀️ We are excited to announce our release for upgrading Goerli testnet to Shanghai / Capella! 🚀 + +This release is MANDATORY for Goerli testnet. You must upgrade your Prysm beacon node and validator client to this +release before Shapella hard fork time epoch=162304 or UTC=14/03/2023, 10:25:36 pm. + +This release is a low-priority for the mainnet. +This release is the same commit as v3.2.2-rc.3. If you are already running v3.2.2-rc.3, then you do not need to update +your client. + +### Added + +- Capella fork epoch +- Validator client REST implementation GetFeeRecipientByPubKey +- New end-to-end test for post-attester duties + +### Changed + +- Storing blind beacon block by default for new Prysm Database +- Raise the max grpc message size to a very large value by default +- Update rules docker to v0.25.0 +- Update distroless base images +- Update protoc-gen-go-cast to suppress tool output +- Update deps for Capella +- Remove gRPC fallback client from validator REST API +- Prysmctl now verifies capella fork for bls to exec message change +- Core block processing cleanup +- Better locking design around forkchoice store +- Core process sync aggregate function returns reward amount +- Use Epoch boundary cache to retrieve balances +- Misc end-to-end test improvements and fixes +- Add slot number to proposal error log + +### Deprecated + +- Deprecate flag --interop-genesis-state + +### Removed + +- Remove Ropsten testnet config and feature flag + +### Security + +This release is required for Goerli to upgrade to Capella. + +## [v3.2.1](https://github.com/prysmaticlabs/prysm/compare/v3.2.0...v3.2.1) - 2023-02-13 + +We are excited to announce the release of Prysm v3.2.1 🎉 + +This is the first release to support Capella / Shanghai. The Sepolia testnet Capella upgrade time is currently set to +2/28/2023, 4:04:48 AM UTC. The Goerli testnet and Mainnet upgrade times are still yet to be determined. In Summary: + +- This is a mandatory upgrade for Sepolia nodes and validators +- This is a recommended upgrade for Goerli and Mainnet nodes and validators + +There are some known issues with this release. + +- mev-boost, relayer, and builder support for Capella upgrade are built in but still need to be tested. Given the lack + of testing infrastructure, none of the clients could test this for withdrawals testnet. There may be hiccups when + using mev-boost on the Capella upgraded testnets. + +### Added + +- Capella Withdrawal support +- Add Capella fork epoch for Sepolia +- Various Validator client REST implementations (Part of EPF) +- Various Beacon API additions +- Cache Fork Digest Computation to save compute +- Beacon node can bootstrap from non-genesis state (i.e bellatrix state) +- Refactor bytesutil, add support for go1.20 slice to array conversions +- Add Span information for attestation record save request +- Metric addition +- Identify invalid signature within batch verification +- Support for getting consensus values from beacon config +- EIP-4881: Spec implementation +- Test helper to generate valid bls-to-exec message +- Spec tests v1.3.0 rc.2 + +### Changed + +- Prysm CLI utility support for exit +- Beacon API improvement +- Prysm API get block RPC +- Prysm API cleanups +- Block processing cleanup, +- Forkchoice logging improvements +- Syncing logging improvement +- Validator client set event improvement for readability and error handling +- Engine API implementation cleanups +- End to end test improvements +- Prysm CLI withdrawal ux improvement +- Better log for the block that never became head + +### Removed + +- Remove cache lookup and lock request for database boltdb transaction + +### Fixed + +- Beacon API +- Use the correct attribute if there's a payload ID cache miss +- Call FCU with an attribute on non-head block +- Sparse merkle trie bug fix +- Waiting For Bandwidth Issue While Syncing +- State Fetcher to retrieve correct epoch +- Exit properly with terminal block hash +- PrepareBeaconProposer API duplicating validator indexes when not persisted in DB +- Multiclient end-to-end +- Deep source warnings + +### Security + +There are no security updates in this release. + +## [v3.2.0](https://github.com/prysmaticlabs/prysm/compare/v3.1.2...v3.2.0) - 2022-12-16 + +This release contains a number of great features and improvements as well as progress towards the upcoming Capella +upgrade. This release also includes some API changes which are reflected in the minor version bump. If you are using +mev-boost, you will need to update your prysm client to v3.2.0 before updating your mev-boost instance in the future. +See [flashbots/mev-boost#404](https://github.com/flashbots/mev-boost/issues/404) for more details. + +### Added + +- Support for non-english mnemonic phrases in wallet creation. +- Exit validator without confirmation prompt using --force-exit flag +- Progress on Capella and eip-4844 upgrades +- Added randao json endpoint. /eth/v1/beacon/states/{state_id}/randao +- Added liveness endpoint /eth/v1/validator/liveness/{epoch} +- Progress on adding json-api support for prysm validator +- Prysmctl can now generate genesis.ssz for forks after phase0. + +### Changed + +- --chain-config-file now throws an error if used concurrently with --network flag. +- Added more histogram metrics for block arrival latency times block_arrival_latency_milliseconds +- Priority queue RetrieveByKey now uses read lock instead of write lock +- Use custom types for certain ethclient requests. Fixes an issue when using prysm on gnosis chain. +- Updated forkchoice endpoint /eth/v1/debug/forkchoice (was /eth/v1/debug/beacon/forkchoice) +- Include empty fields in builder json client. +- Computing committee assignments for slots older than the oldest historical root in the beacon state is now forbidden + +### Removed + +- Deprecated protoarray tests have been removed + +### Fixed + +- Unlock pending block queue if there is any error on inserting a block +- Prysmctl generate-genesis yaml file now uses the correct format +- ENR serialization now correctly serializes some inputs that did not work previously +- Use finalized block hash if a payload ID cache miss occurs +- prysm.sh now works correctly with Mac M1 chips (it downloads darwin-arm64 binaries) +- Use the correct block root for block events api +- Users running a VPN should be able to make p2p dials. +- Several minor typos and code cleanups + +### Security + +- Go is updated to 1.19.4. + +## [v3.1.2](https://github.com/prysmaticlabs/prysm/compare/v3.1.1...v3.1.2) - 2022-10-27 + +### Added + +- Timestamp field to forkchoice node json responses +- Further tests to non-trivial functions of the builder service +- Support for VotedFraction in forkchoice +- Metrics for reorg distance and depths +- Support for optimistic sync spectests +- CLI flag for customizing engine endpoint timeout --engine-endpoint-timeout-seconds +- Support for lodestar identification in p2p monitoring +- --enable-full-ssz-data-logging to display debug ssz data on gossip messages that fail validation +- Progress on capella and withdrawals support +- Validator exit can be performed from prysmctl +- Blinded block support through the json API + +### Changed + +- Refactoring / cleanup of keymanager +- Refactoring / improvements in initial sync +- Forkchoice hardening +- Improved log warnings when fee recipient is not set +- Changed ready for merge log frequency to 1 minute +- Move log Unable to cache headers for execution client votes to debug +- Rename field in invalid pruned blocks log +- Validate checkpoint slot +- Return an error if marshaling invalid Uint256 +- Fallback to uncached getPayload if timeout +- Update bazel to 5.3.0 +- godocs cleanup and other cleanups +- Forkchoice track highest received root +- Metrics updated block arrival time histograms +- Log error and continue when proposer boost roots are missing +- Do not return on error during on_tick +- Do not return on error after update head +- Update default RPC HTTP timeout to 30s +- Improved fee recipient UX. +- Produce block skips mev-boost +- Builder getPayload timeout set to 3s +- Make stategen aware of forkchoice +- Increase verbosity of warning to error when new head cannot be determined when receiving an attestation +- Provide justified balances to forkchoice +- Update head continues without attestations +- Migrate historical states in another goroutine to avoid blocking block execution +- Made API middleware structs public +- Updated web UI to v2.0.2 +- Default value for --block-batch-limit-burst-factor changed from 10 to 2. +- Vendored leaky bucket implementation with minor modifications + +### Deprecated + +- --disable-native-state flag and associated feature + +### Removed + +- Unused WithTimeout for builder client +- Optimistic sync candidate check +- Cleans up proto states +- Protoarray implementation of forkchoice + +### Fixed + +- Block fields to return a fixed sized array rather than slice +- Lost cancel in validator runner +- Release held lock on error +- Properly submit blinded blocks +- Unwanted wrapper of gRPC status errors +- Sync tests fixed and updated spectests to 1.2.0 +- Prevent timeTillDuty from reporting a negative value +- Don't mark /healthz as unhealthy when mev-boost relayer is down +- Proposer index cache and slot is used for GetProposerDuties +- Properly retrieve values for validator monitoring flag from cli +- Fee recipient fixes and persistence +- Handle panic when rpc client is not yet initialized +- Improved comments and error messages +- SSL support for multiple gRPC endpoints +- Addressed some tool feedback and code complaints +- Handle unaggregated attestations in the event feed +- Prune / expire payload ID cache entries when using beacon json API +- Payload ID cache may have missed on skip slots due to incorrect key computation + +### Security + +- Libp2p updated to v0.22.0 + +## [v3.1.1](https://github.com/prysmaticlabs/prysm/compare/v3.1.0...v3.1.1) - 2022-09-09 + +This is another highly recommended release. It contains a forkchoice pruning fix and a gossipsub optimization. It is +recommended to upgrade to this release before the Merge next week, which is currently tracking for Wed Sept +14 (https://bordel.wtf/). Happy staking! See you on the other side! + +### Fixed + +- Fix memory leaks in fork choice store which leads to node becoming slower +- Improve connectivity and solves issues connecting with peers + +### Security + +No security updates in this release. + +## [v3.1.0](https://github.com/prysmaticlabs/prysm/compare/v3.1.0...v3.0.0) - 2022-09-05 + +Updating to this release is highly recommended as it contains several important fixes and features for the merge. You +must be using Prysm v3 or later before Bellatrix activates on September 6th. + +**Important docs links** + +- [How to prepare for the merge](https://docs.prylabs.network/docs/prepare-for-merge) +- [How to check merge readiness status](https://docs.prylabs.network/docs/monitoring/checking-status) + +### Added + +- Add time until next duty in epoch logs for validator +- Builder API: Added support for deleting gas limit endpoint +- Added debug endpoint GetForkChoice for doubly-linked-tree +- Added support for engine API headers. --execution-headers=key=value +- New merge specific metrics. See + +### Changed + +- Deposit cache now returns shallow copy of deposits +- Updated go-ethereum dependency to v1.10.23 +- Updated LLVM compiler version to 13.0.1 +- Builder API: filter 0 bid and empty tx root responses +- Allow attestations/blocks to be received by beacon node when the nodes only optimistically synced +- Add depth and distance to CommonAncestorRoot reorg object +- Allocate slice array to expected length in several methods +- Updated lighthouse to version v3 in E2E runner +- Improved handling of execution client errors +- Updated web3signer version in E2E runner +- Improved error messages for db unmarshalling failures in ancestor state lookup +- Only updated finalized checkpoints in database if its more recent than previous checkpoint + +### Removed + +- Dead / unused code delete + +### Fixed + +- Fixed improper wrapping of certain errors +- Only log fee recipient message if changed +- Simplify ListAttestations RPC method fixes +- Fix several RPC methods to be aware of the appropriate fork +- Fixed encoding issue with builder API register validator method. fixes +- Improved blinded block handling in API. fixes +- Fixed IPC path for windows users +- Fix proposal of blinded blocks +- Prysm no longer crashes on start up if builder endpoint is not available + +### Security + +There are no security updates in this release. + +## [v3.0.0](https://github.com/prysmaticlabs/prysm/compare/v3.0.0...v2.1.4) 2022-08-22 + +### Added + +- Passing spectests v1.2.0-rc.3 +- prysmctl: Generate genesis state via prysmctl testnet generate-genesis [command options] [arguments...] +- Keymanager: Add support for setting the gas limit via API. +- Merge: Mainnet merge epoch and TTD defined! +- Validator: Added expected wait time for pending validator activation in log message. +- Go: Prysm now uses proper versioning suffix v3 for this release. GoDocs and downstream users can now import prysm as + expected for go projects. +- Builder API: Register validator via HTTP REST Beacon API endpoint /eth/v1/validator/register_validator +- Cross compilation support for Mac ARM64 chips (Mac M1, M2) + +### Changed + +- **Require an execution client** `--execution-endpoint=...`. The default value has changed to `localhost:8551` and you + must use the jwt flag `--jwt-secret=...`. Review [the docs](https://docs.prylabs.network/docs/prepare-for-merge) for + more information +- `--http-web3provider` has been renamed to `--execution-endpoint`. Please update your configuration + as `--http-web3provider` will be removed in a future release. +- Insert attestations into forkchoice sooner +- Builder API: `gas_limit` changed from int to string to support JSON / YAML configs. `--suggested-gas-limit` changed + from int to string. +- Fork choice: Improved handling of double locks / deadlocks +- Lower libp2p log level +- Improved re-org logs with additional metadata +- Improved error messages found by semgrep +- Prysm Web UI updated to release v2.0.1 +- Protobuf message renaming (non-breaking changes) +- Enabled feature to use gohashtree by default. Disable with `--disable-vectorized-htr` +- Enabled fork choice doubly linked tree feature by default. Disable with `--disable-forkchoice-doubly-linked-tree` +- Remote signer: Renamed some field names to better represent block types (non-breaking changes for gRPC users, possibly + breaking change for JSON API users) +- Builder API: require header and payload root match. +- Improved responses for json-rpc requests batching when using blinded beacon blocks. +- Builder API: Improved error messages +- Builder API: Issue warning when validator expects builder ready beacon node, but beacon node is not configured with a + relay. +- Execution API: Improved payload ID to handle reorg scenarios + +### Deprecated + +- Several features have been promoted to stable or removed. The following flags are now deprecated and will be removed + in a future + release. `--enable-db-backup-webhook`, `--bolt-mmap-initial-size`, `--disable-discv5`, `--disable-attesting-history-db-cache`, `--enable-vectorized-htr`, `--enable-peer-scorer`, `--enable-forkchoice-doubly-linked-tree`, `--enable-duty-count-down`, `--head-sync`, `--enable-gossip-batch-aggregateion`, `--enable-larger-gossip-history`, `--fallback-web3provider`, `--use-check-point-cache`. +- Several beacon API endpoints marked as deprecated + +### Removed + +- Logging: Removed phase0 fields from validator performance log messages +- Deprecated slasher protos have been removed +- Deprecated beacon API endpoints + removed: `GetBeaconState`, `ProduceBlock`, `ListForkChoiceHeads`, `ListBlocks`, `SubmitValidatorRegistration`, `GetBlock`, `ProposeBlock` +- API: Forkchoice method `GetForkChoice` has been removed. +- All previously deprecated feature flags have been + removed. `--enable-active-balance-cache`, `--correctly-prune-canonical-atts`, `--correctly-insert-orphaned-atts`, `--enable-next-slot-state-cache`, `--enable-batch-gossip-verification`, `--enable-get-block-optimizations`, `--enable-balance-trie-computation`, `--disable-next-slot-state-cache`, `--attestation-aggregation-strategy`, `--attestation-aggregation-force-opt-maxcover`, `--pyrmont`, `--disable-get-block-optimizations`, `--disable-proposer-atts-selection-using-max-cover`, `--disable-optimized-balance-update`, `--disable-active-balance-cache`, `--disable-balance-trie-computation`, `--disable-batch-gossip-verification`, `--disable-correctly-prune-canonical-atts`, `--disable-correctly-insert-orphaned-atts`, `--enable-native-state`, `--enable-peer-scorer`, `--enable-gossip-batch-aggregation`, `--experimental-disable-boundary-checks` +- Validator Web API: Removed unused ImportAccounts and DeleteAccounts rpc options + +### Fixed + +- Keymanager API: Status enum values are now returned as lowercase strings. +- Misc builder API fixes +- API: Fix GetBlock to return canonical block +- Cache: Fix cache overwrite policy for bellatrix proposer payload ID cache. +- Fixed string slice flags with file based configuration + +### Security + +- Upgrade your Prysm beacon node and validator before the merge! + +## [v2.1.4](https://github.com/prysmaticlabs/prysm/compare/v2.1.4...v2.1.3) - 2022-08-10 + +As we prepare our `v3` mainnet release for [The Merge](https://ethereum.org/en/upgrades/merge/), `v2.1.4` marks the end +of the `v2` era. Node operators and validators are **highly encouraged** to upgrade to release `v2.1.4` - many bug fixes +and improvements have been included in preparation for The Merge. `v3` will contain breaking changes, and will be +released within the next few weeks. Using `v2.1.4` in the meantime will give you access to a more streamlined user +experience. See our [v2.1.4 doc](https://docs.prylabs.network/docs/vnext/214-rc) to learn how to use v2.1.4 to run a +Merge-ready configuration on the Goerli-Prater network pair. + +### Added + +- Sepolia testnet configs `--sepolia` +- Goerli as an alias to Prater and testnet configs `--prater` or `--goerli` +- Fee recipient API for key manager +- YML config flag support for web3 signer +- Validator registration API for web3 signer +- JSON tcontent type with optional metadata +- Flashbots MEV boost support +- Store blind block (i.e block with payload header) instead of full block (i.e. block with payload) for storage + efficiency (currently only available when the `enable-only-blinded-beacon-blocks` feature flag is enabled) +- Pcli utility support to print blinded block +- New Web v2.0 release into Prysm + +### Changed + +- Native state improvement is enabled by default +- Use native blocks instead of protobuf blocks +- Peer scorer is enabled by default +- Enable fastssz to use vectorized HTR hash algorithm improvement +- Forkchoice store refactor and cleanups +- Update libp2p library dependency +- RPC proposer duty is now allowed next epoch query +- Do not print traces with `log.withError(err)` +- Testnets are running with pre-defined feature flags + +### Removed + +- Deprecate Step Parameter from our Block By Range Requests + +### Fixed + +- Ignore nil forkchoice node when saving orphaned atts +- Sync: better handling of missing state summary in DB +- Validator: creates invalid terminal block using the same timestamp as payload +- P2P: uses incorrect goodbye codes +- P2p: defaults Incorrectly to using Mplex, which results in losing Teku peers +- Disable returning future state for API +- Eth1 connection API panic + +### Security + +There are no security updates in this release. + +## [v2.1.3](https://github.com/prysmaticlabs/prysm/compare/v2.1.2...v2.1.3) - 2022-07-06 + +### Added + +- Many fuzz test additions +- Support bellatrix blocks with web3signer +- Support for the Sepolia testnet with `--terminal-total-difficulty-override 17000000000000000`. The override flag is + required in this release. +- Support for the Ropsten testnet. No override flag required +- JSON API allows SSZ-serialized blocks in `publishBlock` +- JSON API allows SSZ-serialized blocks in `publishBlindedBlock` +- JSON API allows SSZ-serialized requests in `produceBlockV2` and `produceBlindedBlock` +- Progress towards Builder API and MEV boost support (not ready for testing in this release) +- Support for `DOMAIN_APPLICATION_MARK` configuration +- Ignore subset aggregates if a better aggregate has been seen already +- Reinsertion of reorg'd attestations +- Command `beacon-chain generate-auth-secret` to assist with generating a hex encoded secret for engine API +- Return optimistic status to `ChainHead` related grpc service +- TTD log and prometheus metric +- Panda ascii art banner for the merge! + +### Changed + +- Improvements to forkchoice +- Invalid checksummed (or no checksum) addresses used for fee recipient will log a warning. fixes, +- Use cache backed `getBlock` method in several places of blockchain package +- Reduced log frequency of "beacon node doesn't have a parent in db with root" error +- Improved nil checks for state management +- Enhanced debug logs for p2p block validation +- Many helpful refactoring and cosmetic changes +- Move WARN level message about weak subjectivity sync and improve message content +- Handle connection closing for web3/eth1 nil connection +- Testing improvements +- E2E test improvements +- Increase file descriptor limit up to the maximum by default +- Improved classification of "bad blocks" +- Updated engine API error code handling +- Improved "Synced new block" message to include minimal information based on the log verbosity. +- Add nil checks for nil finalized checkpoints +- Change weak subjectivity sync to use the most recent finalized state rather than the oldest state within the current + period. +- Ensure a finalized root can't be all zeros +- Improved db lookup of HighestSlotBlocksBelow to start from the end of the index rather than the beginning. +- Improved packing of state balances for hashtreeroot +- Improved field trie recomputation + +### Removed + +- Removed handling of `INVALID_TERMINAL_BLOCK` response from engine API + +### Fixed + +- `/eth/v1/beacon/blinded_blocks` JSON API endpoint +- SSZ handling of JSON API payloads +- Config registry fixes +- Withdrawal epoch overflows +- Race condition with blockchain service Head() +- Race condition with validator's highest valid slot accessor +- Do not update cache with the result of a cancelled request +- `validator_index` should be a string integer rather than a number integer per spec. +- Use timestamp heuristic to determine deposits to process rather than simple calculation of follow distance +- Return `IsOptimistic` in `ValidateSync` responses + +### Security + +There are no security updates in this release. + +## [v2.1.2](https://github.com/prysmaticlabs/prysm/compare/v2.1.1...v2.1.2) - 2022-05-16 + +### Added + +- Update forkchoice head before produce block +- Support for blst modern builds on linux amd64 +- [Beacon API support](ethereum/beacon-APIs#194) for blinded block +- Proposer index and graffiti fields in Received block debug log for verbosity +- Forkchoice removes equivocating votes for weight accounting + +### Changed + +- Updated to Go [1.18](https://github.com/golang/go/releases/tag/go1.18) +- Updated go-libp2p to [v0.18.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.18.0) +- Updated beacon API's Postman collection to 2.2.0 +- Moved eth2-types into Prysm for cleaner consolidation of consensus types + +### Removed + +- Prymont testnet support +- Flag `disable-proposer-atts-selection-using-max-cover` which disables defaulting max cover strategy for proposer + selecting attestations +- Flag `disable-get-block-optimizations` which disables optimization with beacon block construction +- Flag `disable-optimized-balance-update"` which disables optimized effective balance update +- Flag `disable-active-balance-cache` which disables active balance cache +- Flag `disable-balance-trie-computation` which disables balance trie optimization for hash tree root +- Flag `disable-batch-gossip-verification` which disables batch gossip verification +- Flag `disable-correctly-insert-orphaned-atts` which disables the fix for orphaned attestations insertion + +### Fixed + +- `end block roots don't match` bug which caused beacon node down time +- Doppelganger off by 1 bug which introduced some false-positive +- Fee recipient warning log is only disabled after Bellatrix fork epoch + +### Security + +There are no security updates in this release. + +## [v2.1.1](https://github.com/prysmaticlabs/prysm/compare/v2.1.0...v2.1.1) - 2022-05-03 + +This patch release includes 3 cherry picked fixes for regressions found in v2.1.0. + +View the full changelist from v2.1.0: https://github.com/prysmaticlabs/prysm/compare/v2.1.0...v2.1.1 + +If upgrading from v2.0.6, please review +the [full changelist](https://github.com/prysmaticlabs/prysm/compare/v2.0.6...v2.1.1) of both v2.1.0 and v2.1.1. + +This release is required for users on v2.1.0 and recommended for anyone on v2.0.6. + +The following known issues exist in v2.1.0 and also exist in this release. + +- Erroneous warning message in validator client when bellatrix fee recipient is unset. This is a cosmetic message and + does not affect run time behavior in Phase0/Altair. +- In Bellatrix/Kiln: Fee recipient flags may not work as expected. See for a fix and more details. + +### Fixed + +- Doppelganger false positives may have caused a failure to start in the validator client. +- Connections to execution layer clients were not properly cleaned up and lead to resource leaks when using ipc. +- Initial sync (or resync when beacon node falls out of sync) could lead to a panic. + +### Security + +There are no security updates in this release. + +## [v2.1.0](https://github.com/prysmaticlabs/prysm/compare/v2.0.6...v2.1.0) - 2022-04-26 + +There are two known issues with this release: + +- Erroneous warning message in validator client when bellatrix fee recipient is unset. This is a cosmetic message and + does not affect run time behavior in Phase0/Altair. +- In Bellatrix/Kiln: Fee recipient flags may not work as expected. See for a fix and more details. + +### Added + +- Web3Signer support. See the [documentation](https://docs.prylabs.network/docs/next/wallet/web3signer) for more + details. +- Bellatrix support. See [kiln testnet instructions](https://hackmd.io/OqIoTiQvS9KOIataIFksBQ?view) +- Weak subjectivity sync / checkpoint sync. This is an experimental feature and may have unintended side effects for + certain operators serving historical data. See + the [documentation](https://docs.prylabs.network/docs/prysm-usage/checkpoint-sync) for more details. +- A faster build of blst for beacon chain on linux amd64. Use the environment variable `USE_PRYSM_MODERN=true` with + prysm.sh, use the "modern" binary, or bazel build with `--define=blst_modern=true`. +- Vectorized sha256. This may have performance improvements with use of the new flag `--enable-vectorized-htr`. +- A new forkchoice structure that uses a doubly linked tree implementation. Try this feature with the + flag `--enable-forkchoice-doubly-linked-tree` +- Fork choice proposer boost is implemented and enabled by default. See PR description for more details. + +### Changed + +- **Flag Default Change** The default value for `--http-web3provider` is now `localhost:8545`. Previously was empty + string. +- Updated spectest compliance to v1.1.10. +- Updated to bazel 5.0.0 +- Gossip peer scorer is now part of the `--dev` flag. + +### Removed + +- Removed released feature for next slot cache. `--disable-next-slot-state-cache` flag has been deprecated and removed. + +### Fixed + +Too many bug fixes and improvements to mention all of them. See +the [full changelist](https://github.com/prysmaticlabs/prysm/compare/v2.0.6...v2.1.0) + +### Security + +There are no security updates in this release. + +## [v2.0.6](https://github.com/prysmaticlabs/prysm/compare/v2.0.5...v2.0.6) 2022-01-31 + +### Added + +- Bellatrix/Merge progress +- Light client support merkle proof retrieval for beacon state finalized root and sync committees +- Web3Signer support (work in progress) +- Implement state management with native go structs (work in progress) +- Added static analysis for mutex lock management +- Add endpoint to query eth1 connections +- Batch gossipsub verification enabled +- Get block optimizations enabled +- Batch decompression for signatures +- Balance trie feature enabled + +### Changed + +- Use build time constants for field lengths. +- Monitoring service logging improvements / cleanup +- Renamed state v3 import alias +- Spec tests passing at tag 1.1.8 +- Bazel version updated to 4.2.2 +- Renamed github.com/eth2-clients -> github.com/eth-clients +- p2p reduce memory allocation in gossip digest calculation +- Allow comma separated formatting for event topics in API requests +- Update builder image from buster to bullseye +- Renaming "merge" to "bellatrix" +- Refactoring / code dedupication / general clean up +- Update libp2p +- Reduce state copy in state upgrades +- Deduplicate sync committee messages from pool before retrieval + +### Removed + +- tools/deployContract: removed k8s specific logic + +### Fixed + +- Sync committee API endpoint can now be queried for future epochs +- Initialize merkle layers and recompute dirty fields in beacon state proofs +- Fixed data race in API calls + +### Security + +- Clean variable filepaths in validator wallet back up commands, e2e tests, and other tooling (gosec G304) + +## [v2.0.5](https://github.com/prysmaticlabs/prysm/compare/v2.0.4...v2.0.5) - 2021-12-13 + +### Added + +- Implement import keystores standard API +- Added more fields to "Processed attestation aggregation" log +- Incremental changes to support The Merge hardfork +- Implement validator monitoring service in beacon chain node via flag `--monitor-indices`. +- Added validator log to display "aggregated since launch" every 5 epochs. +- Add HTTP client wrapper for interfacing with remote signer See +- Update web UI to version v1.0.2. + +### Changed + +- Refactor beacon state to allow for a single cached hasher +- Default config name to "devnet" when not provided in the config yaml. +- Alter erroneously capitalized error messages +- Bump spec tests to version v1.1.6 +- Improvements to Doppelganger check +- Improvements to "grpc client connected" log. +- Update libp2p to v0.15.1 +- Resolve several checks from deepsource +- Update go-ethereum to v1.10.13 +- Update some flags from signed integer flags to unsigned flags. +- Filter errored keys from slashing protection history in standard API. +- Ensure slashing protection exports and key manager api work according to spec +- Improve memory performance by properly allocating slice size +- Typos fix +- Remove unused imports +- Use cashed finalized state when pruning deposits +- Significant slasher improvements +- Various code cleanups +- Standard API improvements for keymanager API +- Use safe sub64 for safer math +- Fix CORS in middleware API +- Add more fields to remote signer request object +- Refactoring to support checkpoint or genesis origin. + +### Deprecated + +Please be advised that Prysm's package path naming will change in the next release. If you are a downstream user of +Prysm (i.e. import prysm libraries into your project) then you may be impacted. Please see +issue https://github.com/prysmaticlabs/prysm/issues/10006. + +### Fixed + +- Allow API requests for next sync committee. +- Check sync status before performing a voluntary exit. +- Fixed issue where historical requests for validator balances would time out by removing the 30s timeout limitation. +- Add missing ssz spec tests + +### Security + +- Add justifications to gosec security finding suppression. + +## [v2.0.4](https://github.com/prysmaticlabs/prysm/compare/v2.0.3...v2.0.4) - 2021-11-29 + +### Added + +- Several changes for The Merge +- More monitoring functionality for blocks and sync committees + +### Changed + +- Improvements to block proposal computation when packing deposits. +- Renaming SignatureSet -> SignatureBatch + +### Deprecated + +### Fixed + +- Revert PR [9830](https://github.com/prysmaticlabs/prysm/pull/9830) to remove performance regression. See: + issue [9935](https://github.com/prysmaticlabs/prysm/issues/9935) + +### Security + +No security updates in this release. + +## [v2.0.3](https://github.com/prysmaticlabs/prysm/compare/v2.0.2...v2.0.3) - 2021-11-22 + +This release also includes a major update to the web UI. Please review the v1 web UI +notes [here](https://github.com/prysmaticlabs/prysm-web-ui/releases/tag/v1.0.0) + +### Added + +- Web v1 released +- Updated Beacon API to v2.1.0 +- Add validation of keystores via validator client RPC endpoint to support new web UI +- GitHub actions: errcheck and gosimple lint +- Event API support for `contribution_and_proof` and `voluntar_exit` events. +- Validator key management standard API schema and some implementation +- Add helpers for The Merge fork epoch calculation +- Add cli overrides for certain constants for The Merge +- Add beacon block and state structs for The Merge +- Validator monitoring improvements +- Cache deposits to improve deposit selection/processing +- Emit warning upon empty validator slashing protection export +- Add balance field trie cache and optimized hash trie root operations. `--enable-balance-trie-computation` + +### Changed + +- Updated to spectests v1.1.5 +- Refactor web authentication +- Added uint64 overflow protection +- Sync committee pool returns empty slice instead of nil on cache miss +- Improved description of datadir flag +- Simplified web password requirements +- Web JWT tokens no longer expire. +- Updated keymanager protos +- Watch and update jwt secret when auth token file updated on disk. +- Update web based slashing protection export from POST to GET +- Reuse helpers to validate fully populated objects. +- Rename interop-cold-start to deterministic-genesis +- Validate password on RPC create wallet request +- Refactor for weak subjectivity sync implementation +- Update naming for Atlair previous epoch attester +- Remove duplicate MerkleizeTrieLeaves method. +- Add explicit error for validator flag checks on out of bound positions +- Simplify method to check if the beacon chain client should update the justified epoch value. +- Rename web UI performance endpoint to "summary" +- Refactor powchain service to be more functional +- Use math.MaxUint64 +- Share / reused finalized state on prysm start up services +- Refactor slashing protection history code packages +- Improve RNG commentary +- Use next slot cache in more areas of the application +- Improve context aware p2p peer scoring loops +- Various code clean up +- Prevent redundant processing of blocks from pending queue +- Enable Altair tests on e2e against prior release client +- Use lazy state balance cache + +### Deprecated + +- Web UI login has been replaced. +- Web UI bar graph removed. + +### Removed + +- Prysmatic Labs' [go-ethereum fork](https://github.com/prysmaticlabs/bazel-go-ethereum) removed from build tooling. + Upstream go-ethereum is now used with familiar go.mod tooling. +- Removed duplicate aggergation validation p2p pipelines. +- Metrics calculation removed extra condition +- Removed superfluous errors from peer scoring parameters registration + +### Fixed + +- Allow submitting sync committee subscriptions for next period +- Ignore validators without committee assignment when fetching attester duties +- Return "version" field for ssz blocks in beacon API +- Fixed bazel build transitions for dbg builds. Allows IDEs to hook into debugger again. +- Fixed case where GetDuties RPC endpoint might return a false positive for sync committee selection for validators that + have no deposited yet +- Fixed validator exits in v1 method, broadcast correct object +- Fix Altair individual votes endpoint +- Validator performance calculations fixed +- Return correct response from key management api service +- Check empty genesis validators root on slashing protection data export +- Fix stategen with genesis state. +- Fixed multiple typos +- Fix genesis state registration in interop mode +- Fix network flags in slashing protection export + +### Security + +- Added another encryption key to security.txt. + +## [v2.0.2](https://github.com/prysmaticlabs/prysm/compare/v2.0.1...v2.0.2) - 2021-10-18 + +### Added + +- Optimizations to block proposals. Enabled with `--enable-get-block-optimizations`. + See [issue 8943](https://github.com/prysmaticlabs/prysm/issues/8943) + and [issue 9708](https://github.com/prysmaticlabs/prysm/issues/9708) before enabling. +- Beacon Standard API: register v1alpha2 endpoints + +### Changed + +- Beacon Standard API: Improved sync error messages +- Beacon Standard API: Omit validators without sync duties +- Beacon Standard API: Return errors for unknown state/block versions +- Spec alignment: Passing spec vectors at v1.1.2 +- Logs: Improved "synced block.." +- Bazel: updated to v4.2.1 +- E2E: more strict participation checks +- Eth1data: Reduce disk i/o saving interval + +### Deprecated + +- ⚠️ v2 Remote slashing protection server disabled for now ⚠️ + +### Fixed + +- Beacon Standard API: fetch sync committee duties for current and next period's epoch +- Beacon Standard API: remove special treatment to graffiti in block results +- Beacon Standard API: fix epoch calculation in sync committee duties +- Doppelganger: Fix false positives +- UI: Validator gRPC gateway health endpoint fixed + +### Security + +- Spec alignment: Update Eth2FastAggregateVerify to match spec +- Helpers: enforce stronger slice index checks +- Deposit Trie: Handle impossible non-power of 2 trie leaves +- UI: Add security headers + +## [v2.0.1](https://github.com/prysmaticlabs/prysm/compare/v2.0.0...v2.0.1) - 2021-10-06 + +### Fixed + +- Updated libp2p transport library to stop metrics logging errors on windows. +- Prysm's web UI assets serve properly +- Eth2 api returns full validator balance rather than effective balance +- Slashing protection service registered properly in validator. + +### Security + +We've updated the Prysm base docker images to a more recent build. + +## [v2.0.0](https://github.com/prysmaticlabs/prysm/compare/v1.4.4...v2.0.0) + +This release is the largest release of Prysm to date. v2.0.0 includes support for the upcoming Altair hard fork on the +mainnet Ethereum Beacon Chain. +This release consists +of [380 changes](https://github.com/prysmaticlabs/prysm/compare/v1.4.4...f7845afa575963302116e673d400d2ab421252ac) to +support Altair, improve performance of phase0 beacon nodes, and various bug fixes from v1.4.4. + +### Upgrading From v1 + +Please update your beacon node to v2.0.0 prior to updating your validator. The beacon node can serve requests to a +v1.4.4 validator, however a v2.0.0 validator will not start against a v1.4.4 beacon node. If you're operating a highly +available beacon chain service, ensure that all of your beacon nodes are updated to v2.0.0 before starting the upgrade +on your validators. + +### Added + +- Full Altair + support. [Learn more about Altair.](https://github.com/ethereum/annotated-spec/blob/8473024d745a3a2b8a84535d57773a8e86b66c9a/altair/beacon-chain.md) +- Added bootnodes from the Nimbus team. +- Revamped slasher implementation. The slasher functionality is no longer a standalone binary. Slasher functionality is + available from the beacon node with the `--slasher` flag. Note: Running the slasher has considerably increased + resource requirements. Be sure to review the latest documentation before enabling this feature. This feature is + experimental. +- Support for standard JSON API in the beacon node. Prysm validators continue to use Prysm's API. +- Configurable subnet peer requirements. Increased minimum desired peers per subnet from 4 to 6. This can be modified + with `--minimum-peers-per-subnet` in the beacon node.. +- Support for go build on darwin_arm64 devices (Mac M1 chips). Cross compiling for darwin_arm64 is not yet supported.. +- Batch verification of pubsub objects. This should improve pubsub processing performance on multithreaded machines. +- Improved attestation pruning. This feature should improve block proposer performance and overall network attestation + inclusion rates. Opt-out with `--disable-correctly-prune-canonical-atts` in the beacon node. +- Active balance cache to improve epoch processing. Opt-out with `--disable-active-balance-cache` +- Experimental database improvements to reduce history state entry space usage in the beaconchain.db. This functionality + can be permanently enabled with the flag `--enable-historical-state-representation`. Enabling this feature can realize + a 25% improvement in space utilization for the average user , while 70 -80% for power users(archival node operators). + Note: once this feature is toggled on, it modifies the structure of the database with a migration and cannot be rolled + back. This feature is experimental and should only be used in non-serving beacon nodes in case of database corruption + or other critical issue. + +#### New Metrics + +**Beacon chain node** + +| Metric | Description | References | +| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | ---------- | +| `p2p_message_ignored_validation_total` | Count of messages that were ignored in validation | | +| `beacon_current_active_validators` | Current total active validators | | +| `beacon_processed_deposits_total` | Total number of deposits processed | | +| `sync_head_state_miss` | The number of sync head state requests that are not present in the cache | | +| `sync_head_state_hit` | The number of sync head state requests that are present in the cache | | +| `total_effective_balance_cache_miss` | The number of get requests that are not present in the cache | | +| `total_effective_balance_cache_hit` | The number of get requests that are present in the cache | | +| `sync_committee_index_cache_miss_total` | The number of committee requests that aren't present in the sync committee index cache | | +| `sync_committee_index_cache_hit_total` | The number of committee requests that are present in the sync committee index cache | | +| `next_slot_cache_hit` | The number of cache hits on the next slot state cache | | +| `next_slot_cache_miss` | The number of cache misses on the next slot state cache | | +| `validator_entry_cache_hit_total` | The number of cache hits on the validator entry cache | | +| `validator_entry_cache_miss_total` | The number of cache misses on the validator entry cache | | +| `validator_entry_cache_delete_total` | The number of cache deletes on the validator entry cache | | +| `saved_sync_committee_message_total` | The number of saved sync committee message total | | +| `saved_sync_committee_contribution_total` | The number of saved sync committee contribution total | | +| `libp2p_peers` | Tracks the total number of libp2p peers | | +| `p2p_status_message_missing` | The number of attempts the connection handler rejects a peer for a missing status message | | +| `p2p_sync_committee_subnet_recovered_broadcasts` | The number of sync committee messages that were attempted to be broadcast with no peers on the subnet | | +| `p2p_sync_committee_subnet_attempted_broadcasts` | The number of sync committees that were attempted to be broadcast | | +| `p2p_subscribed_topic_peer_total` | The number of peers subscribed to topics that a host node is also subscribed to | | +| `saved_orphaned_att_total` | Count the number of times an orphaned attestation is saved | | + +### Changed + +- Much refactoring of "util" packages into more canonical packages. Please review Prysm package structure and godocs. +- Altair object keys in beacon-chain/db/kv are prefixed with "altair". BeaconBlocks and BeaconStates are the only + objects affected by database key changes for Altair. This affects any third party tooling directly querying Prysm's + beaconchain.db. +- Updated Teku bootnodes. +- Updated Lighthouse bootnodes. +- End to end testing now collects jaeger spans +- Improvements to experimental peer quality scoring. This feature is only enabled with `--enable-peer-scorer`. +- Validator performance logging behavior has changed in Altair. Post-Altair hardfork has the following changes: + Inclusion distance and inclusion slots will no longer be displayed. Correctly voted target will only be true if also + included within 32 slots. Correctly voted head will only be true if the attestation was included in the next slot. + Correctly voted source will only be true if attestation is included within 5 slots. Inactivity score will be + displayed. +- Increased pubsub message queue size from 256 to 600 to support larger networks and higher message volume. +- The default attestation aggregation changed to the improved optimized max cover algorithm. +- Prysm is passing spectests at v1.1.0 (latest available release). +- `--subscribe-all-subnets` will subscribe to all attestation subnets and sync subnets in post-altair hard fork. +- "eth2" is now an illegal term. If you say it or type it then something bad might happen. +- Improved cache hit ratio for validator entry cache. +- Reduced memory overhead during database migrations. +- Improvements to beacon state writes to database. + +#### Changed Metrics + +**Beacon chain node** +| Metric | Old Name | Description | References | +| --------------------- | -------------------- | ---------------------------------------------------- | ---------- | +| `beacon_reorgs_total` | `beacon_reorg_total` | Count the number of times a beacon chain has a reorg | | + +### Deprecated + +These flags are hidden from the help text and no longer modify the behavior of Prysm. These flags should be removed from +user runtime configuration as the flags will eventually be removed entirely and Prysm will fail to start if a deleted or +unknown flag is provided. + +- `--enable-active-balance-cache` +- `--correctly-prune-canonical-atts` +- `--correctly-insert-orphaned-atts` +- `--enable-next-slot-state-cache` + +### Removed + +Note: Removed flags will block starting up with an error "flag provided but not defined:". +Please check that you are not using any of the removed flags in this section! + +- Prysm's standalone slasher application (cmd/slasher) has been fully removed. Use the `--slasher` flag with a beacon + chain node for full slasher functionality. +- `--disable-blst` (beacon node and validator). [blst](https://github.com/supranational/blst) is the only BLS library + offered for Prysm. +- `--disable-sync-backtracking` and `--enable-sync-backtracking` (beacon node). This feature has been released for some + time. See. +- `--diable-pruning-deposit-proofs` (beacon node). This feature has been released for some time. See. +- `--disable-eth1-data-majority-vote` (beacon node). This feature is no longer in use in Prysm. See,. +- `--proposer-atts-selection-using-max-cover` (beacon node). This feature has been released for some time. See. +- `--update-head-timely` (beacon node). This feature was released in v1.4.4. See. +- `--enable-optimized-balance-update` (beacon node). This feature was released in v1.4.4. See. +- Kafka support is no longer available in the beacon node. This functionality was never fully completed and did not + fulfill many desirable use cases. This removed the flag `--kafka-url` (beacon node). See. +- Removed tools/faucet. Use the faucet + in [prysmaticlabs/periphery](https://github.com/prysmaticlabs/periphery/tree/c2ac600882c37fc0f2a81b0508039124fb6bcf47/eth-faucet) + if operating a testnet faucet server. +- Tooling for prior testnet contracts has been removed. Any of the old testnet contracts with `drain()` function have + been removed as well. +- Toledo tesnet config is removed. +- Removed --eth-api-port (beacon node). All APIs interactions have been moved to --grpc-gateway-port. See. + +### Fixed + +- Database lock contention improved in block database operations. +- JSON API now returns an error when unknown fields are provided. +- Correctly return `epoch_transition` field in `head` JSON API events stream. +- Various fixes in standard JSON API +- Finalize deposits before initializing the beacon node. This may improve missed proposals +- JSON API returns header "Content-Length" 0 when returning an empty JSON object. +- Initial sync fixed when there is a very long period of missing blocks. +- Fixed log statement when a web3 endpoint failover occurs. +- Windows prysm.bat is fixed + +### Security + +- You MUST update to v2.0.0 or later release before epoch 74240 or your client will fork off from the rest of the + network. +- Prysm's JWT library has been updated to a maintained version of the previous JWT library. JWTs are only used in the + UI. + +Please review our newly +updated [security reporting policy](https://github.com/prysmaticlabs/prysm/blob/develop/SECURITY.md). + +- Fix subcommands such as validator accounts list + +### Security + +There are no security updates in this release. + +# Older than v2.0.0 + +For changelog history for releases older than v2.0.0, please refer to https://github.com/prysmaticlabs/prysm/releases diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5f9cf9811bff..f8b85751f347 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,6 +6,9 @@ Excited by our work and want to get involved in building out our sharding releas You can explore our [Open Issues](https://github.com/prysmaticlabs/prysm/issues) in-the works for our different releases. Feel free to fork our repo and start creating PR’s after assigning yourself to an issue of interest. We are always chatting on [Discord](https://discord.gg/CTYGPUJ) drop us a line there if you want to get more involved or have any questions on our implementation! +> [!IMPORTANT] +> Please, **do not send pull requests for trivial changes**, such as typos, these will be rejected. These types of pull requests incur a cost to reviewers and do not provide much value to the project. If you are unsure, please open an issue first to discuss the change. + ## Contribution Steps **1. Set up Prysm following the instructions in README.md.** @@ -120,15 +123,19 @@ $ git push myrepo feature-in-progress-branch Navigate to your fork of the repo on GitHub. On the upper left where the current branch is listed, change the branch to your feature-in-progress-branch. Open the files that you have worked on and check to make sure they include your changes. -**16. Create a pull request.** +**16. Add an entry to CHANGELOG.md.** + +All PRs must must include a changelog fragment file in the `changelog` directory. If your change is not user-facing or should not be mentioned in the changelog for some other reason, you may use the `Ignored` changelog section in your fragment's header to satisfy this requirement without altering the final release changelog. See the [Maintaining CHANGELOG.md](#maintaining-changelogmd) section for more information. -Navigate your browser to https://github.com/prysmaticlabs/prysm and click on the new pull request button. In the “base” box on the left, leave the default selection “base master”, the branch that you want your changes to be applied to. In the “compare” box on the right, select feature-in-progress-branch, the branch containing the changes you want to apply. You will then be asked to answer a few questions about your pull request. After you complete the questionnaire, the pull request will appear in the list of pull requests at https://github.com/prysmaticlabs/prysm/pulls. +**17. Create a pull request.** -**17. Respond to comments by Core Contributors.** +Navigate your browser to https://github.com/prysmaticlabs/prysm and click on the new pull request button. In the “base” box on the left, leave the default selection “base develop”, the branch that you want your changes to be applied to. In the “compare” box on the right, select feature-in-progress-branch, the branch containing the changes you want to apply. You will then be asked to answer a few questions about your pull request. After you complete the questionnaire, the pull request will appear in the list of pull requests at https://github.com/prysmaticlabs/prysm/pulls. Ensure that you have added an entry to CHANGELOG.md if your PR is a user-facing change. See the [Maintaining CHANGELOG.md](#maintaining-changelogmd) section for more information. + +**18. Respond to comments by Core Contributors.** Core Contributors may ask questions and request that you make edits. If you set notifications at the top of the page to “not watching,” you will still be notified by email whenever someone comments on the page of a pull request you have created. If you are asked to modify your pull request, repeat steps 8 through 15, then leave a comment to notify the Core Contributors that the pull request is ready for further review. -**18. If the number of commits becomes excessive, you may be asked to squash your commits.** +**19. If the number of commits becomes excessive, you may be asked to squash your commits.** You can do this with an interactive rebase. Start by running the following command to determine the commit that is the base of your branch... @@ -136,7 +143,7 @@ Core Contributors may ask questions and request that you make edits. If you set $ git merge-base feature-in-progress-branch prysm/master ``` -**19. The previous command will return a commit-hash that you should use in the following command.** +**20. The previous command will return a commit-hash that you should use in the following command.** ``` $ git rebase -i commit-hash @@ -160,13 +167,24 @@ squash hash add a feature Save and close the file, then a commit command will appear in the terminal that squashes the smaller commits into one. Check to be sure the commit message accurately reflects your changes and then hit enter to execute it. -**20. Update your pull request with the following command.** +**21. Update your pull request with the following command.** ``` $ git push myrepo feature-in-progress-branch -f ``` -**21. Finally, again leave a comment to the Core Contributors on the pull request to let them know that the pull request has been updated.** +**22. Finally, again leave a comment to the Core Contributors on the pull request to let them know that the pull request has been updated.** + +## Maintaining CHANGELOG.md + +This project follows the changelog guidelines from [keepachangelog.com](https://keepachangelog.com/en/1.1.0/). In order to minimize conflicts and workflow headaches, we chose to implement a changelog management +strategy that uses changelog "fragment" files, managed by our changelog management tool called `unclog`. Each PR must include a new changelog fragment file in the `changelog` directory, as specified by unclog's +[README.md](https://github.com/OffchainLabs/unclog?tab=readme-ov-file#what-is-a-changelog-fragment). As the `unclog` README suggests in the [Best Practices](https://github.com/OffchainLabs/unclog?tab=readme-ov-file#best-practices) section, +the standard naming convention for your PR's fragment file, to avoid conflicting with another fragment file, is `changelog/_.md`. + +### Releasing + +When a new release is made, the "Unreleased" section should be moved to a new section with the release version and the current date. Then a new "Unreleased" section is made at the top of the file with the categories listed above. ## Contributor Responsibilities diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 721b295207a9..6b948627a249 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -55,7 +55,7 @@ bazel build //beacon-chain --config=release ## Adding / updating dependencies 1. Add your dependency as you would with go modules. I.e. `go get ...` -1. Run `bazel run //:gazelle -- update-repos -from_file=go.mod` to update the bazel managed dependencies. +1. Run `bazel run //:gazelle -- update-repos -from_file=go.mod -to_macro=deps.bzl%prysm_deps -prune=true` to update the bazel managed dependencies. Example: diff --git a/INTEROP.md b/INTEROP.md index 59cc5ef1c25f..33d3dceedcaa 100644 --- a/INTEROP.md +++ b/INTEROP.md @@ -2,18 +2,21 @@ This README details how to setup Prysm for interop testing for usage with other Ethereum consensus clients. +> [!IMPORTANT] +> This guide is likely to be outdated. The Prysm team does not have capacity to troubleshoot +> outdated interop guides or instructions. If you experience issues with this guide, please file an +> issue for visibility and propose fixes, if possible. + ## Installation & Setup 1. Install [Bazel](https://docs.bazel.build/versions/master/install.html) **(Recommended)** 2. `git clone https://github.com/prysmaticlabs/prysm && cd prysm` -3. `bazel build //...` +3. `bazel build //cmd/...` ## Starting from Genesis -Prysm supports a few ways to quickly launch a beacon node from basic configurations: - -- `NumValidators + GenesisTime`: Launches a beacon node by deterministically generating a state from a num-validators flag along with a genesis time **(Recommended)** -- `SSZ Genesis`: Launches a beacon node from a .ssz file containing a SSZ-encoded, genesis beacon state +Prysm can be started from a built-in mainnet genesis state, or started with a provided genesis state by +using the `--genesis-state` flag and providing a path to the genesis.ssz file. ## Generating a Genesis State @@ -21,21 +24,34 @@ To setup the necessary files for these quick starts, Prysm provides a tool to ge a deterministically generated set of validator private keys following the official interop YAML format [here](https://github.com/ethereum/eth2.0-pm/blob/master/interop/mocked_start). -You can use `bazel run //tools/genesis-state-gen` to create a deterministic genesis state for interop. +You can use `prysmctl` to create a deterministic genesis state for interop. -### Usage +```sh +# Download (or create) a chain config file. +curl https://raw.githubusercontent.com/ethereum/consensus-specs/refs/heads/dev/configs/minimal.yaml -o /tmp/minimal.yaml -- **--genesis-time** uint: Unix timestamp used as the genesis time in the generated genesis state (defaults to now) -- **--num-validators** int: Number of validators to deterministically include in the generated genesis state -- **--output-ssz** string: Output filename of the SSZ marshaling of the generated genesis state -- **--config-name=interop** string: name of the beacon chain config to use when generating the state. ex mainnet|minimal|interop +# Run prysmctl to generate genesis with a 2 minute genesis delay and 256 validators. +bazel run //cmd/prysmctl --config=minimal -- \ + testnet generate-genesis \ + --genesis-time-delay=120 \ + --num-validators=256 \ + --output-ssz=/tmp/genesis.ssz \ + --chain-config-file=/tmp/minimal.yaml +``` -The example below creates 64 validator keys, instantiates a genesis state with those 64 validators and with genesis unix timestamp 1567542540, -and finally writes a ssz encoded output to ~/Desktop/genesis.ssz. This file can be used to kickstart the beacon chain in the next section. When using the `--interop-*` flags, the beacon node will assume the `interop` config should be used, unless a different config is specified on the command line. +The flags are explained below: +- `bazel run //cmd/prysmctl` is the bazel command to compile and run prysmctl. +- `--config=minimal` is a bazel build time configuration flag to compile Prysm with minimal state constants. +- `--` is an argument divider to tell bazel that everything after this divider should be passed as arguments to prysmctl. Without this divider, it isn't clear to bazel if the arguments are meant to be build time arguments or runtime arguments so the operation complains and fails to build without this divider. +- `testnet` is the primary command argument for prysmctl. +- `generate-genesis` is the subcommand to `testnet` in prysmctl. +- `--genesis-time-delay` uint: The number of seconds in the future to define genesis. Example: a value of 60 will set the genesis time to 1 minute in the future. This should be sufficiently large enough to allow for you to start the beacon node before the genesis time. +- `--num-validators` int: Number of validators to deterministically include in the generated genesis state +- `--output-ssz` string: Output filename of the SSZ marshaling of the generated genesis state +- `--chain-config-file` string: Filepath to a chain config yaml file. -``` -bazel run //tools/genesis-state-gen -- --config-name interop --output-ssz ~/Desktop/genesis.ssz --num-validators 64 --genesis-time 1567542540 -``` +Note: This guide saves items to the `/tmp/` directory which will not persist if your machine is +restarted. Consider tweaking the arguments if persistence is needed. ## Launching a Beacon Node + Validator Client @@ -44,45 +60,33 @@ bazel run //tools/genesis-state-gen -- --config-name interop --output-ssz ~/Desk Open up two terminal windows, run: ``` -bazel run //beacon-chain -- \ ---bootstrap-node= \ ---deposit-contract 0x8A04d14125D0FDCDc742F4A05C051De07232EDa4 \ ---datadir=/tmp/beacon-chain-interop \ ---force-clear-db \ ---min-sync-peers=0 \ ---interop-num-validators 64 \ ---interop-eth1data-votes +bazel run //cmd/beacon-chain --config=minimal -- \ + --minimal-config \ + --bootstrap-node= \ + --deposit-contract 0x8A04d14125D0FDCDc742F4A05C051De07232EDa4 \ + --datadir=/tmp/beacon-chain-minimal-devnet \ + --force-clear-db \ + --min-sync-peers=0 \ + --genesis-state=/tmp/genesis.ssz \ + --chain-config-file=/tmp/minimal.yaml ``` -This will deterministically generate a beacon genesis state and start -the system with 64 validators and the genesis time set to the current unix timestamp. -Wait a bit until your beacon chain starts, and in the other window: +This will start the system with 256 validators. The flags used can be explained as such: -``` -bazel run //validator -- --keymanager=interop --keymanageropts='{"keys":64}' -``` - -This will launch and kickstart the system with your 64 validators performing their duties accordingly. - -### Launching from `genesis.ssz` - -Assuming you generated a `genesis.ssz` file with 64 validators, open up two terminal windows, run: - -``` - bazel run //beacon-chain -- \ ---bootstrap-node= \ ---deposit-contract 0x8A04d14125D0FDCDc742F4A05C051De07232EDa4 \ ---datadir=/tmp/beacon-chain-interop \ ---force-clear-db \ ---min-sync-peers=0 \ ---interop-genesis-state /path/to/genesis.ssz \ ---interop-eth1data-votes -``` +- `bazel run //cmd/beacon-chain --config=minimal` builds and runs the beacon node in minimal build configuration. +- `--` is a flag divider to distinguish between bazel flags and flags that should be passed to the application. All flags and arguments after this divider are passed to the beacon chain. +- `--minimal-config` tells the beacon node to use minimal network configuration. This is different from the compile time state configuration flag `--config=minimal` and both are required. +- `--bootstrap-node=` disables the default bootstrap nodes. This prevents the client from attempting to peer with mainnet nodes. +- `--datadir=/tmp/beacon-chain-minimal-devnet` sets the data directory in a temporary location. Change this to your preferred destination. +- `--force-clear-db` will delete the beaconchain.db file without confirming with the user. This is helpful for iteratively running local devnets without changing the datadir, but less helpful for one off runs where there was no database in the data directory. +- `--min-sync-peers=0` allows the beacon node to skip initial sync without peers. This is essential because Prysm expects at least a few peers to start the blockchain. +- `--genesis-state=/tmp/genesis.ssz` defines the path to the generated genesis ssz file. The beacon node will use this as the initial genesis state. +- `--chain-config-file=/tmp/minimal.yaml` defines the path to the yaml file with the chain configuration. -Wait a bit until your beacon chain starts, and in the other window: +As soon as the beacon node has started, start the validator in the other terminal window. ``` -bazel run //validator -- --keymanager=interop --keymanageropts='{"keys":64}' +bazel run //cmd/validator --config=minimal -- --datadir=/tmp/validator --interop-num-validators=256 --minimal-config --suggested-fee-recipient=0x8A04d14125D0FDCDc742F4A05C051De07232EDa4 ``` -This will launch and kickstart the system with your 64 validators performing their duties accordingly. +This will launch and kickstart the system with your 256 validators performing their duties accordingly. diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 20b916264309..d62a47c0f60c 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -1,1653 +1,110 @@ { - "lockFileVersion": 6, - "moduleFileHash": "0e3e315145ac7ee7a4e0ac825e1c5e03c068ec1254dd42c3caaecb27e921dc4d", - "flags": { - "cmdRegistries": [ - "https://bcr.bazel.build/" - ], - "cmdModuleOverrides": {}, - "allowedYankedVersions": [], - "envVarAllowedYankedVersions": "", - "ignoreDevDependency": false, - "directDependenciesMode": "WARNING", - "compatibilityMode": "ERROR" - }, - "localOverrideHashes": { - "bazel_tools": "1ae69322ac3823527337acf02016e8ee95813d8d356f47060255b8956fa642f0" - }, - "moduleDepGraph": { - "": { - "name": "", - "version": "", - "key": "", - "repoName": "", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - } - }, - "bazel_tools@_": { - "name": "bazel_tools", - "version": "", - "key": "bazel_tools@_", - "repoName": "bazel_tools", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [ - "@local_config_cc_toolchains//:all", - "@local_config_sh//:local_sh_toolchain" - ], - "extensionUsages": [ - { - "extensionBzlFile": "@bazel_tools//tools/cpp:cc_configure.bzl", - "extensionName": "cc_configure_extension", - "usingModule": "bazel_tools@_", - "location": { - "file": "@@bazel_tools//:MODULE.bazel", - "line": 18, - "column": 29 - }, - "imports": { - "local_config_cc": "local_config_cc", - "local_config_cc_toolchains": "local_config_cc_toolchains" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - }, - { - "extensionBzlFile": "@bazel_tools//tools/osx:xcode_configure.bzl", - "extensionName": "xcode_configure_extension", - "usingModule": "bazel_tools@_", - "location": { - "file": "@@bazel_tools//:MODULE.bazel", - "line": 22, - "column": 32 - }, - "imports": { - "local_config_xcode": "local_config_xcode" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - }, - { - "extensionBzlFile": "@rules_java//java:extensions.bzl", - "extensionName": "toolchains", - "usingModule": "bazel_tools@_", - "location": { - "file": "@@bazel_tools//:MODULE.bazel", - "line": 25, - "column": 32 - }, - "imports": { - "local_jdk": "local_jdk", - "remote_java_tools": "remote_java_tools", - "remote_java_tools_linux": "remote_java_tools_linux", - "remote_java_tools_windows": "remote_java_tools_windows", - "remote_java_tools_darwin_x86_64": "remote_java_tools_darwin_x86_64", - "remote_java_tools_darwin_arm64": "remote_java_tools_darwin_arm64" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - }, - { - "extensionBzlFile": "@bazel_tools//tools/sh:sh_configure.bzl", - "extensionName": "sh_configure_extension", - "usingModule": "bazel_tools@_", - "location": { - "file": "@@bazel_tools//:MODULE.bazel", - "line": 36, - "column": 39 - }, - "imports": { - "local_config_sh": "local_config_sh" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - }, - { - "extensionBzlFile": "@bazel_tools//tools/test:extensions.bzl", - "extensionName": "remote_coverage_tools_extension", - "usingModule": "bazel_tools@_", - "location": { - "file": "@@bazel_tools//:MODULE.bazel", - "line": 40, - "column": 48 - }, - "imports": { - "remote_coverage_tools": "remote_coverage_tools" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - }, - { - "extensionBzlFile": "@bazel_tools//tools/android:android_extensions.bzl", - "extensionName": "remote_android_tools_extensions", - "usingModule": "bazel_tools@_", - "location": { - "file": "@@bazel_tools//:MODULE.bazel", - "line": 43, - "column": 42 - }, - "imports": { - "android_gmaven_r8": "android_gmaven_r8", - "android_tools": "android_tools" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - }, - { - "extensionBzlFile": "@buildozer//:buildozer_binary.bzl", - "extensionName": "buildozer_binary", - "usingModule": "bazel_tools@_", - "location": { - "file": "@@bazel_tools//:MODULE.bazel", - "line": 47, - "column": 33 - }, - "imports": { - "buildozer_binary": "buildozer_binary" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - } - ], - "deps": { - "rules_cc": "rules_cc@0.0.9", - "rules_java": "rules_java@7.4.0", - "rules_license": "rules_license@0.0.7", - "rules_proto": "rules_proto@5.3.0-21.7", - "rules_python": "rules_python@0.22.1", - "buildozer": "buildozer@6.4.0.2", - "platforms": "platforms@0.0.7", - "com_google_protobuf": "protobuf@21.7", - "zlib": "zlib@1.3", - "build_bazel_apple_support": "apple_support@1.5.0", - "local_config_platform": "local_config_platform@_" - } - }, - "local_config_platform@_": { - "name": "local_config_platform", - "version": "", - "key": "local_config_platform@_", - "repoName": "local_config_platform", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "platforms": "platforms@0.0.7", - "bazel_tools": "bazel_tools@_" - } - }, - "rules_cc@0.0.9": { - "name": "rules_cc", - "version": "0.0.9", - "key": "rules_cc@0.0.9", - "repoName": "rules_cc", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [ - "@local_config_cc_toolchains//:all" - ], - "extensionUsages": [ - { - "extensionBzlFile": "@bazel_tools//tools/cpp:cc_configure.bzl", - "extensionName": "cc_configure_extension", - "usingModule": "rules_cc@0.0.9", - "location": { - "file": "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel", - "line": 9, - "column": 29 - }, - "imports": { - "local_config_cc_toolchains": "local_config_cc_toolchains" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - } - ], - "deps": { - "platforms": "platforms@0.0.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz" - ], - "integrity": "sha256-IDeHW5pEVtzkp50RKorohbvEqtlo5lh9ym5k86CQDN8=", - "strip_prefix": "rules_cc-0.0.9", - "remote_patches": { - "https://bcr.bazel.build/modules/rules_cc/0.0.9/patches/module_dot_bazel_version.patch": "sha256-mM+qzOI0SgAdaJBlWOSMwMPKpaA9b7R37Hj/tp5bb4g=" - }, - "remote_patch_strip": 0 - } - } - }, - "rules_java@7.4.0": { - "name": "rules_java", - "version": "7.4.0", - "key": "rules_java@7.4.0", - "repoName": "rules_java", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [ - "//toolchains:all", - "@local_jdk//:runtime_toolchain_definition", - "@local_jdk//:bootstrap_runtime_toolchain_definition", - "@remotejdk11_linux_toolchain_config_repo//:all", - "@remotejdk11_linux_aarch64_toolchain_config_repo//:all", - "@remotejdk11_linux_ppc64le_toolchain_config_repo//:all", - "@remotejdk11_linux_s390x_toolchain_config_repo//:all", - "@remotejdk11_macos_toolchain_config_repo//:all", - "@remotejdk11_macos_aarch64_toolchain_config_repo//:all", - "@remotejdk11_win_toolchain_config_repo//:all", - "@remotejdk11_win_arm64_toolchain_config_repo//:all", - "@remotejdk17_linux_toolchain_config_repo//:all", - "@remotejdk17_linux_aarch64_toolchain_config_repo//:all", - "@remotejdk17_linux_ppc64le_toolchain_config_repo//:all", - "@remotejdk17_linux_s390x_toolchain_config_repo//:all", - "@remotejdk17_macos_toolchain_config_repo//:all", - "@remotejdk17_macos_aarch64_toolchain_config_repo//:all", - "@remotejdk17_win_toolchain_config_repo//:all", - "@remotejdk17_win_arm64_toolchain_config_repo//:all", - "@remotejdk21_linux_toolchain_config_repo//:all", - "@remotejdk21_linux_aarch64_toolchain_config_repo//:all", - "@remotejdk21_macos_toolchain_config_repo//:all", - "@remotejdk21_macos_aarch64_toolchain_config_repo//:all", - "@remotejdk21_win_toolchain_config_repo//:all" - ], - "extensionUsages": [ - { - "extensionBzlFile": "@rules_java//java:extensions.bzl", - "extensionName": "toolchains", - "usingModule": "rules_java@7.4.0", - "location": { - "file": "https://bcr.bazel.build/modules/rules_java/7.4.0/MODULE.bazel", - "line": 19, - "column": 27 - }, - "imports": { - "remote_java_tools": "remote_java_tools", - "remote_java_tools_linux": "remote_java_tools_linux", - "remote_java_tools_windows": "remote_java_tools_windows", - "remote_java_tools_darwin_x86_64": "remote_java_tools_darwin_x86_64", - "remote_java_tools_darwin_arm64": "remote_java_tools_darwin_arm64", - "local_jdk": "local_jdk", - "remotejdk11_linux_toolchain_config_repo": "remotejdk11_linux_toolchain_config_repo", - "remotejdk11_linux_aarch64_toolchain_config_repo": "remotejdk11_linux_aarch64_toolchain_config_repo", - "remotejdk11_linux_ppc64le_toolchain_config_repo": "remotejdk11_linux_ppc64le_toolchain_config_repo", - "remotejdk11_linux_s390x_toolchain_config_repo": "remotejdk11_linux_s390x_toolchain_config_repo", - "remotejdk11_macos_toolchain_config_repo": "remotejdk11_macos_toolchain_config_repo", - "remotejdk11_macos_aarch64_toolchain_config_repo": "remotejdk11_macos_aarch64_toolchain_config_repo", - "remotejdk11_win_toolchain_config_repo": "remotejdk11_win_toolchain_config_repo", - "remotejdk11_win_arm64_toolchain_config_repo": "remotejdk11_win_arm64_toolchain_config_repo", - "remotejdk17_linux_toolchain_config_repo": "remotejdk17_linux_toolchain_config_repo", - "remotejdk17_linux_aarch64_toolchain_config_repo": "remotejdk17_linux_aarch64_toolchain_config_repo", - "remotejdk17_linux_ppc64le_toolchain_config_repo": "remotejdk17_linux_ppc64le_toolchain_config_repo", - "remotejdk17_linux_s390x_toolchain_config_repo": "remotejdk17_linux_s390x_toolchain_config_repo", - "remotejdk17_macos_toolchain_config_repo": "remotejdk17_macos_toolchain_config_repo", - "remotejdk17_macos_aarch64_toolchain_config_repo": "remotejdk17_macos_aarch64_toolchain_config_repo", - "remotejdk17_win_toolchain_config_repo": "remotejdk17_win_toolchain_config_repo", - "remotejdk17_win_arm64_toolchain_config_repo": "remotejdk17_win_arm64_toolchain_config_repo", - "remotejdk21_linux_toolchain_config_repo": "remotejdk21_linux_toolchain_config_repo", - "remotejdk21_linux_aarch64_toolchain_config_repo": "remotejdk21_linux_aarch64_toolchain_config_repo", - "remotejdk21_macos_toolchain_config_repo": "remotejdk21_macos_toolchain_config_repo", - "remotejdk21_macos_aarch64_toolchain_config_repo": "remotejdk21_macos_aarch64_toolchain_config_repo", - "remotejdk21_win_toolchain_config_repo": "remotejdk21_win_toolchain_config_repo" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - } - ], - "deps": { - "platforms": "platforms@0.0.7", - "rules_cc": "rules_cc@0.0.9", - "bazel_skylib": "bazel_skylib@1.3.0", - "rules_proto": "rules_proto@5.3.0-21.7", - "rules_license": "rules_license@0.0.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/rules_java/releases/download/7.4.0/rules_java-7.4.0.tar.gz" - ], - "integrity": "sha256-l27wi0nJKXQfIBeQ5Z44B8cq2B9CjIvJU82+/1/tFes=", - "strip_prefix": "", - "remote_patches": {}, - "remote_patch_strip": 0 - } - } - }, - "rules_license@0.0.7": { - "name": "rules_license", - "version": "0.0.7", - "key": "rules_license@0.0.7", - "repoName": "rules_license", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz" - ], - "integrity": "sha256-RTHezLkTY5ww5cdRKgVNXYdWmNrrddjPkPKEN1/nw2A=", - "strip_prefix": "", - "remote_patches": {}, - "remote_patch_strip": 0 - } - } - }, - "rules_proto@5.3.0-21.7": { - "name": "rules_proto", - "version": "5.3.0-21.7", - "key": "rules_proto@5.3.0-21.7", - "repoName": "rules_proto", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "bazel_skylib": "bazel_skylib@1.3.0", - "com_google_protobuf": "protobuf@21.7", - "rules_cc": "rules_cc@0.0.9", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz" - ], - "integrity": "sha256-3D+yBqLLNEG0heseQjFlsjEjWh6psDG0Qzz3vB+kYN0=", - "strip_prefix": "rules_proto-5.3.0-21.7", - "remote_patches": {}, - "remote_patch_strip": 0 - } - } - }, - "rules_python@0.22.1": { - "name": "rules_python", - "version": "0.22.1", - "key": "rules_python@0.22.1", - "repoName": "rules_python", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [ - "@bazel_tools//tools/python:autodetecting_toolchain" - ], - "extensionUsages": [ - { - "extensionBzlFile": "@rules_python//python/extensions/private:internal_deps.bzl", - "extensionName": "internal_deps", - "usingModule": "rules_python@0.22.1", - "location": { - "file": "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel", - "line": 14, - "column": 30 - }, - "imports": { - "pypi__build": "pypi__build", - "pypi__click": "pypi__click", - "pypi__colorama": "pypi__colorama", - "pypi__importlib_metadata": "pypi__importlib_metadata", - "pypi__installer": "pypi__installer", - "pypi__more_itertools": "pypi__more_itertools", - "pypi__packaging": "pypi__packaging", - "pypi__pep517": "pypi__pep517", - "pypi__pip": "pypi__pip", - "pypi__pip_tools": "pypi__pip_tools", - "pypi__setuptools": "pypi__setuptools", - "pypi__tomli": "pypi__tomli", - "pypi__wheel": "pypi__wheel", - "pypi__zipp": "pypi__zipp", - "pypi__coverage_cp310_aarch64-apple-darwin": "pypi__coverage_cp310_aarch64-apple-darwin", - "pypi__coverage_cp310_aarch64-unknown-linux-gnu": "pypi__coverage_cp310_aarch64-unknown-linux-gnu", - "pypi__coverage_cp310_x86_64-apple-darwin": "pypi__coverage_cp310_x86_64-apple-darwin", - "pypi__coverage_cp310_x86_64-unknown-linux-gnu": "pypi__coverage_cp310_x86_64-unknown-linux-gnu", - "pypi__coverage_cp311_aarch64-unknown-linux-gnu": "pypi__coverage_cp311_aarch64-unknown-linux-gnu", - "pypi__coverage_cp311_x86_64-apple-darwin": "pypi__coverage_cp311_x86_64-apple-darwin", - "pypi__coverage_cp311_x86_64-unknown-linux-gnu": "pypi__coverage_cp311_x86_64-unknown-linux-gnu", - "pypi__coverage_cp38_aarch64-apple-darwin": "pypi__coverage_cp38_aarch64-apple-darwin", - "pypi__coverage_cp38_aarch64-unknown-linux-gnu": "pypi__coverage_cp38_aarch64-unknown-linux-gnu", - "pypi__coverage_cp38_x86_64-apple-darwin": "pypi__coverage_cp38_x86_64-apple-darwin", - "pypi__coverage_cp38_x86_64-unknown-linux-gnu": "pypi__coverage_cp38_x86_64-unknown-linux-gnu", - "pypi__coverage_cp39_aarch64-apple-darwin": "pypi__coverage_cp39_aarch64-apple-darwin", - "pypi__coverage_cp39_aarch64-unknown-linux-gnu": "pypi__coverage_cp39_aarch64-unknown-linux-gnu", - "pypi__coverage_cp39_x86_64-apple-darwin": "pypi__coverage_cp39_x86_64-apple-darwin", - "pypi__coverage_cp39_x86_64-unknown-linux-gnu": "pypi__coverage_cp39_x86_64-unknown-linux-gnu" - }, - "devImports": [], - "tags": [ - { - "tagName": "install", - "attributeValues": {}, - "devDependency": false, - "location": { - "file": "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel", - "line": 15, - "column": 22 - } - } - ], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - }, - { - "extensionBzlFile": "@rules_python//python/extensions:python.bzl", - "extensionName": "python", - "usingModule": "rules_python@0.22.1", - "location": { - "file": "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel", - "line": 50, - "column": 23 - }, - "imports": { - "pythons_hub": "pythons_hub" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - } - ], - "deps": { - "platforms": "platforms@0.0.7", - "bazel_skylib": "bazel_skylib@1.3.0", - "rules_proto": "rules_proto@5.3.0-21.7", - "com_google_protobuf": "protobuf@21.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/rules_python/releases/download/0.22.1/rules_python-0.22.1.tar.gz" - ], - "integrity": "sha256-pWQP3dS+sD6MH95e1xYMC6a9R359BIZhwwwGk2om/WM=", - "strip_prefix": "rules_python-0.22.1", - "remote_patches": { - "https://bcr.bazel.build/modules/rules_python/0.22.1/patches/module_dot_bazel_version.patch": "sha256-3+VLDH9gYDzNI4eOW7mABC/LKxh1xqF6NhacLbNTucs=" - }, - "remote_patch_strip": 1 - } - } - }, - "buildozer@6.4.0.2": { - "name": "buildozer", - "version": "6.4.0.2", - "key": "buildozer@6.4.0.2", - "repoName": "buildozer", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [ - { - "extensionBzlFile": "@buildozer//:buildozer_binary.bzl", - "extensionName": "buildozer_binary", - "usingModule": "buildozer@6.4.0.2", - "location": { - "file": "https://bcr.bazel.build/modules/buildozer/6.4.0.2/MODULE.bazel", - "line": 7, - "column": 33 - }, - "imports": { - "buildozer_binary": "buildozer_binary" - }, - "devImports": [], - "tags": [ - { - "tagName": "buildozer", - "attributeValues": { - "sha256": { - "darwin-amd64": "d29e347ecd6b5673d72cb1a8de05bf1b06178dd229ff5eb67fad5100c840cc8e", - "darwin-arm64": "9b9e71bdbec5e7223871e913b65d12f6d8fa026684daf991f00e52ed36a6978d", - "linux-amd64": "8dfd6345da4e9042daa738d7fdf34f699c5dfce4632f7207956fceedd8494119", - "linux-arm64": "6559558fded658c8fa7432a9d011f7c4dcbac6b738feae73d2d5c352e5f605fa", - "windows-amd64": "e7f05bf847f7c3689dd28926460ce6e1097ae97380ac8e6ae7147b7b706ba19b" - }, - "version": "6.4.0" - }, - "devDependency": false, - "location": { - "file": "https://bcr.bazel.build/modules/buildozer/6.4.0.2/MODULE.bazel", - "line": 8, - "column": 27 - } - } - ], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - } - ], - "deps": { - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/fmeum/buildozer/releases/download/v6.4.0.2/buildozer-v6.4.0.2.tar.gz" - ], - "integrity": "sha256-k7tFKQMR2AygxpmZfH0yEPnQmF3efFgD9rBPkj+Yz/8=", - "strip_prefix": "buildozer-6.4.0.2", - "remote_patches": { - "https://bcr.bazel.build/modules/buildozer/6.4.0.2/patches/module_dot_bazel_version.patch": "sha256-gKANF2HMilj7bWmuXs4lbBIAAansuWC4IhWGB/CerjU=" - }, - "remote_patch_strip": 1 - } - } - }, - "platforms@0.0.7": { - "name": "platforms", - "version": "0.0.7", - "key": "platforms@0.0.7", - "repoName": "platforms", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "rules_license": "rules_license@0.0.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/platforms/releases/download/0.0.7/platforms-0.0.7.tar.gz" - ], - "integrity": "sha256-OlYcmee9vpFzqmU/1Xn+hJ8djWc5V4CrR3Cx84FDHVE=", - "strip_prefix": "", - "remote_patches": {}, - "remote_patch_strip": 0 - } - } - }, - "protobuf@21.7": { - "name": "protobuf", - "version": "21.7", - "key": "protobuf@21.7", - "repoName": "protobuf", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [ - { - "extensionBzlFile": "@rules_jvm_external//:extensions.bzl", - "extensionName": "maven", - "usingModule": "protobuf@21.7", - "location": { - "file": "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel", - "line": 22, - "column": 22 - }, - "imports": { - "maven": "maven" - }, - "devImports": [], - "tags": [ - { - "tagName": "install", - "attributeValues": { - "name": "maven", - "artifacts": [ - "com.google.code.findbugs:jsr305:3.0.2", - "com.google.code.gson:gson:2.8.9", - "com.google.errorprone:error_prone_annotations:2.3.2", - "com.google.j2objc:j2objc-annotations:1.3", - "com.google.guava:guava:31.1-jre", - "com.google.guava:guava-testlib:31.1-jre", - "com.google.truth:truth:1.1.2", - "junit:junit:4.13.2", - "org.mockito:mockito-core:4.3.1" - ] - }, - "devDependency": false, - "location": { - "file": "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel", - "line": 24, - "column": 14 - } - } - ], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - } - ], - "deps": { - "bazel_skylib": "bazel_skylib@1.3.0", - "rules_python": "rules_python@0.22.1", - "rules_cc": "rules_cc@0.0.9", - "rules_proto": "rules_proto@5.3.0-21.7", - "rules_java": "rules_java@7.4.0", - "rules_pkg": "rules_pkg@0.7.0", - "com_google_abseil": "abseil-cpp@20211102.0", - "zlib": "zlib@1.3", - "upb": "upb@0.0.0-20220923-a547704", - "rules_jvm_external": "rules_jvm_external@4.4.2", - "com_google_googletest": "googletest@1.11.0", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/protocolbuffers/protobuf/releases/download/v21.7/protobuf-all-21.7.zip" - ], - "integrity": "sha256-VJOiH17T/FAuZv7GuUScBqVRztYwAvpIkDxA36jeeko=", - "strip_prefix": "protobuf-21.7", - "remote_patches": { - "https://bcr.bazel.build/modules/protobuf/21.7/patches/add_module_dot_bazel.patch": "sha256-q3V2+eq0v2XF0z8z+V+QF4cynD6JvHI1y3kI/+rzl5s=", - "https://bcr.bazel.build/modules/protobuf/21.7/patches/add_module_dot_bazel_for_examples.patch": "sha256-O7YP6s3lo/1opUiO0jqXYORNHdZ/2q3hjz1QGy8QdIU=", - "https://bcr.bazel.build/modules/protobuf/21.7/patches/relative_repo_names.patch": "sha256-RK9RjW8T5UJNG7flIrnFiNE9vKwWB+8uWWtJqXYT0w4=", - "https://bcr.bazel.build/modules/protobuf/21.7/patches/add_missing_files.patch": "sha256-Hyne4DG2u5bXcWHNxNMirA2QFAe/2Cl8oMm1XJdkQIY=" - }, - "remote_patch_strip": 1 - } - } - }, - "zlib@1.3": { - "name": "zlib", - "version": "1.3", - "key": "zlib@1.3", - "repoName": "zlib", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "platforms": "platforms@0.0.7", - "rules_cc": "rules_cc@0.0.9", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/madler/zlib/releases/download/v1.3/zlib-1.3.tar.gz" - ], - "integrity": "sha256-/wukwpIBPbwnUws6geH5qBPNOd4Byl4Pi/NVcC76WT4=", - "strip_prefix": "zlib-1.3", - "remote_patches": { - "https://bcr.bazel.build/modules/zlib/1.3/patches/add_build_file.patch": "sha256-Ei+FYaaOo7A3jTKunMEodTI0Uw5NXQyZEcboMC8JskY=", - "https://bcr.bazel.build/modules/zlib/1.3/patches/module_dot_bazel.patch": "sha256-fPWLM+2xaF/kuy+kZc1YTfW6hNjrkG400Ho7gckuyJk=" - }, - "remote_patch_strip": 0 - } - } - }, - "apple_support@1.5.0": { - "name": "apple_support", - "version": "1.5.0", - "key": "apple_support@1.5.0", - "repoName": "build_bazel_apple_support", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [ - "@local_config_apple_cc_toolchains//:all" - ], - "extensionUsages": [ - { - "extensionBzlFile": "@build_bazel_apple_support//crosstool:setup.bzl", - "extensionName": "apple_cc_configure_extension", - "usingModule": "apple_support@1.5.0", - "location": { - "file": "https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel", - "line": 17, - "column": 35 - }, - "imports": { - "local_config_apple_cc": "local_config_apple_cc", - "local_config_apple_cc_toolchains": "local_config_apple_cc_toolchains" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - } - ], - "deps": { - "bazel_skylib": "bazel_skylib@1.3.0", - "platforms": "platforms@0.0.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/apple_support/releases/download/1.5.0/apple_support.1.5.0.tar.gz" - ], - "integrity": "sha256-miM41vja0yRPgj8txghKA+TQ+7J8qJLclw5okNW0gYQ=", - "strip_prefix": "", - "remote_patches": {}, - "remote_patch_strip": 0 - } - } - }, - "bazel_skylib@1.3.0": { - "name": "bazel_skylib", - "version": "1.3.0", - "key": "bazel_skylib@1.3.0", - "repoName": "bazel_skylib", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [ - "//toolchains/unittest:cmd_toolchain", - "//toolchains/unittest:bash_toolchain" - ], - "extensionUsages": [], - "deps": { - "platforms": "platforms@0.0.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz" - ], - "integrity": "sha256-dNVE2W9KW7Yw1GXKi7z+Ix41lOWq5X4e2/F6brPKJQY=", - "strip_prefix": "", - "remote_patches": {}, - "remote_patch_strip": 0 - } - } - }, - "rules_pkg@0.7.0": { - "name": "rules_pkg", - "version": "0.7.0", - "key": "rules_pkg@0.7.0", - "repoName": "rules_pkg", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "rules_python": "rules_python@0.22.1", - "bazel_skylib": "bazel_skylib@1.3.0", - "rules_license": "rules_license@0.0.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/rules_pkg/releases/download/0.7.0/rules_pkg-0.7.0.tar.gz" - ], - "integrity": "sha256-iimOgydi7aGDBZfWT+fbWBeKqEzVkm121bdE1lWJQcI=", - "strip_prefix": "", - "remote_patches": { - "https://bcr.bazel.build/modules/rules_pkg/0.7.0/patches/module_dot_bazel.patch": "sha256-4OaEPZwYF6iC71ZTDg6MJ7LLqX7ZA0/kK4mT+4xKqiE=" - }, - "remote_patch_strip": 0 - } - } - }, - "abseil-cpp@20211102.0": { - "name": "abseil-cpp", - "version": "20211102.0", - "key": "abseil-cpp@20211102.0", - "repoName": "abseil-cpp", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "rules_cc": "rules_cc@0.0.9", - "platforms": "platforms@0.0.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/abseil/abseil-cpp/archive/refs/tags/20211102.0.tar.gz" - ], - "integrity": "sha256-3PcbnLqNwMqZQMSzFqDHlr6Pq0KwcLtrfKtitI8OZsQ=", - "strip_prefix": "abseil-cpp-20211102.0", - "remote_patches": { - "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/patches/module_dot_bazel.patch": "sha256-4izqopgGCey4jVZzl/w3M2GVPNohjh2B5TmbThZNvPY=" - }, - "remote_patch_strip": 0 - } - } - }, - "upb@0.0.0-20220923-a547704": { - "name": "upb", - "version": "0.0.0-20220923-a547704", - "key": "upb@0.0.0-20220923-a547704", - "repoName": "upb", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "bazel_skylib": "bazel_skylib@1.3.0", - "rules_proto": "rules_proto@5.3.0-21.7", - "com_google_protobuf": "protobuf@21.7", - "com_google_absl": "abseil-cpp@20211102.0", - "platforms": "platforms@0.0.7", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/protocolbuffers/upb/archive/a5477045acaa34586420942098f5fecd3570f577.tar.gz" - ], - "integrity": "sha256-z39x6v+QskwaKLSWRan/A6mmwecTQpHOcJActj5zZLU=", - "strip_prefix": "upb-a5477045acaa34586420942098f5fecd3570f577", - "remote_patches": { - "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/patches/module_dot_bazel.patch": "sha256-wH4mNS6ZYy+8uC0HoAft/c7SDsq2Kxf+J8dUakXhaB0=" - }, - "remote_patch_strip": 0 - } - } - }, - "rules_jvm_external@4.4.2": { - "name": "rules_jvm_external", - "version": "4.4.2", - "key": "rules_jvm_external@4.4.2", - "repoName": "rules_jvm_external", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [ - { - "extensionBzlFile": "@rules_jvm_external//:non-module-deps.bzl", - "extensionName": "non_module_deps", - "usingModule": "rules_jvm_external@4.4.2", - "location": { - "file": "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel", - "line": 9, - "column": 32 - }, - "imports": { - "io_bazel_rules_kotlin": "io_bazel_rules_kotlin" - }, - "devImports": [], - "tags": [], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - }, - { - "extensionBzlFile": "@rules_jvm_external//:extensions.bzl", - "extensionName": "maven", - "usingModule": "rules_jvm_external@4.4.2", - "location": { - "file": "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel", - "line": 16, - "column": 22 - }, - "imports": { - "rules_jvm_external_deps": "rules_jvm_external_deps" - }, - "devImports": [], - "tags": [ - { - "tagName": "install", - "attributeValues": { - "name": "rules_jvm_external_deps", - "artifacts": [ - "com.google.cloud:google-cloud-core:1.93.10", - "com.google.cloud:google-cloud-storage:1.113.4", - "com.google.code.gson:gson:2.9.0", - "org.apache.maven:maven-artifact:3.8.6", - "software.amazon.awssdk:s3:2.17.183" - ], - "lock_file": "@rules_jvm_external//:rules_jvm_external_deps_install.json" - }, - "devDependency": false, - "location": { - "file": "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel", - "line": 18, - "column": 14 - } - } - ], - "hasDevUseExtension": false, - "hasNonDevUseExtension": true - } - ], - "deps": { - "bazel_skylib": "bazel_skylib@1.3.0", - "io_bazel_stardoc": "stardoc@0.5.1", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/rules_jvm_external/archive/refs/tags/4.4.2.zip" - ], - "integrity": "sha256-c1YC9QgT6y6pPKP15DsZWb2AshO4NqB6YqKddXZwt3s=", - "strip_prefix": "rules_jvm_external-4.4.2", - "remote_patches": {}, - "remote_patch_strip": 0 - } - } - }, - "googletest@1.11.0": { - "name": "googletest", - "version": "1.11.0", - "key": "googletest@1.11.0", - "repoName": "googletest", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "com_google_absl": "abseil-cpp@20211102.0", - "platforms": "platforms@0.0.7", - "rules_cc": "rules_cc@0.0.9", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/google/googletest/archive/refs/tags/release-1.11.0.tar.gz" - ], - "integrity": "sha256-tIcL8SH/d5W6INILzdhie44Ijy0dqymaAxwQNO3ck9U=", - "strip_prefix": "googletest-release-1.11.0", - "remote_patches": { - "https://bcr.bazel.build/modules/googletest/1.11.0/patches/module_dot_bazel.patch": "sha256-HuahEdI/n8KCI071sN3CEziX+7qP/Ec77IWayYunLP0=" - }, - "remote_patch_strip": 0 - } - } - }, - "stardoc@0.5.1": { - "name": "stardoc", - "version": "0.5.1", - "key": "stardoc@0.5.1", - "repoName": "stardoc", - "executionPlatformsToRegister": [], - "toolchainsToRegister": [], - "extensionUsages": [], - "deps": { - "bazel_skylib": "bazel_skylib@1.3.0", - "rules_java": "rules_java@7.4.0", - "bazel_tools": "bazel_tools@_", - "local_config_platform": "local_config_platform@_" - }, - "repoSpec": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "urls": [ - "https://github.com/bazelbuild/stardoc/releases/download/0.5.1/stardoc-0.5.1.tar.gz" - ], - "integrity": "sha256-qoFNrgrEALurLoiB+ZFcb0fElmS/CHxAmhX5BDjSwj4=", - "strip_prefix": "", - "remote_patches": { - "https://bcr.bazel.build/modules/stardoc/0.5.1/patches/module_dot_bazel.patch": "sha256-UAULCuTpJE7SG0YrR9XLjMfxMRmbP+za3uW9ONZ5rjI=" - }, - "remote_patch_strip": 0 - } - } - } + "lockFileVersion": 11, + "registryFileHashes": { + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/source.json": "7e3a9adf473e9af076ae485ed649d5641ad50ec5c11718103f34de03170d94ad", + "https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef", + "https://bcr.bazel.build/modules/apple_support/1.5.0/source.json": "eb98a7627c0bc486b57f598ad8da50f6625d974c8f723e9ea71bd39f709c9862", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/source.json": "c9320aa53cd1c441d24bd6b716da087ad7e4ff0d9742a9884587596edfe53015", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/source.json": "082ed5f9837901fada8c68c2f3ddc958bb22b6d654f71dd73f3df30d45d4b749", + "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", + "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.11.0/source.json": "c73d9ef4268c91bd0c1cd88f1f9dfa08e814b1dbe89b5f594a9f08ba0244d206", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/platforms/0.0.9/source.json": "cd74d854bf16a9e002fb2ca7b1a421f4403cda29f824a765acd3a8c56f8d43e6", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/21.7/source.json": "bbe500720421e582ff2d18b0802464205138c06056f443184de39fbb8187b09b", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/source.json": "1f1ba6fea244b616de4a554a0f4983c91a9301640c8fe0dd1d410254115c8430", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1", + "https://bcr.bazel.build/modules/rules_java/7.6.5/source.json": "a805b889531d1690e3c72a7a7e47a870d00323186a9904b36af83aa3d053ee8d", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/source.json": "a075731e1b46bc8425098512d038d416e966ab19684a10a34f4741295642fc35", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/0.0.7/source.json": "355cc5737a0f294e560d52b1b7a6492d4fff2caf0bef1a315df5a298fca2d34a", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/source.json": "c2557066e0c0342223ba592510ad3d812d4963b9024831f7f66fd0584dd8c66c", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/source.json": "d57902c052424dfda0e71646cb12668d39c4620ee0544294d9d941e7d12bc3a9", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7", + "https://bcr.bazel.build/modules/rules_python/0.22.1/source.json": "57226905e783bae7c37c2dd662be078728e48fa28ee4324a7eabcafb5a43d014", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.1/source.json": "a96f95e02123320aa015b956f29c00cb818fa891ef823d55148e1a362caacf29", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/source.json": "f1ef7d3f9e0e26d4b23d1c39b5f5de71f584dd7d1b4ef83d9bbba6ec7a6a6459", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d" }, + "selectedYankedVersions": {}, "moduleExtensions": { "@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": { "general": { - "bzlTransitiveDigest": "pMLFCYaRPkgXPQ8vtuNkMfiHfPmRBy6QJfnid4sWfv0=", + "bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=", + "usagesDigest": "+hz7IHWN6A1oVJJWNDB6yZRG+RYhF76wAYItpAeIUIg=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { - "local_config_apple_cc": { - "bzlFile": "@@apple_support~//crosstool:setup.bzl", - "ruleClassName": "_apple_cc_autoconf", - "attributes": {} - }, "local_config_apple_cc_toolchains": { "bzlFile": "@@apple_support~//crosstool:setup.bzl", "ruleClassName": "_apple_cc_autoconf_toolchains", "attributes": {} - } - }, - "recordedRepoMappingEntries": [ - [ - "apple_support~", - "bazel_tools", - "bazel_tools" - ] - ] - } - }, - "@@bazel_tools//tools/cpp:cc_configure.bzl%cc_configure_extension": { - "general": { - "bzlTransitiveDigest": "PHpT2yqMGms2U4L3E/aZ+WcQalmZWm+ILdP3yiLsDhA=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "local_config_cc": { - "bzlFile": "@@bazel_tools//tools/cpp:cc_configure.bzl", - "ruleClassName": "cc_autoconf", - "attributes": {} }, - "local_config_cc_toolchains": { - "bzlFile": "@@bazel_tools//tools/cpp:cc_configure.bzl", - "ruleClassName": "cc_autoconf_toolchains", + "local_config_apple_cc": { + "bzlFile": "@@apple_support~//crosstool:setup.bzl", + "ruleClassName": "_apple_cc_autoconf", "attributes": {} } }, "recordedRepoMappingEntries": [ [ - "bazel_tools", + "apple_support~", "bazel_tools", "bazel_tools" ] ] } }, - "@@bazel_tools//tools/osx:xcode_configure.bzl%xcode_configure_extension": { + "@@platforms//host:extension.bzl%host_platform": { "general": { - "bzlTransitiveDigest": "Qh2bWTU6QW6wkrd87qrU4YeY+SG37Nvw3A0PR4Y0L2Y=", + "bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=", + "usagesDigest": "pCYpDQmqMbmiiPI1p2Kd3VLm5T48rRAht5WdW0X2GlA=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { - "local_config_xcode": { - "bzlFile": "@@bazel_tools//tools/osx:xcode_configure.bzl", - "ruleClassName": "xcode_autoconf", - "attributes": { - "xcode_locator": "@bazel_tools//tools/osx:xcode_locator.m", - "remote_xcode": "" - } - } - }, - "recordedRepoMappingEntries": [] - } - }, - "@@bazel_tools//tools/sh:sh_configure.bzl%sh_configure_extension": { - "general": { - "bzlTransitiveDigest": "hp4NgmNjEg5+xgvzfh6L83bt9/aiiWETuNpwNuF1MSU=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "local_config_sh": { - "bzlFile": "@@bazel_tools//tools/sh:sh_configure.bzl", - "ruleClassName": "sh_config", + "host_platform": { + "bzlFile": "@@platforms//host:extension.bzl", + "ruleClassName": "host_platform_repo", "attributes": {} } }, "recordedRepoMappingEntries": [] } - }, - "@@bazel_tools//tools/test:extensions.bzl%remote_coverage_tools_extension": { - "general": { - "bzlTransitiveDigest": "l5mcjH2gWmbmIycx97bzI2stD0Q0M5gpDc0aLOHKIm8=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "remote_coverage_tools": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "sha256": "7006375f6756819b7013ca875eab70a541cf7d89142d9c511ed78ea4fefa38af", - "urls": [ - "https://mirror.bazel.build/bazel_coverage_output_generator/releases/coverage_output_generator-v2.6.zip" - ] - } - } - }, - "recordedRepoMappingEntries": [] - } - }, - "@@rules_java~//java:extensions.bzl%toolchains": { - "general": { - "bzlTransitiveDigest": "tJHbmWnq7m+9eUBnUdv7jZziQ26FmcGL9C5/hU3Q9UQ=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "remotejdk21_linux_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_21\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"21\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk21_linux//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk21_linux//:jdk\",\n)\n" - } - }, - "remotejdk17_linux_s390x_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_17\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"17\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:s390x\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk17_linux_s390x//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:s390x\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk17_linux_s390x//:jdk\",\n)\n" - } - }, - "remotejdk17_macos_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_17\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"17\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk17_macos//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk17_macos//:jdk\",\n)\n" - } - }, - "remotejdk21_macos_aarch64_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_21\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"21\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk21_macos_aarch64//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk21_macos_aarch64//:jdk\",\n)\n" - } - }, - "remotejdk17_linux_aarch64_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_17\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"17\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk17_linux_aarch64//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk17_linux_aarch64//:jdk\",\n)\n" - } - }, - "remotejdk21_macos_aarch64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 21,\n)\n", - "sha256": "e8260516de8b60661422a725f1df2c36ef888f6fb35393566b00e7325db3d04e", - "strip_prefix": "zulu21.32.17-ca-jdk21.0.2-macosx_aarch64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-macosx_aarch64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-macosx_aarch64.tar.gz" - ] - } - }, - "remotejdk17_linux_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_17\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"17\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk17_linux//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk17_linux//:jdk\",\n)\n" - } - }, - "remotejdk17_macos_aarch64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 17,\n)\n", - "sha256": "314b04568ec0ae9b36ba03c9cbd42adc9e1265f74678923b19297d66eb84dcca", - "strip_prefix": "zulu17.44.53-ca-jdk17.0.8.1-macosx_aarch64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-macosx_aarch64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-macosx_aarch64.tar.gz" - ] - } - }, - "remote_java_tools_windows": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "sha256": "fe2f88169696d6c6fc6e90ba61bb46be7d0ae3693cbafdf336041bf56679e8d1", - "urls": [ - "https://mirror.bazel.build/bazel_java_tools/releases/java/v13.4/java_tools_windows-v13.4.zip", - "https://github.com/bazelbuild/java_tools/releases/download/java_v13.4/java_tools_windows-v13.4.zip" - ] - } - }, - "remotejdk11_win": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 11,\n)\n", - "sha256": "43408193ce2fa0862819495b5ae8541085b95660153f2adcf91a52d3a1710e83", - "strip_prefix": "zulu11.66.15-ca-jdk11.0.20-win_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-win_x64.zip", - "https://cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-win_x64.zip" - ] - } - }, - "remotejdk11_win_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_11\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"11\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk11_win//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk11_win//:jdk\",\n)\n" - } - }, - "remotejdk11_linux_aarch64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 11,\n)\n", - "sha256": "54174439f2b3fddd11f1048c397fe7bb45d4c9d66d452d6889b013d04d21c4de", - "strip_prefix": "zulu11.66.15-ca-jdk11.0.20-linux_aarch64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-linux_aarch64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-linux_aarch64.tar.gz" - ] - } - }, - "remotejdk17_linux": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 17,\n)\n", - "sha256": "b9482f2304a1a68a614dfacddcf29569a72f0fac32e6c74f83dc1b9a157b8340", - "strip_prefix": "zulu17.44.53-ca-jdk17.0.8.1-linux_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-linux_x64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-linux_x64.tar.gz" - ] - } - }, - "remotejdk11_linux_s390x_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_11\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"11\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:s390x\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk11_linux_s390x//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:s390x\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk11_linux_s390x//:jdk\",\n)\n" - } - }, - "remotejdk11_linux_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_11\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"11\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk11_linux//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk11_linux//:jdk\",\n)\n" - } - }, - "remotejdk11_macos": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 11,\n)\n", - "sha256": "bcaab11cfe586fae7583c6d9d311c64384354fb2638eb9a012eca4c3f1a1d9fd", - "strip_prefix": "zulu11.66.15-ca-jdk11.0.20-macosx_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-macosx_x64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-macosx_x64.tar.gz" - ] - } - }, - "remotejdk11_win_arm64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 11,\n)\n", - "sha256": "b8a28e6e767d90acf793ea6f5bed0bb595ba0ba5ebdf8b99f395266161e53ec2", - "strip_prefix": "jdk-11.0.13+8", - "urls": [ - "https://mirror.bazel.build/aka.ms/download-jdk/microsoft-jdk-11.0.13.8.1-windows-aarch64.zip" - ] - } - }, - "remotejdk17_macos": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 17,\n)\n", - "sha256": "640453e8afe8ffe0fb4dceb4535fb50db9c283c64665eebb0ba68b19e65f4b1f", - "strip_prefix": "zulu17.44.53-ca-jdk17.0.8.1-macosx_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-macosx_x64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-macosx_x64.tar.gz" - ] - } - }, - "remotejdk21_macos": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 21,\n)\n", - "sha256": "3ad8fe288eb57d975c2786ae453a036aa46e47ab2ac3d81538ebae2a54d3c025", - "strip_prefix": "zulu21.32.17-ca-jdk21.0.2-macosx_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-macosx_x64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-macosx_x64.tar.gz" - ] - } - }, - "remotejdk21_macos_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_21\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"21\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk21_macos//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk21_macos//:jdk\",\n)\n" - } - }, - "remotejdk17_macos_aarch64_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_17\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"17\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk17_macos_aarch64//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk17_macos_aarch64//:jdk\",\n)\n" - } - }, - "remotejdk17_win": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 17,\n)\n", - "sha256": "192f2afca57701de6ec496234f7e45d971bf623ff66b8ee4a5c81582054e5637", - "strip_prefix": "zulu17.44.53-ca-jdk17.0.8.1-win_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-win_x64.zip", - "https://cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-win_x64.zip" - ] - } - }, - "remotejdk11_macos_aarch64_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_11\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"11\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk11_macos_aarch64//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk11_macos_aarch64//:jdk\",\n)\n" - } - }, - "remotejdk11_linux_ppc64le_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_11\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"11\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:ppc\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk11_linux_ppc64le//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:ppc\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk11_linux_ppc64le//:jdk\",\n)\n" - } - }, - "remotejdk21_linux": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 21,\n)\n", - "sha256": "5ad730fbee6bb49bfff10bf39e84392e728d89103d3474a7e5def0fd134b300a", - "strip_prefix": "zulu21.32.17-ca-jdk21.0.2-linux_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-linux_x64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-linux_x64.tar.gz" - ] - } - }, - "remote_java_tools_linux": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "sha256": "ba10f09a138cf185d04cbc807d67a3da42ab13d618c5d1ce20d776e199c33a39", - "urls": [ - "https://mirror.bazel.build/bazel_java_tools/releases/java/v13.4/java_tools_linux-v13.4.zip", - "https://github.com/bazelbuild/java_tools/releases/download/java_v13.4/java_tools_linux-v13.4.zip" - ] - } - }, - "remotejdk21_win": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 21,\n)\n", - "sha256": "f7cc15ca17295e69c907402dfe8db240db446e75d3b150da7bf67243cded93de", - "strip_prefix": "zulu21.32.17-ca-jdk21.0.2-win_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-win_x64.zip", - "https://cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-win_x64.zip" - ] - } - }, - "remotejdk21_linux_aarch64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 21,\n)\n", - "sha256": "ce7df1af5d44a9f455617c4b8891443fbe3e4b269c777d8b82ed66f77167cfe0", - "strip_prefix": "zulu21.32.17-ca-jdk21.0.2-linux_aarch64", - "urls": [ - "https://cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-linux_aarch64.tar.gz", - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu21.32.17-ca-jdk21.0.2-linux_aarch64.tar.gz" - ] - } - }, - "remotejdk11_linux_aarch64_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_11\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"11\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk11_linux_aarch64//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk11_linux_aarch64//:jdk\",\n)\n" - } - }, - "remotejdk11_linux_s390x": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 11,\n)\n", - "sha256": "a58fc0361966af0a5d5a31a2d8a208e3c9bb0f54f345596fd80b99ea9a39788b", - "strip_prefix": "jdk-11.0.15+10", - "urls": [ - "https://mirror.bazel.build/github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15+10/OpenJDK11U-jdk_s390x_linux_hotspot_11.0.15_10.tar.gz", - "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15+10/OpenJDK11U-jdk_s390x_linux_hotspot_11.0.15_10.tar.gz" - ] - } - }, - "remotejdk17_linux_aarch64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 17,\n)\n", - "sha256": "6531cef61e416d5a7b691555c8cf2bdff689201b8a001ff45ab6740062b44313", - "strip_prefix": "zulu17.44.53-ca-jdk17.0.8.1-linux_aarch64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-linux_aarch64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-linux_aarch64.tar.gz" - ] - } - }, - "remotejdk17_win_arm64_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_17\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"17\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:arm64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk17_win_arm64//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:arm64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk17_win_arm64//:jdk\",\n)\n" - } - }, - "remotejdk11_linux": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 11,\n)\n", - "sha256": "a34b404f87a08a61148b38e1416d837189e1df7a040d949e743633daf4695a3c", - "strip_prefix": "zulu11.66.15-ca-jdk11.0.20-linux_x64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-linux_x64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-linux_x64.tar.gz" - ] - } - }, - "remotejdk11_macos_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_11\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"11\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk11_macos//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:macos\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk11_macos//:jdk\",\n)\n" - } - }, - "remotejdk17_linux_ppc64le_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_17\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"17\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:ppc\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk17_linux_ppc64le//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:ppc\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk17_linux_ppc64le//:jdk\",\n)\n" - } - }, - "remotejdk17_win_arm64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 17,\n)\n", - "sha256": "6802c99eae0d788e21f52d03cab2e2b3bf42bc334ca03cbf19f71eb70ee19f85", - "strip_prefix": "zulu17.44.53-ca-jdk17.0.8.1-win_aarch64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-win_aarch64.zip", - "https://cdn.azul.com/zulu/bin/zulu17.44.53-ca-jdk17.0.8.1-win_aarch64.zip" - ] - } - }, - "remote_java_tools_darwin_arm64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "sha256": "076a7e198ad077f8c7d997986ef5102427fae6bbfce7a7852d2e080ed8767528", - "urls": [ - "https://mirror.bazel.build/bazel_java_tools/releases/java/v13.4/java_tools_darwin_arm64-v13.4.zip", - "https://github.com/bazelbuild/java_tools/releases/download/java_v13.4/java_tools_darwin_arm64-v13.4.zip" - ] - } - }, - "remotejdk17_linux_ppc64le": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 17,\n)\n", - "sha256": "00a4c07603d0218cd678461b5b3b7e25b3253102da4022d31fc35907f21a2efd", - "strip_prefix": "jdk-17.0.8.1+1", - "urls": [ - "https://mirror.bazel.build/github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.8.1%2B1/OpenJDK17U-jdk_ppc64le_linux_hotspot_17.0.8.1_1.tar.gz", - "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.8.1%2B1/OpenJDK17U-jdk_ppc64le_linux_hotspot_17.0.8.1_1.tar.gz" - ] - } - }, - "remotejdk21_linux_aarch64_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_21\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"21\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk21_linux_aarch64//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:linux\", \"@platforms//cpu:aarch64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk21_linux_aarch64//:jdk\",\n)\n" - } - }, - "remotejdk11_win_arm64_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_11\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"11\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:arm64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk11_win_arm64//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:arm64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk11_win_arm64//:jdk\",\n)\n" - } - }, - "local_jdk": { - "bzlFile": "@@rules_java~//toolchains:local_java_repository.bzl", - "ruleClassName": "_local_java_repository_rule", - "attributes": { - "java_home": "", - "version": "", - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = {RUNTIME_VERSION},\n)\n" - } - }, - "remote_java_tools_darwin_x86_64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "sha256": "4523aec4d09c587091a2dae6f5c9bc6922c220f3b6030e5aba9c8f015913cc65", - "urls": [ - "https://mirror.bazel.build/bazel_java_tools/releases/java/v13.4/java_tools_darwin_x86_64-v13.4.zip", - "https://github.com/bazelbuild/java_tools/releases/download/java_v13.4/java_tools_darwin_x86_64-v13.4.zip" - ] - } - }, - "remote_java_tools": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "sha256": "e025fd260ac39b47c111f5212d64ec0d00d85dec16e49368aae82fc626a940cf", - "urls": [ - "https://mirror.bazel.build/bazel_java_tools/releases/java/v13.4/java_tools-v13.4.zip", - "https://github.com/bazelbuild/java_tools/releases/download/java_v13.4/java_tools-v13.4.zip" - ] - } - }, - "remotejdk17_linux_s390x": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 17,\n)\n", - "sha256": "ffacba69c6843d7ca70d572489d6cc7ab7ae52c60f0852cedf4cf0d248b6fc37", - "strip_prefix": "jdk-17.0.8.1+1", - "urls": [ - "https://mirror.bazel.build/github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.8.1%2B1/OpenJDK17U-jdk_s390x_linux_hotspot_17.0.8.1_1.tar.gz", - "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.8.1%2B1/OpenJDK17U-jdk_s390x_linux_hotspot_17.0.8.1_1.tar.gz" - ] - } - }, - "remotejdk17_win_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_17\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"17\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk17_win//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk17_win//:jdk\",\n)\n" - } - }, - "remotejdk11_linux_ppc64le": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 11,\n)\n", - "sha256": "a8fba686f6eb8ae1d1a9566821dbd5a85a1108b96ad857fdbac5c1e4649fc56f", - "strip_prefix": "jdk-11.0.15+10", - "urls": [ - "https://mirror.bazel.build/github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15+10/OpenJDK11U-jdk_ppc64le_linux_hotspot_11.0.15_10.tar.gz", - "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15+10/OpenJDK11U-jdk_ppc64le_linux_hotspot_11.0.15_10.tar.gz" - ] - } - }, - "remotejdk11_macos_aarch64": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file_content": "load(\"@rules_java//java:defs.bzl\", \"java_runtime\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\"WORKSPACE\", \"BUILD.bazel\"])\n\nfilegroup(\n name = \"jre\",\n srcs = glob(\n [\n \"jre/bin/**\",\n \"jre/lib/**\",\n ],\n allow_empty = True,\n # In some configurations, Java browser plugin is considered harmful and\n # common antivirus software blocks access to npjp2.dll interfering with Bazel,\n # so do not include it in JRE on Windows.\n exclude = [\"jre/bin/plugin2/**\"],\n ),\n)\n\nfilegroup(\n name = \"jdk-bin\",\n srcs = glob(\n [\"bin/**\"],\n # The JDK on Windows sometimes contains a directory called\n # \"%systemroot%\", which is not a valid label.\n exclude = [\"**/*%*/**\"],\n ),\n)\n\n# This folder holds security policies.\nfilegroup(\n name = \"jdk-conf\",\n srcs = glob(\n [\"conf/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-include\",\n srcs = glob(\n [\"include/**\"],\n allow_empty = True,\n ),\n)\n\nfilegroup(\n name = \"jdk-lib\",\n srcs = glob(\n [\"lib/**\", \"release\"],\n allow_empty = True,\n exclude = [\n \"lib/missioncontrol/**\",\n \"lib/visualvm/**\",\n ],\n ),\n)\n\njava_runtime(\n name = \"jdk\",\n srcs = [\n \":jdk-bin\",\n \":jdk-conf\",\n \":jdk-include\",\n \":jdk-lib\",\n \":jre\",\n ],\n # Provide the 'java` binary explicitly so that the correct path is used by\n # Bazel even when the host platform differs from the execution platform.\n # Exactly one of the two globs will be empty depending on the host platform.\n # When --incompatible_disallow_empty_glob is enabled, each individual empty\n # glob will fail without allow_empty = True, even if the overall result is\n # non-empty.\n java = glob([\"bin/java.exe\", \"bin/java\"], allow_empty = True)[0],\n version = 11,\n)\n", - "sha256": "7632bc29f8a4b7d492b93f3bc75a7b61630894db85d136456035ab2a24d38885", - "strip_prefix": "zulu11.66.15-ca-jdk11.0.20-macosx_aarch64", - "urls": [ - "https://mirror.bazel.build/cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-macosx_aarch64.tar.gz", - "https://cdn.azul.com/zulu/bin/zulu11.66.15-ca-jdk11.0.20-macosx_aarch64.tar.gz" - ] - } - }, - "remotejdk21_win_toolchain_config_repo": { - "bzlFile": "@@rules_java~//toolchains:remote_java_repository.bzl", - "ruleClassName": "_toolchain_config", - "attributes": { - "build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_21\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"21\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk21_win//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk21_win//:jdk\",\n)\n" - } - } - }, - "recordedRepoMappingEntries": [ - [ - "rules_java~", - "bazel_tools", - "bazel_tools" - ], - [ - "rules_java~", - "remote_java_tools", - "rules_java~~toolchains~remote_java_tools" - ] - ] - } } } } diff --git a/WORKSPACE b/WORKSPACE index 20d40d8b9f28..ef4561bc3d29 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -16,6 +16,34 @@ load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") rules_pkg_dependencies() +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "toolchains_protoc", + sha256 = "abb1540f8a9e045422730670ebb2f25b41fa56ca5a7cf795175a110a0a68f4ad", + strip_prefix = "toolchains_protoc-0.3.6", + url = "https://github.com/aspect-build/toolchains_protoc/releases/download/v0.3.6/toolchains_protoc-v0.3.6.tar.gz", +) + +load("@toolchains_protoc//protoc:repositories.bzl", "rules_protoc_dependencies") + +rules_protoc_dependencies() + +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies") + +rules_proto_dependencies() + +load("@bazel_features//:deps.bzl", "bazel_features_deps") + +bazel_features_deps() + +load("@toolchains_protoc//protoc:toolchain.bzl", "protoc_toolchains") + +protoc_toolchains( + name = "protoc_toolchains", + version = "v25.3", +) + HERMETIC_CC_TOOLCHAIN_VERSION = "v3.0.1" http_archive( @@ -101,9 +129,9 @@ http_archive( http_archive( name = "aspect_bazel_lib", - sha256 = "f5ea76682b209cc0bd90d0f5a3b26d2f7a6a2885f0c5f615e72913f4805dbb0d", - strip_prefix = "bazel-lib-2.5.0", - url = "https://github.com/aspect-build/bazel-lib/releases/download/v2.5.0/bazel-lib-v2.5.0.tar.gz", + sha256 = "a272d79bb0ac6b6965aa199b1f84333413452e87f043b53eca7f347a23a478e8", + strip_prefix = "bazel-lib-2.9.3", + url = "https://github.com/bazel-contrib/bazel-lib/releases/download/v2.9.3/bazel-lib-v2.9.3.tar.gz", ) load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "aspect_bazel_lib_register_toolchains") @@ -137,10 +165,10 @@ http_archive( # Expose internals of go_test for custom build transitions. "//third_party:io_bazel_rules_go_test.patch", ], - sha256 = "80a98277ad1311dacd837f9b16db62887702e9f1d1c4c9f796d0121a46c8e184", + sha256 = "b2038e2de2cace18f032249cb4bb0048abf583a36369fa98f687af1b3f880b26", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.46.0/rules_go-v0.46.0.zip", - "https://github.com/bazelbuild/rules_go/releases/download/v0.46.0/rules_go-v0.46.0.zip", + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.48.1/rules_go-v0.48.1.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.48.1/rules_go-v0.48.1.zip", ], ) @@ -165,7 +193,7 @@ load("@rules_oci//oci:pull.bzl", "oci_pull") oci_pull( name = "linux_debian11_multiarch_base", # Debian bullseye digest = "sha256:b82f113425c5b5c714151aaacd8039bc141821cdcd3c65202d42bdf9c43ae60b", # 2023-12-12 - image = "gcr.io/distroless/cc-debian11", + image = "gcr.io/prysmaticlabs/distroless/cc-debian11", platforms = [ "linux/amd64", "linux/arm64/v8", @@ -182,7 +210,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe go_rules_dependencies() go_register_toolchains( - go_version = "1.22.4", + go_version = "1.23.5", nogo = "@//:nogo", ) @@ -227,7 +255,7 @@ filegroup( url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz", ) -consensus_spec_version = "v1.5.0-alpha.3" +consensus_spec_version = "v1.5.0-beta.2" bls_test_version = "v0.1.1" @@ -243,7 +271,7 @@ filegroup( visibility = ["//visibility:public"], ) """, - integrity = "sha256-+byv+GUOQytex5GgtjBGVoNDseJZbiBdAjEtlgCbjEo=", + integrity = "sha256-X/bMxbKg1clo2aFEjBoeuFq/U+BF1eQopgRP/7nI3Qg=", url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version, ) @@ -259,7 +287,7 @@ filegroup( visibility = ["//visibility:public"], ) """, - integrity = "sha256-JJUy/jT1h3kGQkinTuzL7gMOA1+qgmPgJXVrYuH63Cg=", + integrity = "sha256-WSxdri5OJGuNApW+odKle5UzToDyEOx+F3lMiqamJAg=", url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version, ) @@ -275,7 +303,7 @@ filegroup( visibility = ["//visibility:public"], ) """, - integrity = "sha256-T2VM4Qd0SwgGnTjWxjOX297DqEsovO9Ueij1UEJy48Y=", + integrity = "sha256-LYE8l3y/zSt4YVrehrJ3ralqtgeYNildiIp+HR6+xAI=", url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version, ) @@ -290,7 +318,7 @@ filegroup( visibility = ["//visibility:public"], ) """, - integrity = "sha256-OP9BCBcQ7i+93bwj7ktY8pZ5uWsGjgTe4XTp7BDhX+I=", + integrity = "sha256-jvZQ90qcJMTOqMsPO7sgeEVQmewZTHcz7LVDkNqwTFQ=", strip_prefix = "consensus-specs-" + consensus_spec_version[1:], url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version, ) @@ -342,6 +370,22 @@ filegroup( url = "https://github.com/eth-clients/holesky/archive/874c199423ccd180607320c38cbaca05d9a1573a.tar.gz", # 2024-06-18 ) +http_archive( + name = "sepolia_testnet", + build_file_content = """ +filegroup( + name = "configs", + srcs = [ + "metadata/config.yaml", + ], + visibility = ["//visibility:public"], +) +""", + integrity = "sha256-cY/UgpCcYEhQf7JefD65FI8tn/A+rAvKhcm2/qiVdqY=", + strip_prefix = "sepolia-f2c219a93c4491cee3d90c18f2f8e82aed850eab", + url = "https://github.com/eth-clients/sepolia/archive/f2c219a93c4491cee3d90c18f2f8e82aed850eab.tar.gz", # 2024-09-19 +) + http_archive( name = "com_google_protobuf", sha256 = "9bd87b8280ef720d3240514f884e56a712f2218f0d693b48050c836028940a42", diff --git a/api/client/beacon/BUILD.bazel b/api/client/beacon/BUILD.bazel index 11e8ecb2e73e..5990c8be3374 100644 --- a/api/client/beacon/BUILD.bazel +++ b/api/client/beacon/BUILD.bazel @@ -3,7 +3,6 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "checkpoint.go", "client.go", "doc.go", "health.go", @@ -16,28 +15,19 @@ go_library( "//api/client/beacon/iface:go_default_library", "//api/server:go_default_library", "//api/server/structs:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/state:go_default_library", - "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", - "//encoding/ssz/detect:go_default_library", - "//io/file:go_default_library", "//network/forks:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//runtime/version:go_default_library", - "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@org_golang_x_mod//semver:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ - "checkpoint_test.go", "client_test.go", "health_test.go", ], @@ -45,19 +35,7 @@ go_test( deps = [ "//api/client:go_default_library", "//api/client/beacon/testing:go_default_library", - "//beacon-chain/state:go_default_library", - "//config/params:go_default_library", - "//consensus-types/blocks:go_default_library", - "//consensus-types/blocks/testing:go_default_library", - "//consensus-types/primitives:go_default_library", - "//encoding/ssz/detect:go_default_library", - "//network/forks:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//runtime/version:go_default_library", "//testing/require:go_default_library", - "//testing/util:go_default_library", - "//time/slots:go_default_library", - "@com_github_pkg_errors//:go_default_library", "@org_uber_go_mock//gomock:go_default_library", ], ) diff --git a/api/client/beacon/checkpoint.go b/api/client/beacon/checkpoint.go deleted file mode 100644 index bfe3f503e1d7..000000000000 --- a/api/client/beacon/checkpoint.go +++ /dev/null @@ -1,276 +0,0 @@ -package beacon - -import ( - "context" - "fmt" - "path" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/pkg/errors" - base "github.com/prysmaticlabs/prysm/v5/api/client" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" - "github.com/prysmaticlabs/prysm/v5/encoding/ssz/detect" - "github.com/prysmaticlabs/prysm/v5/io/file" - "github.com/prysmaticlabs/prysm/v5/runtime/version" - "github.com/prysmaticlabs/prysm/v5/time/slots" - "github.com/sirupsen/logrus" - "golang.org/x/mod/semver" -) - -var errCheckpointBlockMismatch = errors.New("mismatch between checkpoint sync state and block") - -// OriginData represents the BeaconState and ReadOnlySignedBeaconBlock necessary to start an empty Beacon Node -// using Checkpoint Sync. -type OriginData struct { - sb []byte - bb []byte - st state.BeaconState - b interfaces.ReadOnlySignedBeaconBlock - vu *detect.VersionedUnmarshaler - br [32]byte - sr [32]byte -} - -// SaveBlock saves the downloaded block to a unique file in the given path. -// For readability and collision avoidance, the file name includes: type, config name, slot and root -func (o *OriginData) SaveBlock(dir string) (string, error) { - blockPath := path.Join(dir, fname("block", o.vu, o.b.Block().Slot(), o.br)) - return blockPath, file.WriteFile(blockPath, o.BlockBytes()) -} - -// SaveState saves the downloaded state to a unique file in the given path. -// For readability and collision avoidance, the file name includes: type, config name, slot and root -func (o *OriginData) SaveState(dir string) (string, error) { - statePath := path.Join(dir, fname("state", o.vu, o.st.Slot(), o.sr)) - return statePath, file.WriteFile(statePath, o.StateBytes()) -} - -// StateBytes returns the ssz-encoded bytes of the downloaded BeaconState value. -func (o *OriginData) StateBytes() []byte { - return o.sb -} - -// BlockBytes returns the ssz-encoded bytes of the downloaded ReadOnlySignedBeaconBlock value. -func (o *OriginData) BlockBytes() []byte { - return o.bb -} - -func fname(prefix string, vu *detect.VersionedUnmarshaler, slot primitives.Slot, root [32]byte) string { - return fmt.Sprintf("%s_%s_%s_%d-%#x.ssz", prefix, vu.Config.ConfigName, version.String(vu.Fork), slot, root) -} - -// DownloadFinalizedData downloads the most recently finalized state, and the block most recently applied to that state. -// This pair can be used to initialize a new beacon node via checkpoint sync. -func DownloadFinalizedData(ctx context.Context, client *Client) (*OriginData, error) { - sb, err := client.GetState(ctx, IdFinalized) - if err != nil { - return nil, err - } - vu, err := detect.FromState(sb) - if err != nil { - return nil, errors.Wrap(err, "error detecting chain config for finalized state") - } - - log.WithFields(logrus.Fields{ - "name": vu.Config.ConfigName, - "fork": version.String(vu.Fork), - }).Info("Detected supported config in remote finalized state") - - s, err := vu.UnmarshalBeaconState(sb) - if err != nil { - return nil, errors.Wrap(err, "error unmarshaling finalized state to correct version") - } - - slot := s.LatestBlockHeader().Slot - bb, err := client.GetBlock(ctx, IdFromSlot(slot)) - if err != nil { - return nil, errors.Wrapf(err, "error requesting block by slot = %d", slot) - } - b, err := vu.UnmarshalBeaconBlock(bb) - if err != nil { - return nil, errors.Wrap(err, "unable to unmarshal block to a supported type using the detected fork schedule") - } - br, err := b.Block().HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "error computing hash_tree_root of retrieved block") - } - bodyRoot, err := b.Block().Body().HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "error computing hash_tree_root of retrieved block body") - } - - sbr := bytesutil.ToBytes32(s.LatestBlockHeader().BodyRoot) - if sbr != bodyRoot { - return nil, errors.Wrapf(errCheckpointBlockMismatch, "state body root = %#x, block body root = %#x", sbr, bodyRoot) - } - sr, err := s.HashTreeRoot(ctx) - if err != nil { - return nil, errors.Wrapf(err, "failed to compute htr for finalized state at slot=%d", s.Slot()) - } - - log. - WithField("blockSlot", b.Block().Slot()). - WithField("stateSlot", s.Slot()). - WithField("stateRoot", hexutil.Encode(sr[:])). - WithField("blockRoot", hexutil.Encode(br[:])). - Info("Downloaded checkpoint sync state and block.") - return &OriginData{ - st: s, - b: b, - sb: sb, - bb: bb, - vu: vu, - br: br, - sr: sr, - }, nil -} - -// WeakSubjectivityData represents the state root, block root and epoch of the BeaconState + ReadOnlySignedBeaconBlock -// that falls at the beginning of the current weak subjectivity period. These values can be used to construct -// a weak subjectivity checkpoint beacon node flag to be used for validation. -type WeakSubjectivityData struct { - BlockRoot [32]byte - StateRoot [32]byte - Epoch primitives.Epoch -} - -// CheckpointString returns the standard string representation of a Checkpoint. -// The format is a hex-encoded block root, followed by the epoch of the block, separated by a colon. For example: -// "0x1c35540cac127315fabb6bf29181f2ae0de1a3fc909d2e76ba771e61312cc49a:74888" -func (wsd *WeakSubjectivityData) CheckpointString() string { - return fmt.Sprintf("%#x:%d", wsd.BlockRoot, wsd.Epoch) -} - -// ComputeWeakSubjectivityCheckpoint attempts to use the prysm weak_subjectivity api -// to obtain the current weak_subjectivity checkpoint. -// For non-prysm nodes, the same computation will be performed with extra steps, -// using the head state downloaded from the beacon node api. -func ComputeWeakSubjectivityCheckpoint(ctx context.Context, client *Client) (*WeakSubjectivityData, error) { - ws, err := client.GetWeakSubjectivity(ctx) - if err != nil { - // a 404/405 is expected if querying an endpoint that doesn't support the weak subjectivity checkpoint api - if !errors.Is(err, base.ErrNotOK) { - return nil, errors.Wrap(err, "unexpected API response for prysm-only weak subjectivity checkpoint API") - } - // fall back to vanilla Beacon Node API method - return computeBackwardsCompatible(ctx, client) - } - log.Printf("server weak subjectivity checkpoint response - epoch=%d, block_root=%#x, state_root=%#x", ws.Epoch, ws.BlockRoot, ws.StateRoot) - return ws, nil -} - -const ( - prysmMinimumVersion = "v2.0.7" - prysmImplementationName = "Prysm" -) - -// errUnsupportedPrysmCheckpointVersion indicates remote beacon node can't be used for checkpoint retrieval. -var errUnsupportedPrysmCheckpointVersion = errors.New("node does not meet minimum version requirements for checkpoint retrieval") - -// for older endpoints or clients that do not support the weak_subjectivity api method -// we gather the necessary data for a checkpoint sync by: -// - inspecting the remote server's head state and computing the weak subjectivity epoch locally -// - requesting the state at the first slot of the epoch -// - using hash_tree_root(state.latest_block_header) to compute the block the state integrates -// - requesting that block by its root -func computeBackwardsCompatible(ctx context.Context, client *Client) (*WeakSubjectivityData, error) { - log.Print("falling back to generic checkpoint derivation, weak_subjectivity API not supported by server") - nv, err := client.GetNodeVersion(ctx) - if err != nil { - return nil, errors.Wrap(err, "unable to proceed with fallback method without confirming node version") - } - if nv.implementation == prysmImplementationName && semver.Compare(nv.semver, prysmMinimumVersion) < 0 { - return nil, errors.Wrapf(errUnsupportedPrysmCheckpointVersion, "%s < minimum (%s)", nv.semver, prysmMinimumVersion) - } - epoch, err := getWeakSubjectivityEpochFromHead(ctx, client) - if err != nil { - return nil, errors.Wrap(err, "error computing weak subjectivity epoch via head state inspection") - } - - // use first slot of the epoch for the state slot - slot, err := slots.EpochStart(epoch) - if err != nil { - return nil, errors.Wrapf(err, "error computing first slot of epoch=%d", epoch) - } - - log.Printf("requesting checkpoint state at slot %d", slot) - // get the state at the first slot of the epoch - sb, err := client.GetState(ctx, IdFromSlot(slot)) - if err != nil { - return nil, errors.Wrapf(err, "failed to request state by slot from api, slot=%d", slot) - } - - // ConfigFork is used to unmarshal the BeaconState so we can read the block root in latest_block_header - vu, err := detect.FromState(sb) - if err != nil { - return nil, errors.Wrap(err, "error detecting chain config for beacon state") - } - log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork)) - - s, err := vu.UnmarshalBeaconState(sb) - if err != nil { - return nil, errors.Wrap(err, "error using detected config fork to unmarshal state bytes") - } - - // compute state and block roots - sr, err := s.HashTreeRoot(ctx) - if err != nil { - return nil, errors.Wrap(err, "error computing hash_tree_root of state") - } - - h := s.LatestBlockHeader() - h.StateRoot = sr[:] - br, err := h.HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "error while computing block root using state data") - } - - bb, err := client.GetBlock(ctx, IdFromRoot(br)) - if err != nil { - return nil, errors.Wrapf(err, "error requesting block by root = %d", br) - } - b, err := vu.UnmarshalBeaconBlock(bb) - if err != nil { - return nil, errors.Wrap(err, "unable to unmarshal block to a supported type using the detected fork schedule") - } - br, err = b.Block().HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "error computing hash_tree_root for block obtained via root") - } - - return &WeakSubjectivityData{ - Epoch: epoch, - BlockRoot: br, - StateRoot: sr, - }, nil -} - -// this method downloads the head state, which can be used to find the correct chain config -// and use prysm's helper methods to compute the latest weak subjectivity epoch. -func getWeakSubjectivityEpochFromHead(ctx context.Context, client *Client) (primitives.Epoch, error) { - headBytes, err := client.GetState(ctx, IdHead) - if err != nil { - return 0, err - } - vu, err := detect.FromState(headBytes) - if err != nil { - return 0, errors.Wrap(err, "error detecting chain config for beacon state") - } - log.Printf("detected supported config in remote head state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork)) - headState, err := vu.UnmarshalBeaconState(headBytes) - if err != nil { - return 0, errors.Wrap(err, "error unmarshaling state to correct version") - } - - epoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, headState, vu.Config) - if err != nil { - return 0, errors.Wrap(err, "error computing the weak subjectivity epoch from head state") - } - - log.Printf("(computed client-side) weak subjectivity epoch = %d", epoch) - return epoch, nil -} diff --git a/api/client/beacon/client.go b/api/client/beacon/client.go index 04cdd46fa103..8af0b38bf4b4 100644 --- a/api/client/beacon/client.go +++ b/api/client/beacon/client.go @@ -29,12 +29,13 @@ const ( getSignedBlockPath = "/eth/v2/beacon/blocks" getBlockRootPath = "/eth/v1/beacon/blocks/{{.Id}}/root" getForkForStatePath = "/eth/v1/beacon/states/{{.Id}}/fork" - getWeakSubjectivityPath = "/prysm/v1/beacon/weak_subjectivity" getForkSchedulePath = "/eth/v1/config/fork_schedule" getConfigSpecPath = "/eth/v1/config/spec" getStatePath = "/eth/v2/debug/beacon/states" - getNodeVersionPath = "/eth/v1/node/version" changeBLStoExecutionPath = "/eth/v1/beacon/pool/bls_to_execution_changes" + + GetNodeVersionPath = "/eth/v1/node/version" + GetWeakSubjectivityPath = "/prysm/v1/beacon/weak_subjectivity" ) // StateOrBlockId represents the block_id / state_id parameters that several of the Eth Beacon API methods accept. @@ -80,7 +81,8 @@ func idTemplate(ts string) func(StateOrBlockId) string { return f } -func renderGetBlockPath(id StateOrBlockId) string { +// RenderGetBlockPath formats a block id into a path for the GetBlock API endpoint. +func RenderGetBlockPath(id StateOrBlockId) string { return path.Join(getSignedBlockPath, string(id)) } @@ -104,7 +106,7 @@ func NewClient(host string, opts ...client.ClientOpt) (*Client, error) { // for the named identifiers. // The return value contains the ssz-encoded bytes. func (c *Client) GetBlock(ctx context.Context, blockId StateOrBlockId) ([]byte, error) { - blockPath := renderGetBlockPath(blockId) + blockPath := RenderGetBlockPath(blockId) b, err := c.Get(ctx, blockPath, client.WithSSZEncoding()) if err != nil { return nil, errors.Wrapf(err, "error requesting state by id = %s", blockId) @@ -195,6 +197,10 @@ type NodeVersion struct { systemInfo string } +func (nv *NodeVersion) SetImplementation(impl string) { + nv.implementation = impl +} + var versionRE = regexp.MustCompile(`^(\w+)/(v\d+\.\d+\.\d+[-a-zA-Z0-9]*)\s*/?(.*)$`) func parseNodeVersion(v string) (*NodeVersion, error) { @@ -212,7 +218,7 @@ func parseNodeVersion(v string) (*NodeVersion, error) { // GetNodeVersion requests that the beacon node identify information about its implementation in a format // similar to a HTTP User-Agent field. ex: Lighthouse/v0.1.5 (Linux x86_64) func (c *Client) GetNodeVersion(ctx context.Context) (*NodeVersion, error) { - b, err := c.Get(ctx, getNodeVersionPath) + b, err := c.Get(ctx, GetNodeVersionPath) if err != nil { return nil, errors.Wrap(err, "error requesting node version") } @@ -228,7 +234,8 @@ func (c *Client) GetNodeVersion(ctx context.Context) (*NodeVersion, error) { return parseNodeVersion(d.Data.Version) } -func renderGetStatePath(id StateOrBlockId) string { +// RenderGetStatePath formats a state id into a path for the GetState API endpoint. +func RenderGetStatePath(id StateOrBlockId) string { return path.Join(getStatePath, string(id)) } @@ -246,13 +253,29 @@ func (c *Client) GetState(ctx context.Context, stateId StateOrBlockId) ([]byte, return b, nil } +// WeakSubjectivityData represents the state root, block root and epoch of the BeaconState + ReadOnlySignedBeaconBlock +// that falls at the beginning of the current weak subjectivity period. These values can be used to construct +// a weak subjectivity checkpoint beacon node flag to be used for validation. +type WeakSubjectivityData struct { + BlockRoot [32]byte + StateRoot [32]byte + Epoch primitives.Epoch +} + +// CheckpointString returns the standard string representation of a Checkpoint. +// The format is a hex-encoded block root, followed by the epoch of the block, separated by a colon. For example: +// "0x1c35540cac127315fabb6bf29181f2ae0de1a3fc909d2e76ba771e61312cc49a:74888" +func (wsd *WeakSubjectivityData) CheckpointString() string { + return fmt.Sprintf("%#x:%d", wsd.BlockRoot, wsd.Epoch) +} + // GetWeakSubjectivity calls a proposed API endpoint that is unique to prysm // This api method does the following: // - computes weak subjectivity epoch // - finds the highest non-skipped block preceding the epoch // - returns the htr of the found block and returns this + the value of state_root from the block func (c *Client) GetWeakSubjectivity(ctx context.Context) (*WeakSubjectivityData, error) { - body, err := c.Get(ctx, getWeakSubjectivityPath) + body, err := c.Get(ctx, GetWeakSubjectivityPath) if err != nil { return nil, err } diff --git a/api/client/beacon/client_test.go b/api/client/beacon/client_test.go index 4c84f3642634..5e7adbad5240 100644 --- a/api/client/beacon/client_test.go +++ b/api/client/beacon/client_test.go @@ -97,31 +97,31 @@ func TestValidHostname(t *testing.T) { { name: "hostname with port", hostArg: "mydomain.org:3500", - path: getNodeVersionPath, + path: GetNodeVersionPath, joined: "http://mydomain.org:3500/eth/v1/node/version", }, { name: "https scheme, hostname with port", hostArg: "https://mydomain.org:3500", - path: getNodeVersionPath, + path: GetNodeVersionPath, joined: "https://mydomain.org:3500/eth/v1/node/version", }, { name: "http scheme, hostname without port", hostArg: "http://mydomain.org", - path: getNodeVersionPath, + path: GetNodeVersionPath, joined: "http://mydomain.org/eth/v1/node/version", }, { name: "http scheme, trailing slash, hostname without port", hostArg: "http://mydomain.org/", - path: getNodeVersionPath, + path: GetNodeVersionPath, joined: "http://mydomain.org/eth/v1/node/version", }, { name: "http scheme, hostname with basic auth creds and no port", hostArg: "http://username:pass@mydomain.org/", - path: getNodeVersionPath, + path: GetNodeVersionPath, joined: "http://username:pass@mydomain.org/eth/v1/node/version", }, } diff --git a/api/client/builder/BUILD.bazel b/api/client/builder/BUILD.bazel index e8dd1ce1a27a..7b1802ddb69c 100644 --- a/api/client/builder/BUILD.bazel +++ b/api/client/builder/BUILD.bazel @@ -12,8 +12,11 @@ go_library( visibility = ["//visibility:public"], deps = [ "//api:go_default_library", + "//api/client:go_default_library", + "//api/server:go_default_library", "//api/server/structs:go_default_library", "//config/fieldparams:go_default_library", + "//config/params:go_default_library", "//consensus-types:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", @@ -21,14 +24,16 @@ go_library( "//encoding/bytesutil:go_default_library", "//math:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", + "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) @@ -42,6 +47,7 @@ go_test( data = glob(["testdata/**"]), embed = [":go_default_library"], deps = [ + "//api:go_default_library", "//api/server/structs:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", diff --git a/api/client/builder/bid.go b/api/client/builder/bid.go index f88fd6194eac..87acc37f9156 100644 --- a/api/client/builder/bid.go +++ b/api/client/builder/bid.go @@ -1,12 +1,12 @@ package builder import ( - "github.com/pkg/errors" ssz "github.com/prysmaticlabs/fastssz" consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" ) @@ -22,7 +22,6 @@ type SignedBid interface { // Bid is an interface describing the method set of a builder bid. type Bid interface { Header() (interfaces.ExecutionData, error) - BlobKzgCommitments() ([][]byte, error) Value() primitives.Wei Pubkey() []byte Version() int @@ -31,6 +30,18 @@ type Bid interface { HashTreeRootWith(hh *ssz.Hasher) error } +// BidDeneb is an interface that exposes newly added kzg commitments on top of builder bid +type BidDeneb interface { + Bid + BlobKzgCommitments() [][]byte +} + +// BidElectra is an interface that exposes the newly added execution requests on top of the builder bid +type BidElectra interface { + BidDeneb + ExecutionRequests() *v1.ExecutionRequests +} + type signedBuilderBid struct { p *ethpb.SignedBuilderBid } @@ -115,11 +126,6 @@ func (b builderBid) Header() (interfaces.ExecutionData, error) { return blocks.WrappedExecutionPayloadHeader(b.p.Header) } -// BlobKzgCommitments -- -func (b builderBid) BlobKzgCommitments() ([][]byte, error) { - return [][]byte{}, errors.New("blob kzg commitments not available before Deneb") -} - // Version -- func (b builderBid) Version() int { return version.Bellatrix @@ -169,11 +175,6 @@ func (b builderBidCapella) Header() (interfaces.ExecutionData, error) { return blocks.WrappedExecutionPayloadHeaderCapella(b.p.Header) } -// BlobKzgCommitments -- -func (b builderBidCapella) BlobKzgCommitments() ([][]byte, error) { - return [][]byte{}, errors.New("blob kzg commitments not available before Deneb") -} - // Version -- func (b builderBidCapella) Version() int { return version.Capella @@ -254,8 +255,8 @@ func (b builderBidDeneb) Header() (interfaces.ExecutionData, error) { } // BlobKzgCommitments -- -func (b builderBidDeneb) BlobKzgCommitments() ([][]byte, error) { - return b.p.BlobKzgCommitments, nil +func (b builderBidDeneb) BlobKzgCommitments() [][]byte { + return b.p.BlobKzgCommitments } type signedBuilderBidDeneb struct { @@ -290,3 +291,95 @@ func (b signedBuilderBidDeneb) Version() int { func (b signedBuilderBidDeneb) IsNil() bool { return b.p == nil } + +type builderBidElectra struct { + p *ethpb.BuilderBidElectra +} + +// WrappedBuilderBidElectra is a constructor which wraps a protobuf bid into an interface. +func WrappedBuilderBidElectra(p *ethpb.BuilderBidElectra) (Bid, error) { + w := builderBidElectra{p: p} + if w.IsNil() { + return nil, consensus_types.ErrNilObjectWrapped + } + return w, nil +} + +// Version -- +func (b builderBidElectra) Version() int { + return version.Electra +} + +// Value -- +func (b builderBidElectra) Value() primitives.Wei { + return primitives.LittleEndianBytesToWei(b.p.Value) +} + +// Pubkey -- +func (b builderBidElectra) Pubkey() []byte { + return b.p.Pubkey +} + +// IsNil -- +func (b builderBidElectra) IsNil() bool { + return b.p == nil +} + +// HashTreeRoot -- +func (b builderBidElectra) HashTreeRoot() ([32]byte, error) { + return b.p.HashTreeRoot() +} + +// HashTreeRootWith -- +func (b builderBidElectra) HashTreeRootWith(hh *ssz.Hasher) error { + return b.p.HashTreeRootWith(hh) +} + +// Header -- +func (b builderBidElectra) Header() (interfaces.ExecutionData, error) { + // We have to convert big endian to little endian because the value is coming from the execution layer. + return blocks.WrappedExecutionPayloadHeaderDeneb(b.p.Header) +} + +// ExecutionRequests -- +func (b builderBidElectra) ExecutionRequests() *v1.ExecutionRequests { + return b.p.ExecutionRequests // does not copy +} + +// BlobKzgCommitments -- +func (b builderBidElectra) BlobKzgCommitments() [][]byte { + return b.p.BlobKzgCommitments +} + +type signedBuilderBidElectra struct { + p *ethpb.SignedBuilderBidElectra +} + +// WrappedSignedBuilderBidElectra is a constructor which wraps a protobuf signed bit into an interface. +func WrappedSignedBuilderBidElectra(p *ethpb.SignedBuilderBidElectra) (SignedBid, error) { + w := signedBuilderBidElectra{p: p} + if w.IsNil() { + return nil, consensus_types.ErrNilObjectWrapped + } + return w, nil +} + +// Message -- +func (b signedBuilderBidElectra) Message() (Bid, error) { + return WrappedBuilderBidElectra(b.p.Message) +} + +// Signature -- +func (b signedBuilderBidElectra) Signature() []byte { + return b.p.Signature +} + +// Version -- +func (b signedBuilderBidElectra) Version() int { + return version.Electra +} + +// IsNil -- +func (b signedBuilderBidElectra) IsNil() bool { + return b.p == nil +} diff --git a/api/client/builder/client.go b/api/client/builder/client.go index 97acd7237c58..cb4bdc324cb7 100644 --- a/api/client/builder/client.go +++ b/api/client/builder/client.go @@ -14,16 +14,18 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api" + "github.com/prysmaticlabs/prysm/v5/api/client" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" log "github.com/sirupsen/logrus" - "go.opencensus.io/trace" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) const ( @@ -107,7 +109,7 @@ func NewClient(host string, opts ...ClientOpt) (*Client, error) { return nil, err } c := &Client{ - hc: &http.Client{}, + hc: &http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}, baseURL: u, } for _, o := range opts { @@ -146,13 +148,17 @@ func (c *Client) do(ctx context.Context, method string, path string, body io.Rea u := c.baseURL.ResolveReference(&url.URL{Path: path}) - span.AddAttributes(trace.StringAttribute("url", u.String()), + span.SetAttributes(trace.StringAttribute("url", u.String()), trace.StringAttribute("method", method)) req, err := http.NewRequestWithContext(ctx, method, u.String(), body) if err != nil { return } + if method == http.MethodPost { + req.Header.Set("Content-Type", api.JsonMediaType) + } + req.Header.Set("Accept", api.JsonMediaType) req.Header.Add("User-Agent", version.BuildData()) for _, o := range opts { o(req) @@ -176,7 +182,7 @@ func (c *Client) do(ctx context.Context, method string, path string, body io.Rea err = non200Err(r) return } - res, err = io.ReadAll(r.Body) + res, err = io.ReadAll(io.LimitReader(r.Body, client.MaxBodySize)) if err != nil { err = errors.Wrap(err, "error reading http response body from builder server") return @@ -218,8 +224,23 @@ func (c *Client) GetHeader(ctx context.Context, slot primitives.Slot, parentHash if err := json.Unmarshal(hb, v); err != nil { return nil, errors.Wrapf(err, "error unmarshaling the builder GetHeader response, using slot=%d, parentHash=%#x, pubkey=%#x", slot, parentHash, pubkey) } - switch strings.ToLower(v.Version) { - case strings.ToLower(version.String(version.Deneb)): + + ver, err := version.FromString(strings.ToLower(v.Version)) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("unsupported header version %s", strings.ToLower(v.Version))) + } + if ver >= version.Electra { + hr := &ExecHeaderResponseElectra{} + if err := json.Unmarshal(hb, hr); err != nil { + return nil, errors.Wrapf(err, "error unmarshaling the builder GetHeader response, using slot=%d, parentHash=%#x, pubkey=%#x", slot, parentHash, pubkey) + } + p, err := hr.ToProto() + if err != nil { + return nil, errors.Wrapf(err, "could not extract proto message from header") + } + return WrappedSignedBuilderBidElectra(p) + } + if ver >= version.Deneb { hr := &ExecHeaderResponseDeneb{} if err := json.Unmarshal(hb, hr); err != nil { return nil, errors.Wrapf(err, "error unmarshaling the builder GetHeader response, using slot=%d, parentHash=%#x, pubkey=%#x", slot, parentHash, pubkey) @@ -229,7 +250,8 @@ func (c *Client) GetHeader(ctx context.Context, slot primitives.Slot, parentHash return nil, errors.Wrapf(err, "could not extract proto message from header") } return WrappedSignedBuilderBidDeneb(p) - case strings.ToLower(version.String(version.Capella)): + } + if ver >= version.Capella { hr := &ExecHeaderResponseCapella{} if err := json.Unmarshal(hb, hr); err != nil { return nil, errors.Wrapf(err, "error unmarshaling the builder GetHeader response, using slot=%d, parentHash=%#x, pubkey=%#x", slot, parentHash, pubkey) @@ -239,7 +261,8 @@ func (c *Client) GetHeader(ctx context.Context, slot primitives.Slot, parentHash return nil, errors.Wrapf(err, "could not extract proto message from header") } return WrappedSignedBuilderBidCapella(p) - case strings.ToLower(version.String(version.Bellatrix)): + } + if ver >= version.Bellatrix { hr := &ExecHeaderResponse{} if err := json.Unmarshal(hb, hr); err != nil { return nil, errors.Wrapf(err, "error unmarshaling the builder GetHeader response, using slot=%d, parentHash=%#x, pubkey=%#x", slot, parentHash, pubkey) @@ -249,9 +272,8 @@ func (c *Client) GetHeader(ctx context.Context, slot primitives.Slot, parentHash return nil, errors.Wrap(err, "could not extract proto message from header") } return WrappedSignedBuilderBid(p) - default: - return nil, fmt.Errorf("unsupported header version %s", strings.ToLower(v.Version)) } + return nil, fmt.Errorf("unsupported header version %s", strings.ToLower(v.Version)) } // RegisterValidator encodes the SignedValidatorRegistrationV1 message to json (including hex-encoding the byte @@ -259,7 +281,7 @@ func (c *Client) GetHeader(ctx context.Context, slot primitives.Slot, parentHash func (c *Client) RegisterValidator(ctx context.Context, svr []*ethpb.SignedValidatorRegistrationV1) error { ctx, span := trace.StartSpan(ctx, "builder.client.RegisterValidator") defer span.End() - span.AddAttributes(trace.Int64Attribute("num_reqs", int64(len(svr)))) + span.SetAttributes(trace.Int64Attribute("num_reqs", int64(len(svr)))) if len(svr) == 0 { err := errors.Wrap(errMalformedRequest, "empty validator registration list") @@ -278,7 +300,11 @@ func (c *Client) RegisterValidator(ctx context.Context, svr []*ethpb.SignedValid } _, err = c.do(ctx, http.MethodPost, postRegisterValidatorPath, bytes.NewBuffer(body)) - return err + if err != nil { + return err + } + log.WithField("registrationCount", len(svr)).Debug("Successfully registered validator(s) on builder") + return nil } var errResponseVersionMismatch = errors.New("builder API response uses a different version than requested in " + api.VersionHeader + " header") @@ -354,7 +380,7 @@ func (c *Client) Status(ctx context.Context) error { } func non200Err(response *http.Response) error { - bodyBytes, err := io.ReadAll(response.Body) + bodyBytes, err := io.ReadAll(io.LimitReader(response.Body, client.MaxErrBodySize)) var errMessage ErrorMessage var body string if err != nil { diff --git a/api/client/builder/client_test.go b/api/client/builder/client_test.go index 02070acdb3d6..3d80d547ed02 100644 --- a/api/client/builder/client_test.go +++ b/api/client/builder/client_test.go @@ -12,11 +12,11 @@ import ( "testing" "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - types "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -90,6 +90,8 @@ func TestClient_RegisterValidator(t *testing.T) { expectedPath := "/eth/v1/builder/validators" hc := &http.Client{ Transport: roundtrip(func(r *http.Request) (*http.Response, error) { + require.Equal(t, api.JsonMediaType, r.Header.Get("Content-Type")) + require.Equal(t, api.JsonMediaType, r.Header.Get("Accept")) body, err := io.ReadAll(r.Body) defer func() { require.NoError(t, r.Body.Close()) @@ -124,7 +126,7 @@ func TestClient_RegisterValidator(t *testing.T) { func TestClient_GetHeader(t *testing.T) { ctx := context.Background() expectedPath := "/eth/v1/builder/header/23/0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2/0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" - var slot types.Slot = 23 + var slot primitives.Slot = 23 parentHash := ezDecode(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2") pubkey := ezDecode(t, "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a") t.Run("server error", func(t *testing.T) { @@ -267,9 +269,9 @@ func TestClient_GetHeader(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, value.Int.Cmp(primitives.WeiToBigInt(bid.Value()))) require.Equal(t, bidStr, primitives.WeiToBigInt(bid.Value()).String()) - - kcgCommitments, err := bid.BlobKzgCommitments() - require.NoError(t, err) + dbid, ok := bid.(builderBidDeneb) + require.Equal(t, true, ok) + kcgCommitments := dbid.BlobKzgCommitments() require.Equal(t, len(kcgCommitments) > 0, true) for i := range kcgCommitments { require.Equal(t, len(kcgCommitments[i]) == 48, true) @@ -293,6 +295,50 @@ func TestClient_GetHeader(t *testing.T) { _, err := c.GetHeader(ctx, slot, bytesutil.ToBytes32(parentHash), bytesutil.ToBytes48(pubkey)) require.ErrorContains(t, "could not extract proto message from header: too many blob commitments: 7", err) }) + t.Run("electra", func(t *testing.T) { + hc := &http.Client{ + Transport: roundtrip(func(r *http.Request) (*http.Response, error) { + require.Equal(t, expectedPath, r.URL.Path) + return &http.Response{ + StatusCode: http.StatusOK, + Body: io.NopCloser(bytes.NewBufferString(testExampleHeaderResponseElectra)), + Request: r.Clone(ctx), + }, nil + }), + } + c := &Client{ + hc: hc, + baseURL: &url.URL{Host: "localhost:3500", Scheme: "http"}, + } + h, err := c.GetHeader(ctx, slot, bytesutil.ToBytes32(parentHash), bytesutil.ToBytes48(pubkey)) + require.NoError(t, err) + expectedWithdrawalsRoot := ezDecode(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2") + bid, err := h.Message() + require.NoError(t, err) + bidHeader, err := bid.Header() + require.NoError(t, err) + withdrawalsRoot, err := bidHeader.WithdrawalsRoot() + require.NoError(t, err) + require.Equal(t, true, bytes.Equal(expectedWithdrawalsRoot, withdrawalsRoot)) + + bidStr := "652312848583266388373324160190187140051835877600158453279131187530910662656" + value, err := stringToUint256(bidStr) + require.NoError(t, err) + require.Equal(t, 0, value.Int.Cmp(primitives.WeiToBigInt(bid.Value()))) + require.Equal(t, bidStr, primitives.WeiToBigInt(bid.Value()).String()) + ebid, ok := bid.(builderBidElectra) + require.Equal(t, true, ok) + kcgCommitments := ebid.BlobKzgCommitments() + require.Equal(t, len(kcgCommitments) > 0, true) + for i := range kcgCommitments { + require.Equal(t, len(kcgCommitments[i]) == 48, true) + } + requests := ebid.ExecutionRequests() + require.Equal(t, 1, len(requests.Deposits)) + require.Equal(t, 1, len(requests.Withdrawals)) + require.Equal(t, 1, len(requests.Consolidations)) + + }) t.Run("unsupported version", func(t *testing.T) { hc := &http.Client{ Transport: roundtrip(func(r *http.Request) (*http.Response, error) { @@ -321,8 +367,8 @@ func TestSubmitBlindedBlock(t *testing.T) { Transport: roundtrip(func(r *http.Request) (*http.Response, error) { require.Equal(t, postBlindedBeaconBlockPath, r.URL.Path) require.Equal(t, "bellatrix", r.Header.Get("Eth-Consensus-Version")) - require.Equal(t, "application/json", r.Header.Get("Content-Type")) - require.Equal(t, "application/json", r.Header.Get("Accept")) + require.Equal(t, api.JsonMediaType, r.Header.Get("Content-Type")) + require.Equal(t, api.JsonMediaType, r.Header.Get("Accept")) return &http.Response{ StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString(testExampleExecutionPayload)), @@ -349,8 +395,8 @@ func TestSubmitBlindedBlock(t *testing.T) { Transport: roundtrip(func(r *http.Request) (*http.Response, error) { require.Equal(t, postBlindedBeaconBlockPath, r.URL.Path) require.Equal(t, "capella", r.Header.Get("Eth-Consensus-Version")) - require.Equal(t, "application/json", r.Header.Get("Content-Type")) - require.Equal(t, "application/json", r.Header.Get("Accept")) + require.Equal(t, api.JsonMediaType, r.Header.Get("Content-Type")) + require.Equal(t, api.JsonMediaType, r.Header.Get("Accept")) return &http.Response{ StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString(testExampleExecutionPayloadCapella)), @@ -370,7 +416,7 @@ func TestSubmitBlindedBlock(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, len(withdrawals)) assert.Equal(t, uint64(1), withdrawals[0].Index) - assert.Equal(t, types.ValidatorIndex(1), withdrawals[0].ValidatorIndex) + assert.Equal(t, primitives.ValidatorIndex(1), withdrawals[0].ValidatorIndex) assert.DeepEqual(t, ezDecode(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943"), withdrawals[0].Address) assert.Equal(t, uint64(1), withdrawals[0].Amount) }) @@ -380,8 +426,8 @@ func TestSubmitBlindedBlock(t *testing.T) { Transport: roundtrip(func(r *http.Request) (*http.Response, error) { require.Equal(t, postBlindedBeaconBlockPath, r.URL.Path) require.Equal(t, "deneb", r.Header.Get("Eth-Consensus-Version")) - require.Equal(t, "application/json", r.Header.Get("Content-Type")) - require.Equal(t, "application/json", r.Header.Get("Accept")) + require.Equal(t, api.JsonMediaType, r.Header.Get("Content-Type")) + require.Equal(t, api.JsonMediaType, r.Header.Get("Accept")) var req structs.SignedBlindedBeaconBlockDeneb err := json.NewDecoder(r.Body).Decode(&req) require.NoError(t, err) @@ -409,7 +455,7 @@ func TestSubmitBlindedBlock(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, len(withdrawals)) assert.Equal(t, uint64(1), withdrawals[0].Index) - assert.Equal(t, types.ValidatorIndex(1), withdrawals[0].ValidatorIndex) + assert.Equal(t, primitives.ValidatorIndex(1), withdrawals[0].ValidatorIndex) assert.DeepEqual(t, ezDecode(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943"), withdrawals[0].Address) assert.Equal(t, uint64(1), withdrawals[0].Amount) require.NotNil(t, blobBundle) diff --git a/api/client/builder/types.go b/api/client/builder/types.go index 169df6822ebd..c06ae9f63cca 100644 --- a/api/client/builder/types.go +++ b/api/client/builder/types.go @@ -5,12 +5,15 @@ import ( "fmt" "math/big" "strconv" + "strings" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api/server" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" types "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/math" @@ -413,54 +416,10 @@ func FromProtoDeneb(payload *v1.ExecutionPayloadDeneb) (ExecutionPayloadDeneb, e }, nil } -var errInvalidTypeConversion = errors.New("unable to translate between api and foreign type") - -// ExecutionPayloadResponseFromData converts an ExecutionData interface value to a payload response. -// This involves serializing the execution payload value so that the abstract payload envelope can be used. -func ExecutionPayloadResponseFromData(ed interfaces.ExecutionData, bundle *v1.BlobsBundle) (*ExecutionPayloadResponse, error) { - pb := ed.Proto() - var data interface{} - var err error - var ver string - switch pbStruct := pb.(type) { - case *v1.ExecutionPayload: - ver = version.String(version.Bellatrix) - data, err = FromProto(pbStruct) - if err != nil { - return nil, errors.Wrap(err, "failed to convert a Bellatrix ExecutionPayload to an API response") - } - case *v1.ExecutionPayloadCapella: - ver = version.String(version.Capella) - data, err = FromProtoCapella(pbStruct) - if err != nil { - return nil, errors.Wrap(err, "failed to convert a Capella ExecutionPayload to an API response") - } - case *v1.ExecutionPayloadDeneb: - ver = version.String(version.Deneb) - payloadStruct, err := FromProtoDeneb(pbStruct) - if err != nil { - return nil, errors.Wrap(err, "failed to convert a Deneb ExecutionPayload to an API response") - } - data = &ExecutionPayloadDenebAndBlobsBundle{ - ExecutionPayload: &payloadStruct, - BlobsBundle: FromBundleProto(bundle), - } - default: - return nil, errInvalidTypeConversion - } - encoded, err := json.Marshal(data) - if err != nil { - return nil, errors.Wrapf(err, "failed to marshal execution payload version=%s", ver) - } - return &ExecutionPayloadResponse{ - Version: ver, - Data: encoded, - }, nil -} - // ExecHeaderResponseCapella is the response of builder API /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey} for Capella. type ExecHeaderResponseCapella struct { - Data struct { + Version string `json:"version"` + Data struct { Signature hexutil.Bytes `json:"signature"` Message *BuilderBidCapella `json:"message"` } `json:"data"` @@ -604,17 +563,25 @@ type BlobBundler interface { BundleProto() (*v1.BlobsBundle, error) } +// ParsedExecutionRequests can retrieve the underlying execution requests for the given execution payload response. +type ParsedExecutionRequests interface { + ExecutionRequestsProto() (*v1.ExecutionRequests, error) +} + func (r *ExecutionPayloadResponse) ParsePayload() (ParsedPayload, error) { var toProto ParsedPayload - switch r.Version { - case version.String(version.Bellatrix): - toProto = &ExecutionPayload{} - case version.String(version.Capella): - toProto = &ExecutionPayloadCapella{} - case version.String(version.Deneb): + v, err := version.FromString(strings.ToLower(r.Version)) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("unsupported version %s", strings.ToLower(r.Version))) + } + if v >= version.Deneb { toProto = &ExecutionPayloadDenebAndBlobsBundle{} - default: - return nil, consensusblocks.ErrUnsupportedVersion + } else if v >= version.Capella { + toProto = &ExecutionPayloadCapella{} + } else if v >= version.Bellatrix { + toProto = &ExecutionPayload{} + } else { + return nil, fmt.Errorf("unsupported version %s", strings.ToLower(r.Version)) } if err := json.Unmarshal(r.Data, toProto); err != nil { @@ -989,7 +956,8 @@ func (ch *BLSToExecutionChange) MarshalJSON() ([]byte, error) { // ExecHeaderResponseDeneb is the header response for builder API /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}. type ExecHeaderResponseDeneb struct { - Data struct { + Version string `json:"version"` + Data struct { Signature hexutil.Bytes `json:"signature"` Message *BuilderBidDeneb `json:"message"` } `json:"data"` @@ -1013,7 +981,7 @@ func (bb *BuilderBidDeneb) ToProto() (*eth.BuilderBidDeneb, error) { if err != nil { return nil, err } - if len(bb.BlobKzgCommitments) > fieldparams.MaxBlobsPerBlock { + if len(bb.BlobKzgCommitments) > params.BeaconConfig().DeprecatedMaxBlobsPerBlock { return nil, fmt.Errorf("too many blob commitments: %d", len(bb.BlobKzgCommitments)) } kzgCommitments := make([][]byte, len(bb.BlobKzgCommitments)) @@ -1306,6 +1274,208 @@ func (p *ExecutionPayloadDeneb) ToProto() (*v1.ExecutionPayloadDeneb, error) { }, nil } +// ExecHeaderResponseElectra is the header response for builder API /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}. +type ExecHeaderResponseElectra struct { + Version string `json:"version"` + Data struct { + Signature hexutil.Bytes `json:"signature"` + Message *BuilderBidElectra `json:"message"` + } `json:"data"` +} + +// ToProto creates a SignedBuilderBidElectra Proto from ExecHeaderResponseElectra. +func (ehr *ExecHeaderResponseElectra) ToProto() (*eth.SignedBuilderBidElectra, error) { + bb, err := ehr.Data.Message.ToProto() + if err != nil { + return nil, err + } + return ð.SignedBuilderBidElectra{ + Message: bb, + Signature: bytesutil.SafeCopyBytes(ehr.Data.Signature), + }, nil +} + +// ToProto creates a BuilderBidElectra Proto from BuilderBidElectra. +func (bb *BuilderBidElectra) ToProto() (*eth.BuilderBidElectra, error) { + header, err := bb.Header.ToProto() + if err != nil { + return nil, err + } + if len(bb.BlobKzgCommitments) > params.BeaconConfig().MaxBlobsPerBlockByVersion(version.Electra) { + return nil, fmt.Errorf("blob commitment count %d exceeds the maximum %d", len(bb.BlobKzgCommitments), params.BeaconConfig().MaxBlobsPerBlockByVersion(version.Electra)) + } + kzgCommitments := make([][]byte, len(bb.BlobKzgCommitments)) + for i, commit := range bb.BlobKzgCommitments { + if len(commit) != fieldparams.BLSPubkeyLength { + return nil, fmt.Errorf("commitment length %d is not %d", len(commit), fieldparams.BLSPubkeyLength) + } + kzgCommitments[i] = bytesutil.SafeCopyBytes(commit) + } + // post electra execution requests should not be nil, if no requests exist use an empty request + if bb.ExecutionRequests == nil { + return nil, errors.New("bid contains nil execution requests") + } + executionRequests, err := bb.ExecutionRequests.ToProto() + if err != nil { + return nil, errors.Wrap(err, "failed to convert ExecutionRequests") + } + return ð.BuilderBidElectra{ + Header: header, + BlobKzgCommitments: kzgCommitments, + ExecutionRequests: executionRequests, + // Note that SSZBytes() reverses byte order for the little-endian representation. + // Uint256.Bytes() is big-endian, SSZBytes takes this value and reverses it. + Value: bytesutil.SafeCopyBytes(bb.Value.SSZBytes()), + Pubkey: bytesutil.SafeCopyBytes(bb.Pubkey), + }, nil +} + +// ExecutionRequestsV1 is a wrapper for different execution requests +type ExecutionRequestsV1 struct { + Deposits []*DepositRequestV1 `json:"deposits"` + Withdrawals []*WithdrawalRequestV1 `json:"withdrawals"` + Consolidations []*ConsolidationRequestV1 `json:"consolidations"` +} + +func (er *ExecutionRequestsV1) ToProto() (*v1.ExecutionRequests, error) { + if uint64(len(er.Deposits)) > params.BeaconConfig().MaxDepositRequestsPerPayload { + return nil, fmt.Errorf("deposit requests count %d exceeds the maximum %d", len(er.Deposits), params.BeaconConfig().MaxDepositRequestsPerPayload) + } + deposits := make([]*v1.DepositRequest, len(er.Deposits)) + for i, dep := range er.Deposits { + d, err := dep.ToProto() + if err != nil { + return nil, err + } + deposits[i] = d + } + if uint64(len(er.Withdrawals)) > params.BeaconConfig().MaxWithdrawalRequestsPerPayload { + return nil, fmt.Errorf("withdrawal requests count %d exceeds the maximum %d", len(er.Withdrawals), params.BeaconConfig().MaxWithdrawalRequestsPerPayload) + } + withdrawals := make([]*v1.WithdrawalRequest, len(er.Withdrawals)) + for i, wr := range er.Withdrawals { + w, err := wr.ToProto() + if err != nil { + return nil, err + } + withdrawals[i] = w + } + if uint64(len(er.Consolidations)) > params.BeaconConfig().MaxConsolidationsRequestsPerPayload { + return nil, fmt.Errorf("consolidation requests count %d exceeds the maximum %d", len(er.Consolidations), params.BeaconConfig().MaxConsolidationsRequestsPerPayload) + } + consolidations := make([]*v1.ConsolidationRequest, len(er.Consolidations)) + for i, con := range er.Consolidations { + c, err := con.ToProto() + if err != nil { + return nil, err + } + consolidations[i] = c + } + return &v1.ExecutionRequests{ + Deposits: deposits, + Withdrawals: withdrawals, + Consolidations: consolidations, + }, nil +} + +// BuilderBidElectra is a field of ExecHeaderResponseElectra. +type BuilderBidElectra struct { + Header *ExecutionPayloadHeaderDeneb `json:"header"` + BlobKzgCommitments []hexutil.Bytes `json:"blob_kzg_commitments"` + ExecutionRequests *ExecutionRequestsV1 `json:"execution_requests"` + Value Uint256 `json:"value"` + Pubkey hexutil.Bytes `json:"pubkey"` +} + +// WithdrawalRequestV1 is a field of ExecutionRequestsV1. +type WithdrawalRequestV1 struct { + SourceAddress hexutil.Bytes `json:"source_address"` + ValidatorPubkey hexutil.Bytes `json:"validator_pubkey"` + Amount Uint256 `json:"amount"` +} + +func (wr *WithdrawalRequestV1) ToProto() (*v1.WithdrawalRequest, error) { + srcAddress, err := bytesutil.DecodeHexWithLength(wr.SourceAddress.String(), common.AddressLength) + if err != nil { + return nil, server.NewDecodeError(err, "source_address") + } + pubkey, err := bytesutil.DecodeHexWithLength(wr.ValidatorPubkey.String(), fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, "validator_pubkey") + } + + return &v1.WithdrawalRequest{ + SourceAddress: srcAddress, + ValidatorPubkey: pubkey, + Amount: wr.Amount.Uint64(), + }, nil +} + +// DepositRequestV1 is a field of ExecutionRequestsV1. +type DepositRequestV1 struct { + PubKey hexutil.Bytes `json:"pubkey"` + // withdrawalCredentials: DATA, 32 Bytes + WithdrawalCredentials hexutil.Bytes `json:"withdrawal_credentials"` + // amount: QUANTITY, 64 Bits + Amount Uint256 `json:"amount"` + // signature: DATA, 96 Bytes + Signature hexutil.Bytes `json:"signature"` + // index: QUANTITY, 64 Bits + Index Uint256 `json:"index"` +} + +func (dr *DepositRequestV1) ToProto() (*v1.DepositRequest, error) { + pubkey, err := bytesutil.DecodeHexWithLength(dr.PubKey.String(), fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, "pubkey") + } + wc, err := bytesutil.DecodeHexWithLength(dr.WithdrawalCredentials.String(), fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "withdrawal_credentials") + } + sig, err := bytesutil.DecodeHexWithLength(dr.Signature.String(), fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "signature") + } + return &v1.DepositRequest{ + Pubkey: pubkey, + WithdrawalCredentials: wc, + Amount: dr.Amount.Uint64(), + Signature: sig, + Index: dr.Index.Uint64(), + }, nil +} + +// ConsolidationRequestV1 is a field of ExecutionRequestsV1. +type ConsolidationRequestV1 struct { + // sourceAddress: DATA, 20 Bytes + SourceAddress hexutil.Bytes `json:"source_address"` + // sourcePubkey: DATA, 48 Bytes + SourcePubkey hexutil.Bytes `json:"source_pubkey"` + // targetPubkey: DATA, 48 Bytes + TargetPubkey hexutil.Bytes `json:"target_pubkey"` +} + +func (cr *ConsolidationRequestV1) ToProto() (*v1.ConsolidationRequest, error) { + srcAddress, err := bytesutil.DecodeHexWithLength(cr.SourceAddress.String(), common.AddressLength) + if err != nil { + return nil, server.NewDecodeError(err, "source_address") + } + sourcePubkey, err := bytesutil.DecodeHexWithLength(cr.SourcePubkey.String(), fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, "source_pubkey") + } + targetPubkey, err := bytesutil.DecodeHexWithLength(cr.TargetPubkey.String(), fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, "target_pubkey") + } + return &v1.ConsolidationRequest{ + SourceAddress: srcAddress, + SourcePubkey: sourcePubkey, + TargetPubkey: targetPubkey, + }, nil +} + // ErrorMessage is a JSON representation of the builder API's returned error message. type ErrorMessage struct { Code int `json:"code"` diff --git a/api/client/builder/types_test.go b/api/client/builder/types_test.go index fbcf5a854e7f..d7e84d397462 100644 --- a/api/client/builder/types_test.go +++ b/api/client/builder/types_test.go @@ -154,6 +154,64 @@ var testExampleHeaderResponseDeneb = `{ } }` +var testExampleHeaderResponseElectra = `{ + "version": "electra", + "data": { + "message": { + "header": { + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_number": "1", + "gas_limit": "1", + "gas_used": "1", + "timestamp": "1", + "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "base_fee_per_gas": "1", + "blob_gas_used": "1", + "excess_blob_gas": "1", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "withdrawals_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "blob_kzg_commitments": [ + "0xa94170080872584e54a1cf092d845703b13907f2e6b3b1c0ad573b910530499e3bcd48c6378846b80d2bfa58c81cf3d5" + ], + "execution_requests": { + "deposits": [ + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "amount": "1", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "index": "1" + } + ], + "withdrawals": [ + { + "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "validator_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "amount": "1" + } + ], + "consolidations": [ + { + "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "source_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "target_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" + } + ] + }, + "value": "652312848583266388373324160190187140051835877600158453279131187530910662656", + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } +}` + var testExampleHeaderResponseDenebNoBundle = `{ "version": "deneb", "data": { @@ -1924,9 +1982,9 @@ func TestEmptyResponseBody(t *testing.T) { emptyResponse := &ExecutionPayloadResponse{} require.NoError(t, json.Unmarshal(empty, emptyResponse)) _, err := emptyResponse.ParsePayload() - require.ErrorIs(t, err, consensusblocks.ErrUnsupportedVersion) + require.ErrorContains(t, "unsupported version", err) }) - versions := []int{version.Bellatrix, version.Capella, version.Deneb} + versions := []int{version.Bellatrix, version.Capella, version.Deneb, version.Electra} for i := range versions { vstr := version.String(versions[i]) t.Run("populated version without payload"+vstr, func(t *testing.T) { diff --git a/api/client/client.go b/api/client/client.go index 47c787189327..60bf6f5b335d 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -10,11 +10,18 @@ import ( "github.com/pkg/errors" ) +const ( + MaxBodySize int64 = 1 << 23 // 8MB default, WithMaxBodySize can override + MaxBodySizeState int64 = 1 << 29 // 512MB + MaxErrBodySize int64 = 1 << 17 // 128KB +) + // Client is a wrapper object around the HTTP client. type Client struct { - hc *http.Client - baseURL *url.URL - token string + hc *http.Client + baseURL *url.URL + token string + maxBodySize int64 } // NewClient constructs a new client with the provided options (ex WithTimeout). @@ -26,8 +33,9 @@ func NewClient(host string, opts ...ClientOpt) (*Client, error) { return nil, err } c := &Client{ - hc: &http.Client{}, - baseURL: u, + hc: &http.Client{}, + baseURL: u, + maxBodySize: MaxBodySize, } for _, o := range opts { o(c) @@ -72,7 +80,7 @@ func (c *Client) NodeURL() string { // Get is a generic, opinionated GET function to reduce boilerplate amongst the getters in this package. func (c *Client) Get(ctx context.Context, path string, opts ...ReqOption) ([]byte, error) { u := c.baseURL.ResolveReference(&url.URL{Path: path}) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), http.NoBody) if err != nil { return nil, err } @@ -89,7 +97,7 @@ func (c *Client) Get(ctx context.Context, path string, opts ...ReqOption) ([]byt if r.StatusCode != http.StatusOK { return nil, Non200Err(r) } - b, err := io.ReadAll(r.Body) + b, err := io.ReadAll(io.LimitReader(r.Body, c.maxBodySize)) if err != nil { return nil, errors.Wrap(err, "error reading http response body") } diff --git a/api/client/errors.go b/api/client/errors.go index f3cf4f09a0e6..0599c667ddfb 100644 --- a/api/client/errors.go +++ b/api/client/errors.go @@ -25,16 +25,16 @@ var ErrInvalidNodeVersion = errors.New("invalid node version response") var ErrConnectionIssue = errors.New("could not connect") // Non200Err is a function that parses an HTTP response to handle responses that are not 200 with a formatted error. -func Non200Err(response *http.Response) error { - bodyBytes, err := io.ReadAll(response.Body) +func Non200Err(r *http.Response) error { + b, err := io.ReadAll(io.LimitReader(r.Body, MaxErrBodySize)) var body string if err != nil { body = "(Unable to read response body.)" } else { - body = "response body:\n" + string(bodyBytes) + body = "response body:\n" + string(b) } - msg := fmt.Sprintf("code=%d, url=%s, body=%s", response.StatusCode, response.Request.URL, body) - switch response.StatusCode { + msg := fmt.Sprintf("code=%d, url=%s, body=%s", r.StatusCode, r.Request.URL, body) + switch r.StatusCode { case http.StatusNotFound: return errors.Wrap(ErrNotFound, msg) default: diff --git a/api/client/event/event_stream.go b/api/client/event/event_stream.go index e85269038ddf..57187b8d5571 100644 --- a/api/client/event/event_stream.go +++ b/api/client/event/event_stream.go @@ -93,6 +93,7 @@ func (h *EventStream) Subscribe(eventsChannel chan<- *Event) { EventType: EventConnectionError, Data: []byte(errors.Wrap(err, client.ErrConnectionIssue.Error()).Error()), } + return } defer func() { diff --git a/api/client/event/event_stream_test.go b/api/client/event/event_stream_test.go index 66aa5c05f706..835e59f941b0 100644 --- a/api/client/event/event_stream_test.go +++ b/api/client/event/event_stream_test.go @@ -40,7 +40,7 @@ func TestNewEventStream(t *testing.T) { func TestEventStream(t *testing.T) { mux := http.NewServeMux() - mux.HandleFunc("/eth/v1/events", func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/eth/v1/events", func(w http.ResponseWriter, _ *http.Request) { flusher, ok := w.(http.Flusher) require.Equal(t, true, ok) for i := 1; i <= 3; i++ { @@ -79,3 +79,23 @@ func TestEventStream(t *testing.T) { } } } + +func TestEventStreamRequestError(t *testing.T) { + topics := []string{"head"} + eventsChannel := make(chan *Event, 1) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // use valid url that will result in failed request with nil body + stream, err := NewEventStream(ctx, http.DefaultClient, "http://badhost:1234", topics) + require.NoError(t, err) + + // error will happen when request is made, should be received over events channel + go stream.Subscribe(eventsChannel) + + event := <-eventsChannel + if event.EventType != EventConnectionError { + t.Errorf("Expected event type %q, got %q", EventConnectionError, event.EventType) + } + +} diff --git a/api/client/options.go b/api/client/options.go index e9ce6119bb82..31580ffec383 100644 --- a/api/client/options.go +++ b/api/client/options.go @@ -46,3 +46,10 @@ func WithAuthenticationToken(token string) ClientOpt { c.token = token } } + +// WithMaxBodySize overrides the default max body size of 8MB. +func WithMaxBodySize(size int64) ClientOpt { + return func(c *Client) { + c.maxBodySize = size + } +} diff --git a/api/gateway/BUILD.bazel b/api/gateway/BUILD.bazel deleted file mode 100644 index 0aafeb732956..000000000000 --- a/api/gateway/BUILD.bazel +++ /dev/null @@ -1,43 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "gateway.go", - "log.go", - "modifiers.go", - "options.go", - ], - importpath = "github.com/prysmaticlabs/prysm/v5/api/gateway", - visibility = [ - "//beacon-chain:__subpackages__", - "//validator:__subpackages__", - ], - deps = [ - "//api/server/middleware:go_default_library", - "//runtime:go_default_library", - "@com_github_gorilla_mux//:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", - "@org_golang_google_grpc//:go_default_library", - "@org_golang_google_grpc//connectivity:go_default_library", - "@org_golang_google_grpc//credentials:go_default_library", - "@org_golang_google_grpc//credentials/insecure:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["gateway_test.go"], - embed = [":go_default_library"], - deps = [ - "//cmd/beacon-chain/flags:go_default_library", - "//testing/assert:go_default_library", - "//testing/require:go_default_library", - "@com_github_gorilla_mux//:go_default_library", - "@com_github_sirupsen_logrus//hooks/test:go_default_library", - "@com_github_urfave_cli_v2//:go_default_library", - ], -) diff --git a/api/gateway/gateway.go b/api/gateway/gateway.go deleted file mode 100644 index 29d6365902ad..000000000000 --- a/api/gateway/gateway.go +++ /dev/null @@ -1,212 +0,0 @@ -// Package gateway defines a grpc-gateway server that serves HTTP-JSON traffic and acts a proxy between HTTP and gRPC. -package gateway - -import ( - "context" - "fmt" - "net" - "net/http" - "time" - - "github.com/gorilla/mux" - gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/api/server/middleware" - "github.com/prysmaticlabs/prysm/v5/runtime" - "google.golang.org/grpc" - "google.golang.org/grpc/connectivity" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/credentials/insecure" -) - -var _ runtime.Service = (*Gateway)(nil) - -// PbMux serves grpc-gateway requests for selected patterns using registered protobuf handlers. -type PbMux struct { - Registrations []PbHandlerRegistration // Protobuf registrations to be registered in Mux. - Patterns []string // URL patterns that will be handled by Mux. - Mux *gwruntime.ServeMux // The router that will be used for grpc-gateway requests. -} - -// PbHandlerRegistration is a function that registers a protobuf handler. -type PbHandlerRegistration func(context.Context, *gwruntime.ServeMux, *grpc.ClientConn) error - -// MuxHandler is a function that implements the mux handler functionality. -type MuxHandler func( - h http.HandlerFunc, - w http.ResponseWriter, - req *http.Request, -) - -// Config parameters for setting up the gateway service. -type config struct { - maxCallRecvMsgSize uint64 - remoteCert string - gatewayAddr string - remoteAddr string - allowedOrigins []string - muxHandler MuxHandler - pbHandlers []*PbMux - router *mux.Router - timeout time.Duration -} - -// Gateway is the gRPC gateway to serve HTTP JSON traffic as a proxy and forward it to the gRPC server. -type Gateway struct { - cfg *config - conn *grpc.ClientConn - server *http.Server - cancel context.CancelFunc - ctx context.Context - startFailure error -} - -// New returns a new instance of the Gateway. -func New(ctx context.Context, opts ...Option) (*Gateway, error) { - g := &Gateway{ - ctx: ctx, - cfg: &config{}, - } - for _, opt := range opts { - if err := opt(g); err != nil { - return nil, err - } - } - if g.cfg.router == nil { - g.cfg.router = mux.NewRouter() - } - return g, nil -} - -// Start the gateway service. -func (g *Gateway) Start() { - ctx, cancel := context.WithCancel(g.ctx) - g.cancel = cancel - - conn, err := g.dial(ctx, "tcp", g.cfg.remoteAddr) - if err != nil { - log.WithError(err).Error("Failed to connect to gRPC server") - g.startFailure = err - return - } - g.conn = conn - - for _, h := range g.cfg.pbHandlers { - for _, r := range h.Registrations { - if err := r(ctx, h.Mux, g.conn); err != nil { - log.WithError(err).Error("Failed to register handler") - g.startFailure = err - return - } - } - for _, p := range h.Patterns { - g.cfg.router.PathPrefix(p).Handler(h.Mux) - } - } - - corsMux := middleware.CorsHandler(g.cfg.allowedOrigins).Middleware(g.cfg.router) - - if g.cfg.muxHandler != nil { - g.cfg.router.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - g.cfg.muxHandler(corsMux.ServeHTTP, w, r) - }) - } - - g.server = &http.Server{ - Addr: g.cfg.gatewayAddr, - Handler: corsMux, - ReadHeaderTimeout: time.Second, - } - - go func() { - log.WithField("address", g.cfg.gatewayAddr).Info("Starting gRPC gateway") - if err := g.server.ListenAndServe(); err != http.ErrServerClosed { - log.WithError(err).Error("Failed to start gRPC gateway") - g.startFailure = err - return - } - }() -} - -// Status of grpc gateway. Returns an error if this service is unhealthy. -func (g *Gateway) Status() error { - if g.startFailure != nil { - return g.startFailure - } - if s := g.conn.GetState(); s != connectivity.Ready { - return fmt.Errorf("grpc server is %s", s) - } - return nil -} - -// Stop the gateway with a graceful shutdown. -func (g *Gateway) Stop() error { - if g.server != nil { - shutdownCtx, shutdownCancel := context.WithTimeout(g.ctx, 2*time.Second) - defer shutdownCancel() - if err := g.server.Shutdown(shutdownCtx); err != nil { - if errors.Is(err, context.DeadlineExceeded) { - log.Warn("Existing connections terminated") - } else { - log.WithError(err).Error("Failed to gracefully shut down server") - } - } - } - if g.cancel != nil { - g.cancel() - } - return nil -} - -// dial the gRPC server. -func (g *Gateway) dial(ctx context.Context, network, addr string) (*grpc.ClientConn, error) { - switch network { - case "tcp": - return g.dialTCP(ctx, addr) - case "unix": - return g.dialUnix(ctx, addr) - default: - return nil, fmt.Errorf("unsupported network type %q", network) - } -} - -// dialTCP creates a client connection via TCP. -// "addr" must be a valid TCP address with a port number. -func (g *Gateway) dialTCP(ctx context.Context, addr string) (*grpc.ClientConn, error) { - var security grpc.DialOption - if len(g.cfg.remoteCert) > 0 { - creds, err := credentials.NewClientTLSFromFile(g.cfg.remoteCert, "") - if err != nil { - return nil, err - } - security = grpc.WithTransportCredentials(creds) - } else { - // Use insecure credentials when there's no remote cert provided. - security = grpc.WithTransportCredentials(insecure.NewCredentials()) - } - opts := []grpc.DialOption{ - security, - grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(int(g.cfg.maxCallRecvMsgSize))), - } - return grpc.DialContext(ctx, addr, opts...) -} - -// dialUnix creates a client connection via a unix domain socket. -// "addr" must be a valid path to the socket. -func (g *Gateway) dialUnix(ctx context.Context, addr string) (*grpc.ClientConn, error) { - d := func(addr string, timeout time.Duration) (net.Conn, error) { - return net.DialTimeout("unix", addr, timeout) - } - f := func(ctx context.Context, addr string) (net.Conn, error) { - if deadline, ok := ctx.Deadline(); ok { - return d(addr, time.Until(deadline)) - } - return d(addr, 0) - } - opts := []grpc.DialOption{ - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithContextDialer(f), - grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(int(g.cfg.maxCallRecvMsgSize))), - } - return grpc.DialContext(ctx, addr, opts...) -} diff --git a/api/gateway/gateway_test.go b/api/gateway/gateway_test.go deleted file mode 100644 index d03d0dc28448..000000000000 --- a/api/gateway/gateway_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package gateway - -import ( - "context" - "flag" - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "github.com/gorilla/mux" - "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" - "github.com/prysmaticlabs/prysm/v5/testing/assert" - "github.com/prysmaticlabs/prysm/v5/testing/require" - logTest "github.com/sirupsen/logrus/hooks/test" - "github.com/urfave/cli/v2" -) - -func TestGateway_Customized(t *testing.T) { - r := mux.NewRouter() - cert := "cert" - origins := []string{"origin"} - size := uint64(100) - - opts := []Option{ - WithRouter(r), - WithRemoteCert(cert), - WithAllowedOrigins(origins), - WithMaxCallRecvMsgSize(size), - WithMuxHandler(func( - _ http.HandlerFunc, - _ http.ResponseWriter, - _ *http.Request, - ) { - }), - } - - g, err := New(context.Background(), opts...) - require.NoError(t, err) - - assert.Equal(t, r, g.cfg.router) - assert.Equal(t, cert, g.cfg.remoteCert) - require.Equal(t, 1, len(g.cfg.allowedOrigins)) - assert.Equal(t, origins[0], g.cfg.allowedOrigins[0]) - assert.Equal(t, size, g.cfg.maxCallRecvMsgSize) -} - -func TestGateway_StartStop(t *testing.T) { - hook := logTest.NewGlobal() - - app := cli.App{} - set := flag.NewFlagSet("test", 0) - ctx := cli.NewContext(&app, set, nil) - - gatewayPort := ctx.Int(flags.GRPCGatewayPort.Name) - gatewayHost := ctx.String(flags.GRPCGatewayHost.Name) - rpcHost := ctx.String(flags.RPCHost.Name) - selfAddress := fmt.Sprintf("%s:%d", rpcHost, ctx.Int(flags.RPCPort.Name)) - gatewayAddress := fmt.Sprintf("%s:%d", gatewayHost, gatewayPort) - - opts := []Option{ - WithGatewayAddr(gatewayAddress), - WithRemoteAddr(selfAddress), - WithMuxHandler(func( - _ http.HandlerFunc, - _ http.ResponseWriter, - _ *http.Request, - ) { - }), - } - - g, err := New(context.Background(), opts...) - require.NoError(t, err) - - g.Start() - go func() { - require.LogsContain(t, hook, "Starting gRPC gateway") - require.LogsDoNotContain(t, hook, "Starting API middleware") - }() - err = g.Stop() - require.NoError(t, err) -} - -func TestGateway_NilHandler_NotFoundHandlerRegistered(t *testing.T) { - app := cli.App{} - set := flag.NewFlagSet("test", 0) - ctx := cli.NewContext(&app, set, nil) - - gatewayPort := ctx.Int(flags.GRPCGatewayPort.Name) - gatewayHost := ctx.String(flags.GRPCGatewayHost.Name) - rpcHost := ctx.String(flags.RPCHost.Name) - selfAddress := fmt.Sprintf("%s:%d", rpcHost, ctx.Int(flags.RPCPort.Name)) - gatewayAddress := fmt.Sprintf("%s:%d", gatewayHost, gatewayPort) - - opts := []Option{ - WithGatewayAddr(gatewayAddress), - WithRemoteAddr(selfAddress), - } - - g, err := New(context.Background(), opts...) - require.NoError(t, err) - - writer := httptest.NewRecorder() - g.cfg.router.ServeHTTP(writer, &http.Request{Method: "GET", Host: "localhost", URL: &url.URL{Path: "/foo"}}) - assert.Equal(t, http.StatusNotFound, writer.Code) -} diff --git a/api/gateway/log.go b/api/gateway/log.go deleted file mode 100644 index fe3dcc54cd4d..000000000000 --- a/api/gateway/log.go +++ /dev/null @@ -1,5 +0,0 @@ -package gateway - -import "github.com/sirupsen/logrus" - -var log = logrus.WithField("prefix", "gateway") diff --git a/api/gateway/modifiers.go b/api/gateway/modifiers.go deleted file mode 100644 index dab4e608942f..000000000000 --- a/api/gateway/modifiers.go +++ /dev/null @@ -1,30 +0,0 @@ -package gateway - -import ( - "context" - "net/http" - "strconv" - - gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "google.golang.org/protobuf/proto" -) - -func HttpResponseModifier(ctx context.Context, w http.ResponseWriter, _ proto.Message) error { - md, ok := gwruntime.ServerMetadataFromContext(ctx) - if !ok { - return nil - } - // set http status code - if vals := md.HeaderMD.Get("x-http-code"); len(vals) > 0 { - code, err := strconv.Atoi(vals[0]) - if err != nil { - return err - } - // delete the headers to not expose any grpc-metadata in http response - delete(md.HeaderMD, "x-http-code") - delete(w.Header(), "Grpc-Metadata-X-Http-Code") - w.WriteHeader(code) - } - - return nil -} diff --git a/api/gateway/options.go b/api/gateway/options.go deleted file mode 100644 index f029314214f7..000000000000 --- a/api/gateway/options.go +++ /dev/null @@ -1,79 +0,0 @@ -package gateway - -import ( - "time" - - "github.com/gorilla/mux" - gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" -) - -type Option func(g *Gateway) error - -func WithPbHandlers(handlers []*PbMux) Option { - return func(g *Gateway) error { - g.cfg.pbHandlers = handlers - return nil - } -} - -func WithMuxHandler(m MuxHandler) Option { - return func(g *Gateway) error { - g.cfg.muxHandler = m - return nil - } -} - -func WithGatewayAddr(addr string) Option { - return func(g *Gateway) error { - g.cfg.gatewayAddr = addr - return nil - } -} - -func WithRemoteAddr(addr string) Option { - return func(g *Gateway) error { - g.cfg.remoteAddr = addr - return nil - } -} - -// WithRouter allows adding a custom mux router to the gateway. -func WithRouter(r *mux.Router) Option { - return func(g *Gateway) error { - g.cfg.router = r - return nil - } -} - -// WithAllowedOrigins allows adding a set of allowed origins to the gateway. -func WithAllowedOrigins(origins []string) Option { - return func(g *Gateway) error { - g.cfg.allowedOrigins = origins - return nil - } -} - -// WithRemoteCert allows adding a custom certificate to the gateway, -func WithRemoteCert(cert string) Option { - return func(g *Gateway) error { - g.cfg.remoteCert = cert - return nil - } -} - -// WithMaxCallRecvMsgSize allows specifying the maximum allowed gRPC message size. -func WithMaxCallRecvMsgSize(size uint64) Option { - return func(g *Gateway) error { - g.cfg.maxCallRecvMsgSize = size - return nil - } -} - -// WithTimeout allows changing the timeout value for API calls. -func WithTimeout(seconds uint64) Option { - return func(g *Gateway) error { - g.cfg.timeout = time.Second * time.Duration(seconds) - gwruntime.DefaultContextTimeout = time.Second * time.Duration(seconds) - return nil - } -} diff --git a/api/grpc/BUILD.bazel b/api/grpc/BUILD.bazel index 6ee34f669937..9284944b385b 100644 --- a/api/grpc/BUILD.bazel +++ b/api/grpc/BUILD.bazel @@ -22,9 +22,7 @@ go_test( deps = [ "//testing/assert:go_default_library", "//testing/require:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", - "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//metadata:go_default_library", ], ) diff --git a/api/grpc/grpcutils.go b/api/grpc/grpcutils.go index 53378b6c1a5f..d0dd8be5e484 100644 --- a/api/grpc/grpcutils.go +++ b/api/grpc/grpcutils.go @@ -2,8 +2,6 @@ package grpc import ( "context" - "encoding/json" - "fmt" "strings" "time" @@ -76,21 +74,8 @@ func AppendHeaders(parent context.Context, headers []string) context.Context { logrus.Warnf("Incorrect gRPC header flag format. Skipping %v", keyValue[0]) continue } - parent = metadata.AppendToOutgoingContext(parent, keyValue[0], strings.Join(keyValue[1:], "=")) + parent = metadata.AppendToOutgoingContext(parent, keyValue[0], strings.Join(keyValue[1:], "=")) // nolint:fatcontext } } return parent } - -// AppendCustomErrorHeader sets a CustomErrorMetadataKey gRPC header on the passed in context, -// using the passed in error data as the header's value. The data is serialized as JSON. -func AppendCustomErrorHeader(ctx context.Context, errorData interface{}) error { - j, err := json.Marshal(errorData) - if err != nil { - return fmt.Errorf("could not marshal error data into JSON: %w", err) - } - if err := grpc.SetHeader(ctx, metadata.Pairs(CustomErrorMetadataKey, string(j))); err != nil { - return fmt.Errorf("could not set custom error header: %w", err) - } - return nil -} diff --git a/api/grpc/grpcutils_test.go b/api/grpc/grpcutils_test.go index b7094319b4c1..8bae339a5637 100644 --- a/api/grpc/grpcutils_test.go +++ b/api/grpc/grpcutils_test.go @@ -2,15 +2,11 @@ package grpc import ( "context" - "encoding/json" - "strings" "testing" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" logTest "github.com/sirupsen/logrus/hooks/test" - "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) @@ -62,17 +58,3 @@ func TestAppendHeaders(t *testing.T) { assert.Equal(t, "value=1", md.Get("first")[0]) }) } - -func TestAppendCustomErrorHeader(t *testing.T) { - stream := &runtime.ServerTransportStream{} - ctx := grpc.NewContextWithServerTransportStream(context.Background(), stream) - data := &customErrorData{Message: "foo"} - require.NoError(t, AppendCustomErrorHeader(ctx, data)) - // The stream used in test setup sets the metadata key in lowercase. - value, ok := stream.Header()[strings.ToLower(CustomErrorMetadataKey)] - require.Equal(t, true, ok, "Failed to retrieve custom error metadata value") - expected, err := json.Marshal(data) - require.NoError(t, err) - assert.Equal(t, string(expected), value[0]) - -} diff --git a/api/headers.go b/api/headers.go index b3f7a29ab4be..69e279416c23 100644 --- a/api/headers.go +++ b/api/headers.go @@ -1,5 +1,7 @@ package api +import "net/http" + const ( VersionHeader = "Eth-Consensus-Version" ExecutionPayloadBlindedHeader = "Eth-Execution-Payload-Blinded" @@ -10,3 +12,9 @@ const ( EventStreamMediaType = "text/event-stream" KeepAlive = "keep-alive" ) + +// SetSSEHeaders sets the headers needed for a server-sent event response. +func SetSSEHeaders(w http.ResponseWriter) { + w.Header().Set("Content-Type", EventStreamMediaType) + w.Header().Set("Connection", KeepAlive) +} diff --git a/api/server/httprest/BUILD.bazel b/api/server/httprest/BUILD.bazel new file mode 100644 index 000000000000..f3c7465cf95a --- /dev/null +++ b/api/server/httprest/BUILD.bazel @@ -0,0 +1,31 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = [ + "log.go", + "options.go", + "server.go", + ], + importpath = "github.com/prysmaticlabs/prysm/v5/api/server/httprest", + visibility = ["//visibility:public"], + deps = [ + "//api/server/middleware:go_default_library", + "//runtime:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["server_test.go"], + embed = [":go_default_library"], + deps = [ + "//cmd/beacon-chain/flags:go_default_library", + "//testing/assert:go_default_library", + "//testing/require:go_default_library", + "@com_github_sirupsen_logrus//hooks/test:go_default_library", + "@com_github_urfave_cli_v2//:go_default_library", + ], +) diff --git a/api/server/httprest/log.go b/api/server/httprest/log.go new file mode 100644 index 000000000000..6208a403ea4d --- /dev/null +++ b/api/server/httprest/log.go @@ -0,0 +1,5 @@ +package httprest + +import "github.com/sirupsen/logrus" + +var log = logrus.WithField("prefix", "httprest") diff --git a/api/server/httprest/options.go b/api/server/httprest/options.go new file mode 100644 index 000000000000..98f4dac25464 --- /dev/null +++ b/api/server/httprest/options.go @@ -0,0 +1,44 @@ +package httprest + +import ( + "time" + + "net/http" + + "github.com/prysmaticlabs/prysm/v5/api/server/middleware" +) + +// Option is a http rest server functional parameter type. +type Option func(g *Server) error + +// WithMiddlewares sets the list of middlewares to be applied on routes. +func WithMiddlewares(mw []middleware.Middleware) Option { + return func(g *Server) error { + g.cfg.middlewares = mw + return nil + } +} + +// WithHTTPAddr sets the full address ( host and port ) of the server. +func WithHTTPAddr(addr string) Option { + return func(g *Server) error { + g.cfg.httpAddr = addr + return nil + } +} + +// WithRouter sets the internal router of the server, this is required. +func WithRouter(r *http.ServeMux) Option { + return func(g *Server) error { + g.cfg.router = r + return nil + } +} + +// WithTimeout allows changing the timeout value for API calls. +func WithTimeout(duration time.Duration) Option { + return func(g *Server) error { + g.cfg.timeout = duration + return nil + } +} diff --git a/api/server/httprest/server.go b/api/server/httprest/server.go new file mode 100644 index 000000000000..84eb9fdc3b2e --- /dev/null +++ b/api/server/httprest/server.go @@ -0,0 +1,101 @@ +package httprest + +import ( + "context" + "net/http" + "time" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api/server/middleware" + "github.com/prysmaticlabs/prysm/v5/runtime" +) + +var _ runtime.Service = (*Server)(nil) + +// Config parameters for setting up the http-rest service. +type config struct { + httpAddr string + middlewares []middleware.Middleware + router http.Handler + timeout time.Duration +} + +// Server serves HTTP traffic. +type Server struct { + cfg *config + server *http.Server + cancel context.CancelFunc + ctx context.Context + startFailure error +} + +// New returns a new instance of the Server. +func New(ctx context.Context, opts ...Option) (*Server, error) { + g := &Server{ + ctx: ctx, + cfg: &config{}, + } + for _, opt := range opts { + if err := opt(g); err != nil { + return nil, err + } + } + if g.cfg.router == nil { + return nil, errors.New("router option not configured") + } + var handler http.Handler + defaultReadHeaderTimeout := time.Second + handler = middleware.MiddlewareChain(g.cfg.router, g.cfg.middlewares) + if g.cfg.timeout > 0*time.Second { + defaultReadHeaderTimeout = g.cfg.timeout + handler = http.TimeoutHandler(handler, g.cfg.timeout, "request timed out") + } + g.server = &http.Server{ + Addr: g.cfg.httpAddr, + Handler: handler, + ReadHeaderTimeout: defaultReadHeaderTimeout, + } + + return g, nil +} + +// Start the http rest service. +func (g *Server) Start() { + g.ctx, g.cancel = context.WithCancel(g.ctx) + + go func() { + log.WithField("address", g.cfg.httpAddr).Info("Starting HTTP server") + if err := g.server.ListenAndServe(); err != http.ErrServerClosed { + log.WithError(err).Error("Failed to start HTTP server") + g.startFailure = err + return + } + }() +} + +// Status of the HTTP server. Returns an error if this service is unhealthy. +func (g *Server) Status() error { + if g.startFailure != nil { + return g.startFailure + } + return nil +} + +// Stop the HTTP server with a graceful shutdown. +func (g *Server) Stop() error { + if g.server != nil { + shutdownCtx, shutdownCancel := context.WithTimeout(g.ctx, 2*time.Second) + defer shutdownCancel() + if err := g.server.Shutdown(shutdownCtx); err != nil { + if errors.Is(err, context.DeadlineExceeded) { + log.Warn("Existing connections terminated") + } else { + log.WithError(err).Error("Failed to gracefully shut down server") + } + } + } + if g.cancel != nil { + g.cancel() + } + return nil +} diff --git a/api/server/httprest/server_test.go b/api/server/httprest/server_test.go new file mode 100644 index 000000000000..106e3503af8e --- /dev/null +++ b/api/server/httprest/server_test.go @@ -0,0 +1,71 @@ +package httprest + +import ( + "context" + "flag" + "fmt" + "net" + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" + logTest "github.com/sirupsen/logrus/hooks/test" + "github.com/urfave/cli/v2" +) + +func TestServer_StartStop(t *testing.T) { + hook := logTest.NewGlobal() + + app := cli.App{} + set := flag.NewFlagSet("test", 0) + ctx := cli.NewContext(&app, set, nil) + + port := ctx.Int(flags.HTTPServerPort.Name) + portStr := fmt.Sprintf("%d", port) // Convert port to string + host := ctx.String(flags.HTTPServerHost.Name) + address := net.JoinHostPort(host, portStr) + handler := http.NewServeMux() + opts := []Option{ + WithHTTPAddr(address), + WithRouter(handler), + } + + g, err := New(context.Background(), opts...) + require.NoError(t, err) + + g.Start() + go func() { + require.LogsContain(t, hook, "Starting HTTP server") + require.LogsDoNotContain(t, hook, "Starting API middleware") + }() + err = g.Stop() + require.NoError(t, err) +} + +func TestServer_NilHandler_NotFoundHandlerRegistered(t *testing.T) { + app := cli.App{} + set := flag.NewFlagSet("test", 0) + ctx := cli.NewContext(&app, set, nil) + + handler := http.NewServeMux() + port := ctx.Int(flags.HTTPServerPort.Name) + portStr := fmt.Sprintf("%d", port) // Convert port to string + host := ctx.String(flags.HTTPServerHost.Name) + address := net.JoinHostPort(host, portStr) + + opts := []Option{ + WithHTTPAddr(address), + WithRouter(handler), + } + + g, err := New(context.Background(), opts...) + require.NoError(t, err) + + writer := httptest.NewRecorder() + g.cfg.router.ServeHTTP(writer, &http.Request{Method: "GET", Host: "localhost", URL: &url.URL{Path: "/foo"}}) + assert.Equal(t, http.StatusNotFound, writer.Code) +} diff --git a/api/server/middleware/BUILD.bazel b/api/server/middleware/BUILD.bazel index c210e5049dad..a57086f8bf5e 100644 --- a/api/server/middleware/BUILD.bazel +++ b/api/server/middleware/BUILD.bazel @@ -8,10 +8,7 @@ go_library( ], importpath = "github.com/prysmaticlabs/prysm/v5/api/server/middleware", visibility = ["//visibility:public"], - deps = [ - "@com_github_gorilla_mux//:go_default_library", - "@com_github_rs_cors//:go_default_library", - ], + deps = ["@com_github_rs_cors//:go_default_library"], ) go_test( diff --git a/api/server/middleware/middleware.go b/api/server/middleware/middleware.go index b85e59e895b6..72883372609c 100644 --- a/api/server/middleware/middleware.go +++ b/api/server/middleware/middleware.go @@ -5,10 +5,11 @@ import ( "net/http" "strings" - "github.com/gorilla/mux" "github.com/rs/cors" ) +type Middleware func(http.Handler) http.Handler + // NormalizeQueryValuesHandler normalizes an input query of "key=value1,value2,value3" to "key=value1&key=value2&key=value3" func NormalizeQueryValuesHandler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -21,7 +22,7 @@ func NormalizeQueryValuesHandler(next http.Handler) http.Handler { } // CorsHandler sets the cors settings on api endpoints -func CorsHandler(allowOrigins []string) mux.MiddlewareFunc { +func CorsHandler(allowOrigins []string) Middleware { c := cors.New(cors.Options{ AllowedOrigins: allowOrigins, AllowedMethods: []string{http.MethodPost, http.MethodGet, http.MethodDelete, http.MethodOptions}, @@ -34,7 +35,7 @@ func CorsHandler(allowOrigins []string) mux.MiddlewareFunc { } // ContentTypeHandler checks request for the appropriate media types otherwise returning a http.StatusUnsupportedMediaType error -func ContentTypeHandler(acceptedMediaTypes []string) mux.MiddlewareFunc { +func ContentTypeHandler(acceptedMediaTypes []string) Middleware { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // skip the GET request @@ -67,7 +68,7 @@ func ContentTypeHandler(acceptedMediaTypes []string) mux.MiddlewareFunc { } // AcceptHeaderHandler checks if the client's response preference is handled -func AcceptHeaderHandler(serverAcceptedTypes []string) mux.MiddlewareFunc { +func AcceptHeaderHandler(serverAcceptedTypes []string) Middleware { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { acceptHeader := r.Header.Get("Accept") @@ -110,3 +111,15 @@ func AcceptHeaderHandler(serverAcceptedTypes []string) mux.MiddlewareFunc { }) } } + +func MiddlewareChain(h http.Handler, mw []Middleware) http.Handler { + if len(mw) < 1 { + return h + } + + wrapped := h + for i := len(mw) - 1; i >= 0; i-- { + wrapped = mw[i](wrapped) + } + return wrapped +} diff --git a/api/server/structs/BUILD.bazel b/api/server/structs/BUILD.bazel index df11af3b0221..a0decbcaabbd 100644 --- a/api/server/structs/BUILD.bazel +++ b/api/server/structs/BUILD.bazel @@ -4,8 +4,12 @@ go_library( name = "go_default_library", srcs = [ "block.go", + "block_execution.go", "conversions.go", + "conversions_blob.go", "conversions_block.go", + "conversions_block_execution.go", + "conversions_lightclient.go", "conversions_state.go", "endpoints_beacon.go", "endpoints_blob.go", @@ -26,6 +30,7 @@ go_library( "//api/server:go_default_library", "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", + "//config/params:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", @@ -33,7 +38,9 @@ go_library( "//encoding/bytesutil:go_default_library", "//math:go_default_library", "//proto/engine/v1:go_default_library", + "//proto/eth/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", @@ -42,10 +49,16 @@ go_library( go_test( name = "go_default_test", - srcs = ["conversions_test.go"], + srcs = [ + "conversions_block_execution_test.go", + "conversions_test.go", + ], embed = [":go_default_library"], deps = [ + "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", + "@com_github_ethereum_go_ethereum//common:go_default_library", + "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", ], ) diff --git a/api/server/structs/block.go b/api/server/structs/block.go index 7615f3653a4e..cb25e484c7e1 100644 --- a/api/server/structs/block.go +++ b/api/server/structs/block.go @@ -14,6 +14,10 @@ type SignedMessageJsoner interface { SigString() string } +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + type SignedBeaconBlock struct { Message *BeaconBlock `json:"message"` Signature string `json:"signature"` @@ -48,6 +52,29 @@ type BeaconBlockBody struct { VoluntaryExits []*SignedVoluntaryExit `json:"voluntary_exits"` } +type SignedBeaconBlockHeaderContainer struct { + Header *SignedBeaconBlockHeader `json:"header"` + Root string `json:"root"` + Canonical bool `json:"canonical"` +} + +type SignedBeaconBlockHeader struct { + Message *BeaconBlockHeader `json:"message"` + Signature string `json:"signature"` +} + +type BeaconBlockHeader struct { + Slot string `json:"slot"` + ProposerIndex string `json:"proposer_index"` + ParentRoot string `json:"parent_root"` + StateRoot string `json:"state_root"` + BodyRoot string `json:"body_root"` +} + +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- + type SignedBeaconBlockAltair struct { Message *BeaconBlockAltair `json:"message"` Signature string `json:"signature"` @@ -83,6 +110,10 @@ type BeaconBlockBodyAltair struct { SyncAggregate *SyncAggregate `json:"sync_aggregate"` } +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + type SignedBeaconBlockBellatrix struct { Message *BeaconBlockBellatrix `json:"message"` Signature string `json:"signature"` @@ -155,6 +186,10 @@ type BlindedBeaconBlockBodyBellatrix struct { ExecutionPayloadHeader *ExecutionPayloadHeader `json:"execution_payload_header"` } +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + type SignedBeaconBlockCapella struct { Message *BeaconBlockCapella `json:"message"` Signature string `json:"signature"` @@ -229,6 +264,10 @@ type BlindedBeaconBlockBodyCapella struct { BLSToExecutionChanges []*SignedBLSToExecutionChange `json:"bls_to_execution_changes"` } +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + type SignedBeaconBlockContentsDeneb struct { SignedBlock *SignedBeaconBlockDeneb `json:"signed_block"` KzgProofs []string `json:"kzg_proofs"` @@ -317,131 +356,150 @@ type BlindedBeaconBlockBodyDeneb struct { BlobKzgCommitments []string `json:"blob_kzg_commitments"` } -type SignedBeaconBlockHeaderContainer struct { - Header *SignedBeaconBlockHeader `json:"header"` - Root string `json:"root"` - Canonical bool `json:"canonical"` +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +type SignedBeaconBlockContentsElectra struct { + SignedBlock *SignedBeaconBlockElectra `json:"signed_block"` + KzgProofs []string `json:"kzg_proofs"` + Blobs []string `json:"blobs"` } -type SignedBeaconBlockHeader struct { - Message *BeaconBlockHeader `json:"message"` - Signature string `json:"signature"` +type BeaconBlockContentsElectra struct { + Block *BeaconBlockElectra `json:"block"` + KzgProofs []string `json:"kzg_proofs"` + Blobs []string `json:"blobs"` } -type BeaconBlockHeader struct { - Slot string `json:"slot"` - ProposerIndex string `json:"proposer_index"` - ParentRoot string `json:"parent_root"` - StateRoot string `json:"state_root"` - BodyRoot string `json:"body_root"` +type SignedBeaconBlockElectra struct { + Message *BeaconBlockElectra `json:"message"` + Signature string `json:"signature"` +} + +var _ SignedMessageJsoner = &SignedBeaconBlockElectra{} + +func (s *SignedBeaconBlockElectra) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBeaconBlockElectra) SigString() string { + return s.Signature +} + +type BeaconBlockElectra struct { + Slot string `json:"slot"` + ProposerIndex string `json:"proposer_index"` + ParentRoot string `json:"parent_root"` + StateRoot string `json:"state_root"` + Body *BeaconBlockBodyElectra `json:"body"` +} + +type BeaconBlockBodyElectra struct { + RandaoReveal string `json:"randao_reveal"` + Eth1Data *Eth1Data `json:"eth1_data"` + Graffiti string `json:"graffiti"` + ProposerSlashings []*ProposerSlashing `json:"proposer_slashings"` + AttesterSlashings []*AttesterSlashingElectra `json:"attester_slashings"` + Attestations []*AttestationElectra `json:"attestations"` + Deposits []*Deposit `json:"deposits"` + VoluntaryExits []*SignedVoluntaryExit `json:"voluntary_exits"` + SyncAggregate *SyncAggregate `json:"sync_aggregate"` + ExecutionPayload *ExecutionPayloadDeneb `json:"execution_payload"` + BLSToExecutionChanges []*SignedBLSToExecutionChange `json:"bls_to_execution_changes"` + BlobKzgCommitments []string `json:"blob_kzg_commitments"` + ExecutionRequests *ExecutionRequests `json:"execution_requests"` +} + +type BlindedBeaconBlockElectra struct { + Slot string `json:"slot"` + ProposerIndex string `json:"proposer_index"` + ParentRoot string `json:"parent_root"` + StateRoot string `json:"state_root"` + Body *BlindedBeaconBlockBodyElectra `json:"body"` +} + +type SignedBlindedBeaconBlockElectra struct { + Message *BlindedBeaconBlockElectra `json:"message"` + Signature string `json:"signature"` +} + +var _ SignedMessageJsoner = &SignedBlindedBeaconBlockElectra{} + +func (s *SignedBlindedBeaconBlockElectra) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBlindedBeaconBlockElectra) SigString() string { + return s.Signature +} + +type BlindedBeaconBlockBodyElectra struct { + RandaoReveal string `json:"randao_reveal"` + Eth1Data *Eth1Data `json:"eth1_data"` + Graffiti string `json:"graffiti"` + ProposerSlashings []*ProposerSlashing `json:"proposer_slashings"` + AttesterSlashings []*AttesterSlashingElectra `json:"attester_slashings"` + Attestations []*AttestationElectra `json:"attestations"` + Deposits []*Deposit `json:"deposits"` + VoluntaryExits []*SignedVoluntaryExit `json:"voluntary_exits"` + SyncAggregate *SyncAggregate `json:"sync_aggregate"` + ExecutionPayloadHeader *ExecutionPayloadHeaderDeneb `json:"execution_payload_header"` + BLSToExecutionChanges []*SignedBLSToExecutionChange `json:"bls_to_execution_changes"` + BlobKzgCommitments []string `json:"blob_kzg_commitments"` + ExecutionRequests *ExecutionRequests `json:"execution_requests"` +} + +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +type SignedBeaconBlockContentsFulu struct { + SignedBlock *SignedBeaconBlockFulu `json:"signed_block"` + KzgProofs []string `json:"kzg_proofs"` + Blobs []string `json:"blobs"` +} + +type BeaconBlockContentsFulu struct { + Block *BeaconBlockElectra `json:"block"` + KzgProofs []string `json:"kzg_proofs"` + Blobs []string `json:"blobs"` +} + +type SignedBeaconBlockFulu struct { + Message *BeaconBlockElectra `json:"message"` + Signature string `json:"signature"` +} + +var _ SignedMessageJsoner = &SignedBeaconBlockFulu{} + +func (s *SignedBeaconBlockFulu) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBeaconBlockFulu) SigString() string { + return s.Signature +} + +type BlindedBeaconBlockFulu struct { + Slot string `json:"slot"` + ProposerIndex string `json:"proposer_index"` + ParentRoot string `json:"parent_root"` + StateRoot string `json:"state_root"` + Body *BlindedBeaconBlockBodyElectra `json:"body"` } -type ExecutionPayload struct { - ParentHash string `json:"parent_hash"` - FeeRecipient string `json:"fee_recipient"` - StateRoot string `json:"state_root"` - ReceiptsRoot string `json:"receipts_root"` - LogsBloom string `json:"logs_bloom"` - PrevRandao string `json:"prev_randao"` - BlockNumber string `json:"block_number"` - GasLimit string `json:"gas_limit"` - GasUsed string `json:"gas_used"` - Timestamp string `json:"timestamp"` - ExtraData string `json:"extra_data"` - BaseFeePerGas string `json:"base_fee_per_gas"` - BlockHash string `json:"block_hash"` - Transactions []string `json:"transactions"` -} - -type ExecutionPayloadHeader struct { - ParentHash string `json:"parent_hash"` - FeeRecipient string `json:"fee_recipient"` - StateRoot string `json:"state_root"` - ReceiptsRoot string `json:"receipts_root"` - LogsBloom string `json:"logs_bloom"` - PrevRandao string `json:"prev_randao"` - BlockNumber string `json:"block_number"` - GasLimit string `json:"gas_limit"` - GasUsed string `json:"gas_used"` - Timestamp string `json:"timestamp"` - ExtraData string `json:"extra_data"` - BaseFeePerGas string `json:"base_fee_per_gas"` - BlockHash string `json:"block_hash"` - TransactionsRoot string `json:"transactions_root"` -} - -type ExecutionPayloadCapella struct { - ParentHash string `json:"parent_hash"` - FeeRecipient string `json:"fee_recipient"` - StateRoot string `json:"state_root"` - ReceiptsRoot string `json:"receipts_root"` - LogsBloom string `json:"logs_bloom"` - PrevRandao string `json:"prev_randao"` - BlockNumber string `json:"block_number"` - GasLimit string `json:"gas_limit"` - GasUsed string `json:"gas_used"` - Timestamp string `json:"timestamp"` - ExtraData string `json:"extra_data"` - BaseFeePerGas string `json:"base_fee_per_gas"` - BlockHash string `json:"block_hash"` - Transactions []string `json:"transactions"` - Withdrawals []*Withdrawal `json:"withdrawals"` -} - -type ExecutionPayloadHeaderCapella struct { - ParentHash string `json:"parent_hash"` - FeeRecipient string `json:"fee_recipient"` - StateRoot string `json:"state_root"` - ReceiptsRoot string `json:"receipts_root"` - LogsBloom string `json:"logs_bloom"` - PrevRandao string `json:"prev_randao"` - BlockNumber string `json:"block_number"` - GasLimit string `json:"gas_limit"` - GasUsed string `json:"gas_used"` - Timestamp string `json:"timestamp"` - ExtraData string `json:"extra_data"` - BaseFeePerGas string `json:"base_fee_per_gas"` - BlockHash string `json:"block_hash"` - TransactionsRoot string `json:"transactions_root"` - WithdrawalsRoot string `json:"withdrawals_root"` -} - -type ExecutionPayloadDeneb struct { - ParentHash string `json:"parent_hash"` - FeeRecipient string `json:"fee_recipient"` - StateRoot string `json:"state_root"` - ReceiptsRoot string `json:"receipts_root"` - LogsBloom string `json:"logs_bloom"` - PrevRandao string `json:"prev_randao"` - BlockNumber string `json:"block_number"` - GasLimit string `json:"gas_limit"` - GasUsed string `json:"gas_used"` - Timestamp string `json:"timestamp"` - ExtraData string `json:"extra_data"` - BaseFeePerGas string `json:"base_fee_per_gas"` - BlockHash string `json:"block_hash"` - Transactions []string `json:"transactions"` - Withdrawals []*Withdrawal `json:"withdrawals"` - BlobGasUsed string `json:"blob_gas_used"` - ExcessBlobGas string `json:"excess_blob_gas"` -} - -type ExecutionPayloadHeaderDeneb struct { - ParentHash string `json:"parent_hash"` - FeeRecipient string `json:"fee_recipient"` - StateRoot string `json:"state_root"` - ReceiptsRoot string `json:"receipts_root"` - LogsBloom string `json:"logs_bloom"` - PrevRandao string `json:"prev_randao"` - BlockNumber string `json:"block_number"` - GasLimit string `json:"gas_limit"` - GasUsed string `json:"gas_used"` - Timestamp string `json:"timestamp"` - ExtraData string `json:"extra_data"` - BaseFeePerGas string `json:"base_fee_per_gas"` - BlockHash string `json:"block_hash"` - TransactionsRoot string `json:"transactions_root"` - WithdrawalsRoot string `json:"withdrawals_root"` - BlobGasUsed string `json:"blob_gas_used"` - ExcessBlobGas string `json:"excess_blob_gas"` +type SignedBlindedBeaconBlockFulu struct { + Message *BlindedBeaconBlockFulu `json:"message"` + Signature string `json:"signature"` +} + +var _ SignedMessageJsoner = &SignedBlindedBeaconBlockFulu{} + +func (s *SignedBlindedBeaconBlockFulu) MessageRawJson() ([]byte, error) { + return json.Marshal(s.Message) +} + +func (s *SignedBlindedBeaconBlockFulu) SigString() string { + return s.Signature } diff --git a/api/server/structs/block_execution.go b/api/server/structs/block_execution.go new file mode 100644 index 000000000000..ab4f41831373 --- /dev/null +++ b/api/server/structs/block_execution.go @@ -0,0 +1,157 @@ +package structs + +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + +type ExecutionPayload struct { + ParentHash string `json:"parent_hash"` + FeeRecipient string `json:"fee_recipient"` + StateRoot string `json:"state_root"` + ReceiptsRoot string `json:"receipts_root"` + LogsBloom string `json:"logs_bloom"` + PrevRandao string `json:"prev_randao"` + BlockNumber string `json:"block_number"` + GasLimit string `json:"gas_limit"` + GasUsed string `json:"gas_used"` + Timestamp string `json:"timestamp"` + ExtraData string `json:"extra_data"` + BaseFeePerGas string `json:"base_fee_per_gas"` + BlockHash string `json:"block_hash"` + Transactions []string `json:"transactions"` +} + +type ExecutionPayloadHeader struct { + ParentHash string `json:"parent_hash"` + FeeRecipient string `json:"fee_recipient"` + StateRoot string `json:"state_root"` + ReceiptsRoot string `json:"receipts_root"` + LogsBloom string `json:"logs_bloom"` + PrevRandao string `json:"prev_randao"` + BlockNumber string `json:"block_number"` + GasLimit string `json:"gas_limit"` + GasUsed string `json:"gas_used"` + Timestamp string `json:"timestamp"` + ExtraData string `json:"extra_data"` + BaseFeePerGas string `json:"base_fee_per_gas"` + BlockHash string `json:"block_hash"` + TransactionsRoot string `json:"transactions_root"` +} + +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + +type ExecutionPayloadCapella struct { + ParentHash string `json:"parent_hash"` + FeeRecipient string `json:"fee_recipient"` + StateRoot string `json:"state_root"` + ReceiptsRoot string `json:"receipts_root"` + LogsBloom string `json:"logs_bloom"` + PrevRandao string `json:"prev_randao"` + BlockNumber string `json:"block_number"` + GasLimit string `json:"gas_limit"` + GasUsed string `json:"gas_used"` + Timestamp string `json:"timestamp"` + ExtraData string `json:"extra_data"` + BaseFeePerGas string `json:"base_fee_per_gas"` + BlockHash string `json:"block_hash"` + Transactions []string `json:"transactions"` + Withdrawals []*Withdrawal `json:"withdrawals"` +} + +type ExecutionPayloadHeaderCapella struct { + ParentHash string `json:"parent_hash"` + FeeRecipient string `json:"fee_recipient"` + StateRoot string `json:"state_root"` + ReceiptsRoot string `json:"receipts_root"` + LogsBloom string `json:"logs_bloom"` + PrevRandao string `json:"prev_randao"` + BlockNumber string `json:"block_number"` + GasLimit string `json:"gas_limit"` + GasUsed string `json:"gas_used"` + Timestamp string `json:"timestamp"` + ExtraData string `json:"extra_data"` + BaseFeePerGas string `json:"base_fee_per_gas"` + BlockHash string `json:"block_hash"` + TransactionsRoot string `json:"transactions_root"` + WithdrawalsRoot string `json:"withdrawals_root"` +} + +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + +type ExecutionPayloadDeneb struct { + ParentHash string `json:"parent_hash"` + FeeRecipient string `json:"fee_recipient"` + StateRoot string `json:"state_root"` + ReceiptsRoot string `json:"receipts_root"` + LogsBloom string `json:"logs_bloom"` + PrevRandao string `json:"prev_randao"` + BlockNumber string `json:"block_number"` + GasLimit string `json:"gas_limit"` + GasUsed string `json:"gas_used"` + Timestamp string `json:"timestamp"` + ExtraData string `json:"extra_data"` + BaseFeePerGas string `json:"base_fee_per_gas"` + BlockHash string `json:"block_hash"` + Transactions []string `json:"transactions"` + Withdrawals []*Withdrawal `json:"withdrawals"` + BlobGasUsed string `json:"blob_gas_used"` + ExcessBlobGas string `json:"excess_blob_gas"` +} + +type ExecutionPayloadHeaderDeneb struct { + ParentHash string `json:"parent_hash"` + FeeRecipient string `json:"fee_recipient"` + StateRoot string `json:"state_root"` + ReceiptsRoot string `json:"receipts_root"` + LogsBloom string `json:"logs_bloom"` + PrevRandao string `json:"prev_randao"` + BlockNumber string `json:"block_number"` + GasLimit string `json:"gas_limit"` + GasUsed string `json:"gas_used"` + Timestamp string `json:"timestamp"` + ExtraData string `json:"extra_data"` + BaseFeePerGas string `json:"base_fee_per_gas"` + BlockHash string `json:"block_hash"` + TransactionsRoot string `json:"transactions_root"` + WithdrawalsRoot string `json:"withdrawals_root"` + BlobGasUsed string `json:"blob_gas_used"` + ExcessBlobGas string `json:"excess_blob_gas"` +} + +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +type ExecutionRequests struct { + Deposits []*DepositRequest `json:"deposits"` + Withdrawals []*WithdrawalRequest `json:"withdrawals"` + Consolidations []*ConsolidationRequest `json:"consolidations"` +} + +type DepositRequest struct { + Pubkey string `json:"pubkey"` + WithdrawalCredentials string `json:"withdrawal_credentials"` + Amount string `json:"amount"` + Signature string `json:"signature"` + Index string `json:"index"` +} + +type WithdrawalRequest struct { + SourceAddress string `json:"source_address"` + ValidatorPubkey string `json:"validator_pubkey"` + Amount string `json:"amount"` +} + +type ConsolidationRequest struct { + SourceAddress string `json:"source_address"` + SourcePubkey string `json:"source_pubkey"` + TargetPubkey string `json:"target_pubkey"` +} + +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- diff --git a/api/server/structs/conversions.go b/api/server/structs/conversions.go index 6e1b66ed9852..ac305763f642 100644 --- a/api/server/structs/conversions.go +++ b/api/server/structs/conversions.go @@ -9,12 +9,14 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/server" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/container/slice" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/math" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) @@ -50,6 +52,9 @@ func HistoricalSummaryFromConsensus(s *eth.HistoricalSummary) *HistoricalSummary } func (s *SignedBLSToExecutionChange) ToConsensus() (*eth.SignedBLSToExecutionChange, error) { + if s.Message == nil { + return nil, server.NewDecodeError(errNilValue, "Message") + } change, err := s.Message.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Message") @@ -101,14 +106,17 @@ func SignedBLSChangeFromConsensus(ch *eth.SignedBLSToExecutionChange) *SignedBLS func SignedBLSChangesToConsensus(src []*SignedBLSToExecutionChange) ([]*eth.SignedBLSToExecutionChange, error) { if src == nil { - return nil, errNilValue + return nil, server.NewDecodeError(errNilValue, "SignedBLSToExecutionChanges") } err := slice.VerifyMaxLength(src, 16) if err != nil { - return nil, err + return nil, server.NewDecodeError(err, "SignedBLSToExecutionChanges") } changes := make([]*eth.SignedBLSToExecutionChange, len(src)) for i, ch := range src { + if ch == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i)) + } changes[i], err = ch.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, fmt.Sprintf("[%d]", i)) @@ -154,6 +162,9 @@ func ForkFromConsensus(f *eth.Fork) *Fork { } func (s *SignedValidatorRegistration) ToConsensus() (*eth.SignedValidatorRegistrationV1, error) { + if s.Message == nil { + return nil, server.NewDecodeError(errNilValue, "Message") + } msg, err := s.Message.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Message") @@ -210,6 +221,9 @@ func SignedValidatorRegistrationFromConsensus(vr *eth.SignedValidatorRegistratio } func (s *SignedContributionAndProof) ToConsensus() (*eth.SignedContributionAndProof, error) { + if s.Message == nil { + return nil, server.NewDecodeError(errNilValue, "Message") + } msg, err := s.Message.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Message") @@ -234,6 +248,9 @@ func SignedContributionAndProofFromConsensus(c *eth.SignedContributionAndProof) } func (c *ContributionAndProof) ToConsensus() (*eth.ContributionAndProof, error) { + if c.Contribution == nil { + return nil, server.NewDecodeError(errNilValue, "Contribution") + } contribution, err := c.Contribution.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Contribution") @@ -242,7 +259,7 @@ func (c *ContributionAndProof) ToConsensus() (*eth.ContributionAndProof, error) if err != nil { return nil, server.NewDecodeError(err, "AggregatorIndex") } - selectionProof, err := bytesutil.DecodeHexWithLength(c.SelectionProof, 96) + selectionProof, err := bytesutil.DecodeHexWithLength(c.SelectionProof, fieldparams.BLSSignatureLength) if err != nil { return nil, server.NewDecodeError(err, "SelectionProof") } @@ -305,6 +322,9 @@ func SyncCommitteeContributionFromConsensus(c *eth.SyncCommitteeContribution) *S } func (s *SignedAggregateAttestationAndProof) ToConsensus() (*eth.SignedAggregateAttestationAndProof, error) { + if s.Message == nil { + return nil, server.NewDecodeError(errNilValue, "Message") + } msg, err := s.Message.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Message") @@ -325,11 +345,14 @@ func (a *AggregateAttestationAndProof) ToConsensus() (*eth.AggregateAttestationA if err != nil { return nil, server.NewDecodeError(err, "AggregatorIndex") } + if a.Aggregate == nil { + return nil, server.NewDecodeError(errNilValue, "Aggregate") + } agg, err := a.Aggregate.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Aggregate") } - proof, err := bytesutil.DecodeHexWithLength(a.SelectionProof, 96) + proof, err := bytesutil.DecodeHexWithLength(a.SelectionProof, fieldparams.BLSSignatureLength) if err != nil { return nil, server.NewDecodeError(err, "SelectionProof") } @@ -340,11 +363,56 @@ func (a *AggregateAttestationAndProof) ToConsensus() (*eth.AggregateAttestationA }, nil } +func (s *SignedAggregateAttestationAndProofElectra) ToConsensus() (*eth.SignedAggregateAttestationAndProofElectra, error) { + if s.Message == nil { + return nil, server.NewDecodeError(errNilValue, "Message") + } + msg, err := s.Message.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Message") + } + sig, err := bytesutil.DecodeHexWithLength(s.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + + return ð.SignedAggregateAttestationAndProofElectra{ + Message: msg, + Signature: sig, + }, nil +} + +func (a *AggregateAttestationAndProofElectra) ToConsensus() (*eth.AggregateAttestationAndProofElectra, error) { + aggIndex, err := strconv.ParseUint(a.AggregatorIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "AggregatorIndex") + } + if a.Aggregate == nil { + return nil, server.NewDecodeError(errNilValue, "Aggregate") + } + agg, err := a.Aggregate.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Aggregate") + } + proof, err := bytesutil.DecodeHexWithLength(a.SelectionProof, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "SelectionProof") + } + return ð.AggregateAttestationAndProofElectra{ + AggregatorIndex: primitives.ValidatorIndex(aggIndex), + Aggregate: agg, + SelectionProof: proof, + }, nil +} + func (a *Attestation) ToConsensus() (*eth.Attestation, error) { aggBits, err := hexutil.Decode(a.AggregationBits) if err != nil { return nil, server.NewDecodeError(err, "AggregationBits") } + if a.Data == nil { + return nil, server.NewDecodeError(errNilValue, "Data") + } data, err := a.Data.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Data") @@ -369,6 +437,82 @@ func AttFromConsensus(a *eth.Attestation) *Attestation { } } +func (a *AttestationElectra) ToConsensus() (*eth.AttestationElectra, error) { + aggBits, err := hexutil.Decode(a.AggregationBits) + if err != nil { + return nil, server.NewDecodeError(err, "AggregationBits") + } + if a.Data == nil { + return nil, server.NewDecodeError(errNilValue, "Data") + } + data, err := a.Data.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Data") + } + sig, err := bytesutil.DecodeHexWithLength(a.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + committeeBits, err := hexutil.Decode(a.CommitteeBits) + if err != nil { + return nil, server.NewDecodeError(err, "CommitteeBits") + } + + return ð.AttestationElectra{ + AggregationBits: aggBits, + Data: data, + Signature: sig, + CommitteeBits: committeeBits, + }, nil +} + +func SingleAttFromConsensus(a *eth.SingleAttestation) *SingleAttestation { + return &SingleAttestation{ + CommitteeIndex: fmt.Sprintf("%d", a.CommitteeId), + AttesterIndex: fmt.Sprintf("%d", a.AttesterIndex), + Data: AttDataFromConsensus(a.Data), + Signature: hexutil.Encode(a.Signature), + } +} + +func (a *SingleAttestation) ToConsensus() (*eth.SingleAttestation, error) { + ci, err := strconv.ParseUint(a.CommitteeIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "CommitteeIndex") + } + ai, err := strconv.ParseUint(a.AttesterIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "AttesterIndex") + } + if a.Data == nil { + return nil, server.NewDecodeError(errNilValue, "Data") + } + data, err := a.Data.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Data") + } + sig, err := bytesutil.DecodeHexWithLength(a.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + + return ð.SingleAttestation{ + CommitteeId: primitives.CommitteeIndex(ci), + AttesterIndex: primitives.ValidatorIndex(ai), + Data: data, + Signature: sig, + }, nil +} + +func AttElectraFromConsensus(a *eth.AttestationElectra) *AttestationElectra { + return &AttestationElectra{ + AggregationBits: hexutil.Encode(a.AggregationBits), + Data: AttDataFromConsensus(a.Data), + Signature: hexutil.Encode(a.Signature), + CommitteeBits: hexutil.Encode(a.CommitteeBits), + } +} + func (a *AttestationData) ToConsensus() (*eth.AttestationData, error) { slot, err := strconv.ParseUint(a.Slot, 10, 64) if err != nil { @@ -382,10 +526,16 @@ func (a *AttestationData) ToConsensus() (*eth.AttestationData, error) { if err != nil { return nil, server.NewDecodeError(err, "BeaconBlockRoot") } + if a.Source == nil { + return nil, server.NewDecodeError(errNilValue, "Source") + } source, err := a.Source.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Source") } + if a.Target == nil { + return nil, server.NewDecodeError(errNilValue, "Target") + } target, err := a.Target.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Target") @@ -485,15 +635,17 @@ func (b *BeaconCommitteeSubscription) ToConsensus() (*validator.BeaconCommitteeS } func (e *SignedVoluntaryExit) ToConsensus() (*eth.SignedVoluntaryExit, error) { - sig, err := bytesutil.DecodeHexWithLength(e.Signature, fieldparams.BLSSignatureLength) - if err != nil { - return nil, server.NewDecodeError(err, "Signature") + if e.Message == nil { + return nil, server.NewDecodeError(errNilValue, "Message") } exit, err := e.Message.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Message") } - + sig, err := bytesutil.DecodeHexWithLength(e.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } return ð.SignedVoluntaryExit{ Exit: exit, Signature: sig, @@ -596,10 +748,16 @@ func Eth1DataFromConsensus(e1d *eth.Eth1Data) *Eth1Data { } func (s *ProposerSlashing) ToConsensus() (*eth.ProposerSlashing, error) { + if s.SignedHeader1 == nil { + return nil, server.NewDecodeError(errNilValue, "SignedHeader1") + } h1, err := s.SignedHeader1.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "SignedHeader1") } + if s.SignedHeader2 == nil { + return nil, server.NewDecodeError(errNilValue, "SignedHeader2") + } h2, err := s.SignedHeader2.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "SignedHeader2") @@ -612,10 +770,16 @@ func (s *ProposerSlashing) ToConsensus() (*eth.ProposerSlashing, error) { } func (s *AttesterSlashing) ToConsensus() (*eth.AttesterSlashing, error) { + if s.Attestation1 == nil { + return nil, server.NewDecodeError(errNilValue, "Attestation1") + } att1, err := s.Attestation1.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Attestation1") } + if s.Attestation2 == nil { + return nil, server.NewDecodeError(errNilValue, "Attestation2") + } att2, err := s.Attestation2.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Attestation2") @@ -623,7 +787,29 @@ func (s *AttesterSlashing) ToConsensus() (*eth.AttesterSlashing, error) { return ð.AttesterSlashing{Attestation_1: att1, Attestation_2: att2}, nil } +func (s *AttesterSlashingElectra) ToConsensus() (*eth.AttesterSlashingElectra, error) { + if s.Attestation1 == nil { + return nil, server.NewDecodeError(errNilValue, "Attestation1") + } + att1, err := s.Attestation1.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Attestation1") + } + if s.Attestation2 == nil { + return nil, server.NewDecodeError(errNilValue, "Attestation2") + } + att2, err := s.Attestation2.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Attestation2") + } + return ð.AttesterSlashingElectra{Attestation_1: att1, Attestation_2: att2}, nil +} + func (a *IndexedAttestation) ToConsensus() (*eth.IndexedAttestation, error) { + if err := slice.VerifyMaxLength(a.AttestingIndices, params.BeaconConfig().MaxValidatorsPerCommittee); err != nil { + return nil, err + } + indices := make([]uint64, len(a.AttestingIndices)) var err error for i, ix := range a.AttestingIndices { @@ -632,6 +818,9 @@ func (a *IndexedAttestation) ToConsensus() (*eth.IndexedAttestation, error) { return nil, server.NewDecodeError(err, fmt.Sprintf("AttestingIndices[%d]", i)) } } + if a.Data == nil { + return nil, server.NewDecodeError(errNilValue, "Data") + } data, err := a.Data.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Data") @@ -648,6 +837,41 @@ func (a *IndexedAttestation) ToConsensus() (*eth.IndexedAttestation, error) { }, nil } +func (a *IndexedAttestationElectra) ToConsensus() (*eth.IndexedAttestationElectra, error) { + if err := slice.VerifyMaxLength( + a.AttestingIndices, + params.BeaconConfig().MaxValidatorsPerCommittee*params.BeaconConfig().MaxCommitteesPerSlot, + ); err != nil { + return nil, err + } + + indices := make([]uint64, len(a.AttestingIndices)) + var err error + for i, ix := range a.AttestingIndices { + indices[i], err = strconv.ParseUint(ix, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("AttestingIndices[%d]", i)) + } + } + if a.Data == nil { + return nil, server.NewDecodeError(errNilValue, "Data") + } + data, err := a.Data.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Data") + } + sig, err := bytesutil.DecodeHexWithLength(a.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + + return ð.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: data, + Signature: sig, + }, nil +} + func WithdrawalsFromConsensus(ws []*enginev1.Withdrawal) []*Withdrawal { result := make([]*Withdrawal, len(ws)) for i, w := range ws { @@ -667,11 +891,11 @@ func WithdrawalFromConsensus(w *enginev1.Withdrawal) *Withdrawal { func ProposerSlashingsToConsensus(src []*ProposerSlashing) ([]*eth.ProposerSlashing, error) { if src == nil { - return nil, errNilValue + return nil, server.NewDecodeError(errNilValue, "ProposerSlashings") } err := slice.VerifyMaxLength(src, 16) if err != nil { - return nil, err + return nil, server.NewDecodeError(err, "ProposerSlashings") } proposerSlashings := make([]*eth.ProposerSlashing, len(src)) for i, s := range src { @@ -800,11 +1024,11 @@ func ProposerSlashingFromConsensus(src *eth.ProposerSlashing) *ProposerSlashing func AttesterSlashingsToConsensus(src []*AttesterSlashing) ([]*eth.AttesterSlashing, error) { if src == nil { - return nil, errNilValue + return nil, server.NewDecodeError(errNilValue, "AttesterSlashings") } err := slice.VerifyMaxLength(src, 2) if err != nil { - return nil, err + return nil, server.NewDecodeError(err, "AttesterSlashings") } attesterSlashings := make([]*eth.AttesterSlashing, len(src)) @@ -815,10 +1039,19 @@ func AttesterSlashingsToConsensus(src []*AttesterSlashing) ([]*eth.AttesterSlash if s.Attestation1 == nil { return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation1", i)) } + + if s.Attestation1.Data == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation1.Data", i)) + } + if s.Attestation2 == nil { return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation2", i)) } + if s.Attestation2.Data == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation2.Data", i)) + } + a1Sig, err := bytesutil.DecodeHexWithLength(s.Attestation1.Signature, fieldparams.BLSSignatureLength) if err != nil { return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.Signature", i)) @@ -835,6 +1068,7 @@ func AttesterSlashingsToConsensus(src []*AttesterSlashing) ([]*eth.AttesterSlash } a1AttestingIndices[j] = attestingIndex } + a1Data, err := s.Attestation1.Data.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.Data", i)) @@ -930,17 +1164,162 @@ func AttesterSlashingFromConsensus(src *eth.AttesterSlashing) *AttesterSlashing } } +func AttesterSlashingsElectraToConsensus(src []*AttesterSlashingElectra) ([]*eth.AttesterSlashingElectra, error) { + if src == nil { + return nil, server.NewDecodeError(errNilValue, "AttesterSlashingsElectra") + } + err := slice.VerifyMaxLength(src, fieldparams.MaxAttesterSlashingsElectra) + if err != nil { + return nil, server.NewDecodeError(err, "AttesterSlashingsElectra") + } + + attesterSlashings := make([]*eth.AttesterSlashingElectra, len(src)) + for i, s := range src { + if s == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i)) + } + + if s.Attestation1 == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation1", i)) + } + + if s.Attestation1.Data == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation1.Data", i)) + } + + if s.Attestation2 == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation2", i)) + } + + if s.Attestation2.Data == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d].Attestation2.Data", i)) + } + + a1Sig, err := bytesutil.DecodeHexWithLength(s.Attestation1.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.Signature", i)) + } + err = slice.VerifyMaxLength(s.Attestation1.AttestingIndices, params.BeaconConfig().MaxValidatorsPerCommittee*params.BeaconConfig().MaxCommitteesPerSlot) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.AttestingIndices", i)) + } + a1AttestingIndices := make([]uint64, len(s.Attestation1.AttestingIndices)) + for j, ix := range s.Attestation1.AttestingIndices { + attestingIndex, err := strconv.ParseUint(ix, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.AttestingIndices[%d]", i, j)) + } + a1AttestingIndices[j] = attestingIndex + } + a1Data, err := s.Attestation1.Data.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation1.Data", i)) + } + a2Sig, err := bytesutil.DecodeHexWithLength(s.Attestation2.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation2.Signature", i)) + } + err = slice.VerifyMaxLength(s.Attestation2.AttestingIndices, params.BeaconConfig().MaxValidatorsPerCommittee*params.BeaconConfig().MaxCommitteesPerSlot) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation2.AttestingIndices", i)) + } + a2AttestingIndices := make([]uint64, len(s.Attestation2.AttestingIndices)) + for j, ix := range s.Attestation2.AttestingIndices { + attestingIndex, err := strconv.ParseUint(ix, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation2.AttestingIndices[%d]", i, j)) + } + a2AttestingIndices[j] = attestingIndex + } + a2Data, err := s.Attestation2.Data.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d].Attestation2.Data", i)) + } + attesterSlashings[i] = ð.AttesterSlashingElectra{ + Attestation_1: ð.IndexedAttestationElectra{ + AttestingIndices: a1AttestingIndices, + Data: a1Data, + Signature: a1Sig, + }, + Attestation_2: ð.IndexedAttestationElectra{ + AttestingIndices: a2AttestingIndices, + Data: a2Data, + Signature: a2Sig, + }, + } + } + return attesterSlashings, nil +} + +func AttesterSlashingsElectraFromConsensus(src []*eth.AttesterSlashingElectra) []*AttesterSlashingElectra { + attesterSlashings := make([]*AttesterSlashingElectra, len(src)) + for i, s := range src { + attesterSlashings[i] = AttesterSlashingElectraFromConsensus(s) + } + return attesterSlashings +} + +func AttesterSlashingElectraFromConsensus(src *eth.AttesterSlashingElectra) *AttesterSlashingElectra { + a1AttestingIndices := make([]string, len(src.Attestation_1.AttestingIndices)) + for j, ix := range src.Attestation_1.AttestingIndices { + a1AttestingIndices[j] = fmt.Sprintf("%d", ix) + } + a2AttestingIndices := make([]string, len(src.Attestation_2.AttestingIndices)) + for j, ix := range src.Attestation_2.AttestingIndices { + a2AttestingIndices[j] = fmt.Sprintf("%d", ix) + } + return &AttesterSlashingElectra{ + Attestation1: &IndexedAttestationElectra{ + AttestingIndices: a1AttestingIndices, + Data: &AttestationData{ + Slot: fmt.Sprintf("%d", src.Attestation_1.Data.Slot), + CommitteeIndex: fmt.Sprintf("%d", src.Attestation_1.Data.CommitteeIndex), + BeaconBlockRoot: hexutil.Encode(src.Attestation_1.Data.BeaconBlockRoot), + Source: &Checkpoint{ + Epoch: fmt.Sprintf("%d", src.Attestation_1.Data.Source.Epoch), + Root: hexutil.Encode(src.Attestation_1.Data.Source.Root), + }, + Target: &Checkpoint{ + Epoch: fmt.Sprintf("%d", src.Attestation_1.Data.Target.Epoch), + Root: hexutil.Encode(src.Attestation_1.Data.Target.Root), + }, + }, + Signature: hexutil.Encode(src.Attestation_1.Signature), + }, + Attestation2: &IndexedAttestationElectra{ + AttestingIndices: a2AttestingIndices, + Data: &AttestationData{ + Slot: fmt.Sprintf("%d", src.Attestation_2.Data.Slot), + CommitteeIndex: fmt.Sprintf("%d", src.Attestation_2.Data.CommitteeIndex), + BeaconBlockRoot: hexutil.Encode(src.Attestation_2.Data.BeaconBlockRoot), + Source: &Checkpoint{ + Epoch: fmt.Sprintf("%d", src.Attestation_2.Data.Source.Epoch), + Root: hexutil.Encode(src.Attestation_2.Data.Source.Root), + }, + Target: &Checkpoint{ + Epoch: fmt.Sprintf("%d", src.Attestation_2.Data.Target.Epoch), + Root: hexutil.Encode(src.Attestation_2.Data.Target.Root), + }, + }, + Signature: hexutil.Encode(src.Attestation_2.Signature), + }, + } +} + func AttsToConsensus(src []*Attestation) ([]*eth.Attestation, error) { if src == nil { - return nil, errNilValue + return nil, server.NewDecodeError(errNilValue, "Attestations") } err := slice.VerifyMaxLength(src, 128) if err != nil { - return nil, err + return nil, server.NewDecodeError(err, "Attestations") } atts := make([]*eth.Attestation, len(src)) for i, a := range src { + if a == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i)) + } atts[i], err = a.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, fmt.Sprintf("[%d]", i)) @@ -957,13 +1336,43 @@ func AttsFromConsensus(src []*eth.Attestation) []*Attestation { return atts } +func AttsElectraToConsensus(src []*AttestationElectra) ([]*eth.AttestationElectra, error) { + if src == nil { + return nil, server.NewDecodeError(errNilValue, "AttestationsElectra") + } + err := slice.VerifyMaxLength(src, 8) + if err != nil { + return nil, server.NewDecodeError(err, "AttestationsElectra") + } + + atts := make([]*eth.AttestationElectra, len(src)) + for i, a := range src { + if a == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i)) + } + atts[i], err = a.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("[%d]", i)) + } + } + return atts, nil +} + +func AttsElectraFromConsensus(src []*eth.AttestationElectra) []*AttestationElectra { + atts := make([]*AttestationElectra, len(src)) + for i, a := range src { + atts[i] = AttElectraFromConsensus(a) + } + return atts +} + func DepositsToConsensus(src []*Deposit) ([]*eth.Deposit, error) { if src == nil { - return nil, errNilValue + return nil, server.NewDecodeError(errNilValue, "Deposits") } err := slice.VerifyMaxLength(src, 16) if err != nil { - return nil, err + return nil, server.NewDecodeError(err, "Deposits") } deposits := make([]*eth.Deposit, len(src)) @@ -1035,15 +1444,18 @@ func DepositsFromConsensus(src []*eth.Deposit) []*Deposit { func SignedExitsToConsensus(src []*SignedVoluntaryExit) ([]*eth.SignedVoluntaryExit, error) { if src == nil { - return nil, errNilValue + return nil, server.NewDecodeError(errNilValue, "SignedVoluntaryExits") } err := slice.VerifyMaxLength(src, 16) if err != nil { - return nil, err + return nil, server.NewDecodeError(err, "SignedVoluntaryExits") } exits := make([]*eth.SignedVoluntaryExit, len(src)) for i, e := range src { + if e == nil { + return nil, server.NewDecodeError(errNilValue, fmt.Sprintf("[%d]", i)) + } exits[i], err = e.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, fmt.Sprintf("[%d]", i)) @@ -1087,3 +1499,81 @@ func DepositSnapshotFromConsensus(ds *eth.DepositSnapshot) *DepositSnapshot { ExecutionBlockHeight: fmt.Sprintf("%d", ds.ExecutionDepth), } } + +func PendingDepositsFromConsensus(ds []*eth.PendingDeposit) []*PendingDeposit { + deposits := make([]*PendingDeposit, len(ds)) + for i, d := range ds { + deposits[i] = &PendingDeposit{ + Pubkey: hexutil.Encode(d.PublicKey), + WithdrawalCredentials: hexutil.Encode(d.WithdrawalCredentials), + Amount: fmt.Sprintf("%d", d.Amount), + Signature: hexutil.Encode(d.Signature), + Slot: fmt.Sprintf("%d", d.Slot), + } + } + return deposits +} + +func PendingPartialWithdrawalsFromConsensus(ws []*eth.PendingPartialWithdrawal) []*PendingPartialWithdrawal { + withdrawals := make([]*PendingPartialWithdrawal, len(ws)) + for i, w := range ws { + withdrawals[i] = &PendingPartialWithdrawal{ + Index: fmt.Sprintf("%d", w.Index), + Amount: fmt.Sprintf("%d", w.Amount), + WithdrawableEpoch: fmt.Sprintf("%d", w.WithdrawableEpoch), + } + } + return withdrawals +} + +func PendingConsolidationsFromConsensus(cs []*eth.PendingConsolidation) []*PendingConsolidation { + consolidations := make([]*PendingConsolidation, len(cs)) + for i, c := range cs { + consolidations[i] = &PendingConsolidation{ + SourceIndex: fmt.Sprintf("%d", c.SourceIndex), + TargetIndex: fmt.Sprintf("%d", c.TargetIndex), + } + } + return consolidations +} + +func HeadEventFromV1(event *ethv1.EventHead) *HeadEvent { + return &HeadEvent{ + Slot: fmt.Sprintf("%d", event.Slot), + Block: hexutil.Encode(event.Block), + State: hexutil.Encode(event.State), + EpochTransition: event.EpochTransition, + ExecutionOptimistic: event.ExecutionOptimistic, + PreviousDutyDependentRoot: hexutil.Encode(event.PreviousDutyDependentRoot), + CurrentDutyDependentRoot: hexutil.Encode(event.CurrentDutyDependentRoot), + } +} + +func FinalizedCheckpointEventFromV1(event *ethv1.EventFinalizedCheckpoint) *FinalizedCheckpointEvent { + return &FinalizedCheckpointEvent{ + Block: hexutil.Encode(event.Block), + State: hexutil.Encode(event.State), + Epoch: fmt.Sprintf("%d", event.Epoch), + ExecutionOptimistic: event.ExecutionOptimistic, + } +} + +func EventChainReorgFromV1(event *ethv1.EventChainReorg) *ChainReorgEvent { + return &ChainReorgEvent{ + Slot: fmt.Sprintf("%d", event.Slot), + Depth: fmt.Sprintf("%d", event.Depth), + OldHeadBlock: hexutil.Encode(event.OldHeadBlock), + NewHeadBlock: hexutil.Encode(event.NewHeadBlock), + OldHeadState: hexutil.Encode(event.OldHeadState), + NewHeadState: hexutil.Encode(event.NewHeadState), + Epoch: fmt.Sprintf("%d", event.Epoch), + ExecutionOptimistic: event.ExecutionOptimistic, + } +} + +func SyncAggregateFromConsensus(sa *eth.SyncAggregate) *SyncAggregate { + return &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(sa.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(sa.SyncCommitteeSignature), + } +} diff --git a/api/server/structs/conversions_blob.go b/api/server/structs/conversions_blob.go new file mode 100644 index 000000000000..3d153dc09c9e --- /dev/null +++ b/api/server/structs/conversions_blob.go @@ -0,0 +1,61 @@ +package structs + +import ( + "strconv" + + "github.com/prysmaticlabs/prysm/v5/api/server" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" +) + +func (sc *Sidecar) ToConsensus() (*eth.BlobSidecar, error) { + if sc == nil { + return nil, errNilValue + } + + index, err := strconv.ParseUint(sc.Index, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Index") + } + + blob, err := bytesutil.DecodeHexWithLength(sc.Blob, 131072) + if err != nil { + return nil, server.NewDecodeError(err, "Blob") + } + + kzgCommitment, err := bytesutil.DecodeHexWithLength(sc.KzgCommitment, 48) + if err != nil { + return nil, server.NewDecodeError(err, "KzgCommitment") + } + + kzgProof, err := bytesutil.DecodeHexWithLength(sc.KzgProof, 48) + if err != nil { + return nil, server.NewDecodeError(err, "KzgProof") + } + + header, err := sc.SignedBeaconBlockHeader.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "SignedBeaconBlockHeader") + } + + // decode the commitment inclusion proof + var commitmentInclusionProof [][]byte + for _, proof := range sc.CommitmentInclusionProof { + proofBytes, err := bytesutil.DecodeHexWithLength(proof, 32) + if err != nil { + return nil, server.NewDecodeError(err, "CommitmentInclusionProof") + } + commitmentInclusionProof = append(commitmentInclusionProof, proofBytes) + } + + bsc := ð.BlobSidecar{ + Index: index, + Blob: blob, + KzgCommitment: kzgCommitment, + KzgProof: kzgProof, + SignedBlockHeader: header, + CommitmentInclusionProof: commitmentInclusionProof, + } + + return bsc, nil +} diff --git a/api/server/structs/conversions_block.go b/api/server/structs/conversions_block.go index 6a3f4e912997..166ac2573b15 100644 --- a/api/server/structs/conversions_block.go +++ b/api/server/structs/conversions_block.go @@ -19,7 +19,14 @@ import ( var ErrUnsupportedConversion = errors.New("Could not determine api struct type to use for value") +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + func (h *SignedBeaconBlockHeader) ToConsensus() (*eth.SignedBeaconBlockHeader, error) { + if h == nil { + return nil, errNilValue + } msg, err := h.Message.ToConsensus() if err != nil { return nil, server.NewDecodeError(err, "Message") @@ -36,6 +43,9 @@ func (h *SignedBeaconBlockHeader) ToConsensus() (*eth.SignedBeaconBlockHeader, e } func (h *BeaconBlockHeader) ToConsensus() (*eth.BeaconBlockHeader, error) { + if h == nil { + return nil, errNilValue + } s, err := strconv.ParseUint(h.Slot, 10, 64) if err != nil { return nil, server.NewDecodeError(err, "Slot") @@ -199,6 +209,81 @@ func (b *BeaconBlock) ToConsensus() (*eth.BeaconBlock, error) { }, nil } +func BeaconBlockHeaderFromConsensus(h *eth.BeaconBlockHeader) *BeaconBlockHeader { + return &BeaconBlockHeader{ + Slot: fmt.Sprintf("%d", h.Slot), + ProposerIndex: fmt.Sprintf("%d", h.ProposerIndex), + ParentRoot: hexutil.Encode(h.ParentRoot), + StateRoot: hexutil.Encode(h.StateRoot), + BodyRoot: hexutil.Encode(h.BodyRoot), + } +} + +func BeaconBlockFromConsensus(b *eth.BeaconBlock) *BeaconBlock { + return &BeaconBlock{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BeaconBlockBody{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + }, + } +} + +func SignedBeaconBlockMessageJsoner(block interfaces.ReadOnlySignedBeaconBlock) (SignedMessageJsoner, error) { + pb, err := block.Proto() + if err != nil { + return nil, err + } + switch pbStruct := pb.(type) { + case *eth.SignedBeaconBlock: + return SignedBeaconBlockPhase0FromConsensus(pbStruct), nil + case *eth.SignedBeaconBlockAltair: + return SignedBeaconBlockAltairFromConsensus(pbStruct), nil + case *eth.SignedBlindedBeaconBlockBellatrix: + return SignedBlindedBeaconBlockBellatrixFromConsensus(pbStruct) + case *eth.SignedBeaconBlockBellatrix: + return SignedBeaconBlockBellatrixFromConsensus(pbStruct) + case *eth.SignedBlindedBeaconBlockCapella: + return SignedBlindedBeaconBlockCapellaFromConsensus(pbStruct) + case *eth.SignedBeaconBlockCapella: + return SignedBeaconBlockCapellaFromConsensus(pbStruct) + case *eth.SignedBlindedBeaconBlockDeneb: + return SignedBlindedBeaconBlockDenebFromConsensus(pbStruct) + case *eth.SignedBeaconBlockDeneb: + return SignedBeaconBlockDenebFromConsensus(pbStruct) + case *eth.SignedBlindedBeaconBlockElectra: + return SignedBlindedBeaconBlockElectraFromConsensus(pbStruct) + case *eth.SignedBeaconBlockElectra: + return SignedBeaconBlockElectraFromConsensus(pbStruct) + case *eth.SignedBlindedBeaconBlockFulu: + return SignedBlindedBeaconBlockFuluFromConsensus(pbStruct) + case *eth.SignedBeaconBlockFulu: + return SignedBeaconBlockFuluFromConsensus(pbStruct) + default: + return nil, ErrUnsupportedConversion + } +} + +func SignedBeaconBlockPhase0FromConsensus(b *eth.SignedBeaconBlock) *SignedBeaconBlock { + return &SignedBeaconBlock{ + Message: BeaconBlockFromConsensus(b.Block), + Signature: hexutil.Encode(b.Signature), + } +} + +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- + func (b *SignedBeaconBlockAltair) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { if b == nil { return nil, errNilValue @@ -331,6 +416,40 @@ func (b *BeaconBlockAltair) ToConsensus() (*eth.BeaconBlockAltair, error) { }, nil } +func BeaconBlockAltairFromConsensus(b *eth.BeaconBlockAltair) *BeaconBlockAltair { + return &BeaconBlockAltair{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BeaconBlockBodyAltair{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + SyncAggregate: &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), + }, + }, + } +} + +func SignedBeaconBlockAltairFromConsensus(b *eth.SignedBeaconBlockAltair) *SignedBeaconBlockAltair { + return &SignedBeaconBlockAltair{ + Message: BeaconBlockAltairFromConsensus(b.Block), + Signature: hexutil.Encode(b.Signature), + } +} + +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + func (b *SignedBeaconBlockBellatrix) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { if b == nil { return nil, errNilValue @@ -440,68 +559,9 @@ func (b *BeaconBlockBellatrix) ToConsensus() (*eth.BeaconBlockBellatrix, error) if err != nil { return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") } - payloadParentHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.ParentHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ParentHash") - } - payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.FeeRecipient, fieldparams.FeeRecipientLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.FeeRecipient") - } - payloadStateRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.StateRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.StateRoot") - } - payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.ReceiptsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ReceiptsRoot") - } - payloadLogsBloom, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.LogsBloom, fieldparams.LogsBloomLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.LogsBloom") - } - payloadPrevRandao, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.PrevRandao, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.PrevRandao") - } - payloadBlockNumber, err := strconv.ParseUint(b.Body.ExecutionPayload.BlockNumber, 10, 64) + payload, err := b.Body.ExecutionPayload.ToConsensus() if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlockNumber") - } - payloadGasLimit, err := strconv.ParseUint(b.Body.ExecutionPayload.GasLimit, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.GasLimit") - } - payloadGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayload.GasUsed, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.GasUsed") - } - payloadTimestamp, err := strconv.ParseUint(b.Body.ExecutionPayload.Timestamp, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.Timestamp") - } - payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayload.ExtraData, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ExtraData") - } - payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(b.Body.ExecutionPayload.BaseFeePerGas) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BaseFeePerGas") - } - payloadBlockHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.BlockHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlockHash") - } - err = slice.VerifyMaxLength(b.Body.ExecutionPayload.Transactions, fieldparams.MaxTxsPerPayloadLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.Transactions") - } - payloadTxs := make([][]byte, len(b.Body.ExecutionPayload.Transactions)) - for i, tx := range b.Body.ExecutionPayload.Transactions { - payloadTxs[i], err = bytesutil.DecodeHexWithMaxLength(tx, fieldparams.MaxBytesPerTxLength) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Transactions[%d]", i)) - } + return nil, server.NewDecodeError(err, "Body.ExecutionPayload") } return ð.BeaconBlockBellatrix{ @@ -526,22 +586,7 @@ func (b *BeaconBlockBellatrix) ToConsensus() (*eth.BeaconBlockBellatrix, error) SyncCommitteeBits: syncCommitteeBits, SyncCommitteeSignature: syncCommitteeSig, }, - ExecutionPayload: &enginev1.ExecutionPayload{ - ParentHash: payloadParentHash, - FeeRecipient: payloadFeeRecipient, - StateRoot: payloadStateRoot, - ReceiptsRoot: payloadReceiptsRoot, - LogsBloom: payloadLogsBloom, - PrevRandao: payloadPrevRandao, - BlockNumber: payloadBlockNumber, - GasLimit: payloadGasLimit, - GasUsed: payloadGasUsed, - Timestamp: payloadTimestamp, - ExtraData: payloadExtraData, - BaseFeePerGas: payloadBaseFeePerGas, - BlockHash: payloadBlockHash, - Transactions: payloadTxs, - }, + ExecutionPayload: payload, }, }, nil } @@ -655,61 +700,9 @@ func (b *BlindedBeaconBlockBellatrix) ToConsensus() (*eth.BlindedBeaconBlockBell if err != nil { return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") } - payloadParentHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ParentHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ParentHash") - } - payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.FeeRecipient, fieldparams.FeeRecipientLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.FeeRecipient") - } - payloadStateRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.StateRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.StateRoot") - } - payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ReceiptsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ReceiptsRoot") - } - payloadLogsBloom, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.LogsBloom, fieldparams.LogsBloomLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.LogsBloom") - } - payloadPrevRandao, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.PrevRandao, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.PrevRandao") - } - payloadBlockNumber, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.BlockNumber, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockNumber") - } - payloadGasLimit, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasLimit, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasLimit") - } - payloadGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasUsed, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasUsed") - } - payloadTimestamp, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.Timestamp, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.Timestamp") - } - payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayloadHeader.ExtraData, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ExtraData") - } - payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(b.Body.ExecutionPayloadHeader.BaseFeePerGas) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BaseFeePerGas") - } - payloadBlockHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.BlockHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockHash") - } - payloadTxsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.TransactionsRoot, fieldparams.RootLength) + payload, err := b.Body.ExecutionPayloadHeader.ToConsensus() if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.TransactionsRoot") + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader") } return ð.BlindedBeaconBlockBellatrix{ Slot: primitives.Slot(slot), @@ -733,57 +726,126 @@ func (b *BlindedBeaconBlockBellatrix) ToConsensus() (*eth.BlindedBeaconBlockBell SyncCommitteeBits: syncCommitteeBits, SyncCommitteeSignature: syncCommitteeSig, }, - ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeader{ - ParentHash: payloadParentHash, - FeeRecipient: payloadFeeRecipient, - StateRoot: payloadStateRoot, - ReceiptsRoot: payloadReceiptsRoot, - LogsBloom: payloadLogsBloom, - PrevRandao: payloadPrevRandao, - BlockNumber: payloadBlockNumber, - GasLimit: payloadGasLimit, - GasUsed: payloadGasUsed, - Timestamp: payloadTimestamp, - ExtraData: payloadExtraData, - BaseFeePerGas: payloadBaseFeePerGas, - BlockHash: payloadBlockHash, - TransactionsRoot: payloadTxsRoot, - }, + ExecutionPayloadHeader: payload, }, }, nil } -func (b *SignedBeaconBlockCapella) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { - if b == nil { - return nil, errNilValue - } - - sig, err := bytesutil.DecodeHexWithLength(b.Signature, fieldparams.BLSSignatureLength) - if err != nil { - return nil, server.NewDecodeError(err, "Signature") - } - bl, err := b.Message.ToConsensus() +func BlindedBeaconBlockBellatrixFromConsensus(b *eth.BlindedBeaconBlockBellatrix) (*BlindedBeaconBlockBellatrix, error) { + payload, err := ExecutionPayloadHeaderFromConsensus(b.Body.ExecutionPayloadHeader) if err != nil { - return nil, server.NewDecodeError(err, "Message") - } - block := ð.SignedBeaconBlockCapella{ - Block: bl, - Signature: sig, + return nil, err } - return ð.GenericSignedBeaconBlock{Block: ð.GenericSignedBeaconBlock_Capella{Capella: block}}, nil + + return &BlindedBeaconBlockBellatrix{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BlindedBeaconBlockBodyBellatrix{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + SyncAggregate: &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), + }, + ExecutionPayloadHeader: payload, + }, + }, nil } -func (b *BeaconBlockCapella) ToGeneric() (*eth.GenericBeaconBlock, error) { - block, err := b.ToConsensus() +func SignedBlindedBeaconBlockBellatrixFromConsensus(b *eth.SignedBlindedBeaconBlockBellatrix) (*SignedBlindedBeaconBlockBellatrix, error) { + blindedBlock, err := BlindedBeaconBlockBellatrixFromConsensus(b.Block) if err != nil { return nil, err } - return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_Capella{Capella: block}}, nil + return &SignedBlindedBeaconBlockBellatrix{ + Message: blindedBlock, + Signature: hexutil.Encode(b.Signature), + }, nil } -func (b *BeaconBlockCapella) ToConsensus() (*eth.BeaconBlockCapella, error) { - if b == nil { - return nil, errNilValue +func BeaconBlockBellatrixFromConsensus(b *eth.BeaconBlockBellatrix) (*BeaconBlockBellatrix, error) { + payload, err := ExecutionPayloadFromConsensus(b.Body.ExecutionPayload) + if err != nil { + return nil, err + } + + return &BeaconBlockBellatrix{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BeaconBlockBodyBellatrix{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + SyncAggregate: &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), + }, + ExecutionPayload: payload, + }, + }, nil +} + +func SignedBeaconBlockBellatrixFromConsensus(b *eth.SignedBeaconBlockBellatrix) (*SignedBeaconBlockBellatrix, error) { + block, err := BeaconBlockBellatrixFromConsensus(b.Block) + if err != nil { + return nil, err + } + return &SignedBeaconBlockBellatrix{ + Message: block, + Signature: hexutil.Encode(b.Signature), + }, nil +} + +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + +func (b *SignedBeaconBlockCapella) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { + if b == nil { + return nil, errNilValue + } + + sig, err := bytesutil.DecodeHexWithLength(b.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + bl, err := b.Message.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Message") + } + block := ð.SignedBeaconBlockCapella{ + Block: bl, + Signature: sig, + } + return ð.GenericSignedBeaconBlock{Block: ð.GenericSignedBeaconBlock_Capella{Capella: block}}, nil +} + +func (b *BeaconBlockCapella) ToGeneric() (*eth.GenericBeaconBlock, error) { + block, err := b.ToConsensus() + if err != nil { + return nil, err + } + return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_Capella{Capella: block}}, nil +} + +func (b *BeaconBlockCapella) ToConsensus() (*eth.BeaconBlockCapella, error) { + if b == nil { + return nil, errNilValue } if b.Body == nil { return nil, server.NewDecodeError(errNilValue, "Body") @@ -862,98 +924,12 @@ func (b *BeaconBlockCapella) ToConsensus() (*eth.BeaconBlockCapella, error) { if err != nil { return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") } - payloadParentHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.ParentHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ParentHash") - } - payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.FeeRecipient, fieldparams.FeeRecipientLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.FeeRecipient") - } - payloadStateRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.StateRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.StateRoot") - } - payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.ReceiptsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ReceiptsRoot") - } - payloadLogsBloom, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.LogsBloom, fieldparams.LogsBloomLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.LogsBloom") - } - payloadPrevRandao, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.PrevRandao, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.PrevRandao") - } - payloadBlockNumber, err := strconv.ParseUint(b.Body.ExecutionPayload.BlockNumber, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlockNumber") - } - payloadGasLimit, err := strconv.ParseUint(b.Body.ExecutionPayload.GasLimit, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.GasLimit") - } - payloadGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayload.GasUsed, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.GasUsed") - } - payloadTimestamp, err := strconv.ParseUint(b.Body.ExecutionPayload.Timestamp, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.Timestamp") - } - payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayload.ExtraData, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ExtraData") - } - payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(b.Body.ExecutionPayload.BaseFeePerGas) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BaseFeePerGas") - } - payloadBlockHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.BlockHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlockHash") - } - err = slice.VerifyMaxLength(b.Body.ExecutionPayload.Transactions, fieldparams.MaxTxsPerPayloadLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.Transactions") - } - payloadTxs := make([][]byte, len(b.Body.ExecutionPayload.Transactions)) - for i, tx := range b.Body.ExecutionPayload.Transactions { - payloadTxs[i], err = bytesutil.DecodeHexWithMaxLength(tx, fieldparams.MaxBytesPerTxLength) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Transactions[%d]", i)) - } - } - err = slice.VerifyMaxLength(b.Body.ExecutionPayload.Withdrawals, fieldparams.MaxWithdrawalsPerPayload) + + payload, err := b.Body.ExecutionPayload.ToConsensus() if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.Withdrawals") - } - withdrawals := make([]*enginev1.Withdrawal, len(b.Body.ExecutionPayload.Withdrawals)) - for i, w := range b.Body.ExecutionPayload.Withdrawals { - withdrawalIndex, err := strconv.ParseUint(w.WithdrawalIndex, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Withdrawals[%d].WithdrawalIndex", i)) - } - validatorIndex, err := strconv.ParseUint(w.ValidatorIndex, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Withdrawals[%d].ValidatorIndex", i)) - } - address, err := bytesutil.DecodeHexWithLength(w.ExecutionAddress, common.AddressLength) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Withdrawals[%d].ExecutionAddress", i)) - } - amount, err := strconv.ParseUint(w.Amount, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Withdrawals[%d].Amount", i)) - } - withdrawals[i] = &enginev1.Withdrawal{ - Index: withdrawalIndex, - ValidatorIndex: primitives.ValidatorIndex(validatorIndex), - Address: address, - Amount: amount, - } + return nil, server.NewDecodeError(err, "Body.ExecutionPayload") } + blsChanges, err := SignedBLSChangesToConsensus(b.Body.BLSToExecutionChanges) if err != nil { return nil, server.NewDecodeError(err, "Body.BLSToExecutionChanges") @@ -981,23 +957,7 @@ func (b *BeaconBlockCapella) ToConsensus() (*eth.BeaconBlockCapella, error) { SyncCommitteeBits: syncCommitteeBits, SyncCommitteeSignature: syncCommitteeSig, }, - ExecutionPayload: &enginev1.ExecutionPayloadCapella{ - ParentHash: payloadParentHash, - FeeRecipient: payloadFeeRecipient, - StateRoot: payloadStateRoot, - ReceiptsRoot: payloadReceiptsRoot, - LogsBloom: payloadLogsBloom, - PrevRandao: payloadPrevRandao, - BlockNumber: payloadBlockNumber, - GasLimit: payloadGasLimit, - GasUsed: payloadGasUsed, - Timestamp: payloadTimestamp, - ExtraData: payloadExtraData, - BaseFeePerGas: payloadBaseFeePerGas, - BlockHash: payloadBlockHash, - Transactions: payloadTxs, - Withdrawals: withdrawals, - }, + ExecutionPayload: payload, BlsToExecutionChanges: blsChanges, }, }, nil @@ -1112,66 +1072,12 @@ func (b *BlindedBeaconBlockCapella) ToConsensus() (*eth.BlindedBeaconBlockCapell if err != nil { return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") } - payloadParentHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ParentHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ParentHash") - } - payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.FeeRecipient, fieldparams.FeeRecipientLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.FeeRecipient") - } - payloadStateRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.StateRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.StateRoot") - } - payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ReceiptsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ReceiptsRoot") - } - payloadLogsBloom, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.LogsBloom, fieldparams.LogsBloomLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.LogsBloom") - } - payloadPrevRandao, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.PrevRandao, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.PrevRandao") - } - payloadBlockNumber, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.BlockNumber, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockNumber") - } - payloadGasLimit, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasLimit, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasLimit") - } - payloadGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasUsed, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasUsed") - } - payloadTimestamp, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.Timestamp, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.Timestamp") - } - payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayloadHeader.ExtraData, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ExtraData") - } - payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(b.Body.ExecutionPayloadHeader.BaseFeePerGas) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BaseFeePerGas") - } - payloadBlockHash, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayloadHeader.BlockHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockHash") - } - payloadTxsRoot, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayloadHeader.TransactionsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.TransactionsRoot") - } - payloadWithdrawalsRoot, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayloadHeader.WithdrawalsRoot, fieldparams.RootLength) + + payload, err := b.Body.ExecutionPayloadHeader.ToConsensus() if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.WithdrawalsRoot") + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader") } + blsChanges, err := SignedBLSChangesToConsensus(b.Body.BLSToExecutionChanges) if err != nil { return nil, server.NewDecodeError(err, "Body.BLSToExecutionChanges") @@ -1199,74 +1105,144 @@ func (b *BlindedBeaconBlockCapella) ToConsensus() (*eth.BlindedBeaconBlockCapell SyncCommitteeBits: syncCommitteeBits, SyncCommitteeSignature: syncCommitteeSig, }, - ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderCapella{ - ParentHash: payloadParentHash, - FeeRecipient: payloadFeeRecipient, - StateRoot: payloadStateRoot, - ReceiptsRoot: payloadReceiptsRoot, - LogsBloom: payloadLogsBloom, - PrevRandao: payloadPrevRandao, - BlockNumber: payloadBlockNumber, - GasLimit: payloadGasLimit, - GasUsed: payloadGasUsed, - Timestamp: payloadTimestamp, - ExtraData: payloadExtraData, - BaseFeePerGas: payloadBaseFeePerGas, - BlockHash: payloadBlockHash, - TransactionsRoot: payloadTxsRoot, - WithdrawalsRoot: payloadWithdrawalsRoot, - }, - BlsToExecutionChanges: blsChanges, + ExecutionPayloadHeader: payload, + BlsToExecutionChanges: blsChanges, }, }, nil } -func (b *SignedBeaconBlockContentsDeneb) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { - if b == nil { - return nil, errNilValue - } - - signedDenebBlock, err := b.SignedBlock.ToConsensus() +func BlindedBeaconBlockCapellaFromConsensus(b *eth.BlindedBeaconBlockCapella) (*BlindedBeaconBlockCapella, error) { + payload, err := ExecutionPayloadHeaderCapellaFromConsensus(b.Body.ExecutionPayloadHeader) if err != nil { - return nil, server.NewDecodeError(err, "SignedBlock") - } - proofs := make([][]byte, len(b.KzgProofs)) - for i, proof := range b.KzgProofs { - proofs[i], err = bytesutil.DecodeHexWithLength(proof, fieldparams.BLSPubkeyLength) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("KzgProofs[%d]", i)) - } - } - blbs := make([][]byte, len(b.Blobs)) - for i, blob := range b.Blobs { - blbs[i], err = bytesutil.DecodeHexWithLength(blob, fieldparams.BlobLength) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Blobs[%d]", i)) - } - } - blk := ð.SignedBeaconBlockContentsDeneb{ - Block: signedDenebBlock, - KzgProofs: proofs, - Blobs: blbs, + return nil, err } - return ð.GenericSignedBeaconBlock{Block: ð.GenericSignedBeaconBlock_Deneb{Deneb: blk}}, nil + + return &BlindedBeaconBlockCapella{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BlindedBeaconBlockBodyCapella{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + SyncAggregate: &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), + }, + ExecutionPayloadHeader: payload, + BLSToExecutionChanges: SignedBLSChangesFromConsensus(b.Body.BlsToExecutionChanges), + }, + }, nil } -func (b *SignedBeaconBlockContentsDeneb) ToUnsigned() *BeaconBlockContentsDeneb { - return &BeaconBlockContentsDeneb{ - Block: b.SignedBlock.Message, - KzgProofs: b.KzgProofs, - Blobs: b.Blobs, +func SignedBlindedBeaconBlockCapellaFromConsensus(b *eth.SignedBlindedBeaconBlockCapella) (*SignedBlindedBeaconBlockCapella, error) { + blindedBlock, err := BlindedBeaconBlockCapellaFromConsensus(b.Block) + if err != nil { + return nil, err } + return &SignedBlindedBeaconBlockCapella{ + Message: blindedBlock, + Signature: hexutil.Encode(b.Signature), + }, nil } -func (b *BeaconBlockContentsDeneb) ToGeneric() (*eth.GenericBeaconBlock, error) { - block, err := b.ToConsensus() +func BeaconBlockCapellaFromConsensus(b *eth.BeaconBlockCapella) (*BeaconBlockCapella, error) { + payload, err := ExecutionPayloadCapellaFromConsensus(b.Body.ExecutionPayload) if err != nil { return nil, err } - return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_Deneb{Deneb: block}}, nil + return &BeaconBlockCapella{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BeaconBlockBodyCapella{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + SyncAggregate: &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), + }, + ExecutionPayload: payload, + BLSToExecutionChanges: SignedBLSChangesFromConsensus(b.Body.BlsToExecutionChanges), + }, + }, nil +} + +func SignedBeaconBlockCapellaFromConsensus(b *eth.SignedBeaconBlockCapella) (*SignedBeaconBlockCapella, error) { + block, err := BeaconBlockCapellaFromConsensus(b.Block) + if err != nil { + return nil, err + } + return &SignedBeaconBlockCapella{ + Message: block, + Signature: hexutil.Encode(b.Signature), + }, nil +} + +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + +func (b *SignedBeaconBlockContentsDeneb) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { + if b == nil { + return nil, errNilValue + } + + signedDenebBlock, err := b.SignedBlock.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "SignedBlock") + } + proofs := make([][]byte, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i], err = bytesutil.DecodeHexWithLength(proof, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("KzgProofs[%d]", i)) + } + } + blbs := make([][]byte, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i], err = bytesutil.DecodeHexWithLength(blob, fieldparams.BlobLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Blobs[%d]", i)) + } + } + blk := ð.SignedBeaconBlockContentsDeneb{ + Block: signedDenebBlock, + KzgProofs: proofs, + Blobs: blbs, + } + return ð.GenericSignedBeaconBlock{Block: ð.GenericSignedBeaconBlock_Deneb{Deneb: blk}}, nil +} + +func (b *SignedBeaconBlockContentsDeneb) ToUnsigned() *BeaconBlockContentsDeneb { + return &BeaconBlockContentsDeneb{ + Block: b.SignedBlock.Message, + KzgProofs: b.KzgProofs, + Blobs: b.Blobs, + } +} + +func (b *BeaconBlockContentsDeneb) ToGeneric() (*eth.GenericBeaconBlock, error) { + block, err := b.ToConsensus() + if err != nil { + return nil, err + } + + return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_Deneb{Deneb: block}}, nil } func (b *BeaconBlockContentsDeneb) ToConsensus() (*eth.BeaconBlockContentsDeneb, error) { @@ -1380,106 +1356,9 @@ func (b *BeaconBlockDeneb) ToConsensus() (*eth.BeaconBlockDeneb, error) { if err != nil { return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") } - payloadParentHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.ParentHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ParentHash") - } - payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.FeeRecipient, fieldparams.FeeRecipientLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.FeeRecipient") - } - payloadStateRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.StateRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.StateRoot") - } - payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.ReceiptsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ReceiptsRoot") - } - payloadLogsBloom, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.LogsBloom, fieldparams.LogsBloomLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.LogsBloom") - } - payloadPrevRandao, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.PrevRandao, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.PrevRandao") - } - payloadBlockNumber, err := strconv.ParseUint(b.Body.ExecutionPayload.BlockNumber, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlockNumber") - } - payloadGasLimit, err := strconv.ParseUint(b.Body.ExecutionPayload.GasLimit, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.GasLimit") - } - payloadGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayload.GasUsed, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.GasUsed") - } - payloadTimestamp, err := strconv.ParseUint(b.Body.ExecutionPayload.Timestamp, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.Timestamp") - } - payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayload.ExtraData, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ExtraData") - } - payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(b.Body.ExecutionPayload.BaseFeePerGas) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BaseFeePerGas") - } - payloadBlockHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayload.BlockHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlockHash") - } - err = slice.VerifyMaxLength(b.Body.ExecutionPayload.Transactions, fieldparams.MaxTxsPerPayloadLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.Transactions") - } - txs := make([][]byte, len(b.Body.ExecutionPayload.Transactions)) - for i, tx := range b.Body.ExecutionPayload.Transactions { - txs[i], err = bytesutil.DecodeHexWithMaxLength(tx, fieldparams.MaxBytesPerTxLength) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Transactions[%d]", i)) - } - } - err = slice.VerifyMaxLength(b.Body.ExecutionPayload.Withdrawals, fieldparams.MaxWithdrawalsPerPayload) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.Withdrawals") - } - withdrawals := make([]*enginev1.Withdrawal, len(b.Body.ExecutionPayload.Withdrawals)) - for i, w := range b.Body.ExecutionPayload.Withdrawals { - withdrawalIndex, err := strconv.ParseUint(w.WithdrawalIndex, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Withdrawals[%d].WithdrawalIndex", i)) - } - validatorIndex, err := strconv.ParseUint(w.ValidatorIndex, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Withdrawals[%d].ValidatorIndex", i)) - } - address, err := bytesutil.DecodeHexWithLength(w.ExecutionAddress, common.AddressLength) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Withdrawals[%d].ExecutionAddress", i)) - } - amount, err := strconv.ParseUint(w.Amount, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionPayload.Withdrawals[%d].Amount", i)) - } - withdrawals[i] = &enginev1.Withdrawal{ - Index: withdrawalIndex, - ValidatorIndex: primitives.ValidatorIndex(validatorIndex), - Address: address, - Amount: amount, - } - } - - payloadBlobGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayload.BlobGasUsed, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlobGasUsed") - } - payloadExcessBlobGas, err := strconv.ParseUint(b.Body.ExecutionPayload.ExcessBlobGas, 10, 64) + payload, err := b.Body.ExecutionPayload.ToConsensus() if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ExcessBlobGas") + return nil, server.NewDecodeError(err, "Body.ExecutionPayload") } blsChanges, err := SignedBLSChangesToConsensus(b.Body.BLSToExecutionChanges) if err != nil { @@ -1519,25 +1398,7 @@ func (b *BeaconBlockDeneb) ToConsensus() (*eth.BeaconBlockDeneb, error) { SyncCommitteeBits: syncCommitteeBits, SyncCommitteeSignature: syncCommitteeSig, }, - ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ - ParentHash: payloadParentHash, - FeeRecipient: payloadFeeRecipient, - StateRoot: payloadStateRoot, - ReceiptsRoot: payloadReceiptsRoot, - LogsBloom: payloadLogsBloom, - PrevRandao: payloadPrevRandao, - BlockNumber: payloadBlockNumber, - GasLimit: payloadGasLimit, - GasUsed: payloadGasUsed, - Timestamp: payloadTimestamp, - ExtraData: payloadExtraData, - BaseFeePerGas: payloadBaseFeePerGas, - BlockHash: payloadBlockHash, - Transactions: txs, - Withdrawals: withdrawals, - BlobGasUsed: payloadBlobGasUsed, - ExcessBlobGas: payloadExcessBlobGas, - }, + ExecutionPayload: payload, BlsToExecutionChanges: blsChanges, BlobKzgCommitments: blobKzgCommitments, }, @@ -1681,76 +1542,10 @@ func (b *BlindedBeaconBlockDeneb) ToConsensus() (*eth.BlindedBeaconBlockDeneb, e if err != nil { return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") } - payloadParentHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ParentHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ParentHash") - } - payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.FeeRecipient, fieldparams.FeeRecipientLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.FeeRecipient") - } - payloadStateRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.StateRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.StateRoot") - } - payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ReceiptsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ReceiptsRoot") - } - payloadLogsBloom, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.LogsBloom, fieldparams.LogsBloomLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.LogsBloom") - } - payloadPrevRandao, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.PrevRandao, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.PrevRandao") - } - payloadBlockNumber, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.BlockNumber, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockNumber") - } - payloadGasLimit, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasLimit, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasLimit") - } - payloadGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasUsed, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasUsed") - } - payloadTimestamp, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.Timestamp, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.Timestamp") - } - payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayloadHeader.ExtraData, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ExtraData") - } - payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(b.Body.ExecutionPayloadHeader.BaseFeePerGas) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BaseFeePerGas") - } - payloadBlockHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.BlockHash, common.HashLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockHash") - } - payloadTxsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.TransactionsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.TransactionsRoot") - } - payloadWithdrawalsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.WithdrawalsRoot, fieldparams.RootLength) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.WithdrawalsRoot") - } - - payloadBlobGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.BlobGasUsed, 10, 64) - if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlobGasUsed") - } - payloadExcessBlobGas, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.ExcessBlobGas, 10, 64) + payload, err := b.Body.ExecutionPayloadHeader.ToConsensus() if err != nil { - return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ExcessBlobGas") + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader") } - blsChanges, err := SignedBLSChangesToConsensus(b.Body.BLSToExecutionChanges) if err != nil { return nil, server.NewDecodeError(err, "Body.BLSToExecutionChanges") @@ -1790,27 +1585,9 @@ func (b *BlindedBeaconBlockDeneb) ToConsensus() (*eth.BlindedBeaconBlockDeneb, e SyncCommitteeBits: syncCommitteeBits, SyncCommitteeSignature: syncCommitteeSig, }, - ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ - ParentHash: payloadParentHash, - FeeRecipient: payloadFeeRecipient, - StateRoot: payloadStateRoot, - ReceiptsRoot: payloadReceiptsRoot, - LogsBloom: payloadLogsBloom, - PrevRandao: payloadPrevRandao, - BlockNumber: payloadBlockNumber, - GasLimit: payloadGasLimit, - GasUsed: payloadGasUsed, - Timestamp: payloadTimestamp, - ExtraData: payloadExtraData, - BaseFeePerGas: payloadBaseFeePerGas, - BlockHash: payloadBlockHash, - TransactionsRoot: payloadTxsRoot, - WithdrawalsRoot: payloadWithdrawalsRoot, - BlobGasUsed: payloadBlobGasUsed, - ExcessBlobGas: payloadExcessBlobGas, - }, - BlsToExecutionChanges: blsChanges, - BlobKzgCommitments: blobKzgCommitments, + ExecutionPayloadHeader: payload, + BlsToExecutionChanges: blsChanges, + BlobKzgCommitments: blobKzgCommitments, }, }, nil } @@ -1827,311 +1604,8 @@ func (b *BlindedBeaconBlockDeneb) ToGeneric() (*eth.GenericBeaconBlock, error) { return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_BlindedDeneb{BlindedDeneb: blindedBlock}, IsBlinded: true}, nil } -func BeaconBlockHeaderFromConsensus(h *eth.BeaconBlockHeader) *BeaconBlockHeader { - return &BeaconBlockHeader{ - Slot: fmt.Sprintf("%d", h.Slot), - ProposerIndex: fmt.Sprintf("%d", h.ProposerIndex), - ParentRoot: hexutil.Encode(h.ParentRoot), - StateRoot: hexutil.Encode(h.StateRoot), - BodyRoot: hexutil.Encode(h.BodyRoot), - } -} - -func BeaconBlockFromConsensus(b *eth.BeaconBlock) *BeaconBlock { - return &BeaconBlock{ - Slot: fmt.Sprintf("%d", b.Slot), - ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), - ParentRoot: hexutil.Encode(b.ParentRoot), - StateRoot: hexutil.Encode(b.StateRoot), - Body: &BeaconBlockBody{ - RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), - Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), - Graffiti: hexutil.Encode(b.Body.Graffiti), - ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), - AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), - Attestations: AttsFromConsensus(b.Body.Attestations), - Deposits: DepositsFromConsensus(b.Body.Deposits), - VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), - }, - } -} - -func SignedBeaconBlockMessageJsoner(block interfaces.ReadOnlySignedBeaconBlock) (SignedMessageJsoner, error) { - pb, err := block.Proto() - if err != nil { - return nil, err - } - switch pbStruct := pb.(type) { - case *eth.SignedBeaconBlock: - return SignedBeaconBlockPhase0FromConsensus(pbStruct), nil - case *eth.SignedBeaconBlockAltair: - return SignedBeaconBlockAltairFromConsensus(pbStruct), nil - case *eth.SignedBlindedBeaconBlockBellatrix: - return SignedBlindedBeaconBlockBellatrixFromConsensus(pbStruct) - case *eth.SignedBeaconBlockBellatrix: - return SignedBeaconBlockBellatrixFromConsensus(pbStruct) - case *eth.SignedBlindedBeaconBlockCapella: - return SignedBlindedBeaconBlockCapellaFromConsensus(pbStruct) - case *eth.SignedBeaconBlockCapella: - return SignedBeaconBlockCapellaFromConsensus(pbStruct) - case *eth.SignedBlindedBeaconBlockDeneb: - return SignedBlindedBeaconBlockDenebFromConsensus(pbStruct) - case *eth.SignedBeaconBlockDeneb: - return SignedBeaconBlockDenebFromConsensus(pbStruct) - default: - return nil, ErrUnsupportedConversion - } -} - -func SignedBeaconBlockPhase0FromConsensus(b *eth.SignedBeaconBlock) *SignedBeaconBlock { - return &SignedBeaconBlock{ - Message: BeaconBlockFromConsensus(b.Block), - Signature: hexutil.Encode(b.Signature), - } -} - -func BeaconBlockAltairFromConsensus(b *eth.BeaconBlockAltair) *BeaconBlockAltair { - return &BeaconBlockAltair{ - Slot: fmt.Sprintf("%d", b.Slot), - ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), - ParentRoot: hexutil.Encode(b.ParentRoot), - StateRoot: hexutil.Encode(b.StateRoot), - Body: &BeaconBlockBodyAltair{ - RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), - Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), - Graffiti: hexutil.Encode(b.Body.Graffiti), - ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), - AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), - Attestations: AttsFromConsensus(b.Body.Attestations), - Deposits: DepositsFromConsensus(b.Body.Deposits), - VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), - SyncAggregate: &SyncAggregate{ - SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), - }, - }, - } -} - -func SignedBeaconBlockAltairFromConsensus(b *eth.SignedBeaconBlockAltair) *SignedBeaconBlockAltair { - return &SignedBeaconBlockAltair{ - Message: BeaconBlockAltairFromConsensus(b.Block), - Signature: hexutil.Encode(b.Signature), - } -} - -func BlindedBeaconBlockBellatrixFromConsensus(b *eth.BlindedBeaconBlockBellatrix) (*BlindedBeaconBlockBellatrix, error) { - payload, err := ExecutionPayloadHeaderFromConsensus(b.Body.ExecutionPayloadHeader) - if err != nil { - return nil, err - } - - return &BlindedBeaconBlockBellatrix{ - Slot: fmt.Sprintf("%d", b.Slot), - ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), - ParentRoot: hexutil.Encode(b.ParentRoot), - StateRoot: hexutil.Encode(b.StateRoot), - Body: &BlindedBeaconBlockBodyBellatrix{ - RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), - Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), - Graffiti: hexutil.Encode(b.Body.Graffiti), - ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), - AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), - Attestations: AttsFromConsensus(b.Body.Attestations), - Deposits: DepositsFromConsensus(b.Body.Deposits), - VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), - SyncAggregate: &SyncAggregate{ - SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), - }, - ExecutionPayloadHeader: payload, - }, - }, nil -} - -func SignedBlindedBeaconBlockBellatrixFromConsensus(b *eth.SignedBlindedBeaconBlockBellatrix) (*SignedBlindedBeaconBlockBellatrix, error) { - blindedBlock, err := BlindedBeaconBlockBellatrixFromConsensus(b.Block) - if err != nil { - return nil, err - } - return &SignedBlindedBeaconBlockBellatrix{ - Message: blindedBlock, - Signature: hexutil.Encode(b.Signature), - }, nil -} - -func BeaconBlockBellatrixFromConsensus(b *eth.BeaconBlockBellatrix) (*BeaconBlockBellatrix, error) { - baseFeePerGas, err := sszBytesToUint256String(b.Body.ExecutionPayload.BaseFeePerGas) - if err != nil { - return nil, err - } - transactions := make([]string, len(b.Body.ExecutionPayload.Transactions)) - for i, tx := range b.Body.ExecutionPayload.Transactions { - transactions[i] = hexutil.Encode(tx) - } - - return &BeaconBlockBellatrix{ - Slot: fmt.Sprintf("%d", b.Slot), - ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), - ParentRoot: hexutil.Encode(b.ParentRoot), - StateRoot: hexutil.Encode(b.StateRoot), - Body: &BeaconBlockBodyBellatrix{ - RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), - Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), - Graffiti: hexutil.Encode(b.Body.Graffiti), - ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), - AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), - Attestations: AttsFromConsensus(b.Body.Attestations), - Deposits: DepositsFromConsensus(b.Body.Deposits), - VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), - SyncAggregate: &SyncAggregate{ - SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), - }, - ExecutionPayload: &ExecutionPayload{ - ParentHash: hexutil.Encode(b.Body.ExecutionPayload.ParentHash), - FeeRecipient: hexutil.Encode(b.Body.ExecutionPayload.FeeRecipient), - StateRoot: hexutil.Encode(b.Body.ExecutionPayload.StateRoot), - ReceiptsRoot: hexutil.Encode(b.Body.ExecutionPayload.ReceiptsRoot), - LogsBloom: hexutil.Encode(b.Body.ExecutionPayload.LogsBloom), - PrevRandao: hexutil.Encode(b.Body.ExecutionPayload.PrevRandao), - BlockNumber: fmt.Sprintf("%d", b.Body.ExecutionPayload.BlockNumber), - GasLimit: fmt.Sprintf("%d", b.Body.ExecutionPayload.GasLimit), - GasUsed: fmt.Sprintf("%d", b.Body.ExecutionPayload.GasUsed), - Timestamp: fmt.Sprintf("%d", b.Body.ExecutionPayload.Timestamp), - ExtraData: hexutil.Encode(b.Body.ExecutionPayload.ExtraData), - BaseFeePerGas: baseFeePerGas, - BlockHash: hexutil.Encode(b.Body.ExecutionPayload.BlockHash), - Transactions: transactions, - }, - }, - }, nil -} - -func SignedBeaconBlockBellatrixFromConsensus(b *eth.SignedBeaconBlockBellatrix) (*SignedBeaconBlockBellatrix, error) { - block, err := BeaconBlockBellatrixFromConsensus(b.Block) - if err != nil { - return nil, err - } - return &SignedBeaconBlockBellatrix{ - Message: block, - Signature: hexutil.Encode(b.Signature), - }, nil -} - -func BlindedBeaconBlockCapellaFromConsensus(b *eth.BlindedBeaconBlockCapella) (*BlindedBeaconBlockCapella, error) { - payload, err := ExecutionPayloadHeaderCapellaFromConsensus(b.Body.ExecutionPayloadHeader) - if err != nil { - return nil, err - } - - return &BlindedBeaconBlockCapella{ - Slot: fmt.Sprintf("%d", b.Slot), - ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), - ParentRoot: hexutil.Encode(b.ParentRoot), - StateRoot: hexutil.Encode(b.StateRoot), - Body: &BlindedBeaconBlockBodyCapella{ - RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), - Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), - Graffiti: hexutil.Encode(b.Body.Graffiti), - ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), - AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), - Attestations: AttsFromConsensus(b.Body.Attestations), - Deposits: DepositsFromConsensus(b.Body.Deposits), - VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), - SyncAggregate: &SyncAggregate{ - SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), - }, - ExecutionPayloadHeader: payload, - BLSToExecutionChanges: SignedBLSChangesFromConsensus(b.Body.BlsToExecutionChanges), - }, - }, nil -} - -func SignedBlindedBeaconBlockCapellaFromConsensus(b *eth.SignedBlindedBeaconBlockCapella) (*SignedBlindedBeaconBlockCapella, error) { - blindedBlock, err := BlindedBeaconBlockCapellaFromConsensus(b.Block) - if err != nil { - return nil, err - } - return &SignedBlindedBeaconBlockCapella{ - Message: blindedBlock, - Signature: hexutil.Encode(b.Signature), - }, nil -} - -func BeaconBlockCapellaFromConsensus(b *eth.BeaconBlockCapella) (*BeaconBlockCapella, error) { - baseFeePerGas, err := sszBytesToUint256String(b.Body.ExecutionPayload.BaseFeePerGas) - if err != nil { - return nil, err - } - transactions := make([]string, len(b.Body.ExecutionPayload.Transactions)) - for i, tx := range b.Body.ExecutionPayload.Transactions { - transactions[i] = hexutil.Encode(tx) - } - withdrawals := make([]*Withdrawal, len(b.Body.ExecutionPayload.Withdrawals)) - for i, w := range b.Body.ExecutionPayload.Withdrawals { - withdrawals[i] = &Withdrawal{ - WithdrawalIndex: fmt.Sprintf("%d", w.Index), - ValidatorIndex: fmt.Sprintf("%d", w.ValidatorIndex), - ExecutionAddress: hexutil.Encode(w.Address), - Amount: fmt.Sprintf("%d", w.Amount), - } - } - - return &BeaconBlockCapella{ - Slot: fmt.Sprintf("%d", b.Slot), - ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), - ParentRoot: hexutil.Encode(b.ParentRoot), - StateRoot: hexutil.Encode(b.StateRoot), - Body: &BeaconBlockBodyCapella{ - RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), - Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), - Graffiti: hexutil.Encode(b.Body.Graffiti), - ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), - AttesterSlashings: AttesterSlashingsFromConsensus(b.Body.AttesterSlashings), - Attestations: AttsFromConsensus(b.Body.Attestations), - Deposits: DepositsFromConsensus(b.Body.Deposits), - VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), - SyncAggregate: &SyncAggregate{ - SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), - }, - ExecutionPayload: &ExecutionPayloadCapella{ - ParentHash: hexutil.Encode(b.Body.ExecutionPayload.ParentHash), - FeeRecipient: hexutil.Encode(b.Body.ExecutionPayload.FeeRecipient), - StateRoot: hexutil.Encode(b.Body.ExecutionPayload.StateRoot), - ReceiptsRoot: hexutil.Encode(b.Body.ExecutionPayload.ReceiptsRoot), - LogsBloom: hexutil.Encode(b.Body.ExecutionPayload.LogsBloom), - PrevRandao: hexutil.Encode(b.Body.ExecutionPayload.PrevRandao), - BlockNumber: fmt.Sprintf("%d", b.Body.ExecutionPayload.BlockNumber), - GasLimit: fmt.Sprintf("%d", b.Body.ExecutionPayload.GasLimit), - GasUsed: fmt.Sprintf("%d", b.Body.ExecutionPayload.GasUsed), - Timestamp: fmt.Sprintf("%d", b.Body.ExecutionPayload.Timestamp), - ExtraData: hexutil.Encode(b.Body.ExecutionPayload.ExtraData), - BaseFeePerGas: baseFeePerGas, - BlockHash: hexutil.Encode(b.Body.ExecutionPayload.BlockHash), - Transactions: transactions, - Withdrawals: withdrawals, - }, - BLSToExecutionChanges: SignedBLSChangesFromConsensus(b.Body.BlsToExecutionChanges), - }, - }, nil -} - -func SignedBeaconBlockCapellaFromConsensus(b *eth.SignedBeaconBlockCapella) (*SignedBeaconBlockCapella, error) { - block, err := BeaconBlockCapellaFromConsensus(b.Block) - if err != nil { - return nil, err - } - return &SignedBeaconBlockCapella{ - Message: block, - Signature: hexutil.Encode(b.Signature), - }, nil -} - -func BeaconBlockContentsDenebFromConsensus(b *eth.BeaconBlockContentsDeneb) (*BeaconBlockContentsDeneb, error) { - block, err := BeaconBlockDenebFromConsensus(b.Block) +func BeaconBlockContentsDenebFromConsensus(b *eth.BeaconBlockContentsDeneb) (*BeaconBlockContentsDeneb, error) { + block, err := BeaconBlockDenebFromConsensus(b.Block) if err != nil { return nil, err } @@ -2220,28 +1694,14 @@ func SignedBlindedBeaconBlockDenebFromConsensus(b *eth.SignedBlindedBeaconBlockD } func BeaconBlockDenebFromConsensus(b *eth.BeaconBlockDeneb) (*BeaconBlockDeneb, error) { - baseFeePerGas, err := sszBytesToUint256String(b.Body.ExecutionPayload.BaseFeePerGas) - if err != nil { - return nil, err - } - transactions := make([]string, len(b.Body.ExecutionPayload.Transactions)) - for i, tx := range b.Body.ExecutionPayload.Transactions { - transactions[i] = hexutil.Encode(tx) - } - withdrawals := make([]*Withdrawal, len(b.Body.ExecutionPayload.Withdrawals)) - for i, w := range b.Body.ExecutionPayload.Withdrawals { - withdrawals[i] = &Withdrawal{ - WithdrawalIndex: fmt.Sprintf("%d", w.Index), - ValidatorIndex: fmt.Sprintf("%d", w.ValidatorIndex), - ExecutionAddress: hexutil.Encode(w.Address), - Amount: fmt.Sprintf("%d", w.Amount), - } - } blobKzgCommitments := make([]string, len(b.Body.BlobKzgCommitments)) for i := range b.Body.BlobKzgCommitments { blobKzgCommitments[i] = hexutil.Encode(b.Body.BlobKzgCommitments[i]) } - + payload, err := ExecutionPayloadDenebFromConsensus(b.Body.ExecutionPayload) + if err != nil { + return nil, err + } return &BeaconBlockDeneb{ Slot: fmt.Sprintf("%d", b.Slot), ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), @@ -2260,25 +1720,7 @@ func BeaconBlockDenebFromConsensus(b *eth.BeaconBlockDeneb) (*BeaconBlockDeneb, SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), }, - ExecutionPayload: &ExecutionPayloadDeneb{ - ParentHash: hexutil.Encode(b.Body.ExecutionPayload.ParentHash), - FeeRecipient: hexutil.Encode(b.Body.ExecutionPayload.FeeRecipient), - StateRoot: hexutil.Encode(b.Body.ExecutionPayload.StateRoot), - ReceiptsRoot: hexutil.Encode(b.Body.ExecutionPayload.ReceiptsRoot), - LogsBloom: hexutil.Encode(b.Body.ExecutionPayload.LogsBloom), - PrevRandao: hexutil.Encode(b.Body.ExecutionPayload.PrevRandao), - BlockNumber: fmt.Sprintf("%d", b.Body.ExecutionPayload.BlockNumber), - GasLimit: fmt.Sprintf("%d", b.Body.ExecutionPayload.GasLimit), - GasUsed: fmt.Sprintf("%d", b.Body.ExecutionPayload.GasUsed), - Timestamp: fmt.Sprintf("%d", b.Body.ExecutionPayload.Timestamp), - ExtraData: hexutil.Encode(b.Body.ExecutionPayload.ExtraData), - BaseFeePerGas: baseFeePerGas, - BlockHash: hexutil.Encode(b.Body.ExecutionPayload.BlockHash), - Transactions: transactions, - Withdrawals: withdrawals, - BlobGasUsed: fmt.Sprintf("%d", b.Body.ExecutionPayload.BlobGasUsed), - ExcessBlobGas: fmt.Sprintf("%d", b.Body.ExecutionPayload.ExcessBlobGas), - }, + ExecutionPayload: payload, BLSToExecutionChanges: SignedBLSChangesFromConsensus(b.Body.BlsToExecutionChanges), BlobKzgCommitments: blobKzgCommitments, }, @@ -2296,78 +1738,1150 @@ func SignedBeaconBlockDenebFromConsensus(b *eth.SignedBeaconBlockDeneb) (*Signed }, nil } -func ExecutionPayloadHeaderFromConsensus(payload *enginev1.ExecutionPayloadHeader) (*ExecutionPayloadHeader, error) { - baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) - if err != nil { - return nil, err - } - - return &ExecutionPayloadHeader{ - ParentHash: hexutil.Encode(payload.ParentHash), - FeeRecipient: hexutil.Encode(payload.FeeRecipient), - StateRoot: hexutil.Encode(payload.StateRoot), - ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), - LogsBloom: hexutil.Encode(payload.LogsBloom), - PrevRandao: hexutil.Encode(payload.PrevRandao), - BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), - GasLimit: fmt.Sprintf("%d", payload.GasLimit), - GasUsed: fmt.Sprintf("%d", payload.GasUsed), - Timestamp: fmt.Sprintf("%d", payload.Timestamp), - ExtraData: hexutil.Encode(payload.ExtraData), - BaseFeePerGas: baseFeePerGas, - BlockHash: hexutil.Encode(payload.BlockHash), - TransactionsRoot: hexutil.Encode(payload.TransactionsRoot), - }, nil -} +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- -func ExecutionPayloadHeaderCapellaFromConsensus(payload *enginev1.ExecutionPayloadHeaderCapella) (*ExecutionPayloadHeaderCapella, error) { - baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) - if err != nil { - return nil, err +func (b *SignedBeaconBlockContentsElectra) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { + if b == nil { + return nil, errNilValue } - return &ExecutionPayloadHeaderCapella{ - ParentHash: hexutil.Encode(payload.ParentHash), - FeeRecipient: hexutil.Encode(payload.FeeRecipient), - StateRoot: hexutil.Encode(payload.StateRoot), - ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), - LogsBloom: hexutil.Encode(payload.LogsBloom), - PrevRandao: hexutil.Encode(payload.PrevRandao), - BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), - GasLimit: fmt.Sprintf("%d", payload.GasLimit), - GasUsed: fmt.Sprintf("%d", payload.GasUsed), - Timestamp: fmt.Sprintf("%d", payload.Timestamp), - ExtraData: hexutil.Encode(payload.ExtraData), - BaseFeePerGas: baseFeePerGas, - BlockHash: hexutil.Encode(payload.BlockHash), - TransactionsRoot: hexutil.Encode(payload.TransactionsRoot), - WithdrawalsRoot: hexutil.Encode(payload.WithdrawalsRoot), - }, nil -} - -func ExecutionPayloadHeaderDenebFromConsensus(payload *enginev1.ExecutionPayloadHeaderDeneb) (*ExecutionPayloadHeaderDeneb, error) { - baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) + signedElectraBlock, err := b.SignedBlock.ToConsensus() if err != nil { - return nil, err + return nil, server.NewDecodeError(err, "SignedBlock") } - - return &ExecutionPayloadHeaderDeneb{ - ParentHash: hexutil.Encode(payload.ParentHash), - FeeRecipient: hexutil.Encode(payload.FeeRecipient), - StateRoot: hexutil.Encode(payload.StateRoot), - ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), - LogsBloom: hexutil.Encode(payload.LogsBloom), - PrevRandao: hexutil.Encode(payload.PrevRandao), - BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), - GasLimit: fmt.Sprintf("%d", payload.GasLimit), - GasUsed: fmt.Sprintf("%d", payload.GasUsed), - Timestamp: fmt.Sprintf("%d", payload.Timestamp), - ExtraData: hexutil.Encode(payload.ExtraData), - BaseFeePerGas: baseFeePerGas, - BlockHash: hexutil.Encode(payload.BlockHash), - TransactionsRoot: hexutil.Encode(payload.TransactionsRoot), - WithdrawalsRoot: hexutil.Encode(payload.WithdrawalsRoot), - BlobGasUsed: fmt.Sprintf("%d", payload.BlobGasUsed), - ExcessBlobGas: fmt.Sprintf("%d", payload.ExcessBlobGas), + proofs := make([][]byte, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i], err = bytesutil.DecodeHexWithLength(proof, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("KzgProofs[%d]", i)) + } + } + blbs := make([][]byte, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i], err = bytesutil.DecodeHexWithLength(blob, fieldparams.BlobLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Blobs[%d]", i)) + } + } + blk := ð.SignedBeaconBlockContentsElectra{ + Block: signedElectraBlock, + KzgProofs: proofs, + Blobs: blbs, + } + return ð.GenericSignedBeaconBlock{Block: ð.GenericSignedBeaconBlock_Electra{Electra: blk}}, nil +} + +func (b *SignedBeaconBlockContentsElectra) ToUnsigned() *BeaconBlockContentsElectra { + return &BeaconBlockContentsElectra{ + Block: b.SignedBlock.Message, + KzgProofs: b.KzgProofs, + Blobs: b.Blobs, + } +} + +func (b *BeaconBlockContentsElectra) ToGeneric() (*eth.GenericBeaconBlock, error) { + block, err := b.ToConsensus() + if err != nil { + return nil, err + } + + return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_Electra{Electra: block}}, nil +} + +func (b *BeaconBlockContentsElectra) ToConsensus() (*eth.BeaconBlockContentsElectra, error) { + if b == nil { + return nil, errNilValue + } + + electraBlock, err := b.Block.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Block") + } + proofs := make([][]byte, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i], err = bytesutil.DecodeHexWithLength(proof, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("KzgProofs[%d]", i)) + } + } + blbs := make([][]byte, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i], err = bytesutil.DecodeHexWithLength(blob, fieldparams.BlobLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Blobs[%d]", i)) + } + } + return ð.BeaconBlockContentsElectra{ + Block: electraBlock, + KzgProofs: proofs, + Blobs: blbs, + }, nil +} + +func (b *BeaconBlockElectra) ToConsensus() (*eth.BeaconBlockElectra, error) { + if b == nil { + return nil, errNilValue + } + if b.Body == nil { + return nil, server.NewDecodeError(errNilValue, "Body") + } + if b.Body.Eth1Data == nil { + return nil, server.NewDecodeError(errNilValue, "Body.Eth1Data") + } + if b.Body.SyncAggregate == nil { + return nil, server.NewDecodeError(errNilValue, "Body.SyncAggregate") + } + if b.Body.ExecutionPayload == nil { + return nil, server.NewDecodeError(errNilValue, "Body.ExecutionPayload") + } + if b.Body.ExecutionRequests == nil { + return nil, server.NewDecodeError(errNilValue, "Body.ExecutionRequests") + } + + slot, err := strconv.ParseUint(b.Slot, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Slot") + } + proposerIndex, err := strconv.ParseUint(b.ProposerIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ProposerIndex") + } + parentRoot, err := bytesutil.DecodeHexWithLength(b.ParentRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ParentRoot") + } + stateRoot, err := bytesutil.DecodeHexWithLength(b.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "StateRoot") + } + randaoReveal, err := bytesutil.DecodeHexWithLength(b.Body.RandaoReveal, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.RandaoReveal") + } + depositRoot, err := bytesutil.DecodeHexWithLength(b.Body.Eth1Data.DepositRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.DepositRoot") + } + depositCount, err := strconv.ParseUint(b.Body.Eth1Data.DepositCount, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.DepositCount") + } + blockHash, err := bytesutil.DecodeHexWithLength(b.Body.Eth1Data.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.BlockHash") + } + graffiti, err := bytesutil.DecodeHexWithLength(b.Body.Graffiti, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Graffiti") + } + proposerSlashings, err := ProposerSlashingsToConsensus(b.Body.ProposerSlashings) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ProposerSlashings") + } + attesterSlashings, err := AttesterSlashingsElectraToConsensus(b.Body.AttesterSlashings) + if err != nil { + return nil, server.NewDecodeError(err, "Body.AttesterSlashings") + } + atts, err := AttsElectraToConsensus(b.Body.Attestations) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Attestations") + } + deposits, err := DepositsToConsensus(b.Body.Deposits) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Deposits") + } + exits, err := SignedExitsToConsensus(b.Body.VoluntaryExits) + if err != nil { + return nil, server.NewDecodeError(err, "Body.VoluntaryExits") + } + syncCommitteeBits, err := bytesutil.DecodeHexWithLength(b.Body.SyncAggregate.SyncCommitteeBits, fieldparams.SyncAggregateSyncCommitteeBytesLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeBits") + } + syncCommitteeSig, err := bytesutil.DecodeHexWithLength(b.Body.SyncAggregate.SyncCommitteeSignature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") + } + + payload, err := b.Body.ExecutionPayload.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayload") + } + + blsChanges, err := SignedBLSChangesToConsensus(b.Body.BLSToExecutionChanges) + if err != nil { + return nil, server.NewDecodeError(err, "Body.BLSToExecutionChanges") + } + err = slice.VerifyMaxLength(b.Body.BlobKzgCommitments, fieldparams.MaxBlobCommitmentsPerBlock) + if err != nil { + return nil, server.NewDecodeError(err, "Body.BlobKzgCommitments") + } + blobKzgCommitments := make([][]byte, len(b.Body.BlobKzgCommitments)) + for i, b := range b.Body.BlobKzgCommitments { + kzg, err := bytesutil.DecodeHexWithLength(b, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Body.BlobKzgCommitments[%d]", i)) + } + blobKzgCommitments[i] = kzg + } + + requests, err := b.Body.ExecutionRequests.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionRequests") + } + + return ð.BeaconBlockElectra{ + Slot: primitives.Slot(slot), + ProposerIndex: primitives.ValidatorIndex(proposerIndex), + ParentRoot: parentRoot, + StateRoot: stateRoot, + Body: ð.BeaconBlockBodyElectra{ + RandaoReveal: randaoReveal, + Eth1Data: ð.Eth1Data{ + DepositRoot: depositRoot, + DepositCount: depositCount, + BlockHash: blockHash, + }, + Graffiti: graffiti, + ProposerSlashings: proposerSlashings, + AttesterSlashings: attesterSlashings, + Attestations: atts, + Deposits: deposits, + VoluntaryExits: exits, + SyncAggregate: ð.SyncAggregate{ + SyncCommitteeBits: syncCommitteeBits, + SyncCommitteeSignature: syncCommitteeSig, + }, + ExecutionPayload: payload, + BlsToExecutionChanges: blsChanges, + BlobKzgCommitments: blobKzgCommitments, + ExecutionRequests: requests, + }, + }, nil +} + +func (b *SignedBeaconBlockElectra) ToConsensus() (*eth.SignedBeaconBlockElectra, error) { + if b == nil { + return nil, errNilValue + } + + sig, err := bytesutil.DecodeHexWithLength(b.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + block, err := b.Message.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Message") + } + return ð.SignedBeaconBlockElectra{ + Block: block, + Signature: sig, + }, nil +} + +func (b *SignedBlindedBeaconBlockElectra) ToConsensus() (*eth.SignedBlindedBeaconBlockElectra, error) { + if b == nil { + return nil, errNilValue + } + + sig, err := bytesutil.DecodeHexWithLength(b.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + blindedBlock, err := b.Message.ToConsensus() + if err != nil { + return nil, err + } + return ð.SignedBlindedBeaconBlockElectra{ + Message: blindedBlock, + Signature: sig, + }, nil +} + +func (b *SignedBlindedBeaconBlockElectra) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { + if b == nil { + return nil, errNilValue + } + sig, err := bytesutil.DecodeHexWithLength(b.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + blindedBlock, err := b.Message.ToConsensus() + if err != nil { + return nil, err + } + return ð.GenericSignedBeaconBlock{Block: ð.GenericSignedBeaconBlock_BlindedElectra{BlindedElectra: ð.SignedBlindedBeaconBlockElectra{ + Message: blindedBlock, + Signature: sig, + }}, IsBlinded: true}, nil +} + +func (b *BlindedBeaconBlockElectra) ToConsensus() (*eth.BlindedBeaconBlockElectra, error) { + if b == nil { + return nil, errNilValue + } + if b.Body == nil { + return nil, server.NewDecodeError(errNilValue, "Body") + } + if b.Body.Eth1Data == nil { + return nil, server.NewDecodeError(errNilValue, "Body.Eth1Data") + } + if b.Body.SyncAggregate == nil { + return nil, server.NewDecodeError(errNilValue, "Body.SyncAggregate") + } + if b.Body.ExecutionPayloadHeader == nil { + return nil, server.NewDecodeError(errNilValue, "Body.ExecutionPayloadHeader") + } + if b.Body.ExecutionRequests == nil { + return nil, server.NewDecodeError(errNilValue, "Body.ExecutionRequests") + } + + slot, err := strconv.ParseUint(b.Slot, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Slot") + } + proposerIndex, err := strconv.ParseUint(b.ProposerIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ProposerIndex") + } + parentRoot, err := bytesutil.DecodeHexWithLength(b.ParentRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ParentRoot") + } + stateRoot, err := bytesutil.DecodeHexWithLength(b.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "StateRoot") + } + randaoReveal, err := bytesutil.DecodeHexWithLength(b.Body.RandaoReveal, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.RandaoReveal") + } + depositRoot, err := bytesutil.DecodeHexWithLength(b.Body.Eth1Data.DepositRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.DepositRoot") + } + depositCount, err := strconv.ParseUint(b.Body.Eth1Data.DepositCount, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.DepositCount") + } + blockHash, err := bytesutil.DecodeHexWithLength(b.Body.Eth1Data.BlockHash, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.BlockHash") + } + graffiti, err := bytesutil.DecodeHexWithLength(b.Body.Graffiti, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Graffiti") + } + proposerSlashings, err := ProposerSlashingsToConsensus(b.Body.ProposerSlashings) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ProposerSlashings") + } + attesterSlashings, err := AttesterSlashingsElectraToConsensus(b.Body.AttesterSlashings) + if err != nil { + return nil, server.NewDecodeError(err, "Body.AttesterSlashings") + } + atts, err := AttsElectraToConsensus(b.Body.Attestations) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Attestations") + } + deposits, err := DepositsToConsensus(b.Body.Deposits) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Deposits") + } + exits, err := SignedExitsToConsensus(b.Body.VoluntaryExits) + if err != nil { + return nil, server.NewDecodeError(err, "Body.VoluntaryExits") + } + syncCommitteeBits, err := bytesutil.DecodeHexWithLength(b.Body.SyncAggregate.SyncCommitteeBits, fieldparams.SyncAggregateSyncCommitteeBytesLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeBits") + } + syncCommitteeSig, err := bytesutil.DecodeHexWithLength(b.Body.SyncAggregate.SyncCommitteeSignature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") + } + payloadParentHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ParentHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ParentHash") + } + payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.FeeRecipient, fieldparams.FeeRecipientLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.FeeRecipient") + } + payloadStateRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.StateRoot") + } + payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ReceiptsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ReceiptsRoot") + } + payloadLogsBloom, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.LogsBloom, fieldparams.LogsBloomLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.LogsBloom") + } + payloadPrevRandao, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.PrevRandao, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.PrevRandao") + } + payloadBlockNumber, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.BlockNumber, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockNumber") + } + payloadGasLimit, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasLimit, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasLimit") + } + payloadGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasUsed") + } + payloadTimestamp, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.Timestamp, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.Timestamp") + } + payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayloadHeader.ExtraData, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ExtraData") + } + payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(b.Body.ExecutionPayloadHeader.BaseFeePerGas) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BaseFeePerGas") + } + payloadBlockHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockHash") + } + payloadTxsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.TransactionsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.TransactionsRoot") + } + payloadWithdrawalsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.WithdrawalsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.WithdrawalsRoot") + } + payloadBlobGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.BlobGasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlobGasUsed") + } + payloadExcessBlobGas, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.ExcessBlobGas, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ExcessBlobGas") + } + + blsChanges, err := SignedBLSChangesToConsensus(b.Body.BLSToExecutionChanges) + if err != nil { + return nil, server.NewDecodeError(err, "Body.BLSToExecutionChanges") + } + err = slice.VerifyMaxLength(b.Body.BlobKzgCommitments, fieldparams.MaxBlobCommitmentsPerBlock) + if err != nil { + return nil, server.NewDecodeError(err, "Body.BlobKzgCommitments") + } + blobKzgCommitments := make([][]byte, len(b.Body.BlobKzgCommitments)) + for i, b := range b.Body.BlobKzgCommitments { + kzg, err := bytesutil.DecodeHexWithLength(b, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Body.BlobKzgCommitments[%d]", i)) + } + blobKzgCommitments[i] = kzg + } + + requests, err := b.Body.ExecutionRequests.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionRequests") + } + + return ð.BlindedBeaconBlockElectra{ + Slot: primitives.Slot(slot), + ProposerIndex: primitives.ValidatorIndex(proposerIndex), + ParentRoot: parentRoot, + StateRoot: stateRoot, + Body: ð.BlindedBeaconBlockBodyElectra{ + RandaoReveal: randaoReveal, + Eth1Data: ð.Eth1Data{ + DepositRoot: depositRoot, + DepositCount: depositCount, + BlockHash: blockHash, + }, + Graffiti: graffiti, + ProposerSlashings: proposerSlashings, + AttesterSlashings: attesterSlashings, + Attestations: atts, + Deposits: deposits, + VoluntaryExits: exits, + SyncAggregate: ð.SyncAggregate{ + SyncCommitteeBits: syncCommitteeBits, + SyncCommitteeSignature: syncCommitteeSig, + }, + ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadParentHash, + FeeRecipient: payloadFeeRecipient, + StateRoot: payloadStateRoot, + ReceiptsRoot: payloadReceiptsRoot, + LogsBloom: payloadLogsBloom, + PrevRandao: payloadPrevRandao, + BlockNumber: payloadBlockNumber, + GasLimit: payloadGasLimit, + GasUsed: payloadGasUsed, + Timestamp: payloadTimestamp, + ExtraData: payloadExtraData, + BaseFeePerGas: payloadBaseFeePerGas, + BlockHash: payloadBlockHash, + TransactionsRoot: payloadTxsRoot, + WithdrawalsRoot: payloadWithdrawalsRoot, + BlobGasUsed: payloadBlobGasUsed, + ExcessBlobGas: payloadExcessBlobGas, + }, + BlsToExecutionChanges: blsChanges, + BlobKzgCommitments: blobKzgCommitments, + ExecutionRequests: requests, + }, + }, nil +} + +func (b *BlindedBeaconBlockElectra) ToGeneric() (*eth.GenericBeaconBlock, error) { + if b == nil { + return nil, errNilValue + } + + blindedBlock, err := b.ToConsensus() + if err != nil { + return nil, err + } + return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_BlindedElectra{BlindedElectra: blindedBlock}, IsBlinded: true}, nil +} + +func SignedBeaconBlockContentsElectraFromConsensus(b *eth.SignedBeaconBlockContentsElectra) (*SignedBeaconBlockContentsElectra, error) { + block, err := SignedBeaconBlockElectraFromConsensus(b.Block) + if err != nil { + return nil, err + } + + proofs := make([]string, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i] = hexutil.Encode(proof) + } + + blbs := make([]string, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i] = hexutil.Encode(blob) + } + + return &SignedBeaconBlockContentsElectra{ + SignedBlock: block, + KzgProofs: proofs, + Blobs: blbs, + }, nil +} + +func BlindedBeaconBlockElectraFromConsensus(b *eth.BlindedBeaconBlockElectra) (*BlindedBeaconBlockElectra, error) { + blobKzgCommitments := make([]string, len(b.Body.BlobKzgCommitments)) + for i := range b.Body.BlobKzgCommitments { + blobKzgCommitments[i] = hexutil.Encode(b.Body.BlobKzgCommitments[i]) + } + payload, err := ExecutionPayloadHeaderElectraFromConsensus(b.Body.ExecutionPayloadHeader) + if err != nil { + return nil, err + } + + return &BlindedBeaconBlockElectra{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BlindedBeaconBlockBodyElectra{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsElectraFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsElectraFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + SyncAggregate: &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), + }, + ExecutionPayloadHeader: payload, + BLSToExecutionChanges: SignedBLSChangesFromConsensus(b.Body.BlsToExecutionChanges), + BlobKzgCommitments: blobKzgCommitments, + ExecutionRequests: ExecutionRequestsFromConsensus(b.Body.ExecutionRequests), + }, + }, nil +} + +func BeaconBlockContentsElectraFromConsensus(b *eth.BeaconBlockContentsElectra) (*BeaconBlockContentsElectra, error) { + block, err := BeaconBlockElectraFromConsensus(b.Block) + if err != nil { + return nil, err + } + proofs := make([]string, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i] = hexutil.Encode(proof) + } + blbs := make([]string, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i] = hexutil.Encode(blob) + } + return &BeaconBlockContentsElectra{ + Block: block, + KzgProofs: proofs, + Blobs: blbs, + }, nil +} + +func SignedBlindedBeaconBlockElectraFromConsensus(b *eth.SignedBlindedBeaconBlockElectra) (*SignedBlindedBeaconBlockElectra, error) { + block, err := BlindedBeaconBlockElectraFromConsensus(b.Message) + if err != nil { + return nil, err + } + return &SignedBlindedBeaconBlockElectra{ + Message: block, + Signature: hexutil.Encode(b.Signature), + }, nil +} + +func BeaconBlockElectraFromConsensus(b *eth.BeaconBlockElectra) (*BeaconBlockElectra, error) { + payload, err := ExecutionPayloadElectraFromConsensus(b.Body.ExecutionPayload) + if err != nil { + return nil, err + } + blobKzgCommitments := make([]string, len(b.Body.BlobKzgCommitments)) + for i := range b.Body.BlobKzgCommitments { + blobKzgCommitments[i] = hexutil.Encode(b.Body.BlobKzgCommitments[i]) + } + + return &BeaconBlockElectra{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BeaconBlockBodyElectra{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsElectraFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsElectraFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + SyncAggregate: &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), + }, + ExecutionPayload: payload, + BLSToExecutionChanges: SignedBLSChangesFromConsensus(b.Body.BlsToExecutionChanges), + BlobKzgCommitments: blobKzgCommitments, + ExecutionRequests: ExecutionRequestsFromConsensus(b.Body.ExecutionRequests), + }, + }, nil +} + +func SignedBeaconBlockElectraFromConsensus(b *eth.SignedBeaconBlockElectra) (*SignedBeaconBlockElectra, error) { + block, err := BeaconBlockElectraFromConsensus(b.Block) + if err != nil { + return nil, err + } + return &SignedBeaconBlockElectra{ + Message: block, + Signature: hexutil.Encode(b.Signature), + }, nil +} + +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +func (b *SignedBeaconBlockContentsFulu) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { + if b == nil { + return nil, errNilValue + } + + signedFuluBlock, err := b.SignedBlock.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "SignedBlock") + } + proofs := make([][]byte, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i], err = bytesutil.DecodeHexWithLength(proof, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("KzgProofs[%d]", i)) + } + } + blbs := make([][]byte, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i], err = bytesutil.DecodeHexWithLength(blob, fieldparams.BlobLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Blobs[%d]", i)) + } + } + blk := ð.SignedBeaconBlockContentsFulu{ + Block: signedFuluBlock, + KzgProofs: proofs, + Blobs: blbs, + } + return ð.GenericSignedBeaconBlock{Block: ð.GenericSignedBeaconBlock_Fulu{Fulu: blk}}, nil +} + +func (b *SignedBeaconBlockContentsFulu) ToUnsigned() *BeaconBlockContentsFulu { + return &BeaconBlockContentsFulu{ + Block: b.SignedBlock.Message, + KzgProofs: b.KzgProofs, + Blobs: b.Blobs, + } +} + +func (b *BeaconBlockContentsFulu) ToGeneric() (*eth.GenericBeaconBlock, error) { + block, err := b.ToConsensus() + if err != nil { + return nil, err + } + + return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_Fulu{Fulu: block}}, nil +} + +func (b *BeaconBlockContentsFulu) ToConsensus() (*eth.BeaconBlockContentsFulu, error) { + if b == nil { + return nil, errNilValue + } + + fuluBlock, err := b.Block.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Block") + } + proofs := make([][]byte, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i], err = bytesutil.DecodeHexWithLength(proof, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("KzgProofs[%d]", i)) + } + } + blbs := make([][]byte, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i], err = bytesutil.DecodeHexWithLength(blob, fieldparams.BlobLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Blobs[%d]", i)) + } + } + return ð.BeaconBlockContentsFulu{ + Block: fuluBlock, + KzgProofs: proofs, + Blobs: blbs, + }, nil +} + +func (b *SignedBeaconBlockFulu) ToConsensus() (*eth.SignedBeaconBlockFulu, error) { + if b == nil { + return nil, errNilValue + } + + sig, err := bytesutil.DecodeHexWithLength(b.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + block, err := b.Message.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, "Message") + } + return ð.SignedBeaconBlockFulu{ + Block: block, + Signature: sig, + }, nil +} + +func (b *SignedBlindedBeaconBlockFulu) ToConsensus() (*eth.SignedBlindedBeaconBlockFulu, error) { + if b == nil { + return nil, errNilValue + } + + sig, err := bytesutil.DecodeHexWithLength(b.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + blindedBlock, err := b.Message.ToConsensus() + if err != nil { + return nil, err + } + return ð.SignedBlindedBeaconBlockFulu{ + Message: blindedBlock, + Signature: sig, + }, nil +} + +func (b *SignedBlindedBeaconBlockFulu) ToGeneric() (*eth.GenericSignedBeaconBlock, error) { + if b == nil { + return nil, errNilValue + } + sig, err := bytesutil.DecodeHexWithLength(b.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + blindedBlock, err := b.Message.ToConsensus() + if err != nil { + return nil, err + } + return ð.GenericSignedBeaconBlock{Block: ð.GenericSignedBeaconBlock_BlindedFulu{BlindedFulu: ð.SignedBlindedBeaconBlockFulu{ + Message: blindedBlock, + Signature: sig, + }}, IsBlinded: true}, nil +} + +func (b *BlindedBeaconBlockFulu) ToConsensus() (*eth.BlindedBeaconBlockFulu, error) { + if b == nil { + return nil, errNilValue + } + if b.Body == nil { + return nil, server.NewDecodeError(errNilValue, "Body") + } + if b.Body.Eth1Data == nil { + return nil, server.NewDecodeError(errNilValue, "Body.Eth1Data") + } + if b.Body.SyncAggregate == nil { + return nil, server.NewDecodeError(errNilValue, "Body.SyncAggregate") + } + if b.Body.ExecutionPayloadHeader == nil { + return nil, server.NewDecodeError(errNilValue, "Body.ExecutionPayloadHeader") + } + + slot, err := strconv.ParseUint(b.Slot, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Slot") + } + proposerIndex, err := strconv.ParseUint(b.ProposerIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ProposerIndex") + } + parentRoot, err := bytesutil.DecodeHexWithLength(b.ParentRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ParentRoot") + } + stateRoot, err := bytesutil.DecodeHexWithLength(b.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "StateRoot") + } + randaoReveal, err := bytesutil.DecodeHexWithLength(b.Body.RandaoReveal, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.RandaoReveal") + } + depositRoot, err := bytesutil.DecodeHexWithLength(b.Body.Eth1Data.DepositRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.DepositRoot") + } + depositCount, err := strconv.ParseUint(b.Body.Eth1Data.DepositCount, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.DepositCount") + } + blockHash, err := bytesutil.DecodeHexWithLength(b.Body.Eth1Data.BlockHash, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Eth1Data.BlockHash") + } + graffiti, err := bytesutil.DecodeHexWithLength(b.Body.Graffiti, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Graffiti") + } + proposerSlashings, err := ProposerSlashingsToConsensus(b.Body.ProposerSlashings) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ProposerSlashings") + } + attesterSlashings, err := AttesterSlashingsElectraToConsensus(b.Body.AttesterSlashings) + if err != nil { + return nil, server.NewDecodeError(err, "Body.AttesterSlashings") + } + atts, err := AttsElectraToConsensus(b.Body.Attestations) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Attestations") + } + deposits, err := DepositsToConsensus(b.Body.Deposits) + if err != nil { + return nil, server.NewDecodeError(err, "Body.Deposits") + } + exits, err := SignedExitsToConsensus(b.Body.VoluntaryExits) + if err != nil { + return nil, server.NewDecodeError(err, "Body.VoluntaryExits") + } + syncCommitteeBits, err := bytesutil.DecodeHexWithLength(b.Body.SyncAggregate.SyncCommitteeBits, fieldparams.SyncAggregateSyncCommitteeBytesLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeBits") + } + syncCommitteeSig, err := bytesutil.DecodeHexWithLength(b.Body.SyncAggregate.SyncCommitteeSignature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.SyncAggregate.SyncCommitteeSignature") + } + payloadParentHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ParentHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ParentHash") + } + payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.FeeRecipient, fieldparams.FeeRecipientLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.FeeRecipient") + } + payloadStateRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.StateRoot") + } + payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.ReceiptsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ReceiptsRoot") + } + payloadLogsBloom, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.LogsBloom, fieldparams.LogsBloomLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.LogsBloom") + } + payloadPrevRandao, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.PrevRandao, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.PrevRandao") + } + payloadBlockNumber, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.BlockNumber, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockNumber") + } + payloadGasLimit, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasLimit, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasLimit") + } + payloadGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.GasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.GasUsed") + } + payloadTimestamp, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.Timestamp, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.Timestamp") + } + payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(b.Body.ExecutionPayloadHeader.ExtraData, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.ExtraData") + } + payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(b.Body.ExecutionPayloadHeader.BaseFeePerGas) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BaseFeePerGas") + } + payloadBlockHash, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.BlockHash") + } + payloadTxsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.TransactionsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.TransactionsRoot") + } + payloadWithdrawalsRoot, err := bytesutil.DecodeHexWithLength(b.Body.ExecutionPayloadHeader.WithdrawalsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayloadHeader.WithdrawalsRoot") + } + payloadBlobGasUsed, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.BlobGasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayload.BlobGasUsed") + } + payloadExcessBlobGas, err := strconv.ParseUint(b.Body.ExecutionPayloadHeader.ExcessBlobGas, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Body.ExecutionPayload.ExcessBlobGas") + } + if b.Body.ExecutionRequests == nil { + return nil, server.NewDecodeError(errors.New("nil execution requests"), "Body.ExecutionRequests") + } + depositRequests := make([]*enginev1.DepositRequest, len(b.Body.ExecutionRequests.Deposits)) + for i, d := range b.Body.ExecutionRequests.Deposits { + depositRequests[i], err = d.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionRequests.Deposits[%d]", i)) + } + } + + withdrawalRequests := make([]*enginev1.WithdrawalRequest, len(b.Body.ExecutionRequests.Withdrawals)) + for i, w := range b.Body.ExecutionRequests.Withdrawals { + withdrawalRequests[i], err = w.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionRequests.Withdrawals[%d]", i)) + } + } + + consolidationRequests := make([]*enginev1.ConsolidationRequest, len(b.Body.ExecutionRequests.Consolidations)) + for i, c := range b.Body.ExecutionRequests.Consolidations { + consolidationRequests[i], err = c.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Body.ExecutionRequests.Consolidations[%d]", i)) + } + } + + blsChanges, err := SignedBLSChangesToConsensus(b.Body.BLSToExecutionChanges) + if err != nil { + return nil, server.NewDecodeError(err, "Body.BLSToExecutionChanges") + } + err = slice.VerifyMaxLength(b.Body.BlobKzgCommitments, fieldparams.MaxBlobCommitmentsPerBlock) + if err != nil { + return nil, server.NewDecodeError(err, "Body.BlobKzgCommitments") + } + blobKzgCommitments := make([][]byte, len(b.Body.BlobKzgCommitments)) + for i, b := range b.Body.BlobKzgCommitments { + kzg, err := bytesutil.DecodeHexWithLength(b, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("Body.BlobKzgCommitments[%d]", i)) + } + blobKzgCommitments[i] = kzg + } + + return ð.BlindedBeaconBlockFulu{ + Slot: primitives.Slot(slot), + ProposerIndex: primitives.ValidatorIndex(proposerIndex), + ParentRoot: parentRoot, + StateRoot: stateRoot, + Body: ð.BlindedBeaconBlockBodyElectra{ + RandaoReveal: randaoReveal, + Eth1Data: ð.Eth1Data{ + DepositRoot: depositRoot, + DepositCount: depositCount, + BlockHash: blockHash, + }, + Graffiti: graffiti, + ProposerSlashings: proposerSlashings, + AttesterSlashings: attesterSlashings, + Attestations: atts, + Deposits: deposits, + VoluntaryExits: exits, + SyncAggregate: ð.SyncAggregate{ + SyncCommitteeBits: syncCommitteeBits, + SyncCommitteeSignature: syncCommitteeSig, + }, + ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadParentHash, + FeeRecipient: payloadFeeRecipient, + StateRoot: payloadStateRoot, + ReceiptsRoot: payloadReceiptsRoot, + LogsBloom: payloadLogsBloom, + PrevRandao: payloadPrevRandao, + BlockNumber: payloadBlockNumber, + GasLimit: payloadGasLimit, + GasUsed: payloadGasUsed, + Timestamp: payloadTimestamp, + ExtraData: payloadExtraData, + BaseFeePerGas: payloadBaseFeePerGas, + BlockHash: payloadBlockHash, + TransactionsRoot: payloadTxsRoot, + WithdrawalsRoot: payloadWithdrawalsRoot, + BlobGasUsed: payloadBlobGasUsed, + ExcessBlobGas: payloadExcessBlobGas, + }, + BlsToExecutionChanges: blsChanges, + BlobKzgCommitments: blobKzgCommitments, + ExecutionRequests: &enginev1.ExecutionRequests{ + Deposits: depositRequests, + Withdrawals: withdrawalRequests, + Consolidations: consolidationRequests, + }, + }, + }, nil +} + +func (b *BlindedBeaconBlockFulu) ToGeneric() (*eth.GenericBeaconBlock, error) { + if b == nil { + return nil, errNilValue + } + + blindedBlock, err := b.ToConsensus() + if err != nil { + return nil, err + } + return ð.GenericBeaconBlock{Block: ð.GenericBeaconBlock_BlindedFulu{BlindedFulu: blindedBlock}, IsBlinded: true}, nil +} + +func BeaconBlockContentsFuluFromConsensus(b *eth.BeaconBlockContentsFulu) (*BeaconBlockContentsFulu, error) { + block, err := BeaconBlockFuluFromConsensus(b.Block) + if err != nil { + return nil, err + } + proofs := make([]string, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i] = hexutil.Encode(proof) + } + blbs := make([]string, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i] = hexutil.Encode(blob) + } + return &BeaconBlockContentsFulu{ + Block: block, + KzgProofs: proofs, + Blobs: blbs, + }, nil +} + +func SignedBeaconBlockContentsFuluFromConsensus(b *eth.SignedBeaconBlockContentsFulu) (*SignedBeaconBlockContentsFulu, error) { + block, err := SignedBeaconBlockFuluFromConsensus(b.Block) + if err != nil { + return nil, err + } + + proofs := make([]string, len(b.KzgProofs)) + for i, proof := range b.KzgProofs { + proofs[i] = hexutil.Encode(proof) + } + + blbs := make([]string, len(b.Blobs)) + for i, blob := range b.Blobs { + blbs[i] = hexutil.Encode(blob) + } + + return &SignedBeaconBlockContentsFulu{ + SignedBlock: block, + KzgProofs: proofs, + Blobs: blbs, + }, nil +} + +func BlindedBeaconBlockFuluFromConsensus(b *eth.BlindedBeaconBlockFulu) (*BlindedBeaconBlockFulu, error) { + blobKzgCommitments := make([]string, len(b.Body.BlobKzgCommitments)) + for i := range b.Body.BlobKzgCommitments { + blobKzgCommitments[i] = hexutil.Encode(b.Body.BlobKzgCommitments[i]) + } + payload, err := ExecutionPayloadHeaderFuluFromConsensus(b.Body.ExecutionPayloadHeader) + if err != nil { + return nil, err + } + + return &BlindedBeaconBlockFulu{ + Slot: fmt.Sprintf("%d", b.Slot), + ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex), + ParentRoot: hexutil.Encode(b.ParentRoot), + StateRoot: hexutil.Encode(b.StateRoot), + Body: &BlindedBeaconBlockBodyElectra{ + RandaoReveal: hexutil.Encode(b.Body.RandaoReveal), + Eth1Data: Eth1DataFromConsensus(b.Body.Eth1Data), + Graffiti: hexutil.Encode(b.Body.Graffiti), + ProposerSlashings: ProposerSlashingsFromConsensus(b.Body.ProposerSlashings), + AttesterSlashings: AttesterSlashingsElectraFromConsensus(b.Body.AttesterSlashings), + Attestations: AttsElectraFromConsensus(b.Body.Attestations), + Deposits: DepositsFromConsensus(b.Body.Deposits), + VoluntaryExits: SignedExitsFromConsensus(b.Body.VoluntaryExits), + SyncAggregate: &SyncAggregate{ + SyncCommitteeBits: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeBits), + SyncCommitteeSignature: hexutil.Encode(b.Body.SyncAggregate.SyncCommitteeSignature), + }, + ExecutionPayloadHeader: payload, + BLSToExecutionChanges: SignedBLSChangesFromConsensus(b.Body.BlsToExecutionChanges), + BlobKzgCommitments: blobKzgCommitments, + ExecutionRequests: ExecutionRequestsFromConsensus(b.Body.ExecutionRequests), + }, + }, nil +} + +func SignedBlindedBeaconBlockFuluFromConsensus(b *eth.SignedBlindedBeaconBlockFulu) (*SignedBlindedBeaconBlockFulu, error) { + block, err := BlindedBeaconBlockFuluFromConsensus(b.Message) + if err != nil { + return nil, err + } + return &SignedBlindedBeaconBlockFulu{ + Message: block, + Signature: hexutil.Encode(b.Signature), + }, nil +} + +func SignedBeaconBlockFuluFromConsensus(b *eth.SignedBeaconBlockFulu) (*SignedBeaconBlockFulu, error) { + block, err := BeaconBlockFuluFromConsensus(b.Block) + if err != nil { + return nil, err + } + return &SignedBeaconBlockFulu{ + Message: block, + Signature: hexutil.Encode(b.Signature), }, nil } diff --git a/api/server/structs/conversions_block_execution.go b/api/server/structs/conversions_block_execution.go new file mode 100644 index 000000000000..c3cfc49dbf79 --- /dev/null +++ b/api/server/structs/conversions_block_execution.go @@ -0,0 +1,973 @@ +package structs + +import ( + "fmt" + "strconv" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/prysmaticlabs/prysm/v5/api/server" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/container/slice" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" +) + +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + +func ExecutionPayloadFromConsensus(payload *enginev1.ExecutionPayload) (*ExecutionPayload, error) { + baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) + if err != nil { + return nil, err + } + transactions := make([]string, len(payload.Transactions)) + for i, tx := range payload.Transactions { + transactions[i] = hexutil.Encode(tx) + } + + return &ExecutionPayload{ + ParentHash: hexutil.Encode(payload.ParentHash), + FeeRecipient: hexutil.Encode(payload.FeeRecipient), + StateRoot: hexutil.Encode(payload.StateRoot), + ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), + LogsBloom: hexutil.Encode(payload.LogsBloom), + PrevRandao: hexutil.Encode(payload.PrevRandao), + BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), + GasLimit: fmt.Sprintf("%d", payload.GasLimit), + GasUsed: fmt.Sprintf("%d", payload.GasUsed), + Timestamp: fmt.Sprintf("%d", payload.Timestamp), + ExtraData: hexutil.Encode(payload.ExtraData), + BaseFeePerGas: baseFeePerGas, + BlockHash: hexutil.Encode(payload.BlockHash), + Transactions: transactions, + }, nil +} + +func (e *ExecutionPayload) ToConsensus() (*enginev1.ExecutionPayload, error) { + if e == nil { + return nil, server.NewDecodeError(errNilValue, "ExecutionPayload") + } + payloadParentHash, err := bytesutil.DecodeHexWithLength(e.ParentHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ParentHash") + } + payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(e.FeeRecipient, fieldparams.FeeRecipientLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.FeeRecipient") + } + payloadStateRoot, err := bytesutil.DecodeHexWithLength(e.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.StateRoot") + } + payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(e.ReceiptsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ReceiptsRoot") + } + payloadLogsBloom, err := bytesutil.DecodeHexWithLength(e.LogsBloom, fieldparams.LogsBloomLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.LogsBloom") + } + payloadPrevRandao, err := bytesutil.DecodeHexWithLength(e.PrevRandao, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.PrevRandao") + } + payloadBlockNumber, err := strconv.ParseUint(e.BlockNumber, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BlockNumber") + } + payloadGasLimit, err := strconv.ParseUint(e.GasLimit, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.GasLimit") + } + payloadGasUsed, err := strconv.ParseUint(e.GasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.GasUsed") + } + payloadTimestamp, err := strconv.ParseUint(e.Timestamp, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.Timestamp") + } + payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(e.ExtraData, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ExtraData") + } + payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(e.BaseFeePerGas) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BaseFeePerGas") + } + payloadBlockHash, err := bytesutil.DecodeHexWithLength(e.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BlockHash") + } + err = slice.VerifyMaxLength(e.Transactions, fieldparams.MaxTxsPerPayloadLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.Transactions") + } + payloadTxs := make([][]byte, len(e.Transactions)) + for i, tx := range e.Transactions { + payloadTxs[i], err = bytesutil.DecodeHexWithMaxLength(tx, fieldparams.MaxBytesPerTxLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Transactions[%d]", i)) + } + } + return &enginev1.ExecutionPayload{ + ParentHash: payloadParentHash, + FeeRecipient: payloadFeeRecipient, + StateRoot: payloadStateRoot, + ReceiptsRoot: payloadReceiptsRoot, + LogsBloom: payloadLogsBloom, + PrevRandao: payloadPrevRandao, + BlockNumber: payloadBlockNumber, + GasLimit: payloadGasLimit, + GasUsed: payloadGasUsed, + Timestamp: payloadTimestamp, + ExtraData: payloadExtraData, + BaseFeePerGas: payloadBaseFeePerGas, + BlockHash: payloadBlockHash, + Transactions: payloadTxs, + }, nil +} + +func ExecutionPayloadHeaderFromConsensus(payload *enginev1.ExecutionPayloadHeader) (*ExecutionPayloadHeader, error) { + baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) + if err != nil { + return nil, err + } + + return &ExecutionPayloadHeader{ + ParentHash: hexutil.Encode(payload.ParentHash), + FeeRecipient: hexutil.Encode(payload.FeeRecipient), + StateRoot: hexutil.Encode(payload.StateRoot), + ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), + LogsBloom: hexutil.Encode(payload.LogsBloom), + PrevRandao: hexutil.Encode(payload.PrevRandao), + BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), + GasLimit: fmt.Sprintf("%d", payload.GasLimit), + GasUsed: fmt.Sprintf("%d", payload.GasUsed), + Timestamp: fmt.Sprintf("%d", payload.Timestamp), + ExtraData: hexutil.Encode(payload.ExtraData), + BaseFeePerGas: baseFeePerGas, + BlockHash: hexutil.Encode(payload.BlockHash), + TransactionsRoot: hexutil.Encode(payload.TransactionsRoot), + }, nil +} + +func (e *ExecutionPayloadHeader) ToConsensus() (*enginev1.ExecutionPayloadHeader, error) { + if e == nil { + return nil, server.NewDecodeError(errNilValue, "ExecutionPayloadHeader") + } + payloadParentHash, err := bytesutil.DecodeHexWithLength(e.ParentHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ParentHash") + } + payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(e.FeeRecipient, fieldparams.FeeRecipientLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.FeeRecipient") + } + payloadStateRoot, err := bytesutil.DecodeHexWithLength(e.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.StateRoot") + } + payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(e.ReceiptsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ReceiptsRoot") + } + payloadLogsBloom, err := bytesutil.DecodeHexWithLength(e.LogsBloom, fieldparams.LogsBloomLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.LogsBloom") + } + payloadPrevRandao, err := bytesutil.DecodeHexWithLength(e.PrevRandao, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.PrevRandao") + } + payloadBlockNumber, err := strconv.ParseUint(e.BlockNumber, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BlockNumber") + } + payloadGasLimit, err := strconv.ParseUint(e.GasLimit, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.GasLimit") + } + payloadGasUsed, err := strconv.ParseUint(e.GasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.GasUsed") + } + payloadTimestamp, err := strconv.ParseUint(e.Timestamp, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.Timestamp") + } + payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(e.ExtraData, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ExtraData") + } + payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(e.BaseFeePerGas) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BaseFeePerGas") + } + payloadBlockHash, err := bytesutil.DecodeHexWithLength(e.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BlockHash") + } + payloadTxsRoot, err := bytesutil.DecodeHexWithLength(e.TransactionsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.TransactionsRoot") + } + + return &enginev1.ExecutionPayloadHeader{ + ParentHash: payloadParentHash, + FeeRecipient: payloadFeeRecipient, + StateRoot: payloadStateRoot, + ReceiptsRoot: payloadReceiptsRoot, + LogsBloom: payloadLogsBloom, + PrevRandao: payloadPrevRandao, + BlockNumber: payloadBlockNumber, + GasLimit: payloadGasLimit, + GasUsed: payloadGasUsed, + Timestamp: payloadTimestamp, + ExtraData: payloadExtraData, + BaseFeePerGas: payloadBaseFeePerGas, + BlockHash: payloadBlockHash, + TransactionsRoot: payloadTxsRoot, + }, nil +} + +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + +func ExecutionPayloadCapellaFromConsensus(payload *enginev1.ExecutionPayloadCapella) (*ExecutionPayloadCapella, error) { + baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) + if err != nil { + return nil, err + } + transactions := make([]string, len(payload.Transactions)) + for i, tx := range payload.Transactions { + transactions[i] = hexutil.Encode(tx) + } + + return &ExecutionPayloadCapella{ + ParentHash: hexutil.Encode(payload.ParentHash), + FeeRecipient: hexutil.Encode(payload.FeeRecipient), + StateRoot: hexutil.Encode(payload.StateRoot), + ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), + LogsBloom: hexutil.Encode(payload.LogsBloom), + PrevRandao: hexutil.Encode(payload.PrevRandao), + BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), + GasLimit: fmt.Sprintf("%d", payload.GasLimit), + GasUsed: fmt.Sprintf("%d", payload.GasUsed), + Timestamp: fmt.Sprintf("%d", payload.Timestamp), + ExtraData: hexutil.Encode(payload.ExtraData), + BaseFeePerGas: baseFeePerGas, + BlockHash: hexutil.Encode(payload.BlockHash), + Transactions: transactions, + Withdrawals: WithdrawalsFromConsensus(payload.Withdrawals), + }, nil +} + +func (e *ExecutionPayloadCapella) ToConsensus() (*enginev1.ExecutionPayloadCapella, error) { + if e == nil { + return nil, server.NewDecodeError(errNilValue, "ExecutionPayload") + } + payloadParentHash, err := bytesutil.DecodeHexWithLength(e.ParentHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ParentHash") + } + payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(e.FeeRecipient, fieldparams.FeeRecipientLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.FeeRecipient") + } + payloadStateRoot, err := bytesutil.DecodeHexWithLength(e.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.StateRoot") + } + payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(e.ReceiptsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ReceiptsRoot") + } + payloadLogsBloom, err := bytesutil.DecodeHexWithLength(e.LogsBloom, fieldparams.LogsBloomLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.LogsBloom") + } + payloadPrevRandao, err := bytesutil.DecodeHexWithLength(e.PrevRandao, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.PrevRandao") + } + payloadBlockNumber, err := strconv.ParseUint(e.BlockNumber, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BlockNumber") + } + payloadGasLimit, err := strconv.ParseUint(e.GasLimit, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.GasLimit") + } + payloadGasUsed, err := strconv.ParseUint(e.GasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.GasUsed") + } + payloadTimestamp, err := strconv.ParseUint(e.Timestamp, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.Timestamp") + } + payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(e.ExtraData, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ExtraData") + } + payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(e.BaseFeePerGas) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BaseFeePerGas") + } + payloadBlockHash, err := bytesutil.DecodeHexWithLength(e.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BlockHash") + } + err = slice.VerifyMaxLength(e.Transactions, fieldparams.MaxTxsPerPayloadLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.Transactions") + } + payloadTxs := make([][]byte, len(e.Transactions)) + for i, tx := range e.Transactions { + payloadTxs[i], err = bytesutil.DecodeHexWithMaxLength(tx, fieldparams.MaxBytesPerTxLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Transactions[%d]", i)) + } + } + err = slice.VerifyMaxLength(e.Withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.Withdrawals") + } + withdrawals := make([]*enginev1.Withdrawal, len(e.Withdrawals)) + for i, w := range e.Withdrawals { + withdrawalIndex, err := strconv.ParseUint(w.WithdrawalIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Withdrawals[%d].WithdrawalIndex", i)) + } + validatorIndex, err := strconv.ParseUint(w.ValidatorIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Withdrawals[%d].ValidatorIndex", i)) + } + address, err := bytesutil.DecodeHexWithLength(w.ExecutionAddress, common.AddressLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Withdrawals[%d].ExecutionAddress", i)) + } + amount, err := strconv.ParseUint(w.Amount, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Withdrawals[%d].Amount", i)) + } + withdrawals[i] = &enginev1.Withdrawal{ + Index: withdrawalIndex, + ValidatorIndex: primitives.ValidatorIndex(validatorIndex), + Address: address, + Amount: amount, + } + } + return &enginev1.ExecutionPayloadCapella{ + ParentHash: payloadParentHash, + FeeRecipient: payloadFeeRecipient, + StateRoot: payloadStateRoot, + ReceiptsRoot: payloadReceiptsRoot, + LogsBloom: payloadLogsBloom, + PrevRandao: payloadPrevRandao, + BlockNumber: payloadBlockNumber, + GasLimit: payloadGasLimit, + GasUsed: payloadGasUsed, + Timestamp: payloadTimestamp, + ExtraData: payloadExtraData, + BaseFeePerGas: payloadBaseFeePerGas, + BlockHash: payloadBlockHash, + Transactions: payloadTxs, + Withdrawals: withdrawals, + }, nil +} + +func ExecutionPayloadHeaderCapellaFromConsensus(payload *enginev1.ExecutionPayloadHeaderCapella) (*ExecutionPayloadHeaderCapella, error) { + baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) + if err != nil { + return nil, err + } + + return &ExecutionPayloadHeaderCapella{ + ParentHash: hexutil.Encode(payload.ParentHash), + FeeRecipient: hexutil.Encode(payload.FeeRecipient), + StateRoot: hexutil.Encode(payload.StateRoot), + ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), + LogsBloom: hexutil.Encode(payload.LogsBloom), + PrevRandao: hexutil.Encode(payload.PrevRandao), + BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), + GasLimit: fmt.Sprintf("%d", payload.GasLimit), + GasUsed: fmt.Sprintf("%d", payload.GasUsed), + Timestamp: fmt.Sprintf("%d", payload.Timestamp), + ExtraData: hexutil.Encode(payload.ExtraData), + BaseFeePerGas: baseFeePerGas, + BlockHash: hexutil.Encode(payload.BlockHash), + TransactionsRoot: hexutil.Encode(payload.TransactionsRoot), + WithdrawalsRoot: hexutil.Encode(payload.WithdrawalsRoot), + }, nil +} + +func (e *ExecutionPayloadHeaderCapella) ToConsensus() (*enginev1.ExecutionPayloadHeaderCapella, error) { + if e == nil { + return nil, server.NewDecodeError(errNilValue, "ExecutionPayloadHeader") + } + payloadParentHash, err := bytesutil.DecodeHexWithLength(e.ParentHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ParentHash") + } + payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(e.FeeRecipient, fieldparams.FeeRecipientLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.FeeRecipient") + } + payloadStateRoot, err := bytesutil.DecodeHexWithLength(e.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.StateRoot") + } + payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(e.ReceiptsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ReceiptsRoot") + } + payloadLogsBloom, err := bytesutil.DecodeHexWithLength(e.LogsBloom, fieldparams.LogsBloomLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.LogsBloom") + } + payloadPrevRandao, err := bytesutil.DecodeHexWithLength(e.PrevRandao, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.PrevRandao") + } + payloadBlockNumber, err := strconv.ParseUint(e.BlockNumber, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BlockNumber") + } + payloadGasLimit, err := strconv.ParseUint(e.GasLimit, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.GasLimit") + } + payloadGasUsed, err := strconv.ParseUint(e.GasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.GasUsed") + } + payloadTimestamp, err := strconv.ParseUint(e.Timestamp, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.Timestamp") + } + payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(e.ExtraData, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ExtraData") + } + payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(e.BaseFeePerGas) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BaseFeePerGas") + } + payloadBlockHash, err := bytesutil.DecodeHexWithMaxLength(e.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BlockHash") + } + payloadTxsRoot, err := bytesutil.DecodeHexWithMaxLength(e.TransactionsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.TransactionsRoot") + } + payloadWithdrawalsRoot, err := bytesutil.DecodeHexWithMaxLength(e.WithdrawalsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.WithdrawalsRoot") + } + return &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: payloadParentHash, + FeeRecipient: payloadFeeRecipient, + StateRoot: payloadStateRoot, + ReceiptsRoot: payloadReceiptsRoot, + LogsBloom: payloadLogsBloom, + PrevRandao: payloadPrevRandao, + BlockNumber: payloadBlockNumber, + GasLimit: payloadGasLimit, + GasUsed: payloadGasUsed, + Timestamp: payloadTimestamp, + ExtraData: payloadExtraData, + BaseFeePerGas: payloadBaseFeePerGas, + BlockHash: payloadBlockHash, + TransactionsRoot: payloadTxsRoot, + WithdrawalsRoot: payloadWithdrawalsRoot, + }, nil +} + +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + +func ExecutionPayloadDenebFromConsensus(payload *enginev1.ExecutionPayloadDeneb) (*ExecutionPayloadDeneb, error) { + baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) + if err != nil { + return nil, err + } + transactions := make([]string, len(payload.Transactions)) + for i, tx := range payload.Transactions { + transactions[i] = hexutil.Encode(tx) + } + + return &ExecutionPayloadDeneb{ + ParentHash: hexutil.Encode(payload.ParentHash), + FeeRecipient: hexutil.Encode(payload.FeeRecipient), + StateRoot: hexutil.Encode(payload.StateRoot), + ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), + LogsBloom: hexutil.Encode(payload.LogsBloom), + PrevRandao: hexutil.Encode(payload.PrevRandao), + BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), + GasLimit: fmt.Sprintf("%d", payload.GasLimit), + GasUsed: fmt.Sprintf("%d", payload.GasUsed), + Timestamp: fmt.Sprintf("%d", payload.Timestamp), + ExtraData: hexutil.Encode(payload.ExtraData), + BaseFeePerGas: baseFeePerGas, + BlockHash: hexutil.Encode(payload.BlockHash), + Transactions: transactions, + Withdrawals: WithdrawalsFromConsensus(payload.Withdrawals), + BlobGasUsed: fmt.Sprintf("%d", payload.BlobGasUsed), + ExcessBlobGas: fmt.Sprintf("%d", payload.ExcessBlobGas), + }, nil +} + +func (e *ExecutionPayloadDeneb) ToConsensus() (*enginev1.ExecutionPayloadDeneb, error) { + if e == nil { + return nil, server.NewDecodeError(errNilValue, "ExecutionPayload") + } + payloadParentHash, err := bytesutil.DecodeHexWithLength(e.ParentHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ParentHash") + } + payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(e.FeeRecipient, fieldparams.FeeRecipientLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.FeeRecipient") + } + payloadStateRoot, err := bytesutil.DecodeHexWithLength(e.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.StateRoot") + } + payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(e.ReceiptsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ReceiptsRoot") + } + payloadLogsBloom, err := bytesutil.DecodeHexWithLength(e.LogsBloom, fieldparams.LogsBloomLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.LogsBloom") + } + payloadPrevRandao, err := bytesutil.DecodeHexWithLength(e.PrevRandao, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.PrevRandao") + } + payloadBlockNumber, err := strconv.ParseUint(e.BlockNumber, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BlockNumber") + } + payloadGasLimit, err := strconv.ParseUint(e.GasLimit, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.GasLimit") + } + payloadGasUsed, err := strconv.ParseUint(e.GasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.GasUsed") + } + payloadTimestamp, err := strconv.ParseUint(e.Timestamp, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.Timestamp") + } + payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(e.ExtraData, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ExtraData") + } + payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(e.BaseFeePerGas) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BaseFeePerGas") + } + payloadBlockHash, err := bytesutil.DecodeHexWithLength(e.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BlockHash") + } + err = slice.VerifyMaxLength(e.Transactions, fieldparams.MaxTxsPerPayloadLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.Transactions") + } + txs := make([][]byte, len(e.Transactions)) + for i, tx := range e.Transactions { + txs[i], err = bytesutil.DecodeHexWithMaxLength(tx, fieldparams.MaxBytesPerTxLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Transactions[%d]", i)) + } + } + err = slice.VerifyMaxLength(e.Withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.Withdrawals") + } + withdrawals := make([]*enginev1.Withdrawal, len(e.Withdrawals)) + for i, w := range e.Withdrawals { + withdrawalIndex, err := strconv.ParseUint(w.WithdrawalIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Withdrawals[%d].WithdrawalIndex", i)) + } + validatorIndex, err := strconv.ParseUint(w.ValidatorIndex, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Withdrawals[%d].ValidatorIndex", i)) + } + address, err := bytesutil.DecodeHexWithLength(w.ExecutionAddress, common.AddressLength) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Withdrawals[%d].ExecutionAddress", i)) + } + amount, err := strconv.ParseUint(w.Amount, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionPayload.Withdrawals[%d].Amount", i)) + } + withdrawals[i] = &enginev1.Withdrawal{ + Index: withdrawalIndex, + ValidatorIndex: primitives.ValidatorIndex(validatorIndex), + Address: address, + Amount: amount, + } + } + + payloadBlobGasUsed, err := strconv.ParseUint(e.BlobGasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BlobGasUsed") + } + payloadExcessBlobGas, err := strconv.ParseUint(e.ExcessBlobGas, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ExcessBlobGas") + } + return &enginev1.ExecutionPayloadDeneb{ + ParentHash: payloadParentHash, + FeeRecipient: payloadFeeRecipient, + StateRoot: payloadStateRoot, + ReceiptsRoot: payloadReceiptsRoot, + LogsBloom: payloadLogsBloom, + PrevRandao: payloadPrevRandao, + BlockNumber: payloadBlockNumber, + GasLimit: payloadGasLimit, + GasUsed: payloadGasUsed, + Timestamp: payloadTimestamp, + ExtraData: payloadExtraData, + BaseFeePerGas: payloadBaseFeePerGas, + BlockHash: payloadBlockHash, + Transactions: txs, + Withdrawals: withdrawals, + BlobGasUsed: payloadBlobGasUsed, + ExcessBlobGas: payloadExcessBlobGas, + }, nil +} + +func ExecutionPayloadHeaderDenebFromConsensus(payload *enginev1.ExecutionPayloadHeaderDeneb) (*ExecutionPayloadHeaderDeneb, error) { + baseFeePerGas, err := sszBytesToUint256String(payload.BaseFeePerGas) + if err != nil { + return nil, err + } + + return &ExecutionPayloadHeaderDeneb{ + ParentHash: hexutil.Encode(payload.ParentHash), + FeeRecipient: hexutil.Encode(payload.FeeRecipient), + StateRoot: hexutil.Encode(payload.StateRoot), + ReceiptsRoot: hexutil.Encode(payload.ReceiptsRoot), + LogsBloom: hexutil.Encode(payload.LogsBloom), + PrevRandao: hexutil.Encode(payload.PrevRandao), + BlockNumber: fmt.Sprintf("%d", payload.BlockNumber), + GasLimit: fmt.Sprintf("%d", payload.GasLimit), + GasUsed: fmt.Sprintf("%d", payload.GasUsed), + Timestamp: fmt.Sprintf("%d", payload.Timestamp), + ExtraData: hexutil.Encode(payload.ExtraData), + BaseFeePerGas: baseFeePerGas, + BlockHash: hexutil.Encode(payload.BlockHash), + TransactionsRoot: hexutil.Encode(payload.TransactionsRoot), + WithdrawalsRoot: hexutil.Encode(payload.WithdrawalsRoot), + BlobGasUsed: fmt.Sprintf("%d", payload.BlobGasUsed), + ExcessBlobGas: fmt.Sprintf("%d", payload.ExcessBlobGas), + }, nil +} + +func (e *ExecutionPayloadHeaderDeneb) ToConsensus() (*enginev1.ExecutionPayloadHeaderDeneb, error) { + if e == nil { + return nil, server.NewDecodeError(errNilValue, "ExecutionPayloadHeader") + } + payloadParentHash, err := bytesutil.DecodeHexWithLength(e.ParentHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ParentHash") + } + payloadFeeRecipient, err := bytesutil.DecodeHexWithLength(e.FeeRecipient, fieldparams.FeeRecipientLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.FeeRecipient") + } + payloadStateRoot, err := bytesutil.DecodeHexWithLength(e.StateRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.StateRoot") + } + payloadReceiptsRoot, err := bytesutil.DecodeHexWithLength(e.ReceiptsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ReceiptsRoot") + } + payloadLogsBloom, err := bytesutil.DecodeHexWithLength(e.LogsBloom, fieldparams.LogsBloomLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.LogsBloom") + } + payloadPrevRandao, err := bytesutil.DecodeHexWithLength(e.PrevRandao, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.PrevRandao") + } + payloadBlockNumber, err := strconv.ParseUint(e.BlockNumber, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BlockNumber") + } + payloadGasLimit, err := strconv.ParseUint(e.GasLimit, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.GasLimit") + } + payloadGasUsed, err := strconv.ParseUint(e.GasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.GasUsed") + } + payloadTimestamp, err := strconv.ParseUint(e.Timestamp, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.Timestamp") + } + payloadExtraData, err := bytesutil.DecodeHexWithMaxLength(e.ExtraData, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.ExtraData") + } + payloadBaseFeePerGas, err := bytesutil.Uint256ToSSZBytes(e.BaseFeePerGas) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BaseFeePerGas") + } + payloadBlockHash, err := bytesutil.DecodeHexWithLength(e.BlockHash, common.HashLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.BlockHash") + } + payloadTxsRoot, err := bytesutil.DecodeHexWithLength(e.TransactionsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.TransactionsRoot") + } + payloadWithdrawalsRoot, err := bytesutil.DecodeHexWithLength(e.WithdrawalsRoot, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayloadHeader.WithdrawalsRoot") + } + payloadBlobGasUsed, err := strconv.ParseUint(e.BlobGasUsed, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.BlobGasUsed") + } + payloadExcessBlobGas, err := strconv.ParseUint(e.ExcessBlobGas, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "ExecutionPayload.ExcessBlobGas") + } + return &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadParentHash, + FeeRecipient: payloadFeeRecipient, + StateRoot: payloadStateRoot, + ReceiptsRoot: payloadReceiptsRoot, + LogsBloom: payloadLogsBloom, + PrevRandao: payloadPrevRandao, + BlockNumber: payloadBlockNumber, + GasLimit: payloadGasLimit, + GasUsed: payloadGasUsed, + Timestamp: payloadTimestamp, + ExtraData: payloadExtraData, + BaseFeePerGas: payloadBaseFeePerGas, + BlockHash: payloadBlockHash, + TransactionsRoot: payloadTxsRoot, + WithdrawalsRoot: payloadWithdrawalsRoot, + BlobGasUsed: payloadBlobGasUsed, + ExcessBlobGas: payloadExcessBlobGas, + }, nil +} + +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +var ( + ExecutionPayloadElectraFromConsensus = ExecutionPayloadDenebFromConsensus + ExecutionPayloadHeaderElectraFromConsensus = ExecutionPayloadHeaderDenebFromConsensus +) + +func WithdrawalRequestsFromConsensus(ws []*enginev1.WithdrawalRequest) []*WithdrawalRequest { + result := make([]*WithdrawalRequest, len(ws)) + for i, w := range ws { + result[i] = WithdrawalRequestFromConsensus(w) + } + return result +} + +func WithdrawalRequestFromConsensus(w *enginev1.WithdrawalRequest) *WithdrawalRequest { + return &WithdrawalRequest{ + SourceAddress: hexutil.Encode(w.SourceAddress), + ValidatorPubkey: hexutil.Encode(w.ValidatorPubkey), + Amount: fmt.Sprintf("%d", w.Amount), + } +} + +func (w *WithdrawalRequest) ToConsensus() (*enginev1.WithdrawalRequest, error) { + if w == nil { + return nil, server.NewDecodeError(errNilValue, "WithdrawalRequest") + } + src, err := bytesutil.DecodeHexWithLength(w.SourceAddress, common.AddressLength) + if err != nil { + return nil, server.NewDecodeError(err, "SourceAddress") + } + pubkey, err := bytesutil.DecodeHexWithLength(w.ValidatorPubkey, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, "ValidatorPubkey") + } + amount, err := strconv.ParseUint(w.Amount, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Amount") + } + return &enginev1.WithdrawalRequest{ + SourceAddress: src, + ValidatorPubkey: pubkey, + Amount: amount, + }, nil +} + +func ConsolidationRequestsFromConsensus(cs []*enginev1.ConsolidationRequest) []*ConsolidationRequest { + result := make([]*ConsolidationRequest, len(cs)) + for i, c := range cs { + result[i] = ConsolidationRequestFromConsensus(c) + } + return result +} + +func ConsolidationRequestFromConsensus(c *enginev1.ConsolidationRequest) *ConsolidationRequest { + return &ConsolidationRequest{ + SourceAddress: hexutil.Encode(c.SourceAddress), + SourcePubkey: hexutil.Encode(c.SourcePubkey), + TargetPubkey: hexutil.Encode(c.TargetPubkey), + } +} + +func (c *ConsolidationRequest) ToConsensus() (*enginev1.ConsolidationRequest, error) { + if c == nil { + return nil, server.NewDecodeError(errNilValue, "ConsolidationRequest") + } + srcAddress, err := bytesutil.DecodeHexWithLength(c.SourceAddress, common.AddressLength) + if err != nil { + return nil, server.NewDecodeError(err, "SourceAddress") + } + srcPubkey, err := bytesutil.DecodeHexWithLength(c.SourcePubkey, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, "SourcePubkey") + } + targetPubkey, err := bytesutil.DecodeHexWithLength(c.TargetPubkey, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, "TargetPubkey") + } + return &enginev1.ConsolidationRequest{ + SourceAddress: srcAddress, + SourcePubkey: srcPubkey, + TargetPubkey: targetPubkey, + }, nil +} + +func DepositRequestsFromConsensus(ds []*enginev1.DepositRequest) []*DepositRequest { + result := make([]*DepositRequest, len(ds)) + for i, d := range ds { + result[i] = DepositRequestFromConsensus(d) + } + return result +} + +func DepositRequestFromConsensus(d *enginev1.DepositRequest) *DepositRequest { + return &DepositRequest{ + Pubkey: hexutil.Encode(d.Pubkey), + WithdrawalCredentials: hexutil.Encode(d.WithdrawalCredentials), + Amount: fmt.Sprintf("%d", d.Amount), + Signature: hexutil.Encode(d.Signature), + Index: fmt.Sprintf("%d", d.Index), + } +} + +func (d *DepositRequest) ToConsensus() (*enginev1.DepositRequest, error) { + if d == nil { + return nil, server.NewDecodeError(errNilValue, "DepositRequest") + } + pubkey, err := bytesutil.DecodeHexWithLength(d.Pubkey, fieldparams.BLSPubkeyLength) + if err != nil { + return nil, server.NewDecodeError(err, "Pubkey") + } + withdrawalCredentials, err := bytesutil.DecodeHexWithLength(d.WithdrawalCredentials, fieldparams.RootLength) + if err != nil { + return nil, server.NewDecodeError(err, "WithdrawalCredentials") + } + amount, err := strconv.ParseUint(d.Amount, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Amount") + } + sig, err := bytesutil.DecodeHexWithLength(d.Signature, fieldparams.BLSSignatureLength) + if err != nil { + return nil, server.NewDecodeError(err, "Signature") + } + index, err := strconv.ParseUint(d.Index, 10, 64) + if err != nil { + return nil, server.NewDecodeError(err, "Index") + } + return &enginev1.DepositRequest{ + Pubkey: pubkey, + WithdrawalCredentials: withdrawalCredentials, + Amount: amount, + Signature: sig, + Index: index, + }, nil +} + +func ExecutionRequestsFromConsensus(er *enginev1.ExecutionRequests) *ExecutionRequests { + return &ExecutionRequests{ + Deposits: DepositRequestsFromConsensus(er.Deposits), + Withdrawals: WithdrawalRequestsFromConsensus(er.Withdrawals), + Consolidations: ConsolidationRequestsFromConsensus(er.Consolidations), + } +} + +func (e *ExecutionRequests) ToConsensus() (*enginev1.ExecutionRequests, error) { + if e == nil { + return nil, server.NewDecodeError(errNilValue, "ExecutionRequests") + } + var err error + if err = slice.VerifyMaxLength(e.Deposits, params.BeaconConfig().MaxDepositRequestsPerPayload); err != nil { + return nil, err + } + depositRequests := make([]*enginev1.DepositRequest, len(e.Deposits)) + for i, d := range e.Deposits { + depositRequests[i], err = d.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionRequests.Deposits[%d]", i)) + } + } + + if err = slice.VerifyMaxLength(e.Withdrawals, params.BeaconConfig().MaxWithdrawalRequestsPerPayload); err != nil { + return nil, err + } + withdrawalRequests := make([]*enginev1.WithdrawalRequest, len(e.Withdrawals)) + for i, w := range e.Withdrawals { + withdrawalRequests[i], err = w.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionRequests.Withdrawals[%d]", i)) + } + } + + if err = slice.VerifyMaxLength(e.Consolidations, params.BeaconConfig().MaxConsolidationsRequestsPerPayload); err != nil { + return nil, err + } + consolidationRequests := make([]*enginev1.ConsolidationRequest, len(e.Consolidations)) + for i, c := range e.Consolidations { + consolidationRequests[i], err = c.ToConsensus() + if err != nil { + return nil, server.NewDecodeError(err, fmt.Sprintf("ExecutionRequests.Consolidations[%d]", i)) + } + } + return &enginev1.ExecutionRequests{ + Deposits: depositRequests, + Withdrawals: withdrawalRequests, + Consolidations: consolidationRequests, + }, nil +} + +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +var ( + ExecutionPayloadFuluFromConsensus = ExecutionPayloadDenebFromConsensus + ExecutionPayloadHeaderFuluFromConsensus = ExecutionPayloadHeaderDenebFromConsensus + BeaconBlockFuluFromConsensus = BeaconBlockElectraFromConsensus +) diff --git a/api/server/structs/conversions_block_execution_test.go b/api/server/structs/conversions_block_execution_test.go new file mode 100644 index 000000000000..1ef680288dee --- /dev/null +++ b/api/server/structs/conversions_block_execution_test.go @@ -0,0 +1,563 @@ +package structs + +import ( + "fmt" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +func fillByteSlice(sliceLength int, value byte) []byte { + bytes := make([]byte, sliceLength) + + for index := range bytes { + bytes[index] = value + } + + return bytes +} + +// TestExecutionPayloadFromConsensus_HappyPath checks the +// ExecutionPayloadFromConsensus function under normal conditions. +func TestExecutionPayloadFromConsensus_HappyPath(t *testing.T) { + consensusPayload := &enginev1.ExecutionPayload{ + ParentHash: fillByteSlice(common.HashLength, 0xaa), + FeeRecipient: fillByteSlice(20, 0xbb), + StateRoot: fillByteSlice(32, 0xcc), + ReceiptsRoot: fillByteSlice(32, 0xdd), + LogsBloom: fillByteSlice(256, 0xee), + PrevRandao: fillByteSlice(32, 0xff), + BlockNumber: 12345, + GasLimit: 15000000, + GasUsed: 8000000, + Timestamp: 1680000000, + ExtraData: fillByteSlice(8, 0x11), + BaseFeePerGas: fillByteSlice(32, 0x01), + BlockHash: fillByteSlice(common.HashLength, 0x22), + Transactions: [][]byte{ + fillByteSlice(10, 0x33), + fillByteSlice(10, 0x44), + }, + } + + result, err := ExecutionPayloadFromConsensus(consensusPayload) + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, hexutil.Encode(consensusPayload.ParentHash), result.ParentHash) + require.Equal(t, hexutil.Encode(consensusPayload.FeeRecipient), result.FeeRecipient) + require.Equal(t, hexutil.Encode(consensusPayload.StateRoot), result.StateRoot) + require.Equal(t, hexutil.Encode(consensusPayload.ReceiptsRoot), result.ReceiptsRoot) + require.Equal(t, fmt.Sprintf("%d", consensusPayload.BlockNumber), result.BlockNumber) +} + +// TestExecutionPayload_ToConsensus_HappyPath checks the +// (*ExecutionPayload).ToConsensus function under normal conditions. +func TestExecutionPayload_ToConsensus_HappyPath(t *testing.T) { + payload := &ExecutionPayload{ + ParentHash: hexutil.Encode(fillByteSlice(common.HashLength, 0xaa)), + FeeRecipient: hexutil.Encode(fillByteSlice(20, 0xbb)), + StateRoot: hexutil.Encode(fillByteSlice(32, 0xcc)), + ReceiptsRoot: hexutil.Encode(fillByteSlice(32, 0xdd)), + LogsBloom: hexutil.Encode(fillByteSlice(256, 0xee)), + PrevRandao: hexutil.Encode(fillByteSlice(32, 0xff)), + BlockNumber: "12345", + GasLimit: "15000000", + GasUsed: "8000000", + Timestamp: "1680000000", + ExtraData: "0x11111111", + BaseFeePerGas: "1234", + BlockHash: hexutil.Encode(fillByteSlice(common.HashLength, 0x22)), + Transactions: []string{ + hexutil.Encode(fillByteSlice(10, 0x33)), + hexutil.Encode(fillByteSlice(10, 0x44)), + }, + } + + result, err := payload.ToConsensus() + require.NoError(t, err) + require.DeepEqual(t, result.ParentHash, fillByteSlice(common.HashLength, 0xaa)) + require.DeepEqual(t, result.FeeRecipient, fillByteSlice(20, 0xbb)) + require.DeepEqual(t, result.StateRoot, fillByteSlice(32, 0xcc)) +} + +// TestExecutionPayloadHeaderFromConsensus_HappyPath checks the +// ExecutionPayloadHeaderFromConsensus function under normal conditions. +func TestExecutionPayloadHeaderFromConsensus_HappyPath(t *testing.T) { + consensusHeader := &enginev1.ExecutionPayloadHeader{ + ParentHash: fillByteSlice(common.HashLength, 0xaa), + FeeRecipient: fillByteSlice(20, 0xbb), + StateRoot: fillByteSlice(32, 0xcc), + ReceiptsRoot: fillByteSlice(32, 0xdd), + LogsBloom: fillByteSlice(256, 0xee), + PrevRandao: fillByteSlice(32, 0xff), + BlockNumber: 9999, + GasLimit: 5000000, + GasUsed: 2500000, + Timestamp: 1111111111, + ExtraData: fillByteSlice(4, 0x12), + BaseFeePerGas: fillByteSlice(32, 0x34), + BlockHash: fillByteSlice(common.HashLength, 0x56), + TransactionsRoot: fillByteSlice(32, 0x78), + } + + result, err := ExecutionPayloadHeaderFromConsensus(consensusHeader) + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, hexutil.Encode(consensusHeader.ParentHash), result.ParentHash) + require.Equal(t, fmt.Sprintf("%d", consensusHeader.BlockNumber), result.BlockNumber) +} + +// TestExecutionPayloadHeader_ToConsensus_HappyPath checks the +// (*ExecutionPayloadHeader).ToConsensus function under normal conditions. +func TestExecutionPayloadHeader_ToConsensus_HappyPath(t *testing.T) { + header := &ExecutionPayloadHeader{ + ParentHash: hexutil.Encode(fillByteSlice(common.HashLength, 0xaa)), + FeeRecipient: hexutil.Encode(fillByteSlice(20, 0xbb)), + StateRoot: hexutil.Encode(fillByteSlice(32, 0xcc)), + ReceiptsRoot: hexutil.Encode(fillByteSlice(32, 0xdd)), + LogsBloom: hexutil.Encode(fillByteSlice(256, 0xee)), + PrevRandao: hexutil.Encode(fillByteSlice(32, 0xff)), + BlockNumber: "9999", + GasLimit: "5000000", + GasUsed: "2500000", + Timestamp: "1111111111", + ExtraData: "0x1234abcd", + BaseFeePerGas: "1234", + BlockHash: hexutil.Encode(fillByteSlice(common.HashLength, 0x56)), + TransactionsRoot: hexutil.Encode(fillByteSlice(32, 0x78)), + } + + result, err := header.ToConsensus() + require.NoError(t, err) + require.DeepEqual(t, hexutil.Encode(result.ParentHash), header.ParentHash) + require.DeepEqual(t, hexutil.Encode(result.FeeRecipient), header.FeeRecipient) + require.DeepEqual(t, hexutil.Encode(result.StateRoot), header.StateRoot) +} + +// TestExecutionPayloadCapellaFromConsensus_HappyPath checks the +// ExecutionPayloadCapellaFromConsensus function under normal conditions. +func TestExecutionPayloadCapellaFromConsensus_HappyPath(t *testing.T) { + capellaPayload := &enginev1.ExecutionPayloadCapella{ + ParentHash: fillByteSlice(common.HashLength, 0xaa), + FeeRecipient: fillByteSlice(20, 0xbb), + StateRoot: fillByteSlice(32, 0xcc), + ReceiptsRoot: fillByteSlice(32, 0xdd), + LogsBloom: fillByteSlice(256, 0xee), + PrevRandao: fillByteSlice(32, 0xff), + BlockNumber: 123, + GasLimit: 9876543, + GasUsed: 1234567, + Timestamp: 5555555, + ExtraData: fillByteSlice(6, 0x11), + BaseFeePerGas: fillByteSlice(32, 0x22), + BlockHash: fillByteSlice(common.HashLength, 0x33), + Transactions: [][]byte{ + fillByteSlice(5, 0x44), + }, + Withdrawals: []*enginev1.Withdrawal{ + { + Index: 1, + ValidatorIndex: 2, + Address: fillByteSlice(20, 0xaa), + Amount: 100, + }, + }, + } + + result, err := ExecutionPayloadCapellaFromConsensus(capellaPayload) + require.NoError(t, err) + require.NotNil(t, result) + require.Equal(t, hexutil.Encode(capellaPayload.ParentHash), result.ParentHash) + require.Equal(t, len(capellaPayload.Transactions), len(result.Transactions)) + require.Equal(t, len(capellaPayload.Withdrawals), len(result.Withdrawals)) +} + +// TestExecutionPayloadCapella_ToConsensus_HappyPath checks the +// (*ExecutionPayloadCapella).ToConsensus function under normal conditions. +func TestExecutionPayloadCapella_ToConsensus_HappyPath(t *testing.T) { + capella := &ExecutionPayloadCapella{ + ParentHash: hexutil.Encode(fillByteSlice(common.HashLength, 0xaa)), + FeeRecipient: hexutil.Encode(fillByteSlice(20, 0xbb)), + StateRoot: hexutil.Encode(fillByteSlice(32, 0xcc)), + ReceiptsRoot: hexutil.Encode(fillByteSlice(32, 0xdd)), + LogsBloom: hexutil.Encode(fillByteSlice(256, 0xee)), + PrevRandao: hexutil.Encode(fillByteSlice(32, 0xff)), + BlockNumber: "123", + GasLimit: "9876543", + GasUsed: "1234567", + Timestamp: "5555555", + ExtraData: hexutil.Encode(fillByteSlice(6, 0x11)), + BaseFeePerGas: "1234", + BlockHash: hexutil.Encode(fillByteSlice(common.HashLength, 0x33)), + Transactions: []string{ + hexutil.Encode(fillByteSlice(5, 0x44)), + }, + Withdrawals: []*Withdrawal{ + { + WithdrawalIndex: "1", + ValidatorIndex: "2", + ExecutionAddress: hexutil.Encode(fillByteSlice(20, 0xaa)), + Amount: "100", + }, + }, + } + + result, err := capella.ToConsensus() + require.NoError(t, err) + require.DeepEqual(t, hexutil.Encode(result.ParentHash), capella.ParentHash) + require.DeepEqual(t, hexutil.Encode(result.FeeRecipient), capella.FeeRecipient) + require.DeepEqual(t, hexutil.Encode(result.StateRoot), capella.StateRoot) +} + +// TestExecutionPayloadDenebFromConsensus_HappyPath checks the +// ExecutionPayloadDenebFromConsensus function under normal conditions. +func TestExecutionPayloadDenebFromConsensus_HappyPath(t *testing.T) { + denebPayload := &enginev1.ExecutionPayloadDeneb{ + ParentHash: fillByteSlice(common.HashLength, 0xaa), + FeeRecipient: fillByteSlice(20, 0xbb), + StateRoot: fillByteSlice(32, 0xcc), + ReceiptsRoot: fillByteSlice(32, 0xdd), + LogsBloom: fillByteSlice(256, 0xee), + PrevRandao: fillByteSlice(32, 0xff), + BlockNumber: 999, + GasLimit: 2222222, + GasUsed: 1111111, + Timestamp: 666666, + ExtraData: fillByteSlice(6, 0x11), + BaseFeePerGas: fillByteSlice(32, 0x22), + BlockHash: fillByteSlice(common.HashLength, 0x33), + Transactions: [][]byte{ + fillByteSlice(5, 0x44), + }, + Withdrawals: []*enginev1.Withdrawal{ + { + Index: 1, + ValidatorIndex: 2, + Address: fillByteSlice(20, 0xaa), + Amount: 100, + }, + }, + BlobGasUsed: 1234, + ExcessBlobGas: 5678, + } + + result, err := ExecutionPayloadDenebFromConsensus(denebPayload) + require.NoError(t, err) + require.Equal(t, hexutil.Encode(denebPayload.ParentHash), result.ParentHash) + require.Equal(t, len(denebPayload.Transactions), len(result.Transactions)) + require.Equal(t, len(denebPayload.Withdrawals), len(result.Withdrawals)) + require.Equal(t, "1234", result.BlobGasUsed) + require.Equal(t, fmt.Sprintf("%d", denebPayload.BlockNumber), result.BlockNumber) +} + +// TestExecutionPayloadDeneb_ToConsensus_HappyPath checks the +// (*ExecutionPayloadDeneb).ToConsensus function under normal conditions. +func TestExecutionPayloadDeneb_ToConsensus_HappyPath(t *testing.T) { + deneb := &ExecutionPayloadDeneb{ + ParentHash: hexutil.Encode(fillByteSlice(common.HashLength, 0xaa)), + FeeRecipient: hexutil.Encode(fillByteSlice(20, 0xbb)), + StateRoot: hexutil.Encode(fillByteSlice(32, 0xcc)), + ReceiptsRoot: hexutil.Encode(fillByteSlice(32, 0xdd)), + LogsBloom: hexutil.Encode(fillByteSlice(256, 0xee)), + PrevRandao: hexutil.Encode(fillByteSlice(32, 0xff)), + BlockNumber: "999", + GasLimit: "2222222", + GasUsed: "1111111", + Timestamp: "666666", + ExtraData: hexutil.Encode(fillByteSlice(6, 0x11)), + BaseFeePerGas: "1234", + BlockHash: hexutil.Encode(fillByteSlice(common.HashLength, 0x33)), + Transactions: []string{ + hexutil.Encode(fillByteSlice(5, 0x44)), + }, + Withdrawals: []*Withdrawal{ + { + WithdrawalIndex: "1", + ValidatorIndex: "2", + ExecutionAddress: hexutil.Encode(fillByteSlice(20, 0xaa)), + Amount: "100", + }, + }, + BlobGasUsed: "1234", + ExcessBlobGas: "5678", + } + + result, err := deneb.ToConsensus() + require.NoError(t, err) + require.DeepEqual(t, hexutil.Encode(result.ParentHash), deneb.ParentHash) + require.DeepEqual(t, hexutil.Encode(result.FeeRecipient), deneb.FeeRecipient) + require.Equal(t, result.BlockNumber, uint64(999)) +} + +func TestExecutionPayloadHeaderCapellaFromConsensus_HappyPath(t *testing.T) { + capellaHeader := &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: fillByteSlice(common.HashLength, 0xaa), + FeeRecipient: fillByteSlice(20, 0xbb), + StateRoot: fillByteSlice(32, 0xcc), + ReceiptsRoot: fillByteSlice(32, 0xdd), + LogsBloom: fillByteSlice(256, 0xee), + PrevRandao: fillByteSlice(32, 0xff), + BlockNumber: 555, + GasLimit: 1111111, + GasUsed: 222222, + Timestamp: 3333333333, + ExtraData: fillByteSlice(4, 0x12), + BaseFeePerGas: fillByteSlice(32, 0x34), + BlockHash: fillByteSlice(common.HashLength, 0x56), + TransactionsRoot: fillByteSlice(32, 0x78), + WithdrawalsRoot: fillByteSlice(32, 0x99), + } + + result, err := ExecutionPayloadHeaderCapellaFromConsensus(capellaHeader) + require.NoError(t, err) + require.Equal(t, hexutil.Encode(capellaHeader.ParentHash), result.ParentHash) + require.DeepEqual(t, hexutil.Encode(capellaHeader.WithdrawalsRoot), result.WithdrawalsRoot) +} + +func TestExecutionPayloadHeaderCapella_ToConsensus_HappyPath(t *testing.T) { + header := &ExecutionPayloadHeaderCapella{ + ParentHash: hexutil.Encode(fillByteSlice(common.HashLength, 0xaa)), + FeeRecipient: hexutil.Encode(fillByteSlice(20, 0xbb)), + StateRoot: hexutil.Encode(fillByteSlice(32, 0xcc)), + ReceiptsRoot: hexutil.Encode(fillByteSlice(32, 0xdd)), + LogsBloom: hexutil.Encode(fillByteSlice(256, 0xee)), + PrevRandao: hexutil.Encode(fillByteSlice(32, 0xff)), + BlockNumber: "555", + GasLimit: "1111111", + GasUsed: "222222", + Timestamp: "3333333333", + ExtraData: "0x1234abcd", + BaseFeePerGas: "1234", + BlockHash: hexutil.Encode(fillByteSlice(common.HashLength, 0x56)), + TransactionsRoot: hexutil.Encode(fillByteSlice(32, 0x78)), + WithdrawalsRoot: hexutil.Encode(fillByteSlice(32, 0x99)), + } + + result, err := header.ToConsensus() + require.NoError(t, err) + require.DeepEqual(t, hexutil.Encode(result.ParentHash), header.ParentHash) + require.DeepEqual(t, hexutil.Encode(result.FeeRecipient), header.FeeRecipient) + require.DeepEqual(t, hexutil.Encode(result.StateRoot), header.StateRoot) + require.DeepEqual(t, hexutil.Encode(result.ReceiptsRoot), header.ReceiptsRoot) + require.DeepEqual(t, hexutil.Encode(result.WithdrawalsRoot), header.WithdrawalsRoot) +} + +func TestExecutionPayloadHeaderDenebFromConsensus_HappyPath(t *testing.T) { + denebHeader := &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: fillByteSlice(common.HashLength, 0xaa), + FeeRecipient: fillByteSlice(20, 0xbb), + StateRoot: fillByteSlice(32, 0xcc), + ReceiptsRoot: fillByteSlice(32, 0xdd), + LogsBloom: fillByteSlice(256, 0xee), + PrevRandao: fillByteSlice(32, 0xff), + BlockNumber: 999, + GasLimit: 5000000, + GasUsed: 2500000, + Timestamp: 4444444444, + ExtraData: fillByteSlice(4, 0x12), + BaseFeePerGas: fillByteSlice(32, 0x34), + BlockHash: fillByteSlice(common.HashLength, 0x56), + TransactionsRoot: fillByteSlice(32, 0x78), + WithdrawalsRoot: fillByteSlice(32, 0x99), + BlobGasUsed: 1234, + ExcessBlobGas: 5678, + } + + result, err := ExecutionPayloadHeaderDenebFromConsensus(denebHeader) + require.NoError(t, err) + require.Equal(t, hexutil.Encode(denebHeader.ParentHash), result.ParentHash) + require.DeepEqual(t, hexutil.Encode(denebHeader.FeeRecipient), result.FeeRecipient) + require.DeepEqual(t, hexutil.Encode(denebHeader.StateRoot), result.StateRoot) + require.DeepEqual(t, fmt.Sprintf("%d", denebHeader.BlobGasUsed), result.BlobGasUsed) +} + +func TestExecutionPayloadHeaderDeneb_ToConsensus_HappyPath(t *testing.T) { + header := &ExecutionPayloadHeaderDeneb{ + ParentHash: hexutil.Encode(fillByteSlice(common.HashLength, 0xaa)), + FeeRecipient: hexutil.Encode(fillByteSlice(20, 0xbb)), + StateRoot: hexutil.Encode(fillByteSlice(32, 0xcc)), + ReceiptsRoot: hexutil.Encode(fillByteSlice(32, 0xdd)), + LogsBloom: hexutil.Encode(fillByteSlice(256, 0xee)), + PrevRandao: hexutil.Encode(fillByteSlice(32, 0xff)), + BlockNumber: "999", + GasLimit: "5000000", + GasUsed: "2500000", + Timestamp: "4444444444", + ExtraData: "0x1234abcd", + BaseFeePerGas: "1234", + BlockHash: hexutil.Encode(fillByteSlice(common.HashLength, 0x56)), + TransactionsRoot: hexutil.Encode(fillByteSlice(32, 0x78)), + WithdrawalsRoot: hexutil.Encode(fillByteSlice(32, 0x99)), + BlobGasUsed: "1234", + ExcessBlobGas: "5678", + } + + result, err := header.ToConsensus() + require.NoError(t, err) + require.DeepEqual(t, hexutil.Encode(result.ParentHash), header.ParentHash) + require.DeepEqual(t, result.BlobGasUsed, uint64(1234)) + require.DeepEqual(t, result.ExcessBlobGas, uint64(5678)) + require.DeepEqual(t, result.BlockNumber, uint64(999)) +} + +func TestWithdrawalRequestsFromConsensus_HappyPath(t *testing.T) { + consensusRequests := []*enginev1.WithdrawalRequest{ + { + SourceAddress: fillByteSlice(20, 0xbb), + ValidatorPubkey: fillByteSlice(48, 0xbb), + Amount: 12345, + }, + { + SourceAddress: fillByteSlice(20, 0xcc), + ValidatorPubkey: fillByteSlice(48, 0xcc), + Amount: 54321, + }, + } + + result := WithdrawalRequestsFromConsensus(consensusRequests) + require.DeepEqual(t, len(result), len(consensusRequests)) + require.DeepEqual(t, result[0].Amount, fmt.Sprintf("%d", consensusRequests[0].Amount)) +} + +func TestWithdrawalRequestFromConsensus_HappyPath(t *testing.T) { + req := &enginev1.WithdrawalRequest{ + SourceAddress: fillByteSlice(20, 0xbb), + ValidatorPubkey: fillByteSlice(48, 0xbb), + Amount: 42, + } + result := WithdrawalRequestFromConsensus(req) + require.NotNil(t, result) + require.DeepEqual(t, result.SourceAddress, hexutil.Encode(fillByteSlice(20, 0xbb))) +} + +func TestWithdrawalRequest_ToConsensus_HappyPath(t *testing.T) { + withdrawalReq := &WithdrawalRequest{ + SourceAddress: hexutil.Encode(fillByteSlice(20, 111)), + ValidatorPubkey: hexutil.Encode(fillByteSlice(48, 123)), + Amount: "12345", + } + result, err := withdrawalReq.ToConsensus() + require.NoError(t, err) + require.DeepEqual(t, result.Amount, uint64(12345)) +} + +func TestConsolidationRequestsFromConsensus_HappyPath(t *testing.T) { + consensusRequests := []*enginev1.ConsolidationRequest{ + { + SourceAddress: fillByteSlice(20, 111), + SourcePubkey: fillByteSlice(48, 112), + TargetPubkey: fillByteSlice(48, 113), + }, + } + result := ConsolidationRequestsFromConsensus(consensusRequests) + require.DeepEqual(t, len(result), len(consensusRequests)) + require.DeepEqual(t, result[0].SourceAddress, "0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f") +} + +func TestDepositRequestsFromConsensus_HappyPath(t *testing.T) { + ds := []*enginev1.DepositRequest{ + { + Pubkey: fillByteSlice(48, 0xbb), + WithdrawalCredentials: fillByteSlice(32, 0xdd), + Amount: 98765, + Signature: fillByteSlice(96, 0xff), + Index: 111, + }, + } + result := DepositRequestsFromConsensus(ds) + require.DeepEqual(t, len(result), len(ds)) + require.DeepEqual(t, result[0].Amount, "98765") +} + +func TestDepositRequest_ToConsensus_HappyPath(t *testing.T) { + req := &DepositRequest{ + Pubkey: hexutil.Encode(fillByteSlice(48, 0xbb)), + WithdrawalCredentials: hexutil.Encode(fillByteSlice(32, 0xaa)), + Amount: "123", + Signature: hexutil.Encode(fillByteSlice(96, 0xdd)), + Index: "456", + } + + result, err := req.ToConsensus() + require.NoError(t, err) + require.DeepEqual(t, result.Amount, uint64(123)) + require.DeepEqual(t, result.Signature, fillByteSlice(96, 0xdd)) +} + +func TestExecutionRequestsFromConsensus_HappyPath(t *testing.T) { + er := &enginev1.ExecutionRequests{ + Deposits: []*enginev1.DepositRequest{ + { + Pubkey: fillByteSlice(48, 0xba), + WithdrawalCredentials: fillByteSlice(32, 0xaa), + Amount: 33, + Signature: fillByteSlice(96, 0xff), + Index: 44, + }, + }, + Withdrawals: []*enginev1.WithdrawalRequest{ + { + SourceAddress: fillByteSlice(20, 0xaa), + ValidatorPubkey: fillByteSlice(48, 0xba), + Amount: 555, + }, + }, + Consolidations: []*enginev1.ConsolidationRequest{ + { + SourceAddress: fillByteSlice(20, 0xdd), + SourcePubkey: fillByteSlice(48, 0xdd), + TargetPubkey: fillByteSlice(48, 0xcc), + }, + }, + } + + result := ExecutionRequestsFromConsensus(er) + require.NotNil(t, result) + require.Equal(t, 1, len(result.Deposits)) + require.Equal(t, "33", result.Deposits[0].Amount) + require.Equal(t, 1, len(result.Withdrawals)) + require.Equal(t, "555", result.Withdrawals[0].Amount) + require.Equal(t, 1, len(result.Consolidations)) + require.Equal(t, "0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", result.Consolidations[0].TargetPubkey) +} + +func TestExecutionRequests_ToConsensus_HappyPath(t *testing.T) { + execReq := &ExecutionRequests{ + Deposits: []*DepositRequest{ + { + Pubkey: hexutil.Encode(fillByteSlice(48, 0xbb)), + WithdrawalCredentials: hexutil.Encode(fillByteSlice(32, 0xaa)), + Amount: "33", + Signature: hexutil.Encode(fillByteSlice(96, 0xff)), + Index: "44", + }, + }, + Withdrawals: []*WithdrawalRequest{ + { + SourceAddress: hexutil.Encode(fillByteSlice(20, 0xdd)), + ValidatorPubkey: hexutil.Encode(fillByteSlice(48, 0xbb)), + Amount: "555", + }, + }, + Consolidations: []*ConsolidationRequest{ + { + SourceAddress: hexutil.Encode(fillByteSlice(20, 0xcc)), + SourcePubkey: hexutil.Encode(fillByteSlice(48, 0xbb)), + TargetPubkey: hexutil.Encode(fillByteSlice(48, 0xcc)), + }, + }, + } + + result, err := execReq.ToConsensus() + require.NoError(t, err) + + require.Equal(t, 1, len(result.Deposits)) + require.Equal(t, uint64(33), result.Deposits[0].Amount) + require.Equal(t, 1, len(result.Withdrawals)) + require.Equal(t, uint64(555), result.Withdrawals[0].Amount) + require.Equal(t, 1, len(result.Consolidations)) + require.DeepEqual(t, fillByteSlice(48, 0xcc), result.Consolidations[0].TargetPubkey) +} diff --git a/api/server/structs/conversions_lightclient.go b/api/server/structs/conversions_lightclient.go new file mode 100644 index 000000000000..f533a77f2882 --- /dev/null +++ b/api/server/structs/conversions_lightclient.go @@ -0,0 +1,229 @@ +package structs + +import ( + "encoding/json" + "fmt" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" +) + +func LightClientUpdateFromConsensus(update interfaces.LightClientUpdate) (*LightClientUpdate, error) { + attestedHeader, err := lightClientHeaderToJSON(update.AttestedHeader()) + if err != nil { + return nil, errors.Wrap(err, "could not marshal attested light client header") + } + finalizedHeader, err := lightClientHeaderToJSON(update.FinalizedHeader()) + if err != nil { + return nil, errors.Wrap(err, "could not marshal finalized light client header") + } + + var scBranch [][32]byte + var finalityBranch [][32]byte + if update.Version() >= version.Electra { + scb, err := update.NextSyncCommitteeBranchElectra() + if err != nil { + return nil, err + } + scBranch = scb[:] + fb, err := update.FinalityBranchElectra() + if err != nil { + return nil, err + } + finalityBranch = fb[:] + } else { + scb, err := update.NextSyncCommitteeBranch() + if err != nil { + return nil, err + } + scBranch = scb[:] + fb, err := update.FinalityBranch() + if err != nil { + return nil, err + } + finalityBranch = fb[:] + } + + return &LightClientUpdate{ + AttestedHeader: attestedHeader, + NextSyncCommittee: SyncCommitteeFromConsensus(update.NextSyncCommittee()), + NextSyncCommitteeBranch: branchToJSON(scBranch), + FinalizedHeader: finalizedHeader, + FinalityBranch: branchToJSON(finalityBranch), + SyncAggregate: SyncAggregateFromConsensus(update.SyncAggregate()), + SignatureSlot: fmt.Sprintf("%d", update.SignatureSlot()), + }, nil +} + +func LightClientFinalityUpdateFromConsensus(update interfaces.LightClientFinalityUpdate) (*LightClientFinalityUpdate, error) { + attestedHeader, err := lightClientHeaderToJSON(update.AttestedHeader()) + if err != nil { + return nil, errors.Wrap(err, "could not marshal attested light client header") + } + finalizedHeader, err := lightClientHeaderToJSON(update.FinalizedHeader()) + if err != nil { + return nil, errors.Wrap(err, "could not marshal finalized light client header") + } + + var finalityBranch [][32]byte + if update.Version() >= version.Electra { + b, err := update.FinalityBranchElectra() + if err != nil { + return nil, err + } + finalityBranch = b[:] + } else { + b, err := update.FinalityBranch() + if err != nil { + return nil, err + } + finalityBranch = b[:] + } + + return &LightClientFinalityUpdate{ + AttestedHeader: attestedHeader, + FinalizedHeader: finalizedHeader, + FinalityBranch: branchToJSON(finalityBranch), + SyncAggregate: SyncAggregateFromConsensus(update.SyncAggregate()), + SignatureSlot: fmt.Sprintf("%d", update.SignatureSlot()), + }, nil +} + +func LightClientOptimisticUpdateFromConsensus(update interfaces.LightClientOptimisticUpdate) (*LightClientOptimisticUpdate, error) { + attestedHeader, err := lightClientHeaderToJSON(update.AttestedHeader()) + if err != nil { + return nil, errors.Wrap(err, "could not marshal attested light client header") + } + + return &LightClientOptimisticUpdate{ + AttestedHeader: attestedHeader, + SyncAggregate: SyncAggregateFromConsensus(update.SyncAggregate()), + SignatureSlot: fmt.Sprintf("%d", update.SignatureSlot()), + }, nil +} + +func branchToJSON[S [][32]byte](branchBytes S) []string { + if branchBytes == nil { + return nil + } + branch := make([]string, len(branchBytes)) + for i, root := range branchBytes { + branch[i] = hexutil.Encode(root[:]) + } + return branch +} + +func lightClientHeaderToJSON(header interfaces.LightClientHeader) (json.RawMessage, error) { + // In the case that a finalizedHeader is nil. + if header == nil { + return nil, nil + } + + var result any + + switch v := header.Version(); v { + case version.Altair: + result = &LightClientHeader{Beacon: BeaconBlockHeaderFromConsensus(header.Beacon())} + case version.Capella: + exInterface, err := header.Execution() + if err != nil { + return nil, err + } + ex, ok := exInterface.Proto().(*enginev1.ExecutionPayloadHeaderCapella) + if !ok { + return nil, fmt.Errorf("execution data is not %T", &enginev1.ExecutionPayloadHeaderCapella{}) + } + execution, err := ExecutionPayloadHeaderCapellaFromConsensus(ex) + if err != nil { + return nil, err + } + executionBranch, err := header.ExecutionBranch() + if err != nil { + return nil, err + } + result = &LightClientHeaderCapella{ + Beacon: BeaconBlockHeaderFromConsensus(header.Beacon()), + Execution: execution, + ExecutionBranch: branchToJSON(executionBranch[:]), + } + case version.Deneb: + exInterface, err := header.Execution() + if err != nil { + return nil, err + } + ex, ok := exInterface.Proto().(*enginev1.ExecutionPayloadHeaderDeneb) + if !ok { + return nil, fmt.Errorf("execution data is not %T", &enginev1.ExecutionPayloadHeaderDeneb{}) + } + execution, err := ExecutionPayloadHeaderDenebFromConsensus(ex) + if err != nil { + return nil, err + } + executionBranch, err := header.ExecutionBranch() + if err != nil { + return nil, err + } + result = &LightClientHeaderDeneb{ + Beacon: BeaconBlockHeaderFromConsensus(header.Beacon()), + Execution: execution, + ExecutionBranch: branchToJSON(executionBranch[:]), + } + case version.Electra: + exInterface, err := header.Execution() + if err != nil { + return nil, err + } + ex, ok := exInterface.Proto().(*enginev1.ExecutionPayloadHeaderDeneb) + if !ok { + return nil, fmt.Errorf("execution data is not %T", &enginev1.ExecutionPayloadHeaderDeneb{}) + } + execution, err := ExecutionPayloadHeaderElectraFromConsensus(ex) + if err != nil { + return nil, err + } + executionBranch, err := header.ExecutionBranch() + if err != nil { + return nil, err + } + result = &LightClientHeaderDeneb{ + Beacon: BeaconBlockHeaderFromConsensus(header.Beacon()), + Execution: execution, + ExecutionBranch: branchToJSON(executionBranch[:]), + } + default: + return nil, fmt.Errorf("unsupported header version %s", version.String(v)) + } + + return json.Marshal(result) +} + +func LightClientBootstrapFromConsensus(bootstrap interfaces.LightClientBootstrap) (*LightClientBootstrap, error) { + header, err := lightClientHeaderToJSON(bootstrap.Header()) + if err != nil { + return nil, errors.Wrap(err, "could not marshal light client header") + } + + var scBranch [][32]byte + if bootstrap.Version() >= version.Electra { + b, err := bootstrap.CurrentSyncCommitteeBranchElectra() + if err != nil { + return nil, err + } + scBranch = b[:] + } else { + b, err := bootstrap.CurrentSyncCommitteeBranch() + if err != nil { + return nil, err + } + scBranch = b[:] + } + + return &LightClientBootstrap{ + Header: header, + CurrentSyncCommittee: SyncCommitteeFromConsensus(bootstrap.CurrentSyncCommittee()), + CurrentSyncCommitteeBranch: branchToJSON(scBranch), + }, nil +} diff --git a/api/server/structs/conversions_state.go b/api/server/structs/conversions_state.go index 33dc3af0813a..f7fec1e1a484 100644 --- a/api/server/structs/conversions_state.go +++ b/api/server/structs/conversions_state.go @@ -11,6 +11,10 @@ import ( var errPayloadHeaderNotFound = errors.New("expected payload header not found") +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + func BeaconStateFromConsensus(st beaconState.BeaconState) (*BeaconState, error) { srcBr := st.BlockRoots() br := make([]string, len(srcBr)) @@ -97,6 +101,10 @@ func BeaconStateFromConsensus(st beaconState.BeaconState) (*BeaconState, error) }, nil } +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- + func BeaconStateAltairFromConsensus(st beaconState.BeaconState) (*BeaconStateAltair, error) { srcBr := st.BlockRoots() br := make([]string, len(srcBr)) @@ -202,6 +210,10 @@ func BeaconStateAltairFromConsensus(st beaconState.BeaconState) (*BeaconStateAlt }, nil } +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + func BeaconStateBellatrixFromConsensus(st beaconState.BeaconState) (*BeaconStateBellatrix, error) { srcBr := st.BlockRoots() br := make([]string, len(srcBr)) @@ -320,6 +332,10 @@ func BeaconStateBellatrixFromConsensus(st beaconState.BeaconState) (*BeaconState }, nil } +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + func BeaconStateCapellaFromConsensus(st beaconState.BeaconState) (*BeaconStateCapella, error) { srcBr := st.BlockRoots() br := make([]string, len(srcBr)) @@ -457,6 +473,10 @@ func BeaconStateCapellaFromConsensus(st beaconState.BeaconState) (*BeaconStateCa }, nil } +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + func BeaconStateDenebFromConsensus(st beaconState.BeaconState) (*BeaconStateDeneb, error) { srcBr := st.BlockRoots() br := make([]string, len(srcBr)) @@ -593,3 +613,375 @@ func BeaconStateDenebFromConsensus(st beaconState.BeaconState) (*BeaconStateDene HistoricalSummaries: hs, }, nil } + +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +func BeaconStateElectraFromConsensus(st beaconState.BeaconState) (*BeaconStateElectra, error) { + srcBr := st.BlockRoots() + br := make([]string, len(srcBr)) + for i, r := range srcBr { + br[i] = hexutil.Encode(r) + } + srcSr := st.StateRoots() + sr := make([]string, len(srcSr)) + for i, r := range srcSr { + sr[i] = hexutil.Encode(r) + } + srcHr, err := st.HistoricalRoots() + if err != nil { + return nil, err + } + hr := make([]string, len(srcHr)) + for i, r := range srcHr { + hr[i] = hexutil.Encode(r) + } + srcVotes := st.Eth1DataVotes() + votes := make([]*Eth1Data, len(srcVotes)) + for i, e := range srcVotes { + votes[i] = Eth1DataFromConsensus(e) + } + srcVals := st.Validators() + vals := make([]*Validator, len(srcVals)) + for i, v := range srcVals { + vals[i] = ValidatorFromConsensus(v) + } + srcBals := st.Balances() + bals := make([]string, len(srcBals)) + for i, b := range srcBals { + bals[i] = fmt.Sprintf("%d", b) + } + srcRm := st.RandaoMixes() + rm := make([]string, len(srcRm)) + for i, m := range srcRm { + rm[i] = hexutil.Encode(m) + } + srcSlashings := st.Slashings() + slashings := make([]string, len(srcSlashings)) + for i, s := range srcSlashings { + slashings[i] = fmt.Sprintf("%d", s) + } + srcPrevPart, err := st.PreviousEpochParticipation() + if err != nil { + return nil, err + } + prevPart := make([]string, len(srcPrevPart)) + for i, p := range srcPrevPart { + prevPart[i] = fmt.Sprintf("%d", p) + } + srcCurrPart, err := st.CurrentEpochParticipation() + if err != nil { + return nil, err + } + currPart := make([]string, len(srcCurrPart)) + for i, p := range srcCurrPart { + currPart[i] = fmt.Sprintf("%d", p) + } + srcIs, err := st.InactivityScores() + if err != nil { + return nil, err + } + is := make([]string, len(srcIs)) + for i, s := range srcIs { + is[i] = fmt.Sprintf("%d", s) + } + currSc, err := st.CurrentSyncCommittee() + if err != nil { + return nil, err + } + nextSc, err := st.NextSyncCommittee() + if err != nil { + return nil, err + } + execData, err := st.LatestExecutionPayloadHeader() + if err != nil { + return nil, err + } + srcPayload, ok := execData.Proto().(*enginev1.ExecutionPayloadHeaderDeneb) + if !ok { + return nil, errPayloadHeaderNotFound + } + payload, err := ExecutionPayloadHeaderElectraFromConsensus(srcPayload) + if err != nil { + return nil, err + } + srcHs, err := st.HistoricalSummaries() + if err != nil { + return nil, err + } + hs := make([]*HistoricalSummary, len(srcHs)) + for i, s := range srcHs { + hs[i] = HistoricalSummaryFromConsensus(s) + } + nwi, err := st.NextWithdrawalIndex() + if err != nil { + return nil, err + } + nwvi, err := st.NextWithdrawalValidatorIndex() + if err != nil { + return nil, err + } + drsi, err := st.DepositRequestsStartIndex() + if err != nil { + return nil, err + } + dbtc, err := st.DepositBalanceToConsume() + if err != nil { + return nil, err + } + ebtc, err := st.ExitBalanceToConsume() + if err != nil { + return nil, err + } + eee, err := st.EarliestExitEpoch() + if err != nil { + return nil, err + } + cbtc, err := st.ConsolidationBalanceToConsume() + if err != nil { + return nil, err + } + ece, err := st.EarliestConsolidationEpoch() + if err != nil { + return nil, err + } + pbd, err := st.PendingDeposits() + if err != nil { + return nil, err + } + ppw, err := st.PendingPartialWithdrawals() + if err != nil { + return nil, err + } + pc, err := st.PendingConsolidations() + if err != nil { + return nil, err + } + + return &BeaconStateElectra{ + GenesisTime: fmt.Sprintf("%d", st.GenesisTime()), + GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()), + Slot: fmt.Sprintf("%d", st.Slot()), + Fork: ForkFromConsensus(st.Fork()), + LatestBlockHeader: BeaconBlockHeaderFromConsensus(st.LatestBlockHeader()), + BlockRoots: br, + StateRoots: sr, + HistoricalRoots: hr, + Eth1Data: Eth1DataFromConsensus(st.Eth1Data()), + Eth1DataVotes: votes, + Eth1DepositIndex: fmt.Sprintf("%d", st.Eth1DepositIndex()), + Validators: vals, + Balances: bals, + RandaoMixes: rm, + Slashings: slashings, + PreviousEpochParticipation: prevPart, + CurrentEpochParticipation: currPart, + JustificationBits: hexutil.Encode(st.JustificationBits()), + PreviousJustifiedCheckpoint: CheckpointFromConsensus(st.PreviousJustifiedCheckpoint()), + CurrentJustifiedCheckpoint: CheckpointFromConsensus(st.CurrentJustifiedCheckpoint()), + FinalizedCheckpoint: CheckpointFromConsensus(st.FinalizedCheckpoint()), + InactivityScores: is, + CurrentSyncCommittee: SyncCommitteeFromConsensus(currSc), + NextSyncCommittee: SyncCommitteeFromConsensus(nextSc), + LatestExecutionPayloadHeader: payload, + NextWithdrawalIndex: fmt.Sprintf("%d", nwi), + NextWithdrawalValidatorIndex: fmt.Sprintf("%d", nwvi), + HistoricalSummaries: hs, + DepositRequestsStartIndex: fmt.Sprintf("%d", drsi), + DepositBalanceToConsume: fmt.Sprintf("%d", dbtc), + ExitBalanceToConsume: fmt.Sprintf("%d", ebtc), + EarliestExitEpoch: fmt.Sprintf("%d", eee), + ConsolidationBalanceToConsume: fmt.Sprintf("%d", cbtc), + EarliestConsolidationEpoch: fmt.Sprintf("%d", ece), + PendingDeposits: PendingDepositsFromConsensus(pbd), + PendingPartialWithdrawals: PendingPartialWithdrawalsFromConsensus(ppw), + PendingConsolidations: PendingConsolidationsFromConsensus(pc), + }, nil +} + +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +func BeaconStateFuluFromConsensus(st beaconState.BeaconState) (*BeaconStateFulu, error) { + srcBr := st.BlockRoots() + br := make([]string, len(srcBr)) + for i, r := range srcBr { + br[i] = hexutil.Encode(r) + } + srcSr := st.StateRoots() + sr := make([]string, len(srcSr)) + for i, r := range srcSr { + sr[i] = hexutil.Encode(r) + } + srcHr, err := st.HistoricalRoots() + if err != nil { + return nil, err + } + hr := make([]string, len(srcHr)) + for i, r := range srcHr { + hr[i] = hexutil.Encode(r) + } + srcVotes := st.Eth1DataVotes() + votes := make([]*Eth1Data, len(srcVotes)) + for i, e := range srcVotes { + votes[i] = Eth1DataFromConsensus(e) + } + srcVals := st.Validators() + vals := make([]*Validator, len(srcVals)) + for i, v := range srcVals { + vals[i] = ValidatorFromConsensus(v) + } + srcBals := st.Balances() + bals := make([]string, len(srcBals)) + for i, b := range srcBals { + bals[i] = fmt.Sprintf("%d", b) + } + srcRm := st.RandaoMixes() + rm := make([]string, len(srcRm)) + for i, m := range srcRm { + rm[i] = hexutil.Encode(m) + } + srcSlashings := st.Slashings() + slashings := make([]string, len(srcSlashings)) + for i, s := range srcSlashings { + slashings[i] = fmt.Sprintf("%d", s) + } + srcPrevPart, err := st.PreviousEpochParticipation() + if err != nil { + return nil, err + } + prevPart := make([]string, len(srcPrevPart)) + for i, p := range srcPrevPart { + prevPart[i] = fmt.Sprintf("%d", p) + } + srcCurrPart, err := st.CurrentEpochParticipation() + if err != nil { + return nil, err + } + currPart := make([]string, len(srcCurrPart)) + for i, p := range srcCurrPart { + currPart[i] = fmt.Sprintf("%d", p) + } + srcIs, err := st.InactivityScores() + if err != nil { + return nil, err + } + is := make([]string, len(srcIs)) + for i, s := range srcIs { + is[i] = fmt.Sprintf("%d", s) + } + currSc, err := st.CurrentSyncCommittee() + if err != nil { + return nil, err + } + nextSc, err := st.NextSyncCommittee() + if err != nil { + return nil, err + } + execData, err := st.LatestExecutionPayloadHeader() + if err != nil { + return nil, err + } + srcPayload, ok := execData.Proto().(*enginev1.ExecutionPayloadHeaderDeneb) + if !ok { + return nil, errPayloadHeaderNotFound + } + payload, err := ExecutionPayloadHeaderElectraFromConsensus(srcPayload) + if err != nil { + return nil, err + } + srcHs, err := st.HistoricalSummaries() + if err != nil { + return nil, err + } + hs := make([]*HistoricalSummary, len(srcHs)) + for i, s := range srcHs { + hs[i] = HistoricalSummaryFromConsensus(s) + } + nwi, err := st.NextWithdrawalIndex() + if err != nil { + return nil, err + } + nwvi, err := st.NextWithdrawalValidatorIndex() + if err != nil { + return nil, err + } + drsi, err := st.DepositRequestsStartIndex() + if err != nil { + return nil, err + } + dbtc, err := st.DepositBalanceToConsume() + if err != nil { + return nil, err + } + ebtc, err := st.ExitBalanceToConsume() + if err != nil { + return nil, err + } + eee, err := st.EarliestExitEpoch() + if err != nil { + return nil, err + } + cbtc, err := st.ConsolidationBalanceToConsume() + if err != nil { + return nil, err + } + ece, err := st.EarliestConsolidationEpoch() + if err != nil { + return nil, err + } + pbd, err := st.PendingDeposits() + if err != nil { + return nil, err + } + ppw, err := st.PendingPartialWithdrawals() + if err != nil { + return nil, err + } + pc, err := st.PendingConsolidations() + if err != nil { + return nil, err + } + + return &BeaconStateFulu{ + GenesisTime: fmt.Sprintf("%d", st.GenesisTime()), + GenesisValidatorsRoot: hexutil.Encode(st.GenesisValidatorsRoot()), + Slot: fmt.Sprintf("%d", st.Slot()), + Fork: ForkFromConsensus(st.Fork()), + LatestBlockHeader: BeaconBlockHeaderFromConsensus(st.LatestBlockHeader()), + BlockRoots: br, + StateRoots: sr, + HistoricalRoots: hr, + Eth1Data: Eth1DataFromConsensus(st.Eth1Data()), + Eth1DataVotes: votes, + Eth1DepositIndex: fmt.Sprintf("%d", st.Eth1DepositIndex()), + Validators: vals, + Balances: bals, + RandaoMixes: rm, + Slashings: slashings, + PreviousEpochParticipation: prevPart, + CurrentEpochParticipation: currPart, + JustificationBits: hexutil.Encode(st.JustificationBits()), + PreviousJustifiedCheckpoint: CheckpointFromConsensus(st.PreviousJustifiedCheckpoint()), + CurrentJustifiedCheckpoint: CheckpointFromConsensus(st.CurrentJustifiedCheckpoint()), + FinalizedCheckpoint: CheckpointFromConsensus(st.FinalizedCheckpoint()), + InactivityScores: is, + CurrentSyncCommittee: SyncCommitteeFromConsensus(currSc), + NextSyncCommittee: SyncCommitteeFromConsensus(nextSc), + LatestExecutionPayloadHeader: payload, + NextWithdrawalIndex: fmt.Sprintf("%d", nwi), + NextWithdrawalValidatorIndex: fmt.Sprintf("%d", nwvi), + HistoricalSummaries: hs, + DepositRequestsStartIndex: fmt.Sprintf("%d", drsi), + DepositBalanceToConsume: fmt.Sprintf("%d", dbtc), + ExitBalanceToConsume: fmt.Sprintf("%d", ebtc), + EarliestExitEpoch: fmt.Sprintf("%d", eee), + ConsolidationBalanceToConsume: fmt.Sprintf("%d", cbtc), + EarliestConsolidationEpoch: fmt.Sprintf("%d", ece), + PendingDeposits: PendingDepositsFromConsensus(pbd), + PendingPartialWithdrawals: PendingPartialWithdrawalsFromConsensus(ppw), + PendingConsolidations: PendingConsolidationsFromConsensus(pc), + }, nil +} diff --git a/api/server/structs/conversions_test.go b/api/server/structs/conversions_test.go index a49fd1097721..ff54d9fb2622 100644 --- a/api/server/structs/conversions_test.go +++ b/api/server/structs/conversions_test.go @@ -24,3 +24,96 @@ func TestDepositSnapshotFromConsensus(t *testing.T) { require.Equal(t, "0x1234", res.ExecutionBlockHash) require.Equal(t, "67890", res.ExecutionBlockHeight) } + +func TestSignedBLSToExecutionChange_ToConsensus(t *testing.T) { + s := &SignedBLSToExecutionChange{Message: nil, Signature: ""} + _, err := s.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestSignedValidatorRegistration_ToConsensus(t *testing.T) { + s := &SignedValidatorRegistration{Message: nil, Signature: ""} + _, err := s.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestSignedContributionAndProof_ToConsensus(t *testing.T) { + s := &SignedContributionAndProof{Message: nil, Signature: ""} + _, err := s.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestContributionAndProof_ToConsensus(t *testing.T) { + c := &ContributionAndProof{ + Contribution: nil, + AggregatorIndex: "invalid", + SelectionProof: "", + } + _, err := c.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestSignedAggregateAttestationAndProof_ToConsensus(t *testing.T) { + s := &SignedAggregateAttestationAndProof{Message: nil, Signature: ""} + _, err := s.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestAggregateAttestationAndProof_ToConsensus(t *testing.T) { + a := &AggregateAttestationAndProof{ + AggregatorIndex: "1", + Aggregate: nil, + SelectionProof: "", + } + _, err := a.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestAttestation_ToConsensus(t *testing.T) { + a := &Attestation{ + AggregationBits: "0x10", + Data: nil, + Signature: "", + } + _, err := a.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestSingleAttestation_ToConsensus(t *testing.T) { + s := &SingleAttestation{ + CommitteeIndex: "1", + AttesterIndex: "1", + Data: nil, + Signature: "", + } + _, err := s.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestSignedVoluntaryExit_ToConsensus(t *testing.T) { + s := &SignedVoluntaryExit{Message: nil, Signature: ""} + _, err := s.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestProposerSlashing_ToConsensus(t *testing.T) { + p := &ProposerSlashing{SignedHeader1: nil, SignedHeader2: nil} + _, err := p.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestAttesterSlashing_ToConsensus(t *testing.T) { + a := &AttesterSlashing{Attestation1: nil, Attestation2: nil} + _, err := a.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} + +func TestIndexedAttestation_ToConsensus(t *testing.T) { + a := &IndexedAttestation{ + AttestingIndices: []string{"1"}, + Data: nil, + Signature: "invalid", + } + _, err := a.ToConsensus() + require.ErrorContains(t, errNilValue.Error(), err) +} diff --git a/api/server/structs/endpoints_beacon.go b/api/server/structs/endpoints_beacon.go index 3fa8a4bc8f47..15afc51efe18 100644 --- a/api/server/structs/endpoints_beacon.go +++ b/api/server/structs/endpoints_beacon.go @@ -21,11 +21,12 @@ type GetCommitteesResponse struct { } type ListAttestationsResponse struct { - Data []*Attestation `json:"data"` + Version string `json:"version,omitempty"` + Data json.RawMessage `json:"data"` } type SubmitAttestationsRequest struct { - Data []*Attestation `json:"data"` + Data json.RawMessage `json:"data"` } type ListVoluntaryExitsResponse struct { @@ -133,6 +134,13 @@ type GetBlockAttestationsResponse struct { Data []*Attestation `json:"data"` } +type GetBlockAttestationsV2Response struct { + Version string `json:"version"` + ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` + Data json.RawMessage `json:"data"` // Accepts both `Attestation` and `AttestationElectra` types +} + type GetStateRootResponse struct { ExecutionOptimistic bool `json:"execution_optimistic"` Finalized bool `json:"finalized"` @@ -169,7 +177,8 @@ type BLSToExecutionChangesPoolResponse struct { } type GetAttesterSlashingsResponse struct { - Data []*AttesterSlashing `json:"data"` + Version string `json:"version,omitempty"` + Data json.RawMessage `json:"data"` // Accepts both `[]*AttesterSlashing` and `[]*AttesterSlashingElectra` types } type GetProposerSlashingsResponse struct { @@ -241,3 +250,17 @@ type ChainHead struct { PreviousJustifiedBlockRoot string `json:"previous_justified_block_root"` OptimisticStatus bool `json:"optimistic_status"` } + +type GetPendingDepositsResponse struct { + Version string `json:"version"` + ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` + Data []*PendingDeposit `json:"data"` +} + +type GetPendingPartialWithdrawalsResponse struct { + Version string `json:"version"` + ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` + Data []*PendingPartialWithdrawal `json:"data"` +} diff --git a/api/server/structs/endpoints_blob.go b/api/server/structs/endpoints_blob.go index 2ea737945e27..024d4c5adefd 100644 --- a/api/server/structs/endpoints_blob.go +++ b/api/server/structs/endpoints_blob.go @@ -1,7 +1,10 @@ package structs type SidecarsResponse struct { - Data []*Sidecar `json:"data"` + Version string `json:"version"` + Data []*Sidecar `json:"data"` + ExecutionOptimistic bool `json:"execution_optimistic"` + Finalized bool `json:"finalized"` } type Sidecar struct { @@ -12,3 +15,12 @@ type Sidecar struct { KzgProof string `json:"kzg_proof"` CommitmentInclusionProof []string `json:"kzg_commitment_inclusion_proof"` } + +type BlobSidecars struct { + Sidecars []*Sidecar `json:"sidecars"` +} + +type PublishBlobsRequest struct { + BlobSidecars *BlobSidecars `json:"blob_sidecars"` + BlockRoot string `json:"block_root"` +} diff --git a/api/server/structs/endpoints_events.go b/api/server/structs/endpoints_events.go index 5b6d30cf3f6b..275a94580383 100644 --- a/api/server/structs/endpoints_events.go +++ b/api/server/structs/endpoints_events.go @@ -96,21 +96,7 @@ type LightClientFinalityUpdateEvent struct { Data *LightClientFinalityUpdate `json:"data"` } -type LightClientFinalityUpdate struct { - AttestedHeader *BeaconBlockHeader `json:"attested_header"` - FinalizedHeader *BeaconBlockHeader `json:"finalized_header"` - FinalityBranch []string `json:"finality_branch"` - SyncAggregate *SyncAggregate `json:"sync_aggregate"` - SignatureSlot string `json:"signature_slot"` -} - type LightClientOptimisticUpdateEvent struct { Version string `json:"version"` Data *LightClientOptimisticUpdate `json:"data"` } - -type LightClientOptimisticUpdate struct { - AttestedHeader *BeaconBlockHeader `json:"attested_header"` - SyncAggregate *SyncAggregate `json:"sync_aggregate"` - SignatureSlot string `json:"signature_slot"` -} diff --git a/api/server/structs/endpoints_lightclient.go b/api/server/structs/endpoints_lightclient.go index 7204e177dc5c..197f0b019fee 100644 --- a/api/server/structs/endpoints_lightclient.go +++ b/api/server/structs/endpoints_lightclient.go @@ -1,31 +1,73 @@ package structs -type LightClientBootstrapResponse struct { - Version string `json:"version"` - Data *LightClientBootstrap `json:"data"` +import "encoding/json" + +type LightClientHeader struct { + Beacon *BeaconBlockHeader `json:"beacon"` +} + +type LightClientHeaderCapella struct { + Beacon *BeaconBlockHeader `json:"beacon"` + Execution *ExecutionPayloadHeaderCapella `json:"execution"` + ExecutionBranch []string `json:"execution_branch"` +} + +type LightClientHeaderDeneb struct { + Beacon *BeaconBlockHeader `json:"beacon"` + Execution *ExecutionPayloadHeaderDeneb `json:"execution"` + ExecutionBranch []string `json:"execution_branch"` } type LightClientBootstrap struct { - Header *BeaconBlockHeader `json:"header"` - CurrentSyncCommittee *SyncCommittee `json:"current_sync_committee"` - CurrentSyncCommitteeBranch []string `json:"current_sync_committee_branch"` + Header json.RawMessage `json:"header"` + CurrentSyncCommittee *SyncCommittee `json:"current_sync_committee"` + CurrentSyncCommitteeBranch []string `json:"current_sync_committee_branch"` } type LightClientUpdate struct { - AttestedHeader *BeaconBlockHeader `json:"attested_header"` - NextSyncCommittee *SyncCommittee `json:"next_sync_committee,omitempty"` - FinalizedHeader *BeaconBlockHeader `json:"finalized_header,omitempty"` - SyncAggregate *SyncAggregate `json:"sync_aggregate"` - NextSyncCommitteeBranch []string `json:"next_sync_committee_branch,omitempty"` - FinalityBranch []string `json:"finality_branch,omitempty"` - SignatureSlot string `json:"signature_slot"` + AttestedHeader json.RawMessage `json:"attested_header"` + NextSyncCommittee *SyncCommittee `json:"next_sync_committee,omitempty"` + FinalizedHeader json.RawMessage `json:"finalized_header,omitempty"` + SyncAggregate *SyncAggregate `json:"sync_aggregate"` + NextSyncCommitteeBranch []string `json:"next_sync_committee_branch,omitempty"` + FinalityBranch []string `json:"finality_branch,omitempty"` + SignatureSlot string `json:"signature_slot"` } -type LightClientUpdateWithVersion struct { +type LightClientFinalityUpdate struct { + AttestedHeader json.RawMessage `json:"attested_header"` + FinalizedHeader json.RawMessage `json:"finalized_header"` + FinalityBranch []string `json:"finality_branch"` + SyncAggregate *SyncAggregate `json:"sync_aggregate"` + SignatureSlot string `json:"signature_slot"` +} + +type LightClientOptimisticUpdate struct { + AttestedHeader json.RawMessage `json:"attested_header"` + SyncAggregate *SyncAggregate `json:"sync_aggregate"` + SignatureSlot string `json:"signature_slot"` +} + +type LightClientBootstrapResponse struct { + Version string `json:"version"` + Data *LightClientBootstrap `json:"data"` +} + +type LightClientUpdateResponse struct { Version string `json:"version"` Data *LightClientUpdate `json:"data"` } +type LightClientFinalityUpdateResponse struct { + Version string `json:"version"` + Data *LightClientFinalityUpdate `json:"data"` +} + +type LightClientOptimisticUpdateResponse struct { + Version string `json:"version"` + Data *LightClientOptimisticUpdate `json:"data"` +} + type LightClientUpdatesByRangeResponse struct { - Updates []*LightClientUpdateWithVersion `json:"updates"` + Updates []*LightClientUpdateResponse `json:"updates"` } diff --git a/api/server/structs/endpoints_validator.go b/api/server/structs/endpoints_validator.go index dfb94daea20a..da932c71692f 100644 --- a/api/server/structs/endpoints_validator.go +++ b/api/server/structs/endpoints_validator.go @@ -7,7 +7,8 @@ import ( ) type AggregateAttestationResponse struct { - Data *Attestation `json:"data"` + Version string `json:"version,omitempty"` + Data json.RawMessage `json:"data"` } type SubmitContributionAndProofsRequest struct { @@ -15,7 +16,7 @@ type SubmitContributionAndProofsRequest struct { } type SubmitAggregateAndProofsRequest struct { - Data []*SignedAggregateAttestationAndProof `json:"data"` + Data []json.RawMessage `json:"data"` } type SubmitSyncCommitteeSubscriptionsRequest struct { diff --git a/api/server/structs/other.go b/api/server/structs/other.go index 5694893d13cc..66457d31cbea 100644 --- a/api/server/structs/other.go +++ b/api/server/structs/other.go @@ -29,6 +29,20 @@ type Attestation struct { Signature string `json:"signature"` } +type AttestationElectra struct { + AggregationBits string `json:"aggregation_bits"` + Data *AttestationData `json:"data"` + Signature string `json:"signature"` + CommitteeBits string `json:"committee_bits"` +} + +type SingleAttestation struct { + CommitteeIndex string `json:"committee_index"` + AttesterIndex string `json:"attester_index"` + Data *AttestationData `json:"data"` + Signature string `json:"signature"` +} + type AttestationData struct { Slot string `json:"slot"` CommitteeIndex string `json:"index"` @@ -78,6 +92,17 @@ type AggregateAttestationAndProof struct { SelectionProof string `json:"selection_proof"` } +type SignedAggregateAttestationAndProofElectra struct { + Message *AggregateAttestationAndProofElectra `json:"message"` + Signature string `json:"signature"` +} + +type AggregateAttestationAndProofElectra struct { + AggregatorIndex string `json:"aggregator_index"` + Aggregate *AttestationElectra `json:"aggregate"` + SelectionProof string `json:"selection_proof"` +} + type SyncCommitteeSubscription struct { ValidatorIndex string `json:"validator_index"` SyncCommitteeIndices []string `json:"sync_committee_indices"` @@ -178,6 +203,11 @@ type AttesterSlashing struct { Attestation2 *IndexedAttestation `json:"attestation_2"` } +type AttesterSlashingElectra struct { + Attestation1 *IndexedAttestationElectra `json:"attestation_1"` + Attestation2 *IndexedAttestationElectra `json:"attestation_2"` +} + type Deposit struct { Proof []string `json:"proof"` Data *DepositData `json:"data"` @@ -196,6 +226,12 @@ type IndexedAttestation struct { Signature string `json:"signature"` } +type IndexedAttestationElectra struct { + AttestingIndices []string `json:"attesting_indices"` + Data *AttestationData `json:"data"` + Signature string `json:"signature"` +} + type SyncAggregate struct { SyncCommitteeBits string `json:"sync_committee_bits"` SyncCommitteeSignature string `json:"sync_committee_signature"` @@ -207,3 +243,22 @@ type Withdrawal struct { ExecutionAddress string `json:"address"` Amount string `json:"amount"` } + +type PendingDeposit struct { + Pubkey string `json:"pubkey"` + WithdrawalCredentials string `json:"withdrawal_credentials"` + Amount string `json:"amount"` + Signature string `json:"signature"` + Slot string `json:"slot"` +} + +type PendingPartialWithdrawal struct { + Index string `json:"index"` + Amount string `json:"amount"` + WithdrawableEpoch string `json:"withdrawable_epoch"` +} + +type PendingConsolidation struct { + SourceIndex string `json:"source_index"` + TargetIndex string `json:"target_index"` +} diff --git a/api/server/structs/state.go b/api/server/structs/state.go index 4b07cfc20a8a..de9d382c7165 100644 --- a/api/server/structs/state.go +++ b/api/server/structs/state.go @@ -140,3 +140,83 @@ type BeaconStateDeneb struct { NextWithdrawalValidatorIndex string `json:"next_withdrawal_validator_index"` HistoricalSummaries []*HistoricalSummary `json:"historical_summaries"` } + +type BeaconStateElectra struct { + GenesisTime string `json:"genesis_time"` + GenesisValidatorsRoot string `json:"genesis_validators_root"` + Slot string `json:"slot"` + Fork *Fork `json:"fork"` + LatestBlockHeader *BeaconBlockHeader `json:"latest_block_header"` + BlockRoots []string `json:"block_roots"` + StateRoots []string `json:"state_roots"` + HistoricalRoots []string `json:"historical_roots"` + Eth1Data *Eth1Data `json:"eth1_data"` + Eth1DataVotes []*Eth1Data `json:"eth1_data_votes"` + Eth1DepositIndex string `json:"eth1_deposit_index"` + Validators []*Validator `json:"validators"` + Balances []string `json:"balances"` + RandaoMixes []string `json:"randao_mixes"` + Slashings []string `json:"slashings"` + PreviousEpochParticipation []string `json:"previous_epoch_participation"` + CurrentEpochParticipation []string `json:"current_epoch_participation"` + JustificationBits string `json:"justification_bits"` + PreviousJustifiedCheckpoint *Checkpoint `json:"previous_justified_checkpoint"` + CurrentJustifiedCheckpoint *Checkpoint `json:"current_justified_checkpoint"` + FinalizedCheckpoint *Checkpoint `json:"finalized_checkpoint"` + InactivityScores []string `json:"inactivity_scores"` + CurrentSyncCommittee *SyncCommittee `json:"current_sync_committee"` + NextSyncCommittee *SyncCommittee `json:"next_sync_committee"` + LatestExecutionPayloadHeader *ExecutionPayloadHeaderDeneb `json:"latest_execution_payload_header"` + NextWithdrawalIndex string `json:"next_withdrawal_index"` + NextWithdrawalValidatorIndex string `json:"next_withdrawal_validator_index"` + HistoricalSummaries []*HistoricalSummary `json:"historical_summaries"` + DepositRequestsStartIndex string `json:"deposit_requests_start_index"` + DepositBalanceToConsume string `json:"deposit_balance_to_consume"` + ExitBalanceToConsume string `json:"exit_balance_to_consume"` + EarliestExitEpoch string `json:"earliest_exit_epoch"` + ConsolidationBalanceToConsume string `json:"consolidation_balance_to_consume"` + EarliestConsolidationEpoch string `json:"earliest_consolidation_epoch"` + PendingDeposits []*PendingDeposit `json:"pending_deposits"` + PendingPartialWithdrawals []*PendingPartialWithdrawal `json:"pending_partial_withdrawals"` + PendingConsolidations []*PendingConsolidation `json:"pending_consolidations"` +} + +type BeaconStateFulu struct { + GenesisTime string `json:"genesis_time"` + GenesisValidatorsRoot string `json:"genesis_validators_root"` + Slot string `json:"slot"` + Fork *Fork `json:"fork"` + LatestBlockHeader *BeaconBlockHeader `json:"latest_block_header"` + BlockRoots []string `json:"block_roots"` + StateRoots []string `json:"state_roots"` + HistoricalRoots []string `json:"historical_roots"` + Eth1Data *Eth1Data `json:"eth1_data"` + Eth1DataVotes []*Eth1Data `json:"eth1_data_votes"` + Eth1DepositIndex string `json:"eth1_deposit_index"` + Validators []*Validator `json:"validators"` + Balances []string `json:"balances"` + RandaoMixes []string `json:"randao_mixes"` + Slashings []string `json:"slashings"` + PreviousEpochParticipation []string `json:"previous_epoch_participation"` + CurrentEpochParticipation []string `json:"current_epoch_participation"` + JustificationBits string `json:"justification_bits"` + PreviousJustifiedCheckpoint *Checkpoint `json:"previous_justified_checkpoint"` + CurrentJustifiedCheckpoint *Checkpoint `json:"current_justified_checkpoint"` + FinalizedCheckpoint *Checkpoint `json:"finalized_checkpoint"` + InactivityScores []string `json:"inactivity_scores"` + CurrentSyncCommittee *SyncCommittee `json:"current_sync_committee"` + NextSyncCommittee *SyncCommittee `json:"next_sync_committee"` + LatestExecutionPayloadHeader *ExecutionPayloadHeaderDeneb `json:"latest_execution_payload_header"` + NextWithdrawalIndex string `json:"next_withdrawal_index"` + NextWithdrawalValidatorIndex string `json:"next_withdrawal_validator_index"` + HistoricalSummaries []*HistoricalSummary `json:"historical_summaries"` + DepositRequestsStartIndex string `json:"deposit_requests_start_index"` + DepositBalanceToConsume string `json:"deposit_balance_to_consume"` + ExitBalanceToConsume string `json:"exit_balance_to_consume"` + EarliestExitEpoch string `json:"earliest_exit_epoch"` + ConsolidationBalanceToConsume string `json:"consolidation_balance_to_consume"` + EarliestConsolidationEpoch string `json:"earliest_consolidation_epoch"` + PendingDeposits []*PendingDeposit `json:"pending_deposits"` + PendingPartialWithdrawals []*PendingPartialWithdrawal `json:"pending_partial_withdrawals"` + PendingConsolidations []*PendingConsolidation `json:"pending_consolidations"` +} diff --git a/async/event/BUILD.bazel b/async/event/BUILD.bazel index 1ceb12f4ff73..02ebe83ca95c 100644 --- a/async/event/BUILD.bazel +++ b/async/event/BUILD.bazel @@ -4,26 +4,25 @@ go_library( name = "go_default_library", srcs = [ "feed.go", + "interface.go", "subscription.go", ], importpath = "github.com/prysmaticlabs/prysm/v5/async/event", visibility = ["//visibility:public"], - deps = ["//time/mclock:go_default_library"], + deps = [ + "//time/mclock:go_default_library", + "@com_github_ethereum_go_ethereum//event:go_default_library", + ], ) go_test( name = "go_default_test", size = "small", srcs = [ - "example_feed_test.go", "example_scope_test.go", "example_subscription_test.go", - "feed_test.go", "subscription_test.go", ], embed = [":go_default_library"], - deps = [ - "//testing/assert:go_default_library", - "//testing/require:go_default_library", - ], + deps = ["//testing/require:go_default_library"], ) diff --git a/async/event/example_feed_test.go b/async/event/example_feed_test.go deleted file mode 100644 index ddc3730e2202..000000000000 --- a/async/event/example_feed_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package event_test - -import ( - "fmt" - - "github.com/prysmaticlabs/prysm/v5/async/event" -) - -func ExampleFeed_acknowledgedEvents() { - // This example shows how the return value of Send can be used for request/reply - // interaction between event consumers and producers. - var feed event.Feed - type ackedEvent struct { - i int - ack chan<- struct{} - } - - // Consumers wait for events on the feed and acknowledge processing. - done := make(chan struct{}) - defer close(done) - for i := 0; i < 3; i++ { - ch := make(chan ackedEvent, 100) - sub := feed.Subscribe(ch) - go func() { - defer sub.Unsubscribe() - for { - select { - case ev := <-ch: - fmt.Println(ev.i) // "process" the event - ev.ack <- struct{}{} - case <-done: - return - } - } - }() - } - - // The producer sends values of type ackedEvent with increasing values of i. - // It waits for all consumers to acknowledge before sending the next event. - for i := 0; i < 3; i++ { - acksignal := make(chan struct{}) - n := feed.Send(ackedEvent{i, acksignal}) - for ack := 0; ack < n; ack++ { - <-acksignal - } - } - // Output: - // 0 - // 0 - // 0 - // 1 - // 1 - // 1 - // 2 - // 2 - // 2 -} diff --git a/async/event/feed.go b/async/event/feed.go index 46d7f77753c8..0d44c7685750 100644 --- a/async/event/feed.go +++ b/async/event/feed.go @@ -14,241 +14,12 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Package event contains an event feed implementation for process communication. package event import ( - "errors" - "reflect" - "slices" - "sync" + geth_event "github.com/ethereum/go-ethereum/event" ) -var errBadChannel = errors.New("event: Subscribe argument does not have sendable channel type") - -// Feed implements one-to-many subscriptions where the carrier of events is a channel. -// Values sent to a Feed are delivered to all subscribed channels simultaneously. -// -// Feeds can only be used with a single type. The type is determined by the first Send or -// Subscribe operation. Subsequent calls to these methods panic if the type does not -// match. -// -// The zero value is ready to use. -type Feed struct { - once sync.Once // ensures that init only runs once - sendLock chan struct{} // sendLock has a one-element buffer and is empty when held.It protects sendCases. - removeSub chan interface{} // interrupts Send - sendCases caseList // the active set of select cases used by Send - - // The inbox holds newly subscribed channels until they are added to sendCases. - mu sync.Mutex - inbox caseList - etype reflect.Type -} - -// This is the index of the first actual subscription channel in sendCases. -// sendCases[0] is a SelectRecv case for the removeSub channel. -const firstSubSendCase = 1 - -type feedTypeError struct { - got, want reflect.Type - op string -} - -func (e feedTypeError) Error() string { - return "event: wrong type in " + e.op + " got " + e.got.String() + ", want " + e.want.String() -} - -func (f *Feed) init() { - f.removeSub = make(chan interface{}) - f.sendLock = make(chan struct{}, 1) - f.sendLock <- struct{}{} - f.sendCases = caseList{{Chan: reflect.ValueOf(f.removeSub), Dir: reflect.SelectRecv}} -} - -// Subscribe adds a channel to the feed. Future sends will be delivered on the channel -// until the subscription is canceled. All channels added must have the same element type. -// -// The channel should have ample buffer space to avoid blocking other subscribers. -// Slow subscribers are not dropped. -func (f *Feed) Subscribe(channel interface{}) Subscription { - f.once.Do(f.init) - - chanval := reflect.ValueOf(channel) - chantyp := chanval.Type() - if chantyp.Kind() != reflect.Chan || chantyp.ChanDir()&reflect.SendDir == 0 { - panic(errBadChannel) - } - sub := &feedSub{feed: f, channel: chanval, err: make(chan error, 1)} - - f.mu.Lock() - defer f.mu.Unlock() - if !f.typecheck(chantyp.Elem()) { - panic(feedTypeError{op: "Subscribe", got: chantyp, want: reflect.ChanOf(reflect.SendDir, f.etype)}) - } - // Add the select case to the inbox. - // The next Send will add it to f.sendCases. - cas := reflect.SelectCase{Dir: reflect.SelectSend, Chan: chanval} - f.inbox = append(f.inbox, cas) - return sub -} - -// note: callers must hold f.mu -func (f *Feed) typecheck(typ reflect.Type) bool { - if f.etype == nil { - f.etype = typ - return true - } - // In the event the feed's type is an actual interface, we - // perform an interface conformance check here. - if f.etype.Kind() == reflect.Interface && typ.Implements(f.etype) { - return true - } - return f.etype == typ -} - -func (f *Feed) remove(sub *feedSub) { - // Delete from inbox first, which covers channels - // that have not been added to f.sendCases yet. - ch := sub.channel.Interface() - f.mu.Lock() - index := f.inbox.find(ch) - if index != -1 { - f.inbox = f.inbox.delete(index) - f.mu.Unlock() - return - } - f.mu.Unlock() - - select { - case f.removeSub <- ch: - // Send will remove the channel from f.sendCases. - case <-f.sendLock: - // No Send is in progress, delete the channel now that we have the send lock. - f.sendCases = f.sendCases.delete(f.sendCases.find(ch)) - f.sendLock <- struct{}{} - } -} - -// Send delivers to all subscribed channels simultaneously. -// It returns the number of subscribers that the value was sent to. -func (f *Feed) Send(value interface{}) (nsent int) { - rvalue := reflect.ValueOf(value) - - f.once.Do(f.init) - <-f.sendLock - - // Add new cases from the inbox after taking the send lock. - f.mu.Lock() - f.sendCases = append(f.sendCases, f.inbox...) - f.inbox = nil - - if !f.typecheck(rvalue.Type()) { - f.sendLock <- struct{}{} - f.mu.Unlock() - panic(feedTypeError{op: "Send", got: rvalue.Type(), want: f.etype}) - } - f.mu.Unlock() - - // Set the sent value on all channels. - for i := firstSubSendCase; i < len(f.sendCases); i++ { - f.sendCases[i].Send = rvalue - } - - // Send until all channels except removeSub have been chosen. 'cases' tracks a prefix - // of sendCases. When a send succeeds, the corresponding case moves to the end of - // 'cases' and it shrinks by one element. - cases := f.sendCases - for { - // Fast path: try sending without blocking before adding to the select set. - // This should usually succeed if subscribers are fast enough and have free - // buffer space. - for i := firstSubSendCase; i < len(cases); i++ { - if cases[i].Chan.TrySend(rvalue) { - nsent++ - cases = cases.deactivate(i) - i-- - } - } - if len(cases) == firstSubSendCase { - break - } - // Select on all the receivers, waiting for them to unblock. - chosen, recv, _ := reflect.Select(cases) - if chosen == 0 /* <-f.removeSub */ { - index := f.sendCases.find(recv.Interface()) - f.sendCases = f.sendCases.delete(index) - if index >= 0 && index < len(cases) { - // Shrink 'cases' too because the removed case was still active. - cases = f.sendCases[:len(cases)-1] - } - } else { - cases = cases.deactivate(chosen) - nsent++ - } - } - - // Forget about the sent value and hand off the send lock. - for i := firstSubSendCase; i < len(f.sendCases); i++ { - f.sendCases[i].Send = reflect.Value{} - } - f.sendLock <- struct{}{} - return nsent -} - -type feedSub struct { - feed *Feed - channel reflect.Value - errOnce sync.Once - err chan error -} - -// Unsubscribe remove feed subscription. -func (sub *feedSub) Unsubscribe() { - sub.errOnce.Do(func() { - sub.feed.remove(sub) - close(sub.err) - }) -} - -// Err returns error channel. -func (sub *feedSub) Err() <-chan error { - return sub.err -} - -type caseList []reflect.SelectCase - -// find returns the index of a case containing the given channel. -func (cs caseList) find(channel interface{}) int { - return slices.IndexFunc(cs, func(selectCase reflect.SelectCase) bool { - return selectCase.Chan.Interface() == channel - }) -} - -// delete removes the given case from cs. -func (cs caseList) delete(index int) caseList { - return append(cs[:index], cs[index+1:]...) -} - -// deactivate moves the case at index into the non-accessible portion of the cs slice. -func (cs caseList) deactivate(index int) caseList { - last := len(cs) - 1 - cs[index], cs[last] = cs[last], cs[index] - return cs[:last] -} - -// func (cs caseList) String() string { -// s := "[" -// for i, cas := range cs { -// if i != 0 { -// s += ", " -// } -// switch cas.Dir { -// case reflect.SelectSend: -// s += fmt.Sprintf("%v<-", cas.Chan.Interface()) -// case reflect.SelectRecv: -// s += fmt.Sprintf("<-%v", cas.Chan.Interface()) -// } -// } -// return s + "]" -// } +// Feed is a re-export of the go-ethereum event feed. +type Feed = geth_event.Feed +type Subscription = geth_event.Subscription diff --git a/async/event/feed_test.go b/async/event/feed_test.go deleted file mode 100644 index 5ad594046b17..000000000000 --- a/async/event/feed_test.go +++ /dev/null @@ -1,509 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package event - -import ( - "fmt" - "reflect" - "sync" - "testing" - "time" - - "github.com/prysmaticlabs/prysm/v5/testing/assert" -) - -func TestFeedPanics(t *testing.T) { - { - var f Feed - f.Send(2) - want := feedTypeError{op: "Send", got: reflect.TypeOf(uint64(0)), want: reflect.TypeOf(0)} - assert.NoError(t, checkPanic(want, func() { f.Send(uint64(2)) })) - // Validate it doesn't deadlock. - assert.NoError(t, checkPanic(want, func() { f.Send(uint64(2)) })) - } - { - var f Feed - ch := make(chan int) - f.Subscribe(ch) - want := feedTypeError{op: "Send", got: reflect.TypeOf(uint64(0)), want: reflect.TypeOf(0)} - assert.NoError(t, checkPanic(want, func() { f.Send(uint64(2)) })) - } - { - var f Feed - f.Send(2) - want := feedTypeError{op: "Subscribe", got: reflect.TypeOf(make(chan uint64)), want: reflect.TypeOf(make(chan<- int))} - assert.NoError(t, checkPanic(want, func() { f.Subscribe(make(chan uint64)) })) - } - { - var f Feed - assert.NoError(t, checkPanic(errBadChannel, func() { f.Subscribe(make(<-chan int)) })) - } - { - var f Feed - assert.NoError(t, checkPanic(errBadChannel, func() { f.Subscribe(0) })) - } -} - -func checkPanic(want error, fn func()) (err error) { - defer func() { - panicResult := recover() - if panicResult == nil { - err = fmt.Errorf("didn't panic") - } else if !reflect.DeepEqual(panicResult, want) { - err = fmt.Errorf("panicked with wrong error: got %q, want %q", panicResult, want) - } - }() - fn() - return nil -} - -func TestFeed(t *testing.T) { - var feed Feed - var done, subscribed sync.WaitGroup - subscriber := func(i int) { - defer done.Done() - - subchan := make(chan int) - sub := feed.Subscribe(subchan) - timeout := time.NewTimer(2 * time.Second) - subscribed.Done() - - select { - case v := <-subchan: - if v != 1 { - t.Errorf("%d: received value %d, want 1", i, v) - } - case <-timeout.C: - t.Errorf("%d: receive timeout", i) - } - - sub.Unsubscribe() - select { - case _, ok := <-sub.Err(): - if ok { - t.Errorf("%d: error channel not closed after unsubscribe", i) - } - case <-timeout.C: - t.Errorf("%d: unsubscribe timeout", i) - } - } - - const n = 1000 - done.Add(n) - subscribed.Add(n) - for i := 0; i < n; i++ { - go subscriber(i) - } - subscribed.Wait() - if nsent := feed.Send(1); nsent != n { - t.Errorf("first send delivered %d times, want %d", nsent, n) - } - if nsent := feed.Send(2); nsent != 0 { - t.Errorf("second send delivered %d times, want 0", nsent) - } - done.Wait() -} - -func TestFeedSubscribeSameChannel(t *testing.T) { - var ( - feed Feed - done sync.WaitGroup - ch = make(chan int) - sub1 = feed.Subscribe(ch) - sub2 = feed.Subscribe(ch) - _ = feed.Subscribe(ch) - ) - expectSends := func(value, n int) { - if nsent := feed.Send(value); nsent != n { - t.Errorf("send delivered %d times, want %d", nsent, n) - } - done.Done() - } - expectRecv := func(wantValue, n int) { - for i := 0; i < n; i++ { - if v := <-ch; v != wantValue { - t.Errorf("received %d, want %d", v, wantValue) - } - } - } - - done.Add(1) - go expectSends(1, 3) - expectRecv(1, 3) - done.Wait() - - sub1.Unsubscribe() - - done.Add(1) - go expectSends(2, 2) - expectRecv(2, 2) - done.Wait() - - sub2.Unsubscribe() - - done.Add(1) - go expectSends(3, 1) - expectRecv(3, 1) - done.Wait() -} - -func TestFeedSubscribeBlockedPost(_ *testing.T) { - var ( - feed Feed - nsends = 2000 - ch1 = make(chan int) - ch2 = make(chan int) - wg sync.WaitGroup - ) - defer wg.Wait() - - feed.Subscribe(ch1) - wg.Add(nsends) - for i := 0; i < nsends; i++ { - go func() { - feed.Send(99) - wg.Done() - }() - } - - sub2 := feed.Subscribe(ch2) - defer sub2.Unsubscribe() - - // We're done when ch1 has received N times. - // The number of receives on ch2 depends on scheduling. - for i := 0; i < nsends; { - select { - case <-ch1: - i++ - case <-ch2: - } - } -} - -func TestFeedUnsubscribeBlockedPost(_ *testing.T) { - var ( - feed Feed - nsends = 200 - chans = make([]chan int, 2000) - subs = make([]Subscription, len(chans)) - bchan = make(chan int) - bsub = feed.Subscribe(bchan) - wg sync.WaitGroup - ) - for i := range chans { - chans[i] = make(chan int, nsends) - } - - // Queue up some Sends. None of these can make progress while bchan isn't read. - wg.Add(nsends) - for i := 0; i < nsends; i++ { - go func() { - feed.Send(99) - wg.Done() - }() - } - // Subscribe the other channels. - for i, ch := range chans { - subs[i] = feed.Subscribe(ch) - } - // Unsubscribe them again. - for _, sub := range subs { - sub.Unsubscribe() - } - // Unblock the Sends. - bsub.Unsubscribe() - wg.Wait() -} - -// Checks that unsubscribing a channel during Send works even if that -// channel has already been sent on. -func TestFeedUnsubscribeSentChan(_ *testing.T) { - var ( - feed Feed - ch1 = make(chan int) - ch2 = make(chan int) - sub1 = feed.Subscribe(ch1) - sub2 = feed.Subscribe(ch2) - wg sync.WaitGroup - ) - defer sub2.Unsubscribe() - - wg.Add(1) - go func() { - feed.Send(0) - wg.Done() - }() - - // Wait for the value on ch1. - <-ch1 - // Unsubscribe ch1, removing it from the send cases. - sub1.Unsubscribe() - - // Receive ch2, finishing Send. - <-ch2 - wg.Wait() - - // Send again. This should send to ch2 only, so the wait group will unblock - // as soon as a value is received on ch2. - wg.Add(1) - go func() { - feed.Send(0) - wg.Done() - }() - <-ch2 - wg.Wait() -} - -func TestFeedUnsubscribeFromInbox(t *testing.T) { - var ( - feed Feed - ch1 = make(chan int) - ch2 = make(chan int) - sub1 = feed.Subscribe(ch1) - sub2 = feed.Subscribe(ch1) - sub3 = feed.Subscribe(ch2) - ) - assert.Equal(t, 3, len(feed.inbox)) - assert.Equal(t, 1, len(feed.sendCases), "sendCases is non-empty after unsubscribe") - - sub1.Unsubscribe() - sub2.Unsubscribe() - sub3.Unsubscribe() - assert.Equal(t, 0, len(feed.inbox), "Inbox is non-empty after unsubscribe") - assert.Equal(t, 1, len(feed.sendCases), "sendCases is non-empty after unsubscribe") -} - -func BenchmarkFeedSend1000(b *testing.B) { - var ( - done sync.WaitGroup - feed Feed - nsubs = 1000 - ) - subscriber := func(ch <-chan int) { - for i := 0; i < b.N; i++ { - <-ch - } - done.Done() - } - done.Add(nsubs) - for i := 0; i < nsubs; i++ { - ch := make(chan int, 200) - feed.Subscribe(ch) - go subscriber(ch) - } - - // The actual benchmark. - b.ResetTimer() - for i := 0; i < b.N; i++ { - if feed.Send(i) != nsubs { - panic("wrong number of sends") - } - } - - b.StopTimer() - done.Wait() -} - -func TestFeed_Send(t *testing.T) { - tests := []struct { - name string - evFeed *Feed - testSetup func(fd *Feed, t *testing.T, o interface{}) - obj interface{} - expectPanic bool - }{ - { - name: "normal struct", - evFeed: new(Feed), - testSetup: func(fd *Feed, t *testing.T, o interface{}) { - testChan := make(chan testFeedWithPointer, 1) - fd.Subscribe(testChan) - }, - obj: testFeedWithPointer{ - a: new(uint64), - b: new(string), - }, - expectPanic: false, - }, - { - name: "un-implemented interface", - evFeed: new(Feed), - testSetup: func(fd *Feed, t *testing.T, o interface{}) { - testChan := make(chan testFeedIface, 1) - fd.Subscribe(testChan) - }, - obj: testFeedWithPointer{ - a: new(uint64), - b: new(string), - }, - expectPanic: true, - }, - { - name: "semi-implemented interface", - evFeed: new(Feed), - testSetup: func(fd *Feed, t *testing.T, o interface{}) { - testChan := make(chan testFeedIface, 1) - fd.Subscribe(testChan) - }, - obj: testFeed2{ - a: 0, - b: "", - c: []byte{'A'}, - }, - expectPanic: true, - }, - { - name: "fully-implemented interface", - evFeed: new(Feed), - testSetup: func(fd *Feed, t *testing.T, o interface{}) { - testChan := make(chan testFeedIface) - // Make it unbuffered to allow message to - // pass through - go func() { - a := <-testChan - if !reflect.DeepEqual(a, o) { - t.Errorf("Got = %v, want = %v", a, o) - } - }() - fd.Subscribe(testChan) - }, - obj: testFeed{ - a: 0, - b: "", - }, - expectPanic: false, - }, - { - name: "fully-implemented interface with additional methods", - evFeed: new(Feed), - testSetup: func(fd *Feed, t *testing.T, o interface{}) { - testChan := make(chan testFeedIface) - // Make it unbuffered to allow message to - // pass through - go func() { - a := <-testChan - if !reflect.DeepEqual(a, o) { - t.Errorf("Got = %v, want = %v", a, o) - } - }() - fd.Subscribe(testChan) - }, - obj: testFeed3{ - a: 0, - b: "", - c: []byte{'A'}, - d: []byte{'B'}, - }, - expectPanic: false, - }, - { - name: "concrete types implementing the same interface", - evFeed: new(Feed), - testSetup: func(fd *Feed, t *testing.T, o interface{}) { - testChan := make(chan testFeed, 1) - // Make it unbuffered to allow message to - // pass through - go func() { - a := <-testChan - if !reflect.DeepEqual(a, o) { - t.Errorf("Got = %v, want = %v", a, o) - } - }() - fd.Subscribe(testChan) - }, - obj: testFeed3{ - a: 0, - b: "", - c: []byte{'A'}, - d: []byte{'B'}, - }, - expectPanic: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - if !tt.expectPanic { - t.Errorf("panic triggered when unexpected: %v", r) - } - } else { - if tt.expectPanic { - t.Error("panic not triggered when expected") - } - } - }() - tt.testSetup(tt.evFeed, t, tt.obj) - if gotNsent := tt.evFeed.Send(tt.obj); gotNsent != 1 { - t.Errorf("Send() = %v, want %v", gotNsent, 1) - } - }) - } -} - -// The following objects below are a collection of different -// struct types to test with. -type testFeed struct { - a uint64 - b string -} - -func (testFeed) method1() { - -} - -func (testFeed) method2() { - -} - -type testFeedWithPointer struct { - a *uint64 - b *string -} - -type testFeed2 struct { - a uint64 - b string - c []byte -} - -func (testFeed2) method1() { - -} - -type testFeed3 struct { - a uint64 - b string - c, d []byte -} - -func (testFeed3) method1() { - -} - -func (testFeed3) method2() { - -} - -func (testFeed3) method3() { - -} - -type testFeedIface interface { - method1() - method2() -} diff --git a/async/event/interface.go b/async/event/interface.go new file mode 100644 index 000000000000..d54f9fd32160 --- /dev/null +++ b/async/event/interface.go @@ -0,0 +1,8 @@ +package event + +// SubscriberSender is an abstract representation of an *event.Feed +// to use in describing types that accept or return an *event.Feed. +type SubscriberSender interface { + Subscribe(channel interface{}) Subscription + Send(value interface{}) (nsent int) +} diff --git a/async/event/subscription.go b/async/event/subscription.go index 087810b25d62..9ed0dfe1e854 100644 --- a/async/event/subscription.go +++ b/async/event/subscription.go @@ -28,25 +28,6 @@ import ( // request backoff time. const waitQuotient = 10 -// Subscription represents a stream of events. The carrier of the events is typically a -// channel, but isn't part of the interface. -// -// Subscriptions can fail while established. Failures are reported through an error -// channel. It receives a value if there is an issue with the subscription (e.g. the -// network connection delivering the events has been closed). Only one value will ever be -// sent. -// -// The error channel is closed when the subscription ends successfully (i.e. when the -// source of events is closed). It is also closed when Unsubscribe is called. -// -// The Unsubscribe method cancels the sending of events. You must call Unsubscribe in all -// cases to ensure that resources related to the subscription are released. It can be -// called any number of times. -type Subscription interface { - Err() <-chan error // returns the error channel - Unsubscribe() // cancels sending of events, closing the error channel -} - // NewSubscription runs a producer function as a subscription in a new goroutine. The // channel given to the producer is closed when Unsubscribe is called. If fn returns an // error, it is sent on the subscription's error channel. diff --git a/async/multilock.go b/async/multilock.go index 69c0675f1c04..5de6fa133ded 100644 --- a/async/multilock.go +++ b/async/multilock.go @@ -125,7 +125,7 @@ func getChan(key string) chan byte { // Return a new string with unique elements. func unique(arr []string) []string { - if arr == nil || len(arr) <= 1 { + if len(arr) <= 1 { return arr } diff --git a/beacon-chain/blockchain/BUILD.bazel b/beacon-chain/blockchain/BUILD.bazel index b60a763d0fde..78ca6aaf7f7d 100644 --- a/beacon-chain/blockchain/BUILD.bazel +++ b/beacon-chain/blockchain/BUILD.bazel @@ -13,7 +13,6 @@ go_library( "head.go", "head_sync_committee_info.go", "init_sync_process_block.go", - "lightclient.go", "log.go", "merge_ascii_art.go", "metrics.go", @@ -44,10 +43,12 @@ go_library( "//beacon-chain/cache:go_default_library", "//beacon-chain/core/altair:go_default_library", "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/core/electra:go_default_library", "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/feed:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/core/light-client:go_default_library", "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/transition:go_default_library", @@ -81,10 +82,9 @@ go_library( "//encoding/bytesutil:go_default_library", "//math:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/engine/v1:go_default_library", "//proto/eth/v1:go_default_library", - "//proto/eth/v2:go_default_library", - "//proto/migration:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", "//runtime/version:go_default_library", @@ -97,7 +97,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", ], ) @@ -117,7 +116,6 @@ go_test( "head_test.go", "init_sync_process_block_test.go", "init_test.go", - "lightclient_test.go", "log_test.go", "metrics_test.go", "mock_test.go", @@ -143,6 +141,7 @@ go_test( "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/core/light-client:go_default_library", "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/transition:go_default_library", "//beacon-chain/das:go_default_library", @@ -174,7 +173,6 @@ go_test( "//encoding/bytesutil:go_default_library", "//proto/engine/v1:go_default_library", "//proto/eth/v1:go_default_library", - "//proto/eth/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "//testing/assert:go_default_library", diff --git a/beacon-chain/blockchain/blockchain_test.go b/beacon-chain/blockchain/blockchain_test.go index 9082070a2492..76b6248345a2 100644 --- a/beacon-chain/blockchain/blockchain_test.go +++ b/beacon-chain/blockchain/blockchain_test.go @@ -2,6 +2,7 @@ package blockchain import ( "io" + "os" "testing" "github.com/sirupsen/logrus" @@ -11,5 +12,5 @@ func TestMain(m *testing.M) { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(io.Discard) - m.Run() + os.Exit(m.Run()) } diff --git a/beacon-chain/blockchain/chain_info.go b/beacon-chain/blockchain/chain_info.go index f73652add1a8..f0b59e33ce02 100644 --- a/beacon-chain/blockchain/chain_info.go +++ b/beacon-chain/blockchain/chain_info.go @@ -12,13 +12,14 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" + consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/forkchoice" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // ChainInfoFetcher defines a common interface for methods in blockchain service which @@ -44,7 +45,7 @@ type ForkchoiceFetcher interface { UpdateHead(context.Context, primitives.Slot) HighestReceivedBlockSlot() primitives.Slot ReceivedBlocksLastEpoch() (uint64, error) - InsertNode(context.Context, state.BeaconState, [32]byte) error + InsertNode(context.Context, state.BeaconState, consensus_blocks.ROBlock) error ForkChoiceDump(context.Context) (*forkchoice.Dump, error) NewSlot(context.Context, primitives.Slot) error ProposerBoost() [32]byte @@ -203,7 +204,7 @@ func (s *Service) HeadState(ctx context.Context) (state.BeaconState, error) { defer s.headLock.RUnlock() ok := s.hasHeadState() - span.AddAttributes(trace.BoolAttribute("cache_hit", ok)) + span.SetAttributes(trace.BoolAttribute("cache_hit", ok)) if ok { return s.headState(ctx), nil @@ -225,7 +226,7 @@ func (s *Service) HeadStateReadOnly(ctx context.Context) (state.ReadOnlyBeaconSt defer s.headLock.RUnlock() ok := s.hasHeadState() - span.AddAttributes(trace.BoolAttribute("cache_hit", ok)) + span.SetAttributes(trace.BoolAttribute("cache_hit", ok)) if ok { return s.headStateReadOnly(ctx), nil @@ -242,7 +243,7 @@ func (s *Service) HeadValidatorsIndices(ctx context.Context, epoch primitives.Ep if !s.hasHeadState() { return []primitives.ValidatorIndex{}, nil } - return helpers.ActiveValidatorIndices(ctx, s.headState(ctx), epoch) + return helpers.ActiveValidatorIndices(ctx, s.headStateReadOnly(ctx), epoch) } // HeadGenesisValidatorsRoot returns genesis validators root of the head state. diff --git a/beacon-chain/blockchain/chain_info_forkchoice.go b/beacon-chain/blockchain/chain_info_forkchoice.go index afc02ddd7dac..e61444d1c024 100644 --- a/beacon-chain/blockchain/chain_info_forkchoice.go +++ b/beacon-chain/blockchain/chain_info_forkchoice.go @@ -4,6 +4,7 @@ import ( "context" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/forkchoice" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) @@ -22,13 +23,6 @@ func (s *Service) GetProposerHead() [32]byte { return s.cfg.ForkChoiceStore.GetProposerHead() } -// ShouldOverrideFCU returns the corresponding value from forkchoice -func (s *Service) ShouldOverrideFCU() bool { - s.cfg.ForkChoiceStore.RLock() - defer s.cfg.ForkChoiceStore.RUnlock() - return s.cfg.ForkChoiceStore.ShouldOverrideFCU() -} - // SetForkChoiceGenesisTime sets the genesis time in Forkchoice func (s *Service) SetForkChoiceGenesisTime(timestamp uint64) { s.cfg.ForkChoiceStore.Lock() @@ -51,10 +45,10 @@ func (s *Service) ReceivedBlocksLastEpoch() (uint64, error) { } // InsertNode is a wrapper for node insertion which is self locked -func (s *Service) InsertNode(ctx context.Context, st state.BeaconState, root [32]byte) error { +func (s *Service) InsertNode(ctx context.Context, st state.BeaconState, block consensus_blocks.ROBlock) error { s.cfg.ForkChoiceStore.Lock() defer s.cfg.ForkChoiceStore.Unlock() - return s.cfg.ForkChoiceStore.InsertNode(ctx, st, root) + return s.cfg.ForkChoiceStore.InsertNode(ctx, st, block) } // ForkChoiceDump returns the corresponding value from forkchoice diff --git a/beacon-chain/blockchain/chain_info_test.go b/beacon-chain/blockchain/chain_info_test.go index a328e390dc36..e850f36adad5 100644 --- a/beacon-chain/blockchain/chain_info_test.go +++ b/beacon-chain/blockchain/chain_info_test.go @@ -38,7 +38,7 @@ func prepareForkchoiceState( payloadHash [32]byte, justified *ethpb.Checkpoint, finalized *ethpb.Checkpoint, -) (state.BeaconState, [32]byte, error) { +) (state.BeaconState, blocks.ROBlock, error) { blockHeader := ðpb.BeaconBlockHeader{ ParentRoot: parentRoot[:], } @@ -59,7 +59,26 @@ func prepareForkchoiceState( base.BlockRoots[0] = append(base.BlockRoots[0], blockRoot[:]...) st, err := state_native.InitializeFromProtoBellatrix(base) - return st, blockRoot, err + if err != nil { + return nil, blocks.ROBlock{}, err + } + blk := ðpb.SignedBeaconBlockBellatrix{ + Block: ðpb.BeaconBlockBellatrix{ + Slot: slot, + ParentRoot: parentRoot[:], + Body: ðpb.BeaconBlockBodyBellatrix{ + ExecutionPayload: &enginev1.ExecutionPayload{ + BlockHash: payloadHash[:], + }, + }, + }, + } + signed, err := blocks.NewSignedBeaconBlock(blk) + if err != nil { + return nil, blocks.ROBlock{}, err + } + roblock, err := blocks.NewROBlockWithRoot(signed, blockRoot) + return st, roblock, err } func TestHeadRoot_Nil(t *testing.T) { @@ -122,9 +141,9 @@ func TestUnrealizedJustifiedBlockHash(t *testing.T) { service := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}} ojc := ðpb.Checkpoint{Root: []byte{'j'}} ofc := ðpb.Checkpoint{Root: []byte{'f'}} - st, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) + st, roblock, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) service.cfg.ForkChoiceStore.SetBalancesByRooter(func(_ context.Context, _ [32]byte) ([]uint64, error) { return []uint64{}, nil }) require.NoError(t, service.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(ctx, &forkchoicetypes.Checkpoint{Epoch: 6, Root: [32]byte{'j'}})) @@ -316,24 +335,24 @@ func TestService_ChainHeads(t *testing.T) { c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}} ojc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} ofc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} - st, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) + st, roblock, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 102, [32]byte{'c'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 104, [32]byte{'e'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 104, [32]byte{'e'}, [32]byte{'b'}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) roots, slots := c.ChainHeads() require.Equal(t, 3, len(roots)) @@ -413,12 +432,12 @@ func TestService_IsOptimistic(t *testing.T) { ojc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} ofc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{root: [32]byte{'b'}}} - st, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) + st, roblock, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) opt, err := c.IsOptimistic(ctx) require.NoError(t, err) @@ -449,12 +468,12 @@ func TestService_IsOptimisticForRoot(t *testing.T) { c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{root: [32]byte{'b'}}} ojc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} ofc := ðpb.Checkpoint{Root: params.BeaconConfig().ZeroHash[:]} - st, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) + st, roblock, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 101, [32]byte{'b'}, [32]byte{'a'}, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) + require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) opt, err := c.IsOptimisticForRoot(ctx, [32]byte{'a'}) require.NoError(t, err) diff --git a/beacon-chain/blockchain/execution_engine.go b/beacon-chain/blockchain/execution_engine.go index db911b31ab4e..45e29176ec36 100644 --- a/beacon-chain/blockchain/execution_engine.go +++ b/beacon-chain/blockchain/execution_engine.go @@ -2,13 +2,15 @@ package blockchain import ( "context" - "crypto/sha256" "fmt" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/async/event" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" + statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" @@ -21,15 +23,13 @@ import ( payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) -const blobCommitmentVersionKZG uint8 = 0x01 - var defaultLatestValidHash = bytesutil.PadTo([]byte{0xff}, 32) // notifyForkchoiceUpdate signals execution engine the fork choice updates. Execution engine should: @@ -39,7 +39,7 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *fcuConfig) (* ctx, span := trace.StartSpan(ctx, "blockChain.notifyForkchoiceUpdate") defer span.End() - if arg.headBlock.IsNil() { + if arg.headBlock == nil || arg.headBlock.IsNil() { log.Error("Head block is nil") return nil, nil } @@ -72,6 +72,7 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *fcuConfig) (* if arg.attributes == nil { arg.attributes = payloadattribute.EmptyWithVersion(headBlk.Version()) } + go firePayloadAttributesEvent(ctx, s.cfg.StateNotifier.StateFeed(), arg) payloadID, lastValidHash, err := s.cfg.ExecutionEngineCaller.ForkchoiceUpdated(ctx, fcs, arg.attributes) if err != nil { switch { @@ -170,6 +171,38 @@ func (s *Service) notifyForkchoiceUpdate(ctx context.Context, arg *fcuConfig) (* return payloadID, nil } +func firePayloadAttributesEvent(ctx context.Context, f event.SubscriberSender, cfg *fcuConfig) { + pidx, err := helpers.BeaconProposerIndex(ctx, cfg.headState) + if err != nil { + log.WithError(err). + WithField("head_root", cfg.headRoot[:]). + Error("Could not get proposer index for PayloadAttributes event") + return + } + evd := payloadattribute.EventData{ + ProposerIndex: pidx, + ProposalSlot: cfg.headState.Slot(), + ParentBlockRoot: cfg.headRoot[:], + Attributer: cfg.attributes, + HeadRoot: cfg.headRoot, + HeadState: cfg.headState, + HeadBlock: cfg.headBlock, + } + if cfg.headBlock != nil && !cfg.headBlock.IsNil() { + headPayload, err := cfg.headBlock.Block().Body().Execution() + if err != nil { + log.WithError(err).Error("Could not get execution payload for head block") + return + } + evd.ParentBlockHash = headPayload.BlockHash() + evd.ParentBlockNumber = headPayload.BlockNumber() + } + f.Send(&feed.Event{ + Type: statefeed.PayloadAttributes, + Data: evd, + }) +} + // getPayloadHash returns the payload hash given the block root. // if the block is before bellatrix fork epoch, it returns the zero hash. func (s *Service) getPayloadHash(ctx context.Context, root []byte) ([32]byte, error) { @@ -219,17 +252,28 @@ func (s *Service) notifyNewPayload(ctx context.Context, preStateVersion int, } var lastValidHash []byte + var parentRoot *common.Hash + var versionedHashes []common.Hash + var requests *enginev1.ExecutionRequests if blk.Version() >= version.Deneb { - var versionedHashes []common.Hash versionedHashes, err = kzgCommitmentsToVersionedHashes(blk.Block().Body()) if err != nil { return false, errors.Wrap(err, "could not get versioned hashes to feed the engine") } - pr := common.Hash(blk.Block().ParentRoot()) - lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, versionedHashes, &pr) - } else { - lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, []common.Hash{}, &common.Hash{} /*empty version hashes and root before Deneb*/) + prh := common.Hash(blk.Block().ParentRoot()) + parentRoot = &prh } + if blk.Version() >= version.Electra { + requests, err = blk.Block().Body().ExecutionRequests() + if err != nil { + return false, errors.Wrap(err, "could not get execution requests") + } + if requests == nil { + return false, errors.New("nil execution requests") + } + } + lastValidHash, err = s.cfg.ExecutionEngineCaller.NewPayload(ctx, payload, versionedHashes, parentRoot, requests) + switch { case err == nil: newPayloadValidNodeCount.Inc() @@ -321,15 +365,16 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, return emptyAttri } - var attr payloadattribute.Attributer - switch st.Version() { - case version.Deneb, version.Electra: + v := st.Version() + + if v >= version.Deneb { withdrawals, _, err := st.ExpectedWithdrawals() if err != nil { log.WithError(err).Error("Could not get expected withdrawals to get payload attribute") return emptyAttri } - attr, err = payloadattribute.New(&enginev1.PayloadAttributesV3{ + + attr, err := payloadattribute.New(&enginev1.PayloadAttributesV3{ Timestamp: uint64(t.Unix()), PrevRandao: prevRando, SuggestedFeeRecipient: val.FeeRecipient[:], @@ -340,13 +385,18 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, log.WithError(err).Error("Could not get payload attribute") return emptyAttri } - case version.Capella: + + return attr + } + + if v >= version.Capella { withdrawals, _, err := st.ExpectedWithdrawals() if err != nil { log.WithError(err).Error("Could not get expected withdrawals to get payload attribute") return emptyAttri } - attr, err = payloadattribute.New(&enginev1.PayloadAttributesV2{ + + attr, err := payloadattribute.New(&enginev1.PayloadAttributesV2{ Timestamp: uint64(t.Unix()), PrevRandao: prevRando, SuggestedFeeRecipient: val.FeeRecipient[:], @@ -356,8 +406,12 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, log.WithError(err).Error("Could not get payload attribute") return emptyAttri } - case version.Bellatrix: - attr, err = payloadattribute.New(&enginev1.PayloadAttributes{ + + return attr + } + + if v >= version.Bellatrix { + attr, err := payloadattribute.New(&enginev1.PayloadAttributes{ Timestamp: uint64(t.Unix()), PrevRandao: prevRando, SuggestedFeeRecipient: val.FeeRecipient[:], @@ -366,12 +420,12 @@ func (s *Service) getPayloadAttribute(ctx context.Context, st state.BeaconState, log.WithError(err).Error("Could not get payload attribute") return emptyAttri } - default: - log.WithField("version", st.Version()).Error("Could not get payload attribute due to unknown state version") - return emptyAttri + + return attr } - return attr + log.WithField("version", version.String(st.Version())).Error("Could not get payload attribute due to unknown state version") + return emptyAttri } // removeInvalidBlockAndState removes the invalid block, blob and its corresponding state from the cache and DB. @@ -402,13 +456,7 @@ func kzgCommitmentsToVersionedHashes(body interfaces.ReadOnlyBeaconBlockBody) ([ versionedHashes := make([]common.Hash, len(commitments)) for i, commitment := range commitments { - versionedHashes[i] = ConvertKzgCommitmentToVersionedHash(commitment) + versionedHashes[i] = primitives.ConvertKzgCommitmentToVersionedHash(commitment) } return versionedHashes, nil } - -func ConvertKzgCommitmentToVersionedHash(commitment []byte) common.Hash { - versionedHash := sha256.Sum256(commitment) - versionedHash[0] = blobCommitmentVersionKZG - return versionedHash -} diff --git a/beacon-chain/blockchain/execution_engine_test.go b/beacon-chain/blockchain/execution_engine_test.go index be5d700d52ea..ce8b132bc465 100644 --- a/beacon-chain/blockchain/execution_engine_test.go +++ b/beacon-chain/blockchain/execution_engine_test.go @@ -1135,9 +1135,14 @@ func TestComputePayloadAttribute(t *testing.T) { // Cache hit, advance state, no fee recipient slot := primitives.Slot(1) service.cfg.PayloadIDCache.Set(slot, [32]byte{}, [8]byte{}) + blk := util.NewBeaconBlockBellatrix() + signed, err := consensusblocks.NewSignedBeaconBlock(blk) + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(signed, [32]byte{'a'}) + require.NoError(t, err) cfg := &postBlockProcessConfig{ - ctx: ctx, - blockRoot: [32]byte{'a'}, + ctx: ctx, + roblock: roblock, } fcu := &fcuConfig{ headState: st, diff --git a/beacon-chain/blockchain/forkchoice_update_execution.go b/beacon-chain/blockchain/forkchoice_update_execution.go index fd71f75d27a8..5739f5d2f1c2 100644 --- a/beacon-chain/blockchain/forkchoice_update_execution.go +++ b/beacon-chain/blockchain/forkchoice_update_execution.go @@ -12,9 +12,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) func (s *Service) isNewHead(r [32]byte) bool { diff --git a/beacon-chain/blockchain/head.go b/beacon-chain/blockchain/head.go index bda360a84ba0..458765881cd4 100644 --- a/beacon-chain/blockchain/head.go +++ b/beacon-chain/blockchain/head.go @@ -11,6 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/features" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" @@ -18,11 +19,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/math" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // UpdateAndSaveHeadWithBalances updates the beacon state head after getting justified balanced from cache. @@ -404,13 +405,19 @@ func (s *Service) saveOrphanedOperations(ctx context.Context, orphanedRoot [32]b if a.GetData().Slot+params.BeaconConfig().SlotsPerEpoch < s.CurrentSlot() { continue } - if helpers.IsAggregated(a) { - if err := s.cfg.AttPool.SaveAggregatedAttestation(a); err != nil { + if features.Get().EnableExperimentalAttestationPool { + if err = s.cfg.AttestationCache.Add(a); err != nil { return err } } else { - if err := s.cfg.AttPool.SaveUnaggregatedAttestation(a); err != nil { - return err + if a.IsAggregated() { + if err = s.cfg.AttPool.SaveAggregatedAttestation(a); err != nil { + return err + } + } else { + if err = s.cfg.AttPool.SaveUnaggregatedAttestation(a); err != nil { + return err + } } } saveOrphanedAttCount.Inc() diff --git a/beacon-chain/blockchain/kzg/BUILD.bazel b/beacon-chain/blockchain/kzg/BUILD.bazel index 82c77fb7ca40..57f8c9e30a83 100644 --- a/beacon-chain/blockchain/kzg/BUILD.bazel +++ b/beacon-chain/blockchain/kzg/BUILD.bazel @@ -26,8 +26,7 @@ go_test( deps = [ "//consensus-types/blocks:go_default_library", "//testing/require:go_default_library", - "@com_github_consensys_gnark_crypto//ecc/bls12-381/fr:go_default_library", + "//testing/util:go_default_library", "@com_github_crate_crypto_go_kzg_4844//:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", ], ) diff --git a/beacon-chain/blockchain/kzg/validation.go b/beacon-chain/blockchain/kzg/validation.go index 6689d59d4a38..dd0c6f6d00b0 100644 --- a/beacon-chain/blockchain/kzg/validation.go +++ b/beacon-chain/blockchain/kzg/validation.go @@ -20,16 +20,17 @@ func Verify(sidecars ...blocks.ROBlob) error { cmts := make([]GoKZG.KZGCommitment, len(sidecars)) proofs := make([]GoKZG.KZGProof, len(sidecars)) for i, sidecar := range sidecars { - blobs[i] = bytesToBlob(sidecar.Blob) + blobs[i] = *bytesToBlob(sidecar.Blob) cmts[i] = bytesToCommitment(sidecar.KzgCommitment) proofs[i] = bytesToKZGProof(sidecar.KzgProof) } return kzgContext.VerifyBlobKZGProofBatch(blobs, cmts, proofs) } -func bytesToBlob(blob []byte) (ret GoKZG.Blob) { +func bytesToBlob(blob []byte) *GoKZG.Blob { + var ret GoKZG.Blob copy(ret[:], blob) - return + return &ret } func bytesToCommitment(commitment []byte) (ret GoKZG.KZGCommitment) { diff --git a/beacon-chain/blockchain/kzg/validation_test.go b/beacon-chain/blockchain/kzg/validation_test.go index 832c6f5d79cc..5416ebb0e6ac 100644 --- a/beacon-chain/blockchain/kzg/validation_test.go +++ b/beacon-chain/blockchain/kzg/validation_test.go @@ -1,57 +1,20 @@ package kzg import ( - "bytes" - "crypto/sha256" - "encoding/binary" "testing" - "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" GoKZG "github.com/crate-crypto/go-kzg-4844" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/sirupsen/logrus" + "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func deterministicRandomness(seed int64) [32]byte { - // Converts an int64 to a byte slice - buf := new(bytes.Buffer) - err := binary.Write(buf, binary.BigEndian, seed) - if err != nil { - logrus.WithError(err).Error("Failed to write int64 to bytes buffer") - return [32]byte{} - } - bytes := buf.Bytes() - - return sha256.Sum256(bytes) -} - -// Returns a serialized random field element in big-endian -func GetRandFieldElement(seed int64) [32]byte { - bytes := deterministicRandomness(seed) - var r fr.Element - r.SetBytes(bytes[:]) - - return GoKZG.SerializeScalar(r) -} - -// Returns a random blob using the passed seed as entropy -func GetRandBlob(seed int64) GoKZG.Blob { - var blob GoKZG.Blob - bytesPerBlob := GoKZG.ScalarsPerBlob * GoKZG.SerializedScalarSize - for i := 0; i < bytesPerBlob; i += GoKZG.SerializedScalarSize { - fieldElementBytes := GetRandFieldElement(seed + int64(i)) - copy(blob[i:i+GoKZG.SerializedScalarSize], fieldElementBytes[:]) - } - return blob -} - func GenerateCommitmentAndProof(blob GoKZG.Blob) (GoKZG.KZGCommitment, GoKZG.KZGProof, error) { - commitment, err := kzgContext.BlobToKZGCommitment(blob, 0) + commitment, err := kzgContext.BlobToKZGCommitment(&blob, 0) if err != nil { return GoKZG.KZGCommitment{}, GoKZG.KZGProof{}, err } - proof, err := kzgContext.ComputeBlobKZGProof(blob, commitment, 0) + proof, err := kzgContext.ComputeBlobKZGProof(&blob, commitment, 0) if err != nil { return GoKZG.KZGCommitment{}, GoKZG.KZGProof{}, err } @@ -68,13 +31,13 @@ func TestBytesToAny(t *testing.T) { blob := GoKZG.Blob{0x01, 0x02} commitment := GoKZG.KZGCommitment{0x01, 0x02} proof := GoKZG.KZGProof{0x01, 0x02} - require.DeepEqual(t, blob, bytesToBlob(bytes)) + require.DeepEqual(t, blob, *bytesToBlob(bytes)) require.DeepEqual(t, commitment, bytesToCommitment(bytes)) require.DeepEqual(t, proof, bytesToKZGProof(bytes)) } func TestGenerateCommitmentAndProof(t *testing.T) { - blob := GetRandBlob(123) + blob := util.GetRandBlob(123) commitment, proof, err := GenerateCommitmentAndProof(blob) require.NoError(t, err) expectedCommitment := GoKZG.KZGCommitment{180, 218, 156, 194, 59, 20, 10, 189, 186, 254, 132, 93, 7, 127, 104, 172, 238, 240, 237, 70, 83, 89, 1, 152, 99, 0, 165, 65, 143, 62, 20, 215, 230, 14, 205, 95, 28, 245, 54, 25, 160, 16, 178, 31, 232, 207, 38, 85} diff --git a/beacon-chain/blockchain/lightclient.go b/beacon-chain/blockchain/lightclient.go deleted file mode 100644 index ade4258cbb12..000000000000 --- a/beacon-chain/blockchain/lightclient.go +++ /dev/null @@ -1,245 +0,0 @@ -package blockchain - -import ( - "bytes" - "context" - "fmt" - - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/params" - "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" - ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" - "github.com/prysmaticlabs/prysm/v5/proto/migration" - "github.com/prysmaticlabs/prysm/v5/time/slots" -) - -const ( - FinalityBranchNumOfLeaves = 6 -) - -// CreateLightClientFinalityUpdate - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_finality_update -// def create_light_client_finality_update(update: LightClientUpdate) -> LightClientFinalityUpdate: -// -// return LightClientFinalityUpdate( -// attested_header=update.attested_header, -// finalized_header=update.finalized_header, -// finality_branch=update.finality_branch, -// sync_aggregate=update.sync_aggregate, -// signature_slot=update.signature_slot, -// ) -func CreateLightClientFinalityUpdate(update *ethpbv2.LightClientUpdate) *ethpbv2.LightClientFinalityUpdate { - return ðpbv2.LightClientFinalityUpdate{ - AttestedHeader: update.AttestedHeader, - FinalizedHeader: update.FinalizedHeader, - FinalityBranch: update.FinalityBranch, - SyncAggregate: update.SyncAggregate, - SignatureSlot: update.SignatureSlot, - } -} - -// CreateLightClientOptimisticUpdate - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_optimistic_update -// def create_light_client_optimistic_update(update: LightClientUpdate) -> LightClientOptimisticUpdate: -// -// return LightClientOptimisticUpdate( -// attested_header=update.attested_header, -// sync_aggregate=update.sync_aggregate, -// signature_slot=update.signature_slot, -// ) -func CreateLightClientOptimisticUpdate(update *ethpbv2.LightClientUpdate) *ethpbv2.LightClientOptimisticUpdate { - return ðpbv2.LightClientOptimisticUpdate{ - AttestedHeader: update.AttestedHeader, - SyncAggregate: update.SyncAggregate, - SignatureSlot: update.SignatureSlot, - } -} - -func NewLightClientOptimisticUpdateFromBeaconState( - ctx context.Context, - state state.BeaconState, - block interfaces.ReadOnlySignedBeaconBlock, - attestedState state.BeaconState) (*ethpbv2.LightClientUpdate, error) { - // assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH - attestedEpoch := slots.ToEpoch(attestedState.Slot()) - if attestedEpoch < params.BeaconConfig().AltairForkEpoch { - return nil, fmt.Errorf("invalid attested epoch %d", attestedEpoch) - } - - // assert sum(block.message.body.sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS - syncAggregate, err := block.Block().Body().SyncAggregate() - if err != nil { - return nil, fmt.Errorf("could not get sync aggregate %w", err) - } - - if syncAggregate.SyncCommitteeBits.Count() < params.BeaconConfig().MinSyncCommitteeParticipants { - return nil, fmt.Errorf("invalid sync committee bits count %d", syncAggregate.SyncCommitteeBits.Count()) - } - - // assert state.slot == state.latest_block_header.slot - if state.Slot() != state.LatestBlockHeader().Slot { - return nil, fmt.Errorf("state slot %d not equal to latest block header slot %d", state.Slot(), state.LatestBlockHeader().Slot) - } - - // assert hash_tree_root(header) == hash_tree_root(block.message) - header := state.LatestBlockHeader() - stateRoot, err := state.HashTreeRoot(ctx) - if err != nil { - return nil, fmt.Errorf("could not get state root %w", err) - } - header.StateRoot = stateRoot[:] - - headerRoot, err := header.HashTreeRoot() - if err != nil { - return nil, fmt.Errorf("could not get header root %w", err) - } - - blockRoot, err := block.Block().HashTreeRoot() - if err != nil { - return nil, fmt.Errorf("could not get block root %w", err) - } - - if headerRoot != blockRoot { - return nil, fmt.Errorf("header root %#x not equal to block root %#x", headerRoot, blockRoot) - } - - // assert attested_state.slot == attested_state.latest_block_header.slot - if attestedState.Slot() != attestedState.LatestBlockHeader().Slot { - return nil, fmt.Errorf("attested state slot %d not equal to attested latest block header slot %d", attestedState.Slot(), attestedState.LatestBlockHeader().Slot) - } - - // attested_header = attested_state.latest_block_header.copy() - attestedHeader := attestedState.LatestBlockHeader() - - // attested_header.state_root = hash_tree_root(attested_state) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - if err != nil { - return nil, fmt.Errorf("could not get attested state root %w", err) - } - attestedHeader.StateRoot = attestedStateRoot[:] - - // assert hash_tree_root(attested_header) == block.message.parent_root - attestedHeaderRoot, err := attestedHeader.HashTreeRoot() - if err != nil { - return nil, fmt.Errorf("could not get attested header root %w", err) - } - - if attestedHeaderRoot != block.Block().ParentRoot() { - return nil, fmt.Errorf("attested header root %#x not equal to block parent root %#x", attestedHeaderRoot, block.Block().ParentRoot()) - } - - // Return result - attestedHeaderResult := ðpbv1.BeaconBlockHeader{ - Slot: attestedHeader.Slot, - ProposerIndex: attestedHeader.ProposerIndex, - ParentRoot: attestedHeader.ParentRoot, - StateRoot: attestedHeader.StateRoot, - BodyRoot: attestedHeader.BodyRoot, - } - - syncAggregateResult := ðpbv1.SyncAggregate{ - SyncCommitteeBits: syncAggregate.SyncCommitteeBits, - SyncCommitteeSignature: syncAggregate.SyncCommitteeSignature, - } - - result := ðpbv2.LightClientUpdate{ - AttestedHeader: attestedHeaderResult, - SyncAggregate: syncAggregateResult, - SignatureSlot: block.Block().Slot(), - } - - return result, nil -} - -func NewLightClientFinalityUpdateFromBeaconState( - ctx context.Context, - state state.BeaconState, - block interfaces.ReadOnlySignedBeaconBlock, - attestedState state.BeaconState, - finalizedBlock interfaces.ReadOnlySignedBeaconBlock) (*ethpbv2.LightClientUpdate, error) { - result, err := NewLightClientOptimisticUpdateFromBeaconState( - ctx, - state, - block, - attestedState, - ) - if err != nil { - return nil, err - } - - // Indicate finality whenever possible - var finalizedHeader *ethpbv1.BeaconBlockHeader - var finalityBranch [][]byte - - if finalizedBlock != nil && !finalizedBlock.IsNil() { - if finalizedBlock.Block().Slot() != 0 { - tempFinalizedHeader, err := finalizedBlock.Header() - if err != nil { - return nil, fmt.Errorf("could not get finalized header %w", err) - } - finalizedHeader = migration.V1Alpha1SignedHeaderToV1(tempFinalizedHeader).GetMessage() - - finalizedHeaderRoot, err := finalizedHeader.HashTreeRoot() - if err != nil { - return nil, fmt.Errorf("could not get finalized header root %w", err) - } - - if finalizedHeaderRoot != bytesutil.ToBytes32(attestedState.FinalizedCheckpoint().Root) { - return nil, fmt.Errorf("finalized header root %#x not equal to attested finalized checkpoint root %#x", finalizedHeaderRoot, bytesutil.ToBytes32(attestedState.FinalizedCheckpoint().Root)) - } - } else { - if !bytes.Equal(attestedState.FinalizedCheckpoint().Root, make([]byte, 32)) { - return nil, fmt.Errorf("invalid finalized header root %v", attestedState.FinalizedCheckpoint().Root) - } - - finalizedHeader = ðpbv1.BeaconBlockHeader{ - Slot: 0, - ProposerIndex: 0, - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - BodyRoot: make([]byte, 32), - } - } - - var bErr error - finalityBranch, bErr = attestedState.FinalizedRootProof(ctx) - if bErr != nil { - return nil, fmt.Errorf("could not get finalized root proof %w", bErr) - } - } else { - finalizedHeader = ðpbv1.BeaconBlockHeader{ - Slot: 0, - ProposerIndex: 0, - ParentRoot: make([]byte, 32), - StateRoot: make([]byte, 32), - BodyRoot: make([]byte, 32), - } - - finalityBranch = make([][]byte, FinalityBranchNumOfLeaves) - for i := 0; i < FinalityBranchNumOfLeaves; i++ { - finalityBranch[i] = make([]byte, 32) - } - } - - result.FinalizedHeader = finalizedHeader - result.FinalityBranch = finalityBranch - return result, nil -} - -func NewLightClientUpdateFromFinalityUpdate(update *ethpbv2.LightClientFinalityUpdate) *ethpbv2.LightClientUpdate { - return ðpbv2.LightClientUpdate{ - AttestedHeader: update.AttestedHeader, - FinalizedHeader: update.FinalizedHeader, - FinalityBranch: update.FinalityBranch, - SyncAggregate: update.SyncAggregate, - SignatureSlot: update.SignatureSlot, - } -} - -func NewLightClientUpdateFromOptimisticUpdate(update *ethpbv2.LightClientOptimisticUpdate) *ethpbv2.LightClientUpdate { - return ðpbv2.LightClientUpdate{ - AttestedHeader: update.AttestedHeader, - SyncAggregate: update.SyncAggregate, - SignatureSlot: update.SignatureSlot, - } -} diff --git a/beacon-chain/blockchain/lightclient_test.go b/beacon-chain/blockchain/lightclient_test.go deleted file mode 100644 index 41a3a7cfacdb..000000000000 --- a/beacon-chain/blockchain/lightclient_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package blockchain - -import ( - "context" - "testing" - - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/params" - "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/util" -) - -type testlc struct { - t *testing.T - ctx context.Context - state state.BeaconState - block interfaces.ReadOnlySignedBeaconBlock - attestedState state.BeaconState - attestedHeader *ethpb.BeaconBlockHeader -} - -func newTestLc(t *testing.T) *testlc { - return &testlc{t: t} -} - -func (l *testlc) setupTest() *testlc { - ctx := context.Background() - - slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(l.t, err) - err = attestedState.SetSlot(slot) - require.NoError(l.t, err) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(l.t, err) - - parentHeader, err := signedParent.Header() - require.NoError(l.t, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(l.t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(l.t, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(l.t, err) - - state, err := util.NewBeaconStateCapella() - require.NoError(l.t, err) - err = state.SetSlot(slot) - require.NoError(l.t, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(l.t, err) - - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(l.t, err) - - h, err := signedBlock.Header() - require.NoError(l.t, err) - - err = state.SetLatestBlockHeader(h.Header) - require.NoError(l.t, err) - stateRoot, err := state.HashTreeRoot(ctx) - require.NoError(l.t, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(l.t, err) - - l.state = state - l.attestedState = attestedState - l.attestedHeader = attestedHeader - l.block = signedBlock - l.ctx = ctx - - return l -} - -func (l *testlc) checkAttestedHeader(update *ethpbv2.LightClientUpdate) { - require.Equal(l.t, l.attestedHeader.Slot, update.AttestedHeader.Slot, "Attested header slot is not equal") - require.Equal(l.t, l.attestedHeader.ProposerIndex, update.AttestedHeader.ProposerIndex, "Attested header proposer index is not equal") - require.DeepSSZEqual(l.t, l.attestedHeader.ParentRoot, update.AttestedHeader.ParentRoot, "Attested header parent root is not equal") - require.DeepSSZEqual(l.t, l.attestedHeader.BodyRoot, update.AttestedHeader.BodyRoot, "Attested header body root is not equal") - - attestedStateRoot, err := l.attestedState.HashTreeRoot(l.ctx) - require.NoError(l.t, err) - require.DeepSSZEqual(l.t, attestedStateRoot[:], update.AttestedHeader.StateRoot, "Attested header state root is not equal") -} - -func (l *testlc) checkSyncAggregate(update *ethpbv2.LightClientUpdate) { - syncAggregate, err := l.block.Block().Body().SyncAggregate() - require.NoError(l.t, err) - require.DeepSSZEqual(l.t, syncAggregate.SyncCommitteeBits, update.SyncAggregate.SyncCommitteeBits, "SyncAggregate bits is not equal") - require.DeepSSZEqual(l.t, syncAggregate.SyncCommitteeSignature, update.SyncAggregate.SyncCommitteeSignature, "SyncAggregate signature is not equal") -} - -func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T) { - l := newTestLc(t).setupTest() - - update, err := NewLightClientOptimisticUpdateFromBeaconState(l.ctx, l.state, l.block, l.attestedState) - require.NoError(t, err) - require.NotNil(t, update, "update is nil") - - require.Equal(t, l.block.Block().Slot(), update.SignatureSlot, "Signature slot is not equal") - - l.checkSyncAggregate(update) - l.checkAttestedHeader(update) - - require.Equal(t, (*v1.BeaconBlockHeader)(nil), update.FinalizedHeader, "Finalized header is not nil") - require.DeepSSZEqual(t, ([][]byte)(nil), update.FinalityBranch, "Finality branch is not nil") -} - -func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { - l := newTestLc(t).setupTest() - - update, err := NewLightClientFinalityUpdateFromBeaconState(l.ctx, l.state, l.block, l.attestedState, nil) - require.NoError(t, err) - require.NotNil(t, update, "update is nil") - - require.Equal(t, l.block.Block().Slot(), update.SignatureSlot, "Signature slot is not equal") - - l.checkSyncAggregate(update) - l.checkAttestedHeader(update) - - zeroHash := params.BeaconConfig().ZeroHash[:] - require.NotNil(t, update.FinalizedHeader, "Finalized header is nil") - require.Equal(t, primitives.Slot(0), update.FinalizedHeader.Slot, "Finalized header slot is not zero") - require.Equal(t, primitives.ValidatorIndex(0), update.FinalizedHeader.ProposerIndex, "Finalized header proposer index is not zero") - require.DeepSSZEqual(t, zeroHash, update.FinalizedHeader.ParentRoot, "Finalized header parent root is not zero") - require.DeepSSZEqual(t, zeroHash, update.FinalizedHeader.StateRoot, "Finalized header state root is not zero") - require.DeepSSZEqual(t, zeroHash, update.FinalizedHeader.BodyRoot, "Finalized header body root is not zero") - require.Equal(t, FinalityBranchNumOfLeaves, len(update.FinalityBranch), "Invalid finality branch leaves") - for _, leaf := range update.FinalityBranch { - require.DeepSSZEqual(t, zeroHash, leaf, "Leaf is not zero") - } -} diff --git a/beacon-chain/blockchain/log.go b/beacon-chain/blockchain/log.go index b8f4e0d94168..d67a0b3f2696 100644 --- a/beacon-chain/blockchain/log.go +++ b/beacon-chain/blockchain/log.go @@ -69,6 +69,22 @@ func logStateTransitionData(b interfaces.ReadOnlyBeaconBlock) error { log = log.WithField("kzgCommitmentCount", len(kzgs)) } } + if b.Version() >= version.Electra { + eReqs, err := b.Body().ExecutionRequests() + if err != nil { + log.WithError(err).Error("Failed to get execution requests") + } else { + if len(eReqs.Deposits) > 0 { + log = log.WithField("depositRequestCount", len(eReqs.Deposits)) + } + if len(eReqs.Consolidations) > 0 { + log = log.WithField("consolidationRequestCount", len(eReqs.Consolidations)) + } + if len(eReqs.Withdrawals) > 0 { + log = log.WithField("withdrawalRequestCount", len(eReqs.Withdrawals)) + } + } + } log.Info("Finished applying state transition") return nil } diff --git a/beacon-chain/blockchain/options.go b/beacon-chain/blockchain/options.go index 38492502a1f9..caf746cc74d0 100644 --- a/beacon-chain/blockchain/options.go +++ b/beacon-chain/blockchain/options.go @@ -85,6 +85,14 @@ func WithTrackedValidatorsCache(c *cache.TrackedValidatorsCache) Option { } } +// WithAttestationCache for attestation lifecycle after chain inclusion. +func WithAttestationCache(c *cache.AttestationCache) Option { + return func(s *Service) error { + s.cfg.AttestationCache = c + return nil + } +} + // WithAttestationPool for attestation lifecycle after chain inclusion. func WithAttestationPool(p attestations.Pool) Option { return func(s *Service) error { diff --git a/beacon-chain/blockchain/pow_block.go b/beacon-chain/blockchain/pow_block.go index 00f929d3c19f..3018d31d413d 100644 --- a/beacon-chain/blockchain/pow_block.go +++ b/beacon-chain/blockchain/pow_block.go @@ -46,7 +46,7 @@ func (s *Service) validateMergeBlock(ctx context.Context, b interfaces.ReadOnlyS if err != nil { return err } - if payload.IsNil() { + if payload == nil || payload.IsNil() { return errors.New("nil execution payload") } ok, err := canUseValidatedTerminalBlockHash(b.Block().Slot(), payload) diff --git a/beacon-chain/blockchain/process_attestation.go b/beacon-chain/blockchain/process_attestation.go index d4bd636b7783..540a4ba40047 100644 --- a/beacon-chain/blockchain/process_attestation.go +++ b/beacon-chain/blockchain/process_attestation.go @@ -7,10 +7,10 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // OnAttestation is called whenever an attestation is received, verifies the attestation is valid and saves diff --git a/beacon-chain/blockchain/process_attestation_test.go b/beacon-chain/blockchain/process_attestation_test.go index f24db1f61a39..f8ea9c1b2839 100644 --- a/beacon-chain/blockchain/process_attestation_test.go +++ b/beacon-chain/blockchain/process_attestation_test.go @@ -32,18 +32,18 @@ func TestStore_OnAttestation_ErrorConditions(t *testing.T) { util.SaveBlock(t, ctx, beaconDB, blkWithoutState) cp := ðpb.Checkpoint{} - st, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, cp, cp) + st, roblock, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, cp, cp) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) blkWithStateBadAtt := util.NewBeaconBlock() blkWithStateBadAtt.Block.Slot = 1 r, err := blkWithStateBadAtt.Block.HashTreeRoot() require.NoError(t, err) cp = ðpb.Checkpoint{Root: r[:]} - st, blkRoot, err = prepareForkchoiceState(ctx, blkWithStateBadAtt.Block.Slot, r, [32]byte{}, params.BeaconConfig().ZeroHash, cp, cp) + st, roblock, err = prepareForkchoiceState(ctx, blkWithStateBadAtt.Block.Slot, r, [32]byte{}, params.BeaconConfig().ZeroHash, cp, cp) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) util.SaveBlock(t, ctx, beaconDB, blkWithStateBadAtt) BlkWithStateBadAttRoot, err := blkWithStateBadAtt.Block.HashTreeRoot() require.NoError(t, err) @@ -92,12 +92,12 @@ func TestStore_OnAttestation_ErrorConditions(t *testing.T) { { name: "process nil attestation", a: nil, - wantedErr: "attestation can't be nil", + wantedErr: "attestation is nil", }, { name: "process nil field (a.Data) in attestation", a: ðpb.Attestation{}, - wantedErr: "attestation's data can't be nil", + wantedErr: "attestation is nil", }, { name: "process nil field (a.Target) in attestation", @@ -139,9 +139,9 @@ func TestStore_OnAttestation_Ok_DoublyLinkedTree(t *testing.T) { require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, copied, tRoot)) ojc := ðpb.Checkpoint{Epoch: 0, Root: tRoot[:]} ofc := ðpb.Checkpoint{Epoch: 0, Root: tRoot[:]} - state, blkRoot, err := prepareForkchoiceState(ctx, 0, tRoot, tRoot, params.BeaconConfig().ZeroHash, ojc, ofc) + state, roblock, err := prepareForkchoiceState(ctx, 0, tRoot, tRoot, params.BeaconConfig().ZeroHash, ojc, ofc) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, roblock)) require.NoError(t, service.OnAttestation(ctx, att[0], 0)) } @@ -318,10 +318,9 @@ func TestStore_UpdateCheckpointState(t *testing.T) { require.NoError(t, err) checkpoint := ðpb.Checkpoint{Epoch: epoch, Root: r1[:]} require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(checkpoint.Root))) - st, blkRoot, err := prepareForkchoiceState(ctx, blk.Block.Slot, r1, [32]byte{}, params.BeaconConfig().ZeroHash, checkpoint, checkpoint) + st, roblock, err := prepareForkchoiceState(ctx, blk.Block.Slot, r1, [32]byte{}, params.BeaconConfig().ZeroHash, checkpoint, checkpoint) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, r1)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) returned, err := service.getAttPreState(ctx, checkpoint) require.NoError(t, err) assert.Equal(t, params.BeaconConfig().SlotsPerEpoch.Mul(uint64(checkpoint.Epoch)), returned.Slot(), "Incorrectly returned base state") @@ -337,10 +336,9 @@ func TestStore_UpdateCheckpointState(t *testing.T) { require.NoError(t, err) newCheckpoint := ðpb.Checkpoint{Epoch: epoch, Root: r2[:]} require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, baseState, bytesutil.ToBytes32(newCheckpoint.Root))) - st, blkRoot, err = prepareForkchoiceState(ctx, blk.Block.Slot, r2, r1, params.BeaconConfig().ZeroHash, newCheckpoint, newCheckpoint) + st, roblock, err = prepareForkchoiceState(ctx, blk.Block.Slot, r2, r1, params.BeaconConfig().ZeroHash, newCheckpoint, newCheckpoint) require.NoError(t, err) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, blkRoot)) - require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, r2)) + require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, st, roblock)) returned, err = service.getAttPreState(ctx, newCheckpoint) require.NoError(t, err) s, err := slots.EpochStart(newCheckpoint.Epoch) diff --git a/beacon-chain/blockchain/process_block.go b/beacon-chain/blockchain/process_block.go index 454928b0a39d..a599351fcf1e 100644 --- a/beacon-chain/blockchain/process_block.go +++ b/beacon-chain/blockchain/process_block.go @@ -7,8 +7,6 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" - statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" coreTime "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" @@ -17,7 +15,6 @@ import ( forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/features" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" @@ -25,12 +22,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // A custom slot deadline for processing state slots in our cache. @@ -46,8 +43,7 @@ var initialSyncBlockCacheSize = uint64(2 * params.BeaconConfig().SlotsPerEpoch) // process the beacon block after validating the state transition function type postBlockProcessConfig struct { ctx context.Context - signed interfaces.ReadOnlySignedBeaconBlock - blockRoot [32]byte + roblock consensusblocks.ROBlock headRoot [32]byte postState state.BeaconState isValidPayload bool @@ -61,7 +57,7 @@ func (s *Service) postBlockProcess(cfg *postBlockProcessConfig) error { ctx, span := trace.StartSpan(cfg.ctx, "blockChain.onBlock") defer span.End() cfg.ctx = ctx - if err := consensusblocks.BeaconBlockIsNil(cfg.signed); err != nil { + if err := consensusblocks.BeaconBlockIsNil(cfg.roblock); err != nil { return invalidBlock{error: err} } startTime := time.Now() @@ -70,22 +66,29 @@ func (s *Service) postBlockProcess(cfg *postBlockProcessConfig) error { if s.inRegularSync() { defer s.handleSecondFCUCall(cfg, fcuArgs) } - defer s.sendLightClientFeeds(cfg) + if features.Get().EnableLightClient && slots.ToEpoch(s.CurrentSlot()) >= params.BeaconConfig().AltairForkEpoch { + defer s.processLightClientUpdates(cfg) + defer s.saveLightClientUpdate(cfg) + defer s.saveLightClientBootstrap(cfg) + } defer s.sendStateFeedOnBlock(cfg) defer reportProcessingTime(startTime) - defer reportAttestationInclusion(cfg.signed.Block()) + defer reportAttestationInclusion(cfg.roblock.Block()) - err := s.cfg.ForkChoiceStore.InsertNode(ctx, cfg.postState, cfg.blockRoot) + err := s.cfg.ForkChoiceStore.InsertNode(ctx, cfg.postState, cfg.roblock) if err != nil { - return errors.Wrapf(err, "could not insert block %d to fork choice store", cfg.signed.Block().Slot()) + // Do not use parent context in the event it deadlined + ctx = trace.NewContext(context.Background(), span) + s.rollbackBlock(ctx, cfg.roblock.Root()) + return errors.Wrapf(err, "could not insert block %d to fork choice store", cfg.roblock.Block().Slot()) } - if err := s.handleBlockAttestations(ctx, cfg.signed.Block(), cfg.postState); err != nil { + if err := s.handleBlockAttestations(ctx, cfg.roblock.Block(), cfg.postState); err != nil { return errors.Wrap(err, "could not handle block's attestations") } - s.InsertSlashingsToForkChoiceStore(ctx, cfg.signed.Block().Body().AttesterSlashings()) + s.InsertSlashingsToForkChoiceStore(ctx, cfg.roblock.Block().Body().AttesterSlashings()) if cfg.isValidPayload { - if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, cfg.blockRoot); err != nil { + if err := s.cfg.ForkChoiceStore.SetOptimisticToValid(ctx, cfg.roblock.Root()); err != nil { return errors.Wrap(err, "could not set optimistic block to valid") } } @@ -95,8 +98,8 @@ func (s *Service) postBlockProcess(cfg *postBlockProcessConfig) error { log.WithError(err).Warn("Could not update head") } newBlockHeadElapsedTime.Observe(float64(time.Since(start).Milliseconds())) - if cfg.headRoot != cfg.blockRoot { - s.logNonCanonicalBlockReceived(cfg.blockRoot, cfg.headRoot) + if cfg.headRoot != cfg.roblock.Root() { + s.logNonCanonicalBlockReceived(cfg.roblock.Root(), cfg.headRoot) return nil } if err := s.getFCUArgs(cfg, fcuArgs); err != nil { @@ -154,7 +157,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []consensusblocks.ROBlo } // Fill in missing blocks - if err := s.fillInForkChoiceMissingBlocks(ctx, blks[0].Block(), preState.CurrentJustifiedCheckpoint(), preState.FinalizedCheckpoint()); err != nil { + if err := s.fillInForkChoiceMissingBlocks(ctx, blks[0], preState.CurrentJustifiedCheckpoint(), preState.FinalizedCheckpoint()); err != nil { return errors.Wrap(err, "could not fill in missing blocks to forkchoice") } @@ -234,7 +237,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []consensusblocks.ROBlo if err := avs.IsDataAvailable(ctx, s.CurrentSlot(), b); err != nil { return errors.Wrapf(err, "could not validate blob data availability at slot %d", b.Block().Slot()) } - args := &forkchoicetypes.BlockAndCheckpoints{Block: b.Block(), + args := &forkchoicetypes.BlockAndCheckpoints{Block: b, JustifiedCheckpoint: jCheckpoints[i], FinalizedCheckpoint: fCheckpoints[i]} pendingNodes[len(blks)-i-1] = args @@ -279,7 +282,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []consensusblocks.ROBlo return errors.Wrap(err, "could not insert batch to forkchoice") } // Insert the last block to forkchoice - if err := s.cfg.ForkChoiceStore.InsertNode(ctx, preState, lastBR); err != nil { + if err := s.cfg.ForkChoiceStore.InsertNode(ctx, preState, lastB); err != nil { return errors.Wrap(err, "could not insert last block in batch to forkchoice") } // Set their optimistic status @@ -376,7 +379,11 @@ func (s *Service) handleBlockAttestations(ctx context.Context, blk interfaces.Re r := bytesutil.ToBytes32(a.GetData().BeaconBlockRoot) if s.cfg.ForkChoiceStore.HasNode(r) { s.cfg.ForkChoiceStore.ProcessAttestation(ctx, indices, r, a.GetData().Target.Epoch) - } else if err := s.cfg.AttPool.SaveBlockAttestation(a); err != nil { + } else if features.Get().EnableExperimentalAttestationPool { + if err = s.cfg.AttestationCache.Add(a); err != nil { + return err + } + } else if err = s.cfg.AttPool.SaveBlockAttestation(a); err != nil { return err } } @@ -404,6 +411,9 @@ func (s *Service) savePostStateInfo(ctx context.Context, r [32]byte, b interface return errors.Wrapf(err, "could not save block from slot %d", b.Block().Slot()) } if err := s.cfg.StateGen.SaveState(ctx, r, st); err != nil { + // Do not use parent context in the event it deadlined + ctx = trace.NewContext(context.Background(), span) + s.rollbackBlock(ctx, r) return errors.Wrap(err, "could not save state") } return nil @@ -413,7 +423,11 @@ func (s *Service) savePostStateInfo(ctx context.Context, r [32]byte, b interface func (s *Service) pruneAttsFromPool(headBlock interfaces.ReadOnlySignedBeaconBlock) error { atts := headBlock.Block().Body().Attestations() for _, att := range atts { - if helpers.IsAggregated(att) { + if features.Get().EnableExperimentalAttestationPool { + if err := s.cfg.AttestationCache.DeleteCovered(att); err != nil { + return errors.Wrap(err, "could not delete attestation") + } + } else if att.IsAggregated() { if err := s.cfg.AttPool.DeleteAggregatedAttestation(att); err != nil { return err } @@ -490,24 +504,19 @@ func (s *Service) runLateBlockTasks() { // It returns a map where each key represents a missing BlobSidecar index. // An empty map means we have all indices; a non-empty map can be used to compare incoming // BlobSidecars against the set of known missing sidecars. -func missingIndices(bs *filesystem.BlobStorage, root [32]byte, expected [][]byte) (map[uint64]struct{}, error) { +func missingIndices(bs *filesystem.BlobStorage, root [32]byte, expected [][]byte, slot primitives.Slot) (map[uint64]struct{}, error) { + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(slot) if len(expected) == 0 { return nil, nil } - if len(expected) > fieldparams.MaxBlobsPerBlock { + if len(expected) > maxBlobsPerBlock { return nil, errMaxBlobsExceeded } - indices, err := bs.Indices(root) - if err != nil { - return nil, err - } + indices := bs.Summary(root) missing := make(map[uint64]struct{}, len(expected)) for i := range expected { - ui := uint64(i) - if len(expected[i]) > 0 { - if !indices[i] { - missing[ui] = struct{}{} - } + if len(expected[i]) > 0 && !indices.HasIndex(uint64(i)) { + missing[uint64(i)] = struct{}{} } } return missing, nil @@ -546,7 +555,7 @@ func (s *Service) isDataAvailable(ctx context.Context, root [32]byte, signed int return nil } // get a map of BlobSidecar indices that are not currently available. - missing, err := missingIndices(s.blobStorage, root, kzgCommitments) + missing, err := missingIndices(s.blobStorage, root, kzgCommitments, block.Slot()) if err != nil { return err } @@ -557,7 +566,7 @@ func (s *Service) isDataAvailable(ctx context.Context, root [32]byte, signed int // The gossip handler for blobs writes the index of each verified blob referencing the given // root to the channel returned by blobNotifiers.forRoot. - nc := s.blobNotifiers.forRoot(root) + nc := s.blobNotifiers.forRoot(root, block.Slot()) // Log for DA checks that cross over into the next slot; helpful for debugging. nextSlot := slots.BeginsAt(signed.Block().Slot()+1, s.genesisTime) @@ -614,9 +623,6 @@ func (s *Service) lateBlockTasks(ctx context.Context) { if !s.inRegularSync() { return } - s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ - Type: statefeed.MissedSlot, - }) s.headLock.RLock() headRoot := s.headRoot() headState := s.headState(ctx) @@ -644,6 +650,13 @@ func (s *Service) lateBlockTasks(ctx context.Context) { attribute := s.getPayloadAttribute(ctx, headState, s.CurrentSlot()+1, headRoot[:]) // return early if we are not proposing next slot if attribute.IsEmpty() { + fcuArgs := &fcuConfig{ + headState: headState, + headRoot: headRoot, + headBlock: nil, + attributes: attribute, + } + go firePayloadAttributesEvent(ctx, s.cfg.StateNotifier.StateFeed(), fcuArgs) return } @@ -684,3 +697,15 @@ func (s *Service) handleInvalidExecutionError(ctx context.Context, err error, bl } return err } + +// In the event of an issue processing a block we rollback changes done to the db and our caches +// to always ensure that the node's internal state is consistent. +func (s *Service) rollbackBlock(ctx context.Context, blockRoot [32]byte) { + log.Warnf("Rolling back insertion of block with root %#x due to processing error", blockRoot) + if err := s.cfg.StateGen.DeleteStateFromCaches(ctx, blockRoot); err != nil { + log.WithError(err).Errorf("Could not delete state from caches with block root %#x", blockRoot) + } + if err := s.cfg.BeaconDB.DeleteBlock(ctx, blockRoot); err != nil { + log.WithError(err).Errorf("Could not delete block with block root %#x", blockRoot) + } +} diff --git a/beacon-chain/blockchain/process_block_helpers.go b/beacon-chain/blockchain/process_block_helpers.go index 9e07cb4e17b3..d751f859ca95 100644 --- a/beacon-chain/blockchain/process_block_helpers.go +++ b/beacon-chain/blockchain/process_block_helpers.go @@ -1,10 +1,15 @@ package blockchain import ( + "bytes" "context" "fmt" + "strings" "time" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client" + "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" @@ -13,18 +18,17 @@ import ( doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree" forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/features" field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" + consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" mathutil "github.com/prysmaticlabs/prysm/v5/math" - ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // CurrentSlot returns the current slot based on time. @@ -40,7 +44,7 @@ func (s *Service) getFCUArgs(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) er if !s.inRegularSync() { return nil } - slot := cfg.signed.Block().Slot() + slot := cfg.roblock.Block().Slot() if slots.WithinVotingWindow(uint64(s.genesisTime.Unix()), slot) { return nil } @@ -48,9 +52,9 @@ func (s *Service) getFCUArgs(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) er } func (s *Service) getFCUArgsEarlyBlock(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error { - if cfg.blockRoot == cfg.headRoot { + if cfg.roblock.Root() == cfg.headRoot { fcuArgs.headState = cfg.postState - fcuArgs.headBlock = cfg.signed + fcuArgs.headBlock = cfg.roblock fcuArgs.headRoot = cfg.headRoot fcuArgs.proposingSlot = s.CurrentSlot() + 1 return nil @@ -94,7 +98,7 @@ func (s *Service) fcuArgsNonCanonicalBlock(cfg *postBlockProcessConfig, fcuArgs // sendStateFeedOnBlock sends an event that a new block has been synced func (s *Service) sendStateFeedOnBlock(cfg *postBlockProcessConfig) { - optimistic, err := s.cfg.ForkChoiceStore.IsOptimistic(cfg.blockRoot) + optimistic, err := s.cfg.ForkChoiceStore.IsOptimistic(cfg.roblock.Root()) if err != nil { log.WithError(err).Debug("Could not check if block is optimistic") optimistic = true @@ -103,135 +107,209 @@ func (s *Service) sendStateFeedOnBlock(cfg *postBlockProcessConfig) { s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ Type: statefeed.BlockProcessed, Data: &statefeed.BlockProcessedData{ - Slot: cfg.signed.Block().Slot(), - BlockRoot: cfg.blockRoot, - SignedBlock: cfg.signed, + Slot: cfg.roblock.Block().Slot(), + BlockRoot: cfg.roblock.Root(), + SignedBlock: cfg.roblock, Verified: true, Optimistic: optimistic, }, }) } -// sendLightClientFeeds sends the light client feeds when feature flag is enabled. -func (s *Service) sendLightClientFeeds(cfg *postBlockProcessConfig) { - if features.Get().EnableLightClient { - if _, err := s.sendLightClientOptimisticUpdate(cfg.ctx, cfg.signed, cfg.postState); err != nil { - log.WithError(err).Error("Failed to send light client optimistic update") - } - - // Get the finalized checkpoint - finalized := s.ForkChoicer().FinalizedCheckpoint() - - // LightClientFinalityUpdate needs super majority - s.tryPublishLightClientFinalityUpdate(cfg.ctx, cfg.signed, finalized, cfg.postState) +func (s *Service) processLightClientUpdates(cfg *postBlockProcessConfig) { + if err := s.processLightClientOptimisticUpdate(cfg.ctx, cfg.roblock, cfg.postState); err != nil { + log.WithError(err).Error("Failed to process light client optimistic update") + } + if err := s.processLightClientFinalityUpdate(cfg.ctx, cfg.roblock, cfg.postState); err != nil { + log.WithError(err).Error("Failed to process light client finality update") } } -func (s *Service) tryPublishLightClientFinalityUpdate(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock, finalized *forkchoicetypes.Checkpoint, postState state.BeaconState) { - if finalized.Epoch <= s.lastPublishedLightClientEpoch { +// saveLightClientUpdate saves the light client update for this block +// if it's better than the already saved one, when feature flag is enabled. +func (s *Service) saveLightClientUpdate(cfg *postBlockProcessConfig) { + attestedRoot := cfg.roblock.Block().ParentRoot() + attestedBlock, err := s.getBlock(cfg.ctx, attestedRoot) + if err != nil { + log.WithError(err).Errorf("Saving light client update failed: Could not get attested block for root %#x", attestedRoot) + return + } + if attestedBlock == nil || attestedBlock.IsNil() { + log.Error("Saving light client update failed: Attested block is nil") + return + } + attestedState, err := s.cfg.StateGen.StateByRoot(cfg.ctx, attestedRoot) + if err != nil { + log.WithError(err).Errorf("Saving light client update failed: Could not get attested state for root %#x", attestedRoot) + return + } + if attestedState == nil || attestedState.IsNil() { + log.Error("Saving light client update failed: Attested state is nil") return } - config := params.BeaconConfig() - if finalized.Epoch < config.AltairForkEpoch { + finalizedRoot := attestedState.FinalizedCheckpoint().Root + finalizedBlock, err := s.getBlock(cfg.ctx, [32]byte(finalizedRoot)) + if err != nil { + if errors.Is(err, errBlockNotFoundInCacheOrDB) { + log.Debugf("Skipping saving light client update: Finalized block is nil for root %#x", finalizedRoot) + } else { + log.WithError(err).Errorf("Saving light client update failed: Could not get finalized block for root %#x", finalizedRoot) + } return } - syncAggregate, err := signed.Block().Body().SyncAggregate() - if err != nil || syncAggregate == nil { + update, err := lightclient.NewLightClientUpdateFromBeaconState( + cfg.ctx, + s.CurrentSlot(), + cfg.postState, + cfg.roblock, + attestedState, + attestedBlock, + finalizedBlock, + ) + if err != nil { + log.WithError(err).Error("Saving light client update failed: Could not create light client update") return } - // LightClientFinalityUpdate needs super majority - if syncAggregate.SyncCommitteeBits.Count()*3 < config.SyncCommitteeSize*2 { + period := slots.SyncCommitteePeriod(slots.ToEpoch(attestedState.Slot())) + + oldUpdate, err := s.cfg.BeaconDB.LightClientUpdate(cfg.ctx, period) + if err != nil { + log.WithError(err).Error("Saving light client update failed: Could not get current light client update") return } - _, err = s.sendLightClientFinalityUpdate(ctx, signed, postState) + if oldUpdate == nil { + if err := s.cfg.BeaconDB.SaveLightClientUpdate(cfg.ctx, period, update); err != nil { + log.WithError(err).Error("Saving light client update failed: Could not save light client update") + } else { + log.WithField("period", period).Debug("Saving light client update: Saved new update") + } + return + } + + isNewUpdateBetter, err := lightclient.IsBetterUpdate(update, oldUpdate) if err != nil { - log.WithError(err).Error("Failed to send light client finality update") + log.WithError(err).Error("Saving light client update failed: Could not compare light client updates") + return + } + + if isNewUpdateBetter { + if err := s.cfg.BeaconDB.SaveLightClientUpdate(cfg.ctx, period, update); err != nil { + log.WithError(err).Error("Saving light client update failed: Could not save light client update") + } else { + log.WithField("period", period).Debug("Saving light client update: Saved new update") + } } else { - s.lastPublishedLightClientEpoch = finalized.Epoch + log.WithField("period", period).Debug("Saving light client update: New update is not better than the current one. Skipping save.") + } +} + +// saveLightClientBootstrap saves a light client bootstrap for this block +// when feature flag is enabled. +func (s *Service) saveLightClientBootstrap(cfg *postBlockProcessConfig) { + blockRoot := cfg.roblock.Root() + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(cfg.ctx, s.CurrentSlot(), cfg.postState, cfg.roblock) + if err != nil { + log.WithError(err).Error("Saving light client bootstrap failed: Could not create light client bootstrap") + return + } + err = s.cfg.BeaconDB.SaveLightClientBootstrap(cfg.ctx, blockRoot[:], bootstrap) + if err != nil { + log.WithError(err).Error("Saving light client bootstrap failed: Could not save light client bootstrap in DB") } } -// sendLightClientFinalityUpdate sends a light client finality update notification to the state feed. -func (s *Service) sendLightClientFinalityUpdate(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock, - postState state.BeaconState) (int, error) { - // Get attested state +func (s *Service) processLightClientFinalityUpdate( + ctx context.Context, + signed interfaces.ReadOnlySignedBeaconBlock, + postState state.BeaconState, +) error { attestedRoot := signed.Block().ParentRoot() + attestedBlock, err := s.cfg.BeaconDB.Block(ctx, attestedRoot) + if err != nil { + return errors.Wrapf(err, "could not get attested block for root %#x", attestedRoot) + } attestedState, err := s.cfg.StateGen.StateByRoot(ctx, attestedRoot) if err != nil { - return 0, errors.Wrap(err, "could not get attested state") + return errors.Wrapf(err, "could not get attested state for root %#x", attestedRoot) } - // Get finalized block - var finalizedBlock interfaces.ReadOnlySignedBeaconBlock - finalizedCheckPoint := attestedState.FinalizedCheckpoint() - if finalizedCheckPoint != nil { - finalizedRoot := bytesutil.ToBytes32(finalizedCheckPoint.Root) - finalizedBlock, err = s.cfg.BeaconDB.Block(ctx, finalizedRoot) - if err != nil { - finalizedBlock = nil + finalizedCheckpoint := attestedState.FinalizedCheckpoint() + + // Check if the finalized checkpoint has changed + if finalizedCheckpoint == nil || bytes.Equal(finalizedCheckpoint.GetRoot(), postState.FinalizedCheckpoint().Root) { + return nil + } + + finalizedRoot := bytesutil.ToBytes32(finalizedCheckpoint.Root) + finalizedBlock, err := s.cfg.BeaconDB.Block(ctx, finalizedRoot) + if err != nil { + if errors.Is(err, errBlockNotFoundInCacheOrDB) { + log.Debugf("Skipping processing light client finality update: Finalized block is nil for root %#x", finalizedRoot) + return nil } + return errors.Wrapf(err, "could not get finalized block for root %#x", finalizedRoot) } - update, err := NewLightClientFinalityUpdateFromBeaconState( + update, err := lightclient.NewLightClientFinalityUpdateFromBeaconState( ctx, + postState.Slot(), postState, signed, attestedState, + attestedBlock, finalizedBlock, ) if err != nil { - return 0, errors.Wrap(err, "could not create light client update") + return errors.Wrap(err, "could not create light client finality update") } - // Return the result - result := ðpbv2.LightClientFinalityUpdateWithVersion{ - Version: ethpbv2.Version(signed.Version()), - Data: CreateLightClientFinalityUpdate(update), - } - - // Send event - return s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ + s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ Type: statefeed.LightClientFinalityUpdate, - Data: result, - }), nil + Data: update, + }) + return nil } -// sendLightClientOptimisticUpdate sends a light client optimistic update notification to the state feed. -func (s *Service) sendLightClientOptimisticUpdate(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock, - postState state.BeaconState) (int, error) { - // Get attested state +func (s *Service) processLightClientOptimisticUpdate(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock, + postState state.BeaconState) error { attestedRoot := signed.Block().ParentRoot() + attestedBlock, err := s.cfg.BeaconDB.Block(ctx, attestedRoot) + if err != nil { + return errors.Wrapf(err, "could not get attested block for root %#x", attestedRoot) + } attestedState, err := s.cfg.StateGen.StateByRoot(ctx, attestedRoot) if err != nil { - return 0, errors.Wrap(err, "could not get attested state") + return errors.Wrapf(err, "could not get attested state for root %#x", attestedRoot) } - update, err := NewLightClientOptimisticUpdateFromBeaconState( + update, err := lightclient.NewLightClientOptimisticUpdateFromBeaconState( ctx, + postState.Slot(), postState, signed, attestedState, + attestedBlock, ) if err != nil { - return 0, errors.Wrap(err, "could not create light client update") - } - - // Return the result - result := ðpbv2.LightClientOptimisticUpdateWithVersion{ - Version: ethpbv2.Version(signed.Version()), - Data: CreateLightClientOptimisticUpdate(update), + if strings.Contains(err.Error(), lightclient.ErrNotEnoughSyncCommitteeBits) { + log.WithError(err).Debug("Skipping processing light client optimistic update") + return nil + } + return errors.Wrap(err, "could not create light client optimistic update") } - return s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ + s.cfg.StateNotifier.StateFeed().Send(&feed.Event{ Type: statefeed.LightClientOptimisticUpdate, - Data: result, - }), nil + Data: update, + }) + + return nil } // updateCachesPostBlockProcessing updates the next slot cache and handles the epoch @@ -240,20 +318,21 @@ func (s *Service) sendLightClientOptimisticUpdate(ctx context.Context, signed in // before sending FCU to the engine. func (s *Service) updateCachesPostBlockProcessing(cfg *postBlockProcessConfig) error { slot := cfg.postState.Slot() - if err := transition.UpdateNextSlotCache(cfg.ctx, cfg.blockRoot[:], cfg.postState); err != nil { + root := cfg.roblock.Root() + if err := transition.UpdateNextSlotCache(cfg.ctx, root[:], cfg.postState); err != nil { return errors.Wrap(err, "could not update next slot state cache") } if !slots.IsEpochEnd(slot) { return nil } - return s.handleEpochBoundary(cfg.ctx, slot, cfg.postState, cfg.blockRoot[:]) + return s.handleEpochBoundary(cfg.ctx, slot, cfg.postState, root[:]) } // handleSecondFCUCall handles a second call to FCU when syncing a new block. // This is useful when proposing in the next block and we want to defer the // computation of the next slot shuffling. func (s *Service) handleSecondFCUCall(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) { - if (fcuArgs.attributes == nil || fcuArgs.attributes.IsEmpty()) && cfg.headRoot == cfg.blockRoot { + if (fcuArgs.attributes == nil || fcuArgs.attributes.IsEmpty()) && cfg.headRoot == cfg.roblock.Root() { go s.sendFCUWithAttributes(cfg, fcuArgs) } } @@ -269,7 +348,7 @@ func reportProcessingTime(startTime time.Time) { // called on blocks that arrive after the attestation voting window, or in a // background routine after syncing early blocks. func (s *Service) computePayloadAttributes(cfg *postBlockProcessConfig, fcuArgs *fcuConfig) error { - if cfg.blockRoot == cfg.headRoot { + if cfg.roblock.Root() == cfg.headRoot { if err := s.updateCachesPostBlockProcessing(cfg); err != nil { return err } @@ -426,7 +505,7 @@ func (s *Service) ancestorByDB(ctx context.Context, r [32]byte, slot primitives. // This retrieves missing blocks from DB (ie. the blocks that couldn't be received over sync) and inserts them to fork choice store. // This is useful for block tree visualizer and additional vote accounting. -func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfaces.ReadOnlyBeaconBlock, +func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock, fCheckpoint, jCheckpoint *ethpb.Checkpoint) error { pendingNodes := make([]*forkchoicetypes.BlockAndCheckpoints, 0) @@ -436,10 +515,15 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa if err != nil { return err } - pendingNodes = append(pendingNodes, &forkchoicetypes.BlockAndCheckpoints{Block: blk, + // The first block can have a bogus root since the block is not inserted in forkchoice + roblock, err := consensus_blocks.NewROBlockWithRoot(signed, [32]byte{}) + if err != nil { + return err + } + pendingNodes = append(pendingNodes, &forkchoicetypes.BlockAndCheckpoints{Block: roblock, JustifiedCheckpoint: jCheckpoint, FinalizedCheckpoint: fCheckpoint}) // As long as parent node is not in fork choice store, and parent node is in DB. - root := blk.ParentRoot() + root := roblock.Block().ParentRoot() for !s.cfg.ForkChoiceStore.HasNode(root) && s.cfg.BeaconDB.HasBlock(ctx, root) { b, err := s.getBlock(ctx, root) if err != nil { @@ -448,8 +532,12 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa if b.Block().Slot() <= fSlot { break } + roblock, err := consensus_blocks.NewROBlockWithRoot(b, root) + if err != nil { + return err + } root = b.Block().ParentRoot() - args := &forkchoicetypes.BlockAndCheckpoints{Block: b.Block(), + args := &forkchoicetypes.BlockAndCheckpoints{Block: roblock, JustifiedCheckpoint: jCheckpoint, FinalizedCheckpoint: fCheckpoint} pendingNodes = append(pendingNodes, args) @@ -465,7 +553,8 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa // inserts finalized deposits into our finalized deposit trie, needs to be // called in the background -func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) { +// Post-Electra: prunes all proofs and pending deposits in the cache +func (s *Service) insertFinalizedDepositsAndPrune(ctx context.Context, fRoot [32]byte) { ctx, span := trace.StartSpan(ctx, "blockChain.insertFinalizedDeposits") defer span.End() startTime := time.Now() @@ -476,6 +565,16 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) { log.WithError(err).Error("could not fetch finalized state") return } + + // Check if we should prune all pending deposits. + // In post-Electra(after the legacy deposit mechanism is deprecated), + // we can prune all pending deposits in the deposit cache. + // See: https://eips.ethereum.org/EIPS/eip-6110#eth1data-poll-deprecation + if helpers.DepositRequestsStarted(finalizedState) { + s.pruneAllPendingDepositsAndProofs(ctx) + return + } + // We update the cache up to the last deposit index in the finalized block's state. // We can be confident that these deposits will be included in some block // because the Eth1 follow distance makes such long-range reorgs extremely unlikely. @@ -504,6 +603,12 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) { log.WithField("duration", time.Since(startTime).String()).Debugf("Finalized deposit insertion completed at index %d", finalizedEth1DepIdx) } +// pruneAllPendingDepositsAndProofs prunes all proofs and pending deposits in the cache. +func (s *Service) pruneAllPendingDepositsAndProofs(ctx context.Context) { + s.cfg.DepositCache.PruneAllPendingDeposits(ctx) + s.cfg.DepositCache.PruneAllProofs(ctx) +} + // This ensures that the input root defaults to using genesis root instead of zero hashes. This is needed for handling // fork choice justification routine. func (s *Service) ensureRootNotZeros(root [32]byte) [32]byte { diff --git a/beacon-chain/blockchain/process_block_test.go b/beacon-chain/blockchain/process_block_test.go index 8d47d014cea5..a41e5a178deb 100644 --- a/beacon-chain/blockchain/process_block_test.go +++ b/beacon-chain/blockchain/process_block_test.go @@ -14,6 +14,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + lightClient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v5/beacon-chain/das" @@ -40,6 +41,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" prysmTime "github.com/prysmaticlabs/prysm/v5/time" + "github.com/prysmaticlabs/prysm/v5/time/slots" logTest "github.com/sirupsen/logrus/hooks/test" ) @@ -145,9 +147,8 @@ func TestFillForkChoiceMissingBlocks_CanSave(t *testing.T) { require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot)) fcp2 := &forkchoicetypes.Checkpoint{Epoch: 0, Root: r0} require.NoError(t, service.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(fcp2)) - err = service.fillInForkChoiceMissingBlocks( - context.Background(), wsb.Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) + context.Background(), wsb, beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) require.NoError(t, err) // 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8 @@ -190,7 +191,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch(t *testing.T) { require.NoError(t, service.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(fcp2)) err = service.fillInForkChoiceMissingBlocks( - context.Background(), wsb.Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) + context.Background(), wsb, beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) require.NoError(t, err) // 5 nodes from the block tree 1. B0 - B3 - B4 - B6 - B8 @@ -246,7 +247,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized(t *testing.T) { // Set finalized epoch to 2. require.NoError(t, service.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 2, Root: r64})) err = service.fillInForkChoiceMissingBlocks( - context.Background(), wsb.Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) + context.Background(), wsb, beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) require.NoError(t, err) // There should be 1 node: block 65 @@ -279,7 +280,7 @@ func TestFillForkChoiceMissingBlocks_FinalizedSibling(t *testing.T) { require.NoError(t, err) err = service.fillInForkChoiceMissingBlocks( - context.Background(), wsb.Block(), beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) + context.Background(), wsb, beaconState.FinalizedCheckpoint(), beaconState.CurrentJustifiedCheckpoint()) require.Equal(t, ErrNotDescendantOfFinalized.Error(), err.Error()) } @@ -566,7 +567,9 @@ func TestOnBlock_CanFinalize_WithOnTick(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, r, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, r, [32]byte{}, postState, true})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, r) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) require.NoError(t, service.updateJustificationOnBlock(ctx, preState, postState, currStoreJustifiedEpoch)) _, err = service.updateFinalizationOnBlock(ctx, preState, postState, currStoreFinalizedEpoch) require.NoError(t, err) @@ -614,7 +617,9 @@ func TestOnBlock_CanFinalize(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, r, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, r, [32]byte{}, postState, true})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, r) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) require.NoError(t, service.updateJustificationOnBlock(ctx, preState, postState, currStoreJustifiedEpoch)) _, err = service.updateFinalizationOnBlock(ctx, preState, postState, currStoreFinalizedEpoch) require.NoError(t, err) @@ -640,7 +645,9 @@ func TestOnBlock_CanFinalize(t *testing.T) { func TestOnBlock_NilBlock(t *testing.T) { service, tr := minimalTestService(t) - err := service.postBlockProcess(&postBlockProcessConfig{tr.ctx, nil, [32]byte{}, [32]byte{}, nil, true}) + signed := &consensusblocks.SignedBeaconBlock{} + roblock := consensusblocks.ROBlock{ReadOnlySignedBeaconBlock: signed} + err := service.postBlockProcess(&postBlockProcessConfig{tr.ctx, roblock, [32]byte{}, nil, true}) require.Equal(t, true, IsInvalidBlock(err)) } @@ -688,7 +695,9 @@ func TestOnBlock_CallNewPayloadAndForkchoiceUpdated(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, r, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, r, [32]byte{}, postState, false})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, r) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) testState, err = service.cfg.StateGen.StateByRoot(ctx, r) require.NoError(t, err) } @@ -714,7 +723,7 @@ func TestInsertFinalizedDeposits(t *testing.T) { Signature: zeroSig[:], }, Proof: [][]byte{root}}, 100+i, int64(i), bytesutil.ToBytes32(root))) } - service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'}) + service.insertFinalizedDepositsAndPrune(ctx, [32]byte{'m', 'o', 'c', 'k'}) fDeposits, err := depositCache.FinalizedDeposits(ctx) require.NoError(t, err) assert.Equal(t, 7, int(fDeposits.MerkleTrieIndex()), "Finalized deposits not inserted correctly") @@ -750,7 +759,7 @@ func TestInsertFinalizedDeposits_PrunePendingDeposits(t *testing.T) { Signature: zeroSig[:], }, Proof: [][]byte{root}}, 100+i, int64(i), bytesutil.ToBytes32(root)) } - service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'}) + service.insertFinalizedDepositsAndPrune(ctx, [32]byte{'m', 'o', 'c', 'k'}) fDeposits, err := depositCache.FinalizedDeposits(ctx) require.NoError(t, err) assert.Equal(t, 7, int(fDeposits.MerkleTrieIndex()), "Finalized deposits not inserted correctly") @@ -790,7 +799,7 @@ func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) { } // Insert 3 deposits before hand. require.NoError(t, depositCache.InsertFinalizedDeposits(ctx, 2, [32]byte{}, 0)) - service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'}) + service.insertFinalizedDepositsAndPrune(ctx, [32]byte{'m', 'o', 'c', 'k'}) fDeposits, err := depositCache.FinalizedDeposits(ctx) require.NoError(t, err) assert.Equal(t, 5, int(fDeposits.MerkleTrieIndex()), "Finalized deposits not inserted correctly") @@ -801,7 +810,7 @@ func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) { } // Insert New Finalized State with higher deposit count. - service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k', '2'}) + service.insertFinalizedDepositsAndPrune(ctx, [32]byte{'m', 'o', 'c', 'k', '2'}) fDeposits, err = depositCache.FinalizedDeposits(ctx) require.NoError(t, err) assert.Equal(t, 12, int(fDeposits.MerkleTrieIndex()), "Finalized deposits not inserted correctly") @@ -1067,6 +1076,48 @@ func TestService_insertSlashingsToForkChoiceStore(t *testing.T) { service.InsertSlashingsToForkChoiceStore(ctx, wb.Block().Body().AttesterSlashings()) } +func TestService_insertSlashingsToForkChoiceStoreElectra(t *testing.T) { + service, tr := minimalTestService(t) + ctx := tr.ctx + + beaconState, privKeys := util.DeterministicGenesisStateElectra(t, 100) + att1 := util.HydrateIndexedAttestationElectra(ðpb.IndexedAttestationElectra{ + Data: ðpb.AttestationData{ + Source: ðpb.Checkpoint{Epoch: 1}, + }, + AttestingIndices: []uint64{0, 1}, + }) + domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot()) + require.NoError(t, err) + signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) + assert.NoError(t, err, "Could not get signing root of beacon block header") + sig0 := privKeys[0].Sign(signingRoot[:]) + sig1 := privKeys[1].Sign(signingRoot[:]) + aggregateSig := bls.AggregateSignatures([]bls.Signature{sig0, sig1}) + att1.Signature = aggregateSig.Marshal() + + att2 := util.HydrateIndexedAttestationElectra(ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{0, 1}, + }) + signingRoot, err = signing.ComputeSigningRoot(att2.Data, domain) + assert.NoError(t, err, "Could not get signing root of beacon block header") + sig0 = privKeys[0].Sign(signingRoot[:]) + sig1 = privKeys[1].Sign(signingRoot[:]) + aggregateSig = bls.AggregateSignatures([]bls.Signature{sig0, sig1}) + att2.Signature = aggregateSig.Marshal() + slashings := []*ethpb.AttesterSlashingElectra{ + { + Attestation_1: att1, + Attestation_2: att2, + }, + } + b := util.NewBeaconBlockElectra() + b.Block.Body.AttesterSlashings = slashings + wb, err := consensusblocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + service.InsertSlashingsToForkChoiceStore(ctx, wb.Block().Body().AttesterSlashings()) +} + func TestOnBlock_ProcessBlocksParallel(t *testing.T) { service, tr := minimalTestService(t) ctx := tr.ctx @@ -1114,7 +1165,9 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb1) require.NoError(t, err) lock.Lock() - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb1, r1, [32]byte{}, postState, true})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb1, r1) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) lock.Unlock() wg.Done() }() @@ -1124,7 +1177,9 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb2) require.NoError(t, err) lock.Lock() - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb2, r2, [32]byte{}, postState, true})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb2, r2) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) lock.Unlock() wg.Done() }() @@ -1134,7 +1189,9 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb3) require.NoError(t, err) lock.Lock() - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb3, r3, [32]byte{}, postState, true})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb3, r3) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) lock.Unlock() wg.Done() }() @@ -1144,7 +1201,9 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb4) require.NoError(t, err) lock.Lock() - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb4, r4, [32]byte{}, postState, true})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb4, r4) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) lock.Unlock() wg.Done() }() @@ -1219,7 +1278,9 @@ func TestStore_NoViableHead_FCU(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) } for i := 6; i < 12; i++ { @@ -1237,7 +1298,9 @@ func TestStore_NoViableHead_FCU(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) } @@ -1256,7 +1319,9 @@ func TestStore_NoViableHead_FCU(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) } // Check that we haven't justified the second epoch yet @@ -1278,7 +1343,9 @@ func TestStore_NoViableHead_FCU(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, firstInvalidRoot, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, firstInvalidRoot, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, firstInvalidRoot) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) jc = service.cfg.ForkChoiceStore.JustifiedCheckpoint() require.Equal(t, primitives.Epoch(2), jc.Epoch) @@ -1306,7 +1373,9 @@ func TestStore_NoViableHead_FCU(t *testing.T) { postState, err = service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false}) + roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.ErrorContains(t, "received an INVALID payload from execution engine", err) // Check that forkchoice's head is the last invalid block imported. The // store's headroot is the previous head (since the invalid block did @@ -1335,7 +1404,9 @@ func TestStore_NoViableHead_FCU(t *testing.T) { postState, err = service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, true}) + roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true}) require.NoError(t, err) // Check the newly imported block is head, it justified the right // checkpoint and the node is no longer optimistic @@ -1397,7 +1468,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) } for i := 6; i < 12; i++ { @@ -1415,7 +1488,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) } @@ -1435,7 +1510,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) } // Check that we haven't justified the second epoch yet @@ -1457,7 +1534,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, firstInvalidRoot, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, firstInvalidRoot, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, firstInvalidRoot) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) jc = service.cfg.ForkChoiceStore.JustifiedCheckpoint() require.Equal(t, primitives.Epoch(2), jc.Epoch) @@ -1485,7 +1564,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { require.NoError(t, err) preStateVersion, preStateHeader, err := getStateVersionAndPayload(preState) require.NoError(t, err) - _, err = service.validateExecutionOnBlock(ctx, preStateVersion, preStateHeader, wsb, root) + rowsb, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + _, err = service.validateExecutionOnBlock(ctx, preStateVersion, preStateHeader, rowsb) require.ErrorContains(t, "received an INVALID payload from execution engine", err) // Check that forkchoice's head and store's headroot are the previous head (since the invalid block did // not finish importing and it was never imported to forkchoice). Check @@ -1513,7 +1594,9 @@ func TestStore_NoViableHead_NewPayload(t *testing.T) { postState, err = service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, true}) + roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true}) require.NoError(t, err) // Check the newly imported block is head, it justified the right // checkpoint and the node is no longer optimistic @@ -1578,7 +1661,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) } for i := 6; i < 12; i++ { @@ -1597,7 +1682,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) } @@ -1616,7 +1703,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, lastValidRoot, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, lastValidRoot, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, lastValidRoot) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) // save the post state and the payload Hash of this block since it will // be the LVH @@ -1643,7 +1732,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, invalidRoots[i-13], wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, invalidRoots[i-13], [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, invalidRoots[i-13]) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) } // Check that we have justified the second epoch @@ -1669,7 +1760,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { require.NoError(t, err) preStateVersion, preStateHeader, err := getStateVersionAndPayload(preState) require.NoError(t, err) - _, err = service.validateExecutionOnBlock(ctx, preStateVersion, preStateHeader, wsb, root) + rowsb, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + _, err = service.validateExecutionOnBlock(ctx, preStateVersion, preStateHeader, rowsb) require.ErrorContains(t, "received an INVALID payload from execution engine", err) // Check that forkchoice's head and store's headroot are the previous head (since the invalid block did @@ -1708,7 +1801,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { postState, err = service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, true})) + roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true})) // Check that the head is still INVALID and the node is still optimistic require.Equal(t, invalidHeadRoot, service.cfg.ForkChoiceStore.CachedHeadRoot()) optimistic, err = service.IsOptimistic(ctx) @@ -1731,7 +1826,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, true}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true}) require.NoError(t, err) st, err = service.cfg.StateGen.StateByRoot(ctx, root) require.NoError(t, err) @@ -1757,7 +1854,9 @@ func TestStore_NoViableHead_Liveness(t *testing.T) { postState, err = service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, true}) + roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, true}) require.NoError(t, err) require.Equal(t, root, service.cfg.ForkChoiceStore.CachedHeadRoot()) sjc = service.CurrentJustifiedCheckpt() @@ -1813,7 +1912,9 @@ func TestNoViableHead_Reboot(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) } for i := 6; i < 12; i++ { @@ -1831,7 +1932,9 @@ func TestNoViableHead_Reboot(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) } @@ -1850,7 +1953,9 @@ func TestNoViableHead_Reboot(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, lastValidRoot, wsb, postState)) - err = service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, lastValidRoot, [32]byte{}, postState, false}) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, lastValidRoot) + require.NoError(t, err) + err = service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false}) require.NoError(t, err) // save the post state and the payload Hash of this block since it will // be the LVH @@ -1879,7 +1984,9 @@ func TestNoViableHead_Reboot(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) require.NoError(t, service.updateJustificationOnBlock(ctx, preState, postState, currStoreJustifiedEpoch)) _, err = service.updateFinalizationOnBlock(ctx, preState, postState, currStoreFinalizedEpoch) require.NoError(t, err) @@ -1905,7 +2012,9 @@ func TestNoViableHead_Reboot(t *testing.T) { require.NoError(t, err) preStateVersion, preStateHeader, err := getStateVersionAndPayload(preState) require.NoError(t, err) - _, err = service.validateExecutionOnBlock(ctx, preStateVersion, preStateHeader, wsb, root) + rowsb, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + _, err = service.validateExecutionOnBlock(ctx, preStateVersion, preStateHeader, rowsb) require.ErrorContains(t, "received an INVALID payload from execution engine", err) // Check that the headroot/state are not in DB and restart the node @@ -1995,7 +2104,9 @@ func TestOnBlock_HandleBlockAttestations(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) st, err = service.HeadState(ctx) require.NoError(t, err) @@ -2044,7 +2155,11 @@ func TestOnBlock_HandleBlockAttestations(t *testing.T) { st, err = service.HeadState(ctx) require.NoError(t, err) - b, err := util.GenerateFullBlockElectra(st, keys, util.DefaultBlockGenConfig(), 1) + defaultConfig := util.DefaultBlockGenConfig() + defaultConfig.NumWithdrawalRequests = 1 + defaultConfig.NumDepositRequests = 2 + defaultConfig.NumConsolidationRequests = 1 + b, err := util.GenerateFullBlockElectra(st, keys, defaultConfig, 1) require.NoError(t, err) wsb, err := consensusblocks.NewSignedBeaconBlock(b) require.NoError(t, err) @@ -2055,11 +2170,13 @@ func TestOnBlock_HandleBlockAttestations(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, root, [32]byte{}, postState, false})) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) st, err = service.HeadState(ctx) require.NoError(t, err) - b, err = util.GenerateFullBlockElectra(st, keys, util.DefaultBlockGenConfig(), 2) + b, err = util.GenerateFullBlockElectra(st, keys, defaultConfig, 2) require.NoError(t, err) wsb, err = consensusblocks.NewSignedBeaconBlock(b) require.NoError(t, err) @@ -2067,7 +2184,7 @@ func TestOnBlock_HandleBlockAttestations(t *testing.T) { // prepare another block that is not inserted st3, err := transition.ExecuteStateTransition(ctx, st, wsb) require.NoError(t, err) - b3, err := util.GenerateFullBlockElectra(st3, keys, util.DefaultBlockGenConfig(), 3) + b3, err := util.GenerateFullBlockElectra(st3, keys, defaultConfig, 3) require.NoError(t, err) wsb3, err := consensusblocks.NewSignedBeaconBlock(b3) require.NoError(t, err) @@ -2131,23 +2248,23 @@ func TestMissingIndices(t *testing.T) { }, { name: "expected exceeds max", - expected: fakeCommitments(fieldparams.MaxBlobsPerBlock + 1), + expected: fakeCommitments(params.BeaconConfig().MaxBlobsPerBlock(0) + 1), err: errMaxBlobsExceeded, }, { name: "first missing", - expected: fakeCommitments(fieldparams.MaxBlobsPerBlock), + expected: fakeCommitments(params.BeaconConfig().MaxBlobsPerBlock(0)), present: []uint64{1, 2, 3, 4, 5}, result: fakeResult([]uint64{0}), }, { name: "all missing", - expected: fakeCommitments(fieldparams.MaxBlobsPerBlock), + expected: fakeCommitments(params.BeaconConfig().MaxBlobsPerBlock(0)), result: fakeResult([]uint64{0, 1, 2, 3, 4, 5}), }, { name: "none missing", - expected: fakeCommitments(fieldparams.MaxBlobsPerBlock), + expected: fakeCommitments(params.BeaconConfig().MaxBlobsPerBlock(0)), present: []uint64{0, 1, 2, 3, 4, 5}, result: fakeResult([]uint64{}), }, @@ -2180,8 +2297,8 @@ func TestMissingIndices(t *testing.T) { for _, c := range cases { bm, bs := filesystem.NewEphemeralBlobStorageWithMocker(t) t.Run(c.name, func(t *testing.T) { - require.NoError(t, bm.CreateFakeIndices(c.root, c.present...)) - missing, err := missingIndices(bs, c.root, c.expected) + require.NoError(t, bm.CreateFakeIndices(c.root, 0, c.present...)) + missing, err := missingIndices(bs, c.root, c.expected, 0) if c.err != nil { require.ErrorIs(t, err, c.err) return @@ -2205,11 +2322,11 @@ func Test_getFCUArgs(t *testing.T) { require.NoError(t, err) wsb, err := consensusblocks.NewSignedBeaconBlock(b) require.NoError(t, err) - + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, [32]byte{'a'}) + require.NoError(t, err) cfg := &postBlockProcessConfig{ ctx: ctx, - signed: wsb, - blockRoot: [32]byte{'a'}, + roblock: roblock, postState: st, isValidPayload: true, } @@ -2219,11 +2336,199 @@ func Test_getFCUArgs(t *testing.T) { require.ErrorContains(t, "block does not exist", err) // canonical branch - cfg.headRoot = cfg.blockRoot + cfg.headRoot = cfg.roblock.Root() fcuArgs = &fcuConfig{} err = s.getFCUArgs(cfg, fcuArgs) require.NoError(t, err) - require.Equal(t, cfg.blockRoot, fcuArgs.headRoot) + require.Equal(t, cfg.roblock.Root(), fcuArgs.headRoot) +} + +func TestRollbackBlock(t *testing.T) { + service, tr := minimalTestService(t) + ctx := tr.ctx + + st, keys := util.DeterministicGenesisState(t, 64) + stateRoot, err := st.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + require.NoError(t, service.saveGenesisData(ctx, st)) + + genesis := blocks.NewGenesisBlock(stateRoot[:]) + wsb, err := consensusblocks.NewSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wsb), "Could not save genesis block") + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st, parentRoot), "Could not save genesis state") + require.NoError(t, service.cfg.BeaconDB.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + st, err = service.HeadState(ctx) + require.NoError(t, err) + b, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), 1) + require.NoError(t, err) + wsb, err = consensusblocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + root, err := b.Block.HashTreeRoot() + require.NoError(t, err) + preState, err := service.getBlockPreState(ctx, wsb.Block()) + require.NoError(t, err) + postState, err := service.validateStateTransition(ctx, preState, wsb) + require.NoError(t, err) + require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) + + require.Equal(t, true, service.cfg.BeaconDB.HasBlock(ctx, root)) + hasState, err := service.cfg.StateGen.HasState(ctx, root) + require.NoError(t, err) + require.Equal(t, true, hasState) + + // Set invalid parent root to trigger forkchoice error. + wsb.SetParentRoot([]byte("bad")) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + + // Rollback block insertion into db and caches. + require.ErrorContains(t, fmt.Sprintf("could not insert block %d to fork choice store", roblock.Block().Slot()), service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + + // The block should no longer exist. + require.Equal(t, false, service.cfg.BeaconDB.HasBlock(ctx, root)) + hasState, err = service.cfg.StateGen.HasState(ctx, root) + require.NoError(t, err) + require.Equal(t, false, hasState) +} + +func TestRollbackBlock_SavePostStateInfo_ContextDeadline(t *testing.T) { + service, tr := minimalTestService(t) + ctx := tr.ctx + + st, keys := util.DeterministicGenesisState(t, 64) + stateRoot, err := st.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + require.NoError(t, service.saveGenesisData(ctx, st)) + + genesis := blocks.NewGenesisBlock(stateRoot[:]) + wsb, err := consensusblocks.NewSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wsb), "Could not save genesis block") + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st, parentRoot), "Could not save genesis state") + require.NoError(t, service.cfg.BeaconDB.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + require.NoError(t, service.cfg.BeaconDB.SaveJustifiedCheckpoint(ctx, ðpb.Checkpoint{Root: parentRoot[:]})) + require.NoError(t, service.cfg.BeaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Root: parentRoot[:]})) + + st, err = service.HeadState(ctx) + require.NoError(t, err) + b, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), 128) + require.NoError(t, err) + wsb, err = consensusblocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + root, err := b.Block.HashTreeRoot() + require.NoError(t, err) + preState, err := service.getBlockPreState(ctx, wsb.Block()) + require.NoError(t, err) + postState, err := service.validateStateTransition(ctx, preState, wsb) + require.NoError(t, err) + + // Save state summaries so that the cache is flushed and saved to disk + // later. + for i := 1; i <= 127; i++ { + require.NoError(t, service.cfg.BeaconDB.SaveStateSummary(ctx, ðpb.StateSummary{ + Slot: primitives.Slot(i), + Root: bytesutil.Bytes32(uint64(i)), + })) + } + + // Set deadlined context when saving block and state + cancCtx, canc := context.WithCancel(ctx) + canc() + + require.ErrorContains(t, context.Canceled.Error(), service.savePostStateInfo(cancCtx, root, wsb, postState)) + + // The block should no longer exist. + require.Equal(t, false, service.cfg.BeaconDB.HasBlock(ctx, root)) + hasState, err := service.cfg.StateGen.HasState(ctx, root) + require.NoError(t, err) + require.Equal(t, false, hasState) +} + +func TestRollbackBlock_ContextDeadline(t *testing.T) { + service, tr := minimalTestService(t) + ctx := tr.ctx + + st, keys := util.DeterministicGenesisState(t, 64) + stateRoot, err := st.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + require.NoError(t, service.saveGenesisData(ctx, st)) + + genesis := blocks.NewGenesisBlock(stateRoot[:]) + wsb, err := consensusblocks.NewSignedBeaconBlock(genesis) + require.NoError(t, err) + require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wsb), "Could not save genesis block") + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, service.cfg.BeaconDB.SaveState(ctx, st, parentRoot), "Could not save genesis state") + require.NoError(t, service.cfg.BeaconDB.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + require.NoError(t, service.cfg.BeaconDB.SaveJustifiedCheckpoint(ctx, ðpb.Checkpoint{Root: parentRoot[:]})) + require.NoError(t, service.cfg.BeaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Root: parentRoot[:]})) + + st, err = service.HeadState(ctx) + require.NoError(t, err) + b, err := util.GenerateFullBlock(st, keys, util.DefaultBlockGenConfig(), 33) + require.NoError(t, err) + wsb, err = consensusblocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + root, err := b.Block.HashTreeRoot() + require.NoError(t, err) + preState, err := service.getBlockPreState(ctx, wsb.Block()) + require.NoError(t, err) + postState, err := service.validateStateTransition(ctx, preState, wsb) + require.NoError(t, err) + require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) + + b, err = util.GenerateFullBlock(postState, keys, util.DefaultBlockGenConfig(), 34) + require.NoError(t, err) + wsb, err = consensusblocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + root, err = b.Block.HashTreeRoot() + require.NoError(t, err) + preState, err = service.getBlockPreState(ctx, wsb.Block()) + require.NoError(t, err) + postState, err = service.validateStateTransition(ctx, preState, wsb) + require.NoError(t, err) + require.NoError(t, service.savePostStateInfo(ctx, root, wsb, postState)) + + require.Equal(t, true, service.cfg.BeaconDB.HasBlock(ctx, root)) + hasState, err := service.cfg.StateGen.HasState(ctx, root) + require.NoError(t, err) + require.Equal(t, true, hasState) + + // Set deadlined context when processing the block + cancCtx, canc := context.WithCancel(context.Background()) + canc() + roblock, err = consensusblocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + + parentRoot = roblock.Block().ParentRoot() + + cj := ðpb.Checkpoint{} + cj.Epoch = 1 + cj.Root = parentRoot[:] + require.NoError(t, postState.SetCurrentJustifiedCheckpoint(cj)) + require.NoError(t, postState.SetFinalizedCheckpoint(cj)) + + // Rollback block insertion into db and caches. + require.ErrorContains(t, "context canceled", service.postBlockProcess(&postBlockProcessConfig{cancCtx, roblock, [32]byte{}, postState, false})) + + // The block should no longer exist. + require.Equal(t, false, service.cfg.BeaconDB.HasBlock(ctx, root)) + hasState, err = service.cfg.StateGen.HasState(ctx, root) + require.NoError(t, err) + require.Equal(t, false, hasState) } func fakeCommitments(n int) [][]byte { @@ -2241,3 +2546,605 @@ func fakeResult(missing []uint64) map[uint64]struct{} { } return r } + +func TestSaveLightClientUpdate(t *testing.T) { + featCfg := &features.Flags{} + featCfg.EnableLightClient = true + reset := features.InitWithReset(featCfg) + + s, tr := minimalTestService(t) + ctx := tr.ctx + + t.Run("Altair", func(t *testing.T) { + t.Run("No old update", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().AltairForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + s.saveLightClientUpdate(cfg) + + // Check that the light client update is saved + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + attestedStateRoot, err := l.AttestedState.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, attestedStateRoot, [32]byte(u.AttestedHeader().Beacon().StateRoot)) + require.Equal(t, u.Version(), version.Altair) + }) + + t.Run("New update is better", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().AltairForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + + // create and save old update + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) + require.NoError(t, err) + + s.saveLightClientUpdate(cfg) + + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + attestedStateRoot, err := l.AttestedState.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, attestedStateRoot, [32]byte(u.AttestedHeader().Beacon().StateRoot)) + require.Equal(t, u.Version(), version.Altair) + }) + + t.Run("Old update is better", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().AltairForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + + // create and save old update + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + require.NoError(t, err) + + scb := make([]byte, 64) + for i := 0; i < 5; i++ { + scb[i] = 0x01 + } + oldUpdate.SetSyncAggregate(ðpb.SyncAggregate{ + SyncCommitteeBits: scb, + SyncCommitteeSignature: make([]byte, 96), + }) + + err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) + require.NoError(t, err) + + s.saveLightClientUpdate(cfg) + + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + require.DeepEqual(t, oldUpdate, u) + require.Equal(t, u.Version(), version.Altair) + }) + }) + + t.Run("Capella", func(t *testing.T) { + t.Run("No old update", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().CapellaForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + s.saveLightClientUpdate(cfg) + + // Check that the light client update is saved + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + attestedStateRoot, err := l.AttestedState.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, attestedStateRoot, [32]byte(u.AttestedHeader().Beacon().StateRoot)) + require.Equal(t, u.Version(), version.Capella) + }) + + t.Run("New update is better", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().CapellaForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + + // create and save old update + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) + require.NoError(t, err) + + s.saveLightClientUpdate(cfg) + + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + attestedStateRoot, err := l.AttestedState.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, attestedStateRoot, [32]byte(u.AttestedHeader().Beacon().StateRoot)) + require.Equal(t, u.Version(), version.Capella) + }) + + t.Run("Old update is better", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().CapellaForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + + // create and save old update + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + require.NoError(t, err) + + scb := make([]byte, 64) + for i := 0; i < 5; i++ { + scb[i] = 0x01 + } + oldUpdate.SetSyncAggregate(ðpb.SyncAggregate{ + SyncCommitteeBits: scb, + SyncCommitteeSignature: make([]byte, 96), + }) + + err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) + require.NoError(t, err) + + s.saveLightClientUpdate(cfg) + + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + require.DeepEqual(t, oldUpdate, u) + require.Equal(t, u.Version(), version.Capella) + }) + }) + + t.Run("Deneb", func(t *testing.T) { + t.Run("No old update", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().DenebForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + s.saveLightClientUpdate(cfg) + + // Check that the light client update is saved + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + attestedStateRoot, err := l.AttestedState.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, attestedStateRoot, [32]byte(u.AttestedHeader().Beacon().StateRoot)) + require.Equal(t, u.Version(), version.Deneb) + }) + + t.Run("New update is better", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().DenebForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + + // create and save old update + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) + require.NoError(t, err) + + s.saveLightClientUpdate(cfg) + + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + attestedStateRoot, err := l.AttestedState.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, attestedStateRoot, [32]byte(u.AttestedHeader().Beacon().StateRoot)) + require.Equal(t, u.Version(), version.Deneb) + }) + + t.Run("Old update is better", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().DenebForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + err := s.cfg.BeaconDB.SaveBlock(ctx, l.AttestedBlock) + require.NoError(t, err) + attestedBlockRoot, err := l.AttestedBlock.Block().HashTreeRoot() + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.AttestedState, attestedBlockRoot) + require.NoError(t, err) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, l.FinalizedBlock) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + period := slots.SyncCommitteePeriod(slots.ToEpoch(l.AttestedState.Slot())) + + // create and save old update + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(s.CurrentSlot(), l.AttestedState) + require.NoError(t, err) + + scb := make([]byte, 64) + for i := 0; i < 5; i++ { + scb[i] = 0x01 + } + oldUpdate.SetSyncAggregate(ðpb.SyncAggregate{ + SyncCommitteeBits: scb, + SyncCommitteeSignature: make([]byte, 96), + }) + + err = s.cfg.BeaconDB.SaveLightClientUpdate(ctx, period, oldUpdate) + require.NoError(t, err) + + s.saveLightClientUpdate(cfg) + + u, err := s.cfg.BeaconDB.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.NotNil(t, u) + require.DeepEqual(t, oldUpdate, u) + require.Equal(t, u.Version(), version.Deneb) + }) + }) + + reset() +} + +func TestSaveLightClientBootstrap(t *testing.T) { + featCfg := &features.Flags{} + featCfg.EnableLightClient = true + reset := features.InitWithReset(featCfg) + + s, tr := minimalTestService(t) + ctx := tr.ctx + + t.Run("Altair", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().AltairForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + s.saveLightClientBootstrap(cfg) + + // Check that the light client bootstrap is saved + b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:]) + require.NoError(t, err) + require.NotNil(t, b) + + stateRoot, err := l.State.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, stateRoot, [32]byte(b.Header().Beacon().StateRoot)) + require.Equal(t, b.Version(), version.Altair) + }) + + t.Run("Capella", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().CapellaForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + s.saveLightClientBootstrap(cfg) + + // Check that the light client bootstrap is saved + b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:]) + require.NoError(t, err) + require.NotNil(t, b) + + stateRoot, err := l.State.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, stateRoot, [32]byte(b.Header().Beacon().StateRoot)) + require.Equal(t, b.Version(), version.Capella) + }) + + t.Run("Deneb", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) + + s.genesisTime = time.Unix(time.Now().Unix()-(int64(params.BeaconConfig().DenebForkEpoch)*int64(params.BeaconConfig().SlotsPerEpoch)*int64(params.BeaconConfig().SecondsPerSlot)), 0) + + currentBlockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(l.Block, currentBlockRoot) + require.NoError(t, err) + + err = s.cfg.BeaconDB.SaveBlock(ctx, roblock) + require.NoError(t, err) + err = s.cfg.BeaconDB.SaveState(ctx, l.State, currentBlockRoot) + require.NoError(t, err) + + cfg := &postBlockProcessConfig{ + ctx: ctx, + roblock: roblock, + postState: l.State, + isValidPayload: true, + } + + s.saveLightClientBootstrap(cfg) + + // Check that the light client bootstrap is saved + b, err := s.cfg.BeaconDB.LightClientBootstrap(ctx, currentBlockRoot[:]) + require.NoError(t, err) + require.NotNil(t, b) + + stateRoot, err := l.State.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, stateRoot, [32]byte(b.Header().Beacon().StateRoot)) + require.Equal(t, b.Version(), version.Deneb) + }) + + reset() +} diff --git a/beacon-chain/blockchain/receive_attestation.go b/beacon-chain/blockchain/receive_attestation.go index 89f344383cf6..a3666d847126 100644 --- a/beacon-chain/blockchain/receive_attestation.go +++ b/beacon-chain/blockchain/receive_attestation.go @@ -9,13 +9,15 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // reorgLateBlockCountAttestations is the time until the end of the slot in which we count @@ -165,7 +167,13 @@ func (s *Service) UpdateHead(ctx context.Context, proposingSlot primitives.Slot) // This processes fork choice attestations from the pool to account for validator votes and fork choice. func (s *Service) processAttestations(ctx context.Context, disparity time.Duration) { - atts := s.cfg.AttPool.ForkchoiceAttestations() + var atts []ethpb.Att + if features.Get().EnableExperimentalAttestationPool { + atts = s.cfg.AttestationCache.ForkchoiceAttestations() + } else { + atts = s.cfg.AttPool.ForkchoiceAttestations() + } + for _, a := range atts { // Based on the spec, don't process the attestation until the subsequent slot. // This delays consideration in the fork choice until their slot is in the past. @@ -181,7 +189,11 @@ func (s *Service) processAttestations(ctx context.Context, disparity time.Durati continue } - if err := s.cfg.AttPool.DeleteForkchoiceAttestation(a); err != nil { + if features.Get().EnableExperimentalAttestationPool { + if err := s.cfg.AttestationCache.DeleteForkchoiceAttestation(a); err != nil { + log.WithError(err).Error("Could not delete fork choice attestation in pool") + } + } else if err := s.cfg.AttPool.DeleteForkchoiceAttestation(a); err != nil { log.WithError(err).Error("Could not delete fork choice attestation in pool") } @@ -190,13 +202,26 @@ func (s *Service) processAttestations(ctx context.Context, disparity time.Durati } if err := s.receiveAttestationNoPubsub(ctx, a, disparity); err != nil { - log.WithFields(logrus.Fields{ - "slot": a.GetData().Slot, - "committeeIndex": a.GetData().CommitteeIndex, - "beaconBlockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.GetData().BeaconBlockRoot)), - "targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.GetData().Target.Root)), - "aggregationCount": a.GetAggregationBits().Count(), - }).WithError(err).Warn("Could not process attestation for fork choice") + var fields logrus.Fields + if a.Version() >= version.Electra { + fields = logrus.Fields{ + "slot": a.GetData().Slot, + "committeeCount": a.CommitteeBitsVal().Count(), + "committeeIndices": a.CommitteeBitsVal().BitIndices(), + "beaconBlockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.GetData().BeaconBlockRoot)), + "targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.GetData().Target.Root)), + "aggregatedCount": a.GetAggregationBits().Count(), + } + } else { + fields = logrus.Fields{ + "slot": a.GetData().Slot, + "committeeIndex": a.GetData().CommitteeIndex, + "beaconBlockRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.GetData().BeaconBlockRoot)), + "targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc(a.GetData().Target.Root)), + "aggregatedCount": a.GetAggregationBits().Count(), + } + } + log.WithFields(fields).WithError(err).Warn("Could not process attestation for fork choice") } } } diff --git a/beacon-chain/blockchain/receive_attestation_test.go b/beacon-chain/blockchain/receive_attestation_test.go index d0df3e1b23a0..0d4ec5698d88 100644 --- a/beacon-chain/blockchain/receive_attestation_test.go +++ b/beacon-chain/blockchain/receive_attestation_test.go @@ -46,7 +46,7 @@ func TestVerifyLMDFFGConsistent(t *testing.T) { require.NoError(t, err) require.NoError(t, f.InsertNode(ctx, state, r32)) - state, r33, err := prepareForkchoiceState(ctx, 33, [32]byte{'b'}, r32, params.BeaconConfig().ZeroHash, fc, fc) + state, r33, err := prepareForkchoiceState(ctx, 33, [32]byte{'b'}, r32.Root(), params.BeaconConfig().ZeroHash, fc, fc) require.NoError(t, err) require.NoError(t, f.InsertNode(ctx, state, r33)) @@ -54,10 +54,12 @@ func TestVerifyLMDFFGConsistent(t *testing.T) { a := util.NewAttestation() a.Data.Target.Epoch = 1 a.Data.Target.Root = []byte{'c'} - a.Data.BeaconBlockRoot = r33[:] + r33Root := r33.Root() + a.Data.BeaconBlockRoot = r33Root[:] require.ErrorContains(t, wanted, service.VerifyLmdFfgConsistency(context.Background(), a)) - a.Data.Target.Root = r32[:] + r32Root := r32.Root() + a.Data.Target.Root = r32Root[:] err = service.VerifyLmdFfgConsistency(context.Background(), a) require.NoError(t, err, "Could not verify LMD and FFG votes to be consistent") } @@ -84,9 +86,7 @@ func TestProcessAttestations_Ok(t *testing.T) { require.NoError(t, err) require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot)) attsToSave := make([]ethpb.Att, len(atts)) - for i, a := range atts { - attsToSave[i] = a - } + copy(attsToSave, atts) require.NoError(t, service.cfg.AttPool.SaveForkchoiceAttestations(attsToSave)) service.processAttestations(ctx, 0) require.Equal(t, 0, len(service.cfg.AttPool.ForkchoiceAttestations())) @@ -116,7 +116,9 @@ func TestService_ProcessAttestationsAndUpdateHead(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, tRoot, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, tRoot, [32]byte{}, postState, false})) + roblock, err := blocks.NewROBlockWithRoot(wsb, tRoot) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) copied, err = service.cfg.StateGen.StateByRoot(ctx, tRoot) require.NoError(t, err) require.Equal(t, 2, fcs.NodeCount()) @@ -126,9 +128,7 @@ func TestService_ProcessAttestationsAndUpdateHead(t *testing.T) { atts, err := util.GenerateAttestations(copied, pks, 1, 1, false) require.NoError(t, err) attsToSave := make([]ethpb.Att, len(atts)) - for i, a := range atts { - attsToSave[i] = a - } + copy(attsToSave, atts) require.NoError(t, service.cfg.AttPool.SaveForkchoiceAttestations(attsToSave)) // Verify the target is in forkchoice require.Equal(t, true, fcs.HasNode(bytesutil.ToBytes32(atts[0].GetData().BeaconBlockRoot))) @@ -176,7 +176,9 @@ func TestService_UpdateHead_NoAtts(t *testing.T) { postState, err := service.validateStateTransition(ctx, preState, wsb) require.NoError(t, err) require.NoError(t, service.savePostStateInfo(ctx, tRoot, wsb, postState)) - require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, wsb, tRoot, [32]byte{}, postState, false})) + roblock, err := blocks.NewROBlockWithRoot(wsb, tRoot) + require.NoError(t, err) + require.NoError(t, service.postBlockProcess(&postBlockProcessConfig{ctx, roblock, [32]byte{}, postState, false})) require.Equal(t, 2, fcs.NodeCount()) require.NoError(t, service.cfg.BeaconDB.SaveBlock(ctx, wsb)) require.Equal(t, tRoot, service.head.root) diff --git a/beacon-chain/blockchain/receive_blob.go b/beacon-chain/blockchain/receive_blob.go index e6d81dc48dd4..303130812149 100644 --- a/beacon-chain/blockchain/receive_blob.go +++ b/beacon-chain/blockchain/receive_blob.go @@ -4,12 +4,13 @@ import ( "context" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) // SendNewBlobEvent sends a message to the BlobNotifier channel that the blob // for the block root `root` is ready in the database -func (s *Service) sendNewBlobEvent(root [32]byte, index uint64) { - s.blobNotifiers.notifyIndex(root, index) +func (s *Service) sendNewBlobEvent(root [32]byte, index uint64, slot primitives.Slot) { + s.blobNotifiers.notifyIndex(root, index, slot) } // ReceiveBlob saves the blob to database and sends the new event @@ -18,6 +19,6 @@ func (s *Service) ReceiveBlob(ctx context.Context, b blocks.VerifiedROBlob) erro return err } - s.sendNewBlobEvent(b.BlockRoot(), b.Index) + s.sendNewBlobEvent(b.BlockRoot(), b.Index, b.Slot()) return nil } diff --git a/beacon-chain/blockchain/receive_block.go b/beacon-chain/blockchain/receive_block.go index e439de0badd4..64c5444569aa 100644 --- a/beacon-chain/blockchain/receive_block.go +++ b/beacon-chain/blockchain/receive_block.go @@ -7,6 +7,7 @@ import ( "time" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" @@ -21,12 +22,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" "golang.org/x/sync/errgroup" ) @@ -83,7 +84,12 @@ func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.ReadOnlySig } currentCheckpoints := s.saveCurrentCheckpoints(preState) - postState, isValidPayload, err := s.validateExecutionAndConsensus(ctx, preState, blockCopy, blockRoot) + roblock, err := blocks.NewROBlockWithRoot(blockCopy, blockRoot) + if err != nil { + return err + } + + postState, isValidPayload, err := s.validateExecutionAndConsensus(ctx, preState, roblock) if err != nil { return err } @@ -102,8 +108,7 @@ func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.ReadOnlySig } args := &postBlockProcessConfig{ ctx: ctx, - signed: blockCopy, - blockRoot: blockRoot, + roblock: roblock, postState: postState, isValidPayload: isValidPayload, } @@ -184,8 +189,7 @@ func (s *Service) updateCheckpoints( func (s *Service) validateExecutionAndConsensus( ctx context.Context, preState state.BeaconState, - block interfaces.SignedBeaconBlock, - blockRoot [32]byte, + block blocks.ROBlock, ) (state.BeaconState, bool, error) { preStateVersion, preStateHeader, err := getStateVersionAndPayload(preState) if err != nil { @@ -204,7 +208,7 @@ func (s *Service) validateExecutionAndConsensus( var isValidPayload bool eg.Go(func() error { var err error - isValidPayload, err = s.validateExecutionOnBlock(ctx, preStateVersion, preStateHeader, block, blockRoot) + isValidPayload, err = s.validateExecutionOnBlock(ctx, preStateVersion, preStateHeader, block) if err != nil { return errors.Wrap(err, "could not notify the engine of the new payload") } @@ -273,12 +277,12 @@ func (s *Service) reportPostBlockProcessing( func (s *Service) executePostFinalizationTasks(ctx context.Context, finalizedState state.BeaconState) { finalized := s.cfg.ForkChoiceStore.FinalizedCheckpoint() go func() { - finalizedState.SaveValidatorIndices() // used to handle Validator index invariant from EIP6110 s.sendNewFinalizedEvent(ctx, finalizedState) }() + depCtx, cancel := context.WithTimeout(context.Background(), depositDeadline) go func() { - s.insertFinalizedDeposits(depCtx, finalized.Root) + s.insertFinalizedDepositsAndPrune(depCtx, finalized.Root) cancel() }() } @@ -350,6 +354,9 @@ func (s *Service) ReceiveBlockBatch(ctx context.Context, blocks []blocks.ROBlock // HasBlock returns true if the block of the input root exists in initial sync blocks cache or DB. func (s *Service) HasBlock(ctx context.Context, root [32]byte) bool { + if s.BlockBeingSynced(root) { + return false + } return s.hasBlockInInitSyncOrDB(ctx, root) } @@ -463,6 +470,9 @@ func (s *Service) validateStateTransition(ctx context.Context, preState state.Be stateTransitionStartTime := time.Now() postState, err := transition.ExecuteStateTransition(ctx, preState, signed) if err != nil { + if ctx.Err() != nil || electra.IsExecutionRequestError(err) { + return nil, err + } return nil, invalidBlock{error: err} } stateTransitionProcessingTime.Observe(float64(time.Since(stateTransitionStartTime).Milliseconds())) @@ -553,16 +563,16 @@ func (s *Service) sendBlockAttestationsToSlasher(signed interfaces.ReadOnlySigne } // validateExecutionOnBlock notifies the engine of the incoming block execution payload and returns true if the payload is valid -func (s *Service) validateExecutionOnBlock(ctx context.Context, ver int, header interfaces.ExecutionData, signed interfaces.ReadOnlySignedBeaconBlock, blockRoot [32]byte) (bool, error) { - isValidPayload, err := s.notifyNewPayload(ctx, ver, header, signed) +func (s *Service) validateExecutionOnBlock(ctx context.Context, ver int, header interfaces.ExecutionData, block blocks.ROBlock) (bool, error) { + isValidPayload, err := s.notifyNewPayload(ctx, ver, header, block) if err != nil { s.cfg.ForkChoiceStore.Lock() - err = s.handleInvalidExecutionError(ctx, err, blockRoot, signed.Block().ParentRoot()) + err = s.handleInvalidExecutionError(ctx, err, block.Root(), block.Block().ParentRoot()) s.cfg.ForkChoiceStore.Unlock() return false, err } - if signed.Version() < version.Capella && isValidPayload { - if err := s.validateMergeTransitionBlock(ctx, ver, header, signed); err != nil { + if block.Block().Version() < version.Capella && isValidPayload { + if err := s.validateMergeTransitionBlock(ctx, ver, header, block); err != nil { return isValidPayload, err } } diff --git a/beacon-chain/blockchain/receive_block_test.go b/beacon-chain/blockchain/receive_block_test.go index 1fdcb196e450..1dae450b801b 100644 --- a/beacon-chain/blockchain/receive_block_test.go +++ b/beacon-chain/blockchain/receive_block_test.go @@ -278,6 +278,8 @@ func TestService_HasBlock(t *testing.T) { r, err = b.Block.HashTreeRoot() require.NoError(t, err) require.Equal(t, true, s.HasBlock(context.Background(), r)) + s.blockBeingSynced.set(r) + require.Equal(t, false, s.HasBlock(context.Background(), r)) } func TestCheckSaveHotStateDB_Enabling(t *testing.T) { @@ -453,41 +455,81 @@ func Test_executePostFinalizationTasks(t *testing.T) { Root: headRoot[:], })) require.NoError(t, headState.SetGenesisValidatorsRoot(params.BeaconConfig().ZeroHash[:])) + t.Run("pre deposit request", func(t *testing.T) { + require.NoError(t, headState.SetEth1DepositIndex(1)) + s, tr := minimalTestService(t, WithFinalizedStateAtStartUp(headState)) + ctx, beaconDB, stateGen := tr.ctx, tr.db, tr.sg + + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, genesisRoot)) + util.SaveBlock(t, ctx, beaconDB, genesis) + require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot)) + require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot)) + util.SaveBlock(t, ctx, beaconDB, headBlock) + require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(finalizedSlot), Root: headRoot[:]})) - s, tr := minimalTestService(t, WithFinalizedStateAtStartUp(headState)) - ctx, beaconDB, stateGen := tr.ctx, tr.db, tr.sg - - require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, genesisRoot)) - util.SaveBlock(t, ctx, beaconDB, genesis) - require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot)) - require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot)) - util.SaveBlock(t, ctx, beaconDB, headBlock) - require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(finalizedSlot), Root: headRoot[:]})) - - require.NoError(t, err) - require.NoError(t, stateGen.SaveState(ctx, headRoot, headState)) - require.NoError(t, beaconDB.SaveLastValidatedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(finalizedSlot), Root: headRoot[:]})) - - notifier := &blockchainTesting.MockStateNotifier{RecordEvents: true} - s.cfg.StateNotifier = notifier - s.executePostFinalizationTasks(s.ctx, headState) - - time.Sleep(1 * time.Second) // sleep for a second because event is in a separate go routine - require.Equal(t, 1, len(notifier.ReceivedEvents())) - e := notifier.ReceivedEvents()[0] - assert.Equal(t, statefeed.FinalizedCheckpoint, int(e.Type)) - fc, ok := e.Data.(*ethpbv1.EventFinalizedCheckpoint) - require.Equal(t, true, ok, "event has wrong data type") - assert.Equal(t, primitives.Epoch(123), fc.Epoch) - assert.DeepEqual(t, headRoot[:], fc.Block) - assert.DeepEqual(t, finalizedStRoot[:], fc.State) - assert.Equal(t, false, fc.ExecutionOptimistic) + require.NoError(t, err) + require.NoError(t, stateGen.SaveState(ctx, headRoot, headState)) + require.NoError(t, beaconDB.SaveLastValidatedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(finalizedSlot), Root: headRoot[:]})) + + notifier := &blockchainTesting.MockStateNotifier{RecordEvents: true} + s.cfg.StateNotifier = notifier + s.executePostFinalizationTasks(s.ctx, headState) + + time.Sleep(1 * time.Second) // sleep for a second because event is in a separate go routine + require.Equal(t, 1, len(notifier.ReceivedEvents())) + e := notifier.ReceivedEvents()[0] + assert.Equal(t, statefeed.FinalizedCheckpoint, int(e.Type)) + fc, ok := e.Data.(*ethpbv1.EventFinalizedCheckpoint) + require.Equal(t, true, ok, "event has wrong data type") + assert.Equal(t, primitives.Epoch(123), fc.Epoch) + assert.DeepEqual(t, headRoot[:], fc.Block) + assert.DeepEqual(t, finalizedStRoot[:], fc.State) + assert.Equal(t, false, fc.ExecutionOptimistic) + + // check the cache + index, ok := headState.ValidatorIndexByPubkey(bytesutil.ToBytes48(key)) + require.Equal(t, true, ok) + require.Equal(t, primitives.ValidatorIndex(0), index) // first index + + // check deposit + require.LogsContain(t, logHook, "Finalized deposit insertion completed at index") + }) + t.Run("deposit requests started", func(t *testing.T) { + require.NoError(t, headState.SetEth1DepositIndex(1)) + require.NoError(t, headState.SetDepositRequestsStartIndex(1)) + s, tr := minimalTestService(t, WithFinalizedStateAtStartUp(headState)) + ctx, beaconDB, stateGen := tr.ctx, tr.db, tr.sg + + require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, genesisRoot)) + util.SaveBlock(t, ctx, beaconDB, genesis) + require.NoError(t, beaconDB.SaveState(ctx, headState, headRoot)) + require.NoError(t, beaconDB.SaveState(ctx, headState, genesisRoot)) + util.SaveBlock(t, ctx, beaconDB, headBlock) + require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(finalizedSlot), Root: headRoot[:]})) - // check the cache - index, ok := headState.ValidatorIndexByPubkey(bytesutil.ToBytes48(key)) - require.Equal(t, true, ok) - require.Equal(t, primitives.ValidatorIndex(0), index) // first index + require.NoError(t, err) + require.NoError(t, stateGen.SaveState(ctx, headRoot, headState)) + require.NoError(t, beaconDB.SaveLastValidatedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(finalizedSlot), Root: headRoot[:]})) + + notifier := &blockchainTesting.MockStateNotifier{RecordEvents: true} + s.cfg.StateNotifier = notifier + s.executePostFinalizationTasks(s.ctx, headState) + + time.Sleep(1 * time.Second) // sleep for a second because event is in a separate go routine + require.Equal(t, 1, len(notifier.ReceivedEvents())) + e := notifier.ReceivedEvents()[0] + assert.Equal(t, statefeed.FinalizedCheckpoint, int(e.Type)) + fc, ok := e.Data.(*ethpbv1.EventFinalizedCheckpoint) + require.Equal(t, true, ok, "event has wrong data type") + assert.Equal(t, primitives.Epoch(123), fc.Epoch) + assert.DeepEqual(t, headRoot[:], fc.Block) + assert.DeepEqual(t, finalizedStRoot[:], fc.State) + assert.Equal(t, false, fc.ExecutionOptimistic) + + // check the cache + index, ok := headState.ValidatorIndexByPubkey(bytesutil.ToBytes48(key)) + require.Equal(t, true, ok) + require.Equal(t, primitives.ValidatorIndex(0), index) // first index + }) - // check deposit - require.LogsContain(t, logHook, "Finalized deposit insertion completed at index") } diff --git a/beacon-chain/blockchain/service.go b/beacon-chain/blockchain/service.go index efbc70c7941f..dbd7685714bd 100644 --- a/beacon-chain/blockchain/service.go +++ b/beacon-chain/blockchain/service.go @@ -33,40 +33,38 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen" "github.com/prysmaticlabs/prysm/v5/config/features" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" prysmTime "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // Service represents a service that handles the internal // logic of managing the full PoS beacon chain. type Service struct { - cfg *config - ctx context.Context - cancel context.CancelFunc - genesisTime time.Time - head *head - headLock sync.RWMutex - originBlockRoot [32]byte // genesis root, or weak subjectivity checkpoint root, depending on how the node is initialized - boundaryRoots [][32]byte - checkpointStateCache *cache.CheckpointStateCache - initSyncBlocks map[[32]byte]interfaces.ReadOnlySignedBeaconBlock - initSyncBlocksLock sync.RWMutex - wsVerifier *WeakSubjectivityVerifier - clockSetter startup.ClockSetter - clockWaiter startup.ClockWaiter - syncComplete chan struct{} - blobNotifiers *blobNotifierMap - blockBeingSynced *currentlySyncingBlock - blobStorage *filesystem.BlobStorage - lastPublishedLightClientEpoch primitives.Epoch + cfg *config + ctx context.Context + cancel context.CancelFunc + genesisTime time.Time + head *head + headLock sync.RWMutex + originBlockRoot [32]byte // genesis root, or weak subjectivity checkpoint root, depending on how the node is initialized + boundaryRoots [][32]byte + checkpointStateCache *cache.CheckpointStateCache + initSyncBlocks map[[32]byte]interfaces.ReadOnlySignedBeaconBlock + initSyncBlocksLock sync.RWMutex + wsVerifier *WeakSubjectivityVerifier + clockSetter startup.ClockSetter + clockWaiter startup.ClockWaiter + syncComplete chan struct{} + blobNotifiers *blobNotifierMap + blockBeingSynced *currentlySyncingBlock + blobStorage *filesystem.BlobStorage } // config options for the service. @@ -77,6 +75,7 @@ type config struct { DepositCache cache.DepositCache PayloadIDCache *cache.PayloadIDCache TrackedValidatorsCache *cache.TrackedValidatorsCache + AttestationCache *cache.AttestationCache AttPool attestations.Pool ExitPool voluntaryexits.PoolManager SlashingPool slashings.PoolManager @@ -106,18 +105,22 @@ var ErrMissingClockSetter = errors.New("blockchain Service initialized without a type blobNotifierMap struct { sync.RWMutex notifiers map[[32]byte]chan uint64 - seenIndex map[[32]byte][fieldparams.MaxBlobsPerBlock]bool + seenIndex map[[32]byte][]bool } // notifyIndex notifies a blob by its index for a given root. // It uses internal maps to keep track of seen indices and notifier channels. -func (bn *blobNotifierMap) notifyIndex(root [32]byte, idx uint64) { - if idx >= fieldparams.MaxBlobsPerBlock { +func (bn *blobNotifierMap) notifyIndex(root [32]byte, idx uint64, slot primitives.Slot) { + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(slot) + if idx >= uint64(maxBlobsPerBlock) { return } bn.Lock() seen := bn.seenIndex[root] + if seen == nil { + seen = make([]bool, maxBlobsPerBlock) + } if seen[idx] { bn.Unlock() return @@ -128,7 +131,7 @@ func (bn *blobNotifierMap) notifyIndex(root [32]byte, idx uint64) { // Retrieve or create the notifier channel for the given root. c, ok := bn.notifiers[root] if !ok { - c = make(chan uint64, fieldparams.MaxBlobsPerBlock) + c = make(chan uint64, maxBlobsPerBlock) bn.notifiers[root] = c } @@ -137,12 +140,13 @@ func (bn *blobNotifierMap) notifyIndex(root [32]byte, idx uint64) { c <- idx } -func (bn *blobNotifierMap) forRoot(root [32]byte) chan uint64 { +func (bn *blobNotifierMap) forRoot(root [32]byte, slot primitives.Slot) chan uint64 { + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(slot) bn.Lock() defer bn.Unlock() c, ok := bn.notifiers[root] if !ok { - c = make(chan uint64, fieldparams.MaxBlobsPerBlock) + c = make(chan uint64, maxBlobsPerBlock) bn.notifiers[root] = c } return c @@ -168,7 +172,7 @@ func NewService(ctx context.Context, opts ...Option) (*Service, error) { ctx, cancel := context.WithCancel(ctx) bn := &blobNotifierMap{ notifiers: make(map[[32]byte]chan uint64), - seenIndex: make(map[[32]byte][fieldparams.MaxBlobsPerBlock]bool), + seenIndex: make(map[[32]byte][]bool), } srv := &Service{ ctx: ctx, @@ -303,7 +307,15 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error { if err != nil { return errors.Wrap(err, "could not get finalized checkpoint state") } - if err := s.cfg.ForkChoiceStore.InsertNode(s.ctx, st, fRoot); err != nil { + finalizedBlock, err := s.cfg.BeaconDB.Block(s.ctx, fRoot) + if err != nil { + return errors.Wrap(err, "could not get finalized checkpoint block") + } + roblock, err := blocks.NewROBlockWithRoot(finalizedBlock, fRoot) + if err != nil { + return err + } + if err := s.cfg.ForkChoiceStore.InsertNode(s.ctx, st, roblock); err != nil { return errors.Wrap(err, "could not insert finalized block to forkchoice") } if !features.Get().EnableStartOptimistic { @@ -329,8 +341,6 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error { return errors.Wrap(err, "failed to initialize blockchain service") } - saved.SaveValidatorIndices() // used to handle Validator index invariant from EIP6110 - return nil } @@ -517,7 +527,11 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState state.Beacon s.cfg.ForkChoiceStore.Lock() defer s.cfg.ForkChoiceStore.Unlock() - if err := s.cfg.ForkChoiceStore.InsertNode(ctx, genesisState, genesisBlkRoot); err != nil { + gb, err := blocks.NewROBlockWithRoot(genesisBlk, genesisBlkRoot) + if err != nil { + return err + } + if err := s.cfg.ForkChoiceStore.InsertNode(ctx, genesisState, gb); err != nil { log.WithError(err).Fatal("Could not process genesis block for fork choice") } s.cfg.ForkChoiceStore.SetOriginRoot(genesisBlkRoot) diff --git a/beacon-chain/blockchain/service_test.go b/beacon-chain/blockchain/service_test.go index a2bf18ac1485..fee2705842fc 100644 --- a/beacon-chain/blockchain/service_test.go +++ b/beacon-chain/blockchain/service_test.go @@ -376,11 +376,15 @@ func TestHasBlock_ForkChoiceAndDB_DoublyLinkedTree(t *testing.T) { cfg: &config{ForkChoiceStore: doublylinkedtree.New(), BeaconDB: beaconDB}, } b := util.NewBeaconBlock() + wsb, err := consensusblocks.NewSignedBeaconBlock(b) + require.NoError(t, err) r, err := b.Block.HashTreeRoot() require.NoError(t, err) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, r) + require.NoError(t, err) beaconState, err := util.NewBeaconState() require.NoError(t, err) - require.NoError(t, s.cfg.ForkChoiceStore.InsertNode(ctx, beaconState, r)) + require.NoError(t, s.cfg.ForkChoiceStore.InsertNode(ctx, beaconState, roblock)) assert.Equal(t, false, s.hasBlock(ctx, [32]byte{}), "Should not have block") assert.Equal(t, true, s.hasBlock(ctx, r), "Should have block") @@ -453,7 +457,11 @@ func BenchmarkHasBlockForkChoiceStore_DoublyLinkedTree(b *testing.B) { require.NoError(b, err) beaconState, err := util.NewBeaconState() require.NoError(b, err) - require.NoError(b, s.cfg.ForkChoiceStore.InsertNode(ctx, beaconState, r)) + wsb, err := consensusblocks.NewSignedBeaconBlock(blk) + require.NoError(b, err) + roblock, err := consensusblocks.NewROBlockWithRoot(wsb, r) + require.NoError(b, err) + require.NoError(b, s.cfg.ForkChoiceStore.InsertNode(ctx, beaconState, roblock)) b.ResetTimer() for i := 0; i < b.N; i++ { @@ -579,7 +587,7 @@ func (s *MockClockSetter) SetClock(g *startup.Clock) error { func TestNotifyIndex(t *testing.T) { // Initialize a blobNotifierMap bn := &blobNotifierMap{ - seenIndex: make(map[[32]byte][fieldparams.MaxBlobsPerBlock]bool), + seenIndex: make(map[[32]byte][]bool), notifiers: make(map[[32]byte]chan uint64), } @@ -588,7 +596,7 @@ func TestNotifyIndex(t *testing.T) { copy(root[:], "exampleRoot") // Test notifying a new index - bn.notifyIndex(root, 1) + bn.notifyIndex(root, 1, 1) if !bn.seenIndex[root][1] { t.Errorf("Index was not marked as seen") } @@ -599,13 +607,13 @@ func TestNotifyIndex(t *testing.T) { } // Test notifying an already seen index - bn.notifyIndex(root, 1) + bn.notifyIndex(root, 1, 1) if len(bn.notifiers[root]) > 1 { t.Errorf("Notifier channel should not receive multiple messages for the same index") } // Test notifying a new index again - bn.notifyIndex(root, 2) + bn.notifyIndex(root, 2, 1) if !bn.seenIndex[root][2] { t.Errorf("Index was not marked as seen") } diff --git a/beacon-chain/blockchain/setup_test.go b/beacon-chain/blockchain/setup_test.go index 22acd22147c8..f21ddc69155d 100644 --- a/beacon-chain/blockchain/setup_test.go +++ b/beacon-chain/blockchain/setup_test.go @@ -32,7 +32,7 @@ type mockBeaconNode struct { } // StateFeed mocks the same method in the beacon node. -func (mbn *mockBeaconNode) StateFeed() *event.Feed { +func (mbn *mockBeaconNode) StateFeed() event.SubscriberSender { mbn.mu.Lock() defer mbn.mu.Unlock() if mbn.stateFeed == nil { diff --git a/beacon-chain/blockchain/testing/mock.go b/beacon-chain/blockchain/testing/mock.go index d0da4f0cd07b..92edfa23a9a7 100644 --- a/beacon-chain/blockchain/testing/mock.go +++ b/beacon-chain/blockchain/testing/mock.go @@ -98,6 +98,44 @@ func (s *ChainService) BlockNotifier() blockfeed.Notifier { return s.blockNotifier } +type EventFeedWrapper struct { + feed *event.Feed + subscribed chan struct{} // this channel is closed once a subscription is made +} + +func (w *EventFeedWrapper) Subscribe(channel interface{}) event.Subscription { + select { + case <-w.subscribed: + break // already closed + default: + close(w.subscribed) + } + return w.feed.Subscribe(channel) +} + +func (w *EventFeedWrapper) Send(value interface{}) int { + return w.feed.Send(value) +} + +// WaitForSubscription allows test to wait for the feed to have a subscription before beginning to send events. +func (w *EventFeedWrapper) WaitForSubscription(ctx context.Context) error { + select { + case <-w.subscribed: + return nil + case <-ctx.Done(): + return ctx.Err() + } +} + +var _ event.SubscriberSender = &EventFeedWrapper{} + +func NewEventFeedWrapper() *EventFeedWrapper { + return &EventFeedWrapper{ + feed: new(event.Feed), + subscribed: make(chan struct{}), + } +} + // MockBlockNotifier mocks the block notifier. type MockBlockNotifier struct { feed *event.Feed @@ -131,7 +169,7 @@ func (msn *MockStateNotifier) ReceivedEvents() []*feed.Event { } // StateFeed returns a state feed. -func (msn *MockStateNotifier) StateFeed() *event.Feed { +func (msn *MockStateNotifier) StateFeed() event.SubscriberSender { msn.feedLock.Lock() defer msn.feedLock.Unlock() @@ -159,6 +197,23 @@ func (msn *MockStateNotifier) StateFeed() *event.Feed { return msn.feed } +// NewSimpleStateNotifier makes a state feed without the custom mock feed machinery. +func NewSimpleStateNotifier() *MockStateNotifier { + return &MockStateNotifier{feed: new(event.Feed)} +} + +type SimpleNotifier struct { + Feed event.SubscriberSender +} + +func (n *SimpleNotifier) StateFeed() event.SubscriberSender { + return n.Feed +} + +func (n *SimpleNotifier) OperationFeed() event.SubscriberSender { + return n.Feed +} + // OperationNotifier mocks the same method in the chain service. func (s *ChainService) OperationNotifier() opfeed.Notifier { if s.opNotifier == nil { @@ -173,7 +228,7 @@ type MockOperationNotifier struct { } // OperationFeed returns an operation feed. -func (mon *MockOperationNotifier) OperationFeed() *event.Feed { +func (mon *MockOperationNotifier) OperationFeed() event.SubscriberSender { if mon.feed == nil { mon.feed = new(event.Feed) } @@ -512,7 +567,7 @@ func prepareForkchoiceState( payloadHash [32]byte, justified *ethpb.Checkpoint, finalized *ethpb.Checkpoint, -) (state.BeaconState, [32]byte, error) { +) (state.BeaconState, blocks.ROBlock, error) { blockHeader := ðpb.BeaconBlockHeader{ ParentRoot: parentRoot[:], } @@ -533,7 +588,26 @@ func prepareForkchoiceState( base.BlockRoots[0] = append(base.BlockRoots[0], blockRoot[:]...) st, err := state_native.InitializeFromProtoBellatrix(base) - return st, blockRoot, err + if err != nil { + return nil, blocks.ROBlock{}, err + } + blk := ðpb.SignedBeaconBlockBellatrix{ + Block: ðpb.BeaconBlockBellatrix{ + Slot: slot, + ParentRoot: parentRoot[:], + Body: ðpb.BeaconBlockBodyBellatrix{ + ExecutionPayload: &enginev1.ExecutionPayload{ + BlockHash: payloadHash[:], + }, + }, + }, + } + signed, err := blocks.NewSignedBeaconBlock(blk) + if err != nil { + return nil, blocks.ROBlock{}, err + } + roblock, err := blocks.NewROBlockWithRoot(signed, blockRoot) + return st, roblock, err } // CachedHeadRoot mocks the same method in the chain service @@ -576,9 +650,9 @@ func (s *ChainService) HighestReceivedBlockSlot() primitives.Slot { } // InsertNode mocks the same method in the chain service -func (s *ChainService) InsertNode(ctx context.Context, st state.BeaconState, root [32]byte) error { +func (s *ChainService) InsertNode(ctx context.Context, st state.BeaconState, block blocks.ROBlock) error { if s.ForkChoiceStore != nil { - return s.ForkChoiceStore.InsertNode(ctx, st, root) + return s.ForkChoiceStore.InsertNode(ctx, st, block) } return nil } diff --git a/beacon-chain/builder/BUILD.bazel b/beacon-chain/builder/BUILD.bazel index 3e14089a4b30..f115fbeb845b 100644 --- a/beacon-chain/builder/BUILD.bazel +++ b/beacon-chain/builder/BUILD.bazel @@ -19,6 +19,7 @@ go_library( "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_pkg_errors//:go_default_library", @@ -26,7 +27,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/builder/service.go b/beacon-chain/builder/service.go index 0f227d6b2e53..b2098193eba7 100644 --- a/beacon-chain/builder/service.go +++ b/beacon-chain/builder/service.go @@ -14,10 +14,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" log "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // ErrNoBuilder is used when builder endpoint is not configured. diff --git a/beacon-chain/builder/testing/mock.go b/beacon-chain/builder/testing/mock.go index e1c1d913aff8..8465de7712d4 100644 --- a/beacon-chain/builder/testing/mock.go +++ b/beacon-chain/builder/testing/mock.go @@ -33,6 +33,7 @@ type MockBuilderService struct { Bid *ethpb.SignedBuilderBid BidCapella *ethpb.SignedBuilderBidCapella BidDeneb *ethpb.SignedBuilderBidDeneb + BidElectra *ethpb.SignedBuilderBidElectra RegistrationCache *cache.RegistrationCache ErrGetHeader error ErrRegisterValidator error @@ -59,7 +60,7 @@ func (s *MockBuilderService) SubmitBlindedBlock(_ context.Context, b interfaces. return nil, nil, errors.Wrap(err, "could not wrap capella payload") } return w, nil, s.ErrSubmitBlindedBlock - case version.Deneb: + case version.Deneb, version.Electra: w, err := blocks.WrappedExecutionPayloadDeneb(s.PayloadDeneb) if err != nil { return nil, nil, errors.Wrap(err, "could not wrap deneb payload") @@ -72,6 +73,9 @@ func (s *MockBuilderService) SubmitBlindedBlock(_ context.Context, b interfaces. // GetHeader for mocking. func (s *MockBuilderService) GetHeader(_ context.Context, slot primitives.Slot, _ [32]byte, _ [48]byte) (builder.SignedBid, error) { + if slots.ToEpoch(slot) >= params.BeaconConfig().ElectraForkEpoch || s.BidElectra != nil { + return builder.WrappedSignedBuilderBidElectra(s.BidElectra) + } if slots.ToEpoch(slot) >= params.BeaconConfig().DenebForkEpoch || s.BidDeneb != nil { return builder.WrappedSignedBuilderBidDeneb(s.BidDeneb) } diff --git a/beacon-chain/cache/BUILD.bazel b/beacon-chain/cache/BUILD.bazel index 8a0b9d7a99f0..633060a7e1a0 100644 --- a/beacon-chain/cache/BUILD.bazel +++ b/beacon-chain/cache/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "active_balance.go", "active_balance_disabled.go", # keep + "attestation.go", "attestation_data.go", "balance_cache_key.go", "checkpoint_state.go", @@ -36,17 +37,21 @@ go_library( ], deps = [ "//beacon-chain/forkchoice/types:go_default_library", + "//beacon-chain/operations/attestations/attmap:go_default_library", "//beacon-chain/state:go_default_library", "//cache/lru:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//container/slice:go_default_library", + "//crypto/bls:go_default_library", "//crypto/hash:go_default_library", "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//math:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//proto/prysm/v1alpha1/attestation:go_default_library", "//runtime/version:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_hashicorp_golang_lru//:go_default_library", @@ -56,7 +61,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_k8s_client_go//tools/cache:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -66,6 +70,7 @@ go_test( srcs = [ "active_balance_test.go", "attestation_data_test.go", + "attestation_test.go", "cache_test.go", "checkpoint_state_test.go", "committee_fuzz_test.go", @@ -79,6 +84,7 @@ go_test( "sync_committee_head_state_test.go", "sync_committee_test.go", "sync_subnet_ids_test.go", + "tracked_validators_test.go", ], embed = [":go_default_library"], deps = [ @@ -88,14 +94,17 @@ go_test( "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", + "//crypto/bls/blst:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//proto/prysm/v1alpha1/attestation:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_google_gofuzz//:go_default_library", "@com_github_hashicorp_golang_lru//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_stretchr_testify//require:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], diff --git a/beacon-chain/cache/attestation.go b/beacon-chain/cache/attestation.go new file mode 100644 index 000000000000..817ddef5680f --- /dev/null +++ b/beacon-chain/cache/attestation.go @@ -0,0 +1,275 @@ +package cache + +import ( + "sync" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations/attmap" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/crypto/bls" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" + log "github.com/sirupsen/logrus" +) + +type attGroup struct { + slot primitives.Slot + atts []ethpb.Att +} + +// AttestationCache holds a map of attGroup items that group together all attestations for a single slot. +// When we add an attestation to the cache by calling Add, we either create a new group with this attestation +// (if this is the first attestation for some slot) or two things can happen: +// +// - If the attestation is unaggregated, we add its attestation bit to attestation bits of the first +// attestation in the group. +// - If the attestation is aggregated, we append it to the group. There should be no redundancy +// in the list because we ignore redundant aggregates in gossip. +// +// The first bullet point above means that we keep one aggregate attestation to which we keep appending bits +// as new single-bit attestations arrive. This means that at any point during seconds 0-4 of a slot +// we will have only one attestation for this slot in the cache. +// +// NOTE: This design in principle can result in worse aggregates since we lose the ability to aggregate some +// single bit attestations in case of overlaps with incoming aggregates. +// +// The cache also keeps forkchoice attestations in a separate struct. These attestations are used for +// forkchoice-related operations. +type AttestationCache struct { + atts map[attestation.Id]*attGroup + sync.RWMutex + forkchoiceAtts *attmap.Attestations +} + +// NewAttestationCache creates a new cache instance. +func NewAttestationCache() *AttestationCache { + return &AttestationCache{ + atts: make(map[attestation.Id]*attGroup), + forkchoiceAtts: attmap.New(), + } +} + +// Add does one of two things: +// +// - For unaggregated attestations, it adds the attestation bit to attestation bits of the running aggregate, +// which is the first aggregate for the slot. +// - For aggregated attestations, it appends the attestation to the existing list of attestations for the slot. +func (c *AttestationCache) Add(att ethpb.Att) error { + if att.IsNil() { + log.Debug("Attempted to add a nil attestation to the attestation cache") + return nil + } + if len(att.GetAggregationBits().BitIndices()) == 0 { + log.Debug("Attempted to add an attestation with 0 bits set to the attestation cache") + return nil + } + + c.Lock() + defer c.Unlock() + + id, err := attestation.NewId(att, attestation.Data) + if err != nil { + return errors.Wrapf(err, "could not create attestation ID") + } + + group := c.atts[id] + if group == nil { + group = &attGroup{ + slot: att.GetData().Slot, + atts: []ethpb.Att{att}, + } + c.atts[id] = group + return nil + } + + if att.IsAggregated() { + group.atts = append(group.atts, att.Clone()) + return nil + } + + // This should never happen because we return early for a new group. + if len(group.atts) == 0 { + log.Error("Attestation group contains no attestations, skipping insertion") + return nil + } + + a := group.atts[0] + + // Indexing is safe because we have guarded against 0 bits set. + bit := att.GetAggregationBits().BitIndices()[0] + if a.GetAggregationBits().BitAt(uint64(bit)) { + return nil + } + sig, err := aggregateSig(a, att) + if err != nil { + return errors.Wrapf(err, "could not aggregate signatures") + } + + a.GetAggregationBits().SetBitAt(uint64(bit), true) + a.SetSignature(sig) + + return nil +} + +// GetAll returns all attestations in the cache, excluding forkchoice attestations. +func (c *AttestationCache) GetAll() []ethpb.Att { + c.RLock() + defer c.RUnlock() + + var result []ethpb.Att + for _, group := range c.atts { + result = append(result, group.atts...) + } + return result +} + +// Count returns the number of all attestations in the cache, excluding forkchoice attestations. +func (c *AttestationCache) Count() int { + c.RLock() + defer c.RUnlock() + + count := 0 + for _, group := range c.atts { + count += len(group.atts) + } + return count +} + +// DeleteCovered removes all attestations whose attestation bits are a proper subset of the passed-in attestation. +func (c *AttestationCache) DeleteCovered(att ethpb.Att) error { + if att.IsNil() { + return nil + } + + c.Lock() + defer c.Unlock() + + id, err := attestation.NewId(att, attestation.Data) + if err != nil { + return errors.Wrapf(err, "could not create attestation ID") + } + + group := c.atts[id] + if group == nil { + return nil + } + + idx := 0 + for _, a := range group.atts { + if covered, err := att.GetAggregationBits().Contains(a.GetAggregationBits()); err != nil { + return err + } else if !covered { + group.atts[idx] = a + idx++ + } + } + group.atts = group.atts[:idx] + + if len(group.atts) == 0 { + delete(c.atts, id) + } + + return nil +} + +// PruneBefore removes all attestations whose slot is earlier than the passed-in slot. +func (c *AttestationCache) PruneBefore(slot primitives.Slot) uint64 { + c.Lock() + defer c.Unlock() + + var pruneCount int + for id, group := range c.atts { + if group.slot < slot { + pruneCount += len(group.atts) + delete(c.atts, id) + } + } + return uint64(pruneCount) +} + +// AggregateIsRedundant checks whether all attestation bits of the passed-in aggregate +// are already included by any aggregate in the cache. +func (c *AttestationCache) AggregateIsRedundant(att ethpb.Att) (bool, error) { + if att.IsNil() { + return true, nil + } + + c.RLock() + defer c.RUnlock() + + id, err := attestation.NewId(att, attestation.Data) + if err != nil { + return true, errors.Wrapf(err, "could not create attestation ID") + } + + group := c.atts[id] + if group == nil { + return false, nil + } + + for _, a := range group.atts { + if redundant, err := a.GetAggregationBits().Contains(att.GetAggregationBits()); err != nil { + return true, err + } else if redundant { + return true, nil + } + } + + return false, nil +} + +// SaveForkchoiceAttestations saves forkchoice attestations. +func (c *AttestationCache) SaveForkchoiceAttestations(att []ethpb.Att) error { + return c.forkchoiceAtts.SaveMany(att) +} + +// ForkchoiceAttestations returns all forkchoice attestations. +func (c *AttestationCache) ForkchoiceAttestations() []ethpb.Att { + return c.forkchoiceAtts.GetAll() +} + +// DeleteForkchoiceAttestation deletes a forkchoice attestation. +func (c *AttestationCache) DeleteForkchoiceAttestation(att ethpb.Att) error { + return c.forkchoiceAtts.Delete(att) +} + +// GetBySlotAndCommitteeIndex returns all attestations in the cache that match the provided slot +// and committee index. Forkchoice attestations are not returned. +// +// NOTE: This function cannot be declared as a method on the AttestationCache because it is a generic function. +func GetBySlotAndCommitteeIndex[T ethpb.Att](c *AttestationCache, slot primitives.Slot, committeeIndex primitives.CommitteeIndex) []T { + c.RLock() + defer c.RUnlock() + + var result []T + + for _, group := range c.atts { + if len(group.atts) > 0 { + // We can safely compare the first attestation because all attestations in a group + // must have the same slot and committee index, since they are under the same key. + a, ok := group.atts[0].(T) + if ok && a.GetData().Slot == slot && a.CommitteeBitsVal().BitAt(uint64(committeeIndex)) { + for _, a := range group.atts { + a, ok := a.(T) + if ok { + result = append(result, a) + } + } + } + } + } + + return result +} + +func aggregateSig(agg ethpb.Att, att ethpb.Att) ([]byte, error) { + aggSig, err := bls.SignatureFromBytesNoValidation(agg.GetSignature()) + if err != nil { + return nil, err + } + attSig, err := bls.SignatureFromBytesNoValidation(att.GetSignature()) + if err != nil { + return nil, err + } + return bls.AggregateSignatures([]bls.Signature{aggSig, attSig}).Marshal(), nil +} diff --git a/beacon-chain/cache/attestation_data.go b/beacon-chain/cache/attestation_data.go index f2529d97a0d2..d4f4a25da2dc 100644 --- a/beacon-chain/cache/attestation_data.go +++ b/beacon-chain/cache/attestation_data.go @@ -15,24 +15,24 @@ type AttestationConsensusData struct { Source forkchoicetypes.Checkpoint } -// AttestationCache stores cached results of AttestationData requests. -type AttestationCache struct { +// AttestationDataCache stores cached results of AttestationData requests. +type AttestationDataCache struct { a *AttestationConsensusData sync.RWMutex } -// NewAttestationCache creates a new instance of AttestationCache. -func NewAttestationCache() *AttestationCache { - return &AttestationCache{} +// NewAttestationDataCache creates a new instance of AttestationDataCache. +func NewAttestationDataCache() *AttestationDataCache { + return &AttestationDataCache{} } // Get retrieves cached attestation data, recording a cache hit or miss. This method is lock free. -func (c *AttestationCache) Get() *AttestationConsensusData { +func (c *AttestationDataCache) Get() *AttestationConsensusData { return c.a } // Put adds a response to the cache. This method is lock free. -func (c *AttestationCache) Put(a *AttestationConsensusData) error { +func (c *AttestationDataCache) Put(a *AttestationConsensusData) error { if a == nil { return errors.New("attestation cannot be nil") } diff --git a/beacon-chain/cache/attestation_data_test.go b/beacon-chain/cache/attestation_data_test.go index 05ddc9403fff..a4d170ec166b 100644 --- a/beacon-chain/cache/attestation_data_test.go +++ b/beacon-chain/cache/attestation_data_test.go @@ -9,7 +9,7 @@ import ( ) func TestAttestationCache_RoundTrip(t *testing.T) { - c := cache.NewAttestationCache() + c := cache.NewAttestationDataCache() a := c.Get() require.Nil(t, a) diff --git a/beacon-chain/cache/attestation_test.go b/beacon-chain/cache/attestation_test.go new file mode 100644 index 000000000000..1f3419ea05a5 --- /dev/null +++ b/beacon-chain/cache/attestation_test.go @@ -0,0 +1,353 @@ +package cache + +import ( + "testing" + + "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/crypto/bls/blst" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +func TestAdd(t *testing.T) { + k, err := blst.RandKey() + require.NoError(t, err) + sig := k.Sign([]byte{'X'}) + + t.Run("new ID", func(t *testing.T) { + t.Run("first ID ever", func(t *testing.T) { + c := NewAttestationCache() + ab := bitfield.NewBitlist(8) + ab.SetBitAt(0, true) + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: ab, + Signature: sig.Marshal(), + } + id, err := attestation.NewId(att, attestation.Data) + require.NoError(t, err) + require.NoError(t, c.Add(att)) + + require.Equal(t, 1, len(c.atts)) + group, ok := c.atts[id] + require.Equal(t, true, ok) + assert.Equal(t, primitives.Slot(123), group.slot) + require.Equal(t, 1, len(group.atts)) + assert.DeepEqual(t, group.atts[0], att) + }) + t.Run("other ID exists", func(t *testing.T) { + c := NewAttestationCache() + ab := bitfield.NewBitlist(8) + ab.SetBitAt(0, true) + existingAtt := ðpb.Attestation{ + Data: ðpb.AttestationData{BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: ab, + Signature: sig.Marshal(), + } + existingId, err := attestation.NewId(existingAtt, attestation.Data) + require.NoError(t, err) + c.atts[existingId] = &attGroup{slot: existingAtt.Data.Slot, atts: []ethpb.Att{existingAtt}} + + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: ab, + Signature: sig.Marshal(), + } + id, err := attestation.NewId(att, attestation.Data) + require.NoError(t, err) + require.NoError(t, c.Add(att)) + + require.Equal(t, 2, len(c.atts)) + group, ok := c.atts[id] + require.Equal(t, true, ok) + assert.Equal(t, primitives.Slot(123), group.slot) + require.Equal(t, 1, len(group.atts)) + assert.DeepEqual(t, group.atts[0], att) + }) + }) + t.Run("aggregated", func(t *testing.T) { + c := NewAttestationCache() + existingAtt := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + id, err := attestation.NewId(existingAtt, attestation.Data) + require.NoError(t, err) + c.atts[id] = &attGroup{slot: existingAtt.Data.Slot, atts: []ethpb.Att{existingAtt}} + + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + att.AggregationBits.SetBitAt(1, true) + require.NoError(t, c.Add(att)) + + require.Equal(t, 1, len(c.atts)) + group, ok := c.atts[id] + require.Equal(t, true, ok) + assert.Equal(t, primitives.Slot(123), group.slot) + require.Equal(t, 2, len(group.atts)) + assert.DeepEqual(t, group.atts[0], existingAtt) + assert.DeepEqual(t, group.atts[1], att) + }) + t.Run("unaggregated - existing bit", func(t *testing.T) { + c := NewAttestationCache() + existingAtt := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + existingAtt.AggregationBits.SetBitAt(0, true) + id, err := attestation.NewId(existingAtt, attestation.Data) + require.NoError(t, err) + c.atts[id] = &attGroup{slot: existingAtt.Data.Slot, atts: []ethpb.Att{existingAtt}} + + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + require.NoError(t, c.Add(att)) + + require.Equal(t, 1, len(c.atts)) + group, ok := c.atts[id] + require.Equal(t, true, ok) + assert.Equal(t, primitives.Slot(123), group.slot) + require.Equal(t, 1, len(group.atts)) + assert.DeepEqual(t, []int{0}, group.atts[0].GetAggregationBits().BitIndices()) + }) + t.Run("unaggregated - new bit", func(t *testing.T) { + c := NewAttestationCache() + existingAtt := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + existingAtt.AggregationBits.SetBitAt(0, true) + id, err := attestation.NewId(existingAtt, attestation.Data) + require.NoError(t, err) + c.atts[id] = &attGroup{slot: existingAtt.Data.Slot, atts: []ethpb.Att{existingAtt}} + + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(1, true) + require.NoError(t, c.Add(att)) + + require.Equal(t, 1, len(c.atts)) + group, ok := c.atts[id] + require.Equal(t, true, ok) + assert.Equal(t, primitives.Slot(123), group.slot) + require.Equal(t, 1, len(group.atts)) + assert.DeepEqual(t, []int{0, 1}, group.atts[0].GetAggregationBits().BitIndices()) + }) +} + +func TestGetAll(t *testing.T) { + c := NewAttestationCache() + c.atts[bytesutil.ToBytes32([]byte("id1"))] = &attGroup{atts: []ethpb.Att{ðpb.Attestation{}, ðpb.Attestation{}}} + c.atts[bytesutil.ToBytes32([]byte("id2"))] = &attGroup{atts: []ethpb.Att{ðpb.Attestation{}}} + + assert.Equal(t, 3, len(c.GetAll())) +} + +func TestCount(t *testing.T) { + c := NewAttestationCache() + c.atts[bytesutil.ToBytes32([]byte("id1"))] = &attGroup{atts: []ethpb.Att{ðpb.Attestation{}, ðpb.Attestation{}}} + c.atts[bytesutil.ToBytes32([]byte("id2"))] = &attGroup{atts: []ethpb.Att{ðpb.Attestation{}}} + + assert.Equal(t, 3, c.Count()) +} + +func TestDeleteCovered(t *testing.T) { + k, err := blst.RandKey() + require.NoError(t, err) + sig := k.Sign([]byte{'X'}) + + att1 := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att1.AggregationBits.SetBitAt(0, true) + + att2 := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att2.AggregationBits.SetBitAt(1, true) + att2.AggregationBits.SetBitAt(2, true) + + att3 := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att3.AggregationBits.SetBitAt(1, true) + att3.AggregationBits.SetBitAt(3, true) + att3.AggregationBits.SetBitAt(4, true) + + c := NewAttestationCache() + id, err := attestation.NewId(att1, attestation.Data) + require.NoError(t, err) + c.atts[id] = &attGroup{slot: att1.Data.Slot, atts: []ethpb.Att{att1, att2, att3}} + + t.Run("no matching group", func(t *testing.T) { + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 456, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + att.AggregationBits.SetBitAt(1, true) + att.AggregationBits.SetBitAt(2, true) + att.AggregationBits.SetBitAt(3, true) + att.AggregationBits.SetBitAt(4, true) + require.NoError(t, c.DeleteCovered(att)) + + assert.Equal(t, 3, len(c.atts[id].atts)) + }) + t.Run("covered atts deleted", func(t *testing.T) { + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + att.AggregationBits.SetBitAt(1, true) + att.AggregationBits.SetBitAt(3, true) + att.AggregationBits.SetBitAt(4, true) + require.NoError(t, c.DeleteCovered(att)) + + atts := c.atts[id].atts + require.Equal(t, 1, len(atts)) + assert.DeepEqual(t, att2, atts[0]) + }) + t.Run("last att in group deleted", func(t *testing.T) { + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + att.AggregationBits.SetBitAt(1, true) + att.AggregationBits.SetBitAt(2, true) + att.AggregationBits.SetBitAt(3, true) + att.AggregationBits.SetBitAt(4, true) + require.NoError(t, c.DeleteCovered(att)) + + assert.Equal(t, 0, len(c.atts)) + }) +} + +func TestPruneBefore(t *testing.T) { + c := NewAttestationCache() + c.atts[bytesutil.ToBytes32([]byte("id1"))] = &attGroup{slot: 1, atts: []ethpb.Att{ðpb.Attestation{}, ðpb.Attestation{}}} + c.atts[bytesutil.ToBytes32([]byte("id2"))] = &attGroup{slot: 3, atts: []ethpb.Att{ðpb.Attestation{}}} + c.atts[bytesutil.ToBytes32([]byte("id3"))] = &attGroup{slot: 2, atts: []ethpb.Att{ðpb.Attestation{}}} + + count := c.PruneBefore(3) + + require.Equal(t, 1, len(c.atts)) + _, ok := c.atts[bytesutil.ToBytes32([]byte("id2"))] + assert.Equal(t, true, ok) + assert.Equal(t, uint64(3), count) +} + +func TestAggregateIsRedundant(t *testing.T) { + k, err := blst.RandKey() + require.NoError(t, err) + sig := k.Sign([]byte{'X'}) + + c := NewAttestationCache() + existingAtt := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 123, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + existingAtt.AggregationBits.SetBitAt(0, true) + existingAtt.AggregationBits.SetBitAt(1, true) + id, err := attestation.NewId(existingAtt, attestation.Data) + require.NoError(t, err) + c.atts[id] = &attGroup{slot: existingAtt.Data.Slot, atts: []ethpb.Att{existingAtt}} + + t.Run("no matching group", func(t *testing.T) { + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: 456, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + + redundant, err := c.AggregateIsRedundant(att) + require.NoError(t, err) + assert.Equal(t, false, redundant) + }) + t.Run("redundant", func(t *testing.T) { + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: existingAtt.Data.Slot, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + + redundant, err := c.AggregateIsRedundant(att) + require.NoError(t, err) + assert.Equal(t, true, redundant) + }) + t.Run("not redundant", func(t *testing.T) { + t.Run("strictly better", func(t *testing.T) { + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: existingAtt.Data.Slot, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + att.AggregationBits.SetBitAt(1, true) + att.AggregationBits.SetBitAt(2, true) + + redundant, err := c.AggregateIsRedundant(att) + require.NoError(t, err) + assert.Equal(t, false, redundant) + }) + t.Run("overlapping and new bits", func(t *testing.T) { + att := ðpb.Attestation{ + Data: ðpb.AttestationData{Slot: existingAtt.Data.Slot, BeaconBlockRoot: make([]byte, 32), Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, + AggregationBits: bitfield.NewBitlist(8), + Signature: sig.Marshal(), + } + att.AggregationBits.SetBitAt(0, true) + att.AggregationBits.SetBitAt(2, true) + + redundant, err := c.AggregateIsRedundant(att) + require.NoError(t, err) + assert.Equal(t, false, redundant) + }) + }) +} + +func TestGetBySlotAndCommitteeIndex(t *testing.T) { + c := NewAttestationCache() + c.atts[bytesutil.ToBytes32([]byte("id1"))] = &attGroup{slot: 1, atts: []ethpb.Att{ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1, CommitteeIndex: 1}}, ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1, CommitteeIndex: 1}}}} + c.atts[bytesutil.ToBytes32([]byte("id2"))] = &attGroup{slot: 2, atts: []ethpb.Att{ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 2}}}} + c.atts[bytesutil.ToBytes32([]byte("id3"))] = &attGroup{slot: 1, atts: []ethpb.Att{ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 2}}}} + + // committeeIndex has to be small enough to fit in the bitvector + atts := GetBySlotAndCommitteeIndex[*ethpb.Attestation](c, 1, 1) + require.Equal(t, 2, len(atts)) + assert.Equal(t, primitives.Slot(1), atts[0].Data.Slot) + assert.Equal(t, primitives.Slot(1), atts[1].Data.Slot) + assert.Equal(t, primitives.CommitteeIndex(1), atts[0].Data.CommitteeIndex) + assert.Equal(t, primitives.CommitteeIndex(1), atts[1].Data.CommitteeIndex) +} diff --git a/beacon-chain/cache/cache_test.go b/beacon-chain/cache/cache_test.go index df4bf4b2f53d..faf441456192 100644 --- a/beacon-chain/cache/cache_test.go +++ b/beacon-chain/cache/cache_test.go @@ -1,9 +1,10 @@ package cache import ( + "os" "testing" ) func TestMain(m *testing.M) { - m.Run() + os.Exit(m.Run()) } diff --git a/beacon-chain/cache/common.go b/beacon-chain/cache/common.go index be1950c16544..5eff08f49e23 100644 --- a/beacon-chain/cache/common.go +++ b/beacon-chain/cache/common.go @@ -17,6 +17,6 @@ func trim(queue *cache.FIFO, maxSize uint64) { } // popProcessNoopFunc is a no-op function that never returns an error. -func popProcessNoopFunc(_ interface{}) error { +func popProcessNoopFunc(_ interface{}, _ bool) error { return nil } diff --git a/beacon-chain/cache/depositsnapshot/BUILD.bazel b/beacon-chain/cache/depositsnapshot/BUILD.bazel index c300f81f31fa..12a1835540b9 100644 --- a/beacon-chain/cache/depositsnapshot/BUILD.bazel +++ b/beacon-chain/cache/depositsnapshot/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "deposit_fetcher.go", "deposit_inserter.go", + "deposit_pruner.go", "deposit_tree.go", "deposit_tree_snapshot.go", "merkle_tree.go", @@ -19,6 +20,7 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//math:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_pkg_errors//:go_default_library", @@ -26,7 +28,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_wealdtech_go_bytesutil//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -35,6 +36,7 @@ go_test( srcs = [ "deposit_cache_test.go", "deposit_fetcher_test.go", + "deposit_pruner_test.go", "deposit_tree_snapshot_test.go", "merkle_tree_test.go", "spec_test.go", diff --git a/beacon-chain/cache/depositsnapshot/deposit_cache_test.go b/beacon-chain/cache/depositsnapshot/deposit_cache_test.go index 2c17e8428b5c..34e2cae987a8 100644 --- a/beacon-chain/cache/depositsnapshot/deposit_cache_test.go +++ b/beacon-chain/cache/depositsnapshot/deposit_cache_test.go @@ -903,189 +903,6 @@ func TestMin(t *testing.T) { } -func TestPruneProofs_Ok(t *testing.T) { - dc, err := New() - require.NoError(t, err) - - deposits := []struct { - blkNum uint64 - deposit *ethpb.Deposit - index int64 - }{ - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, - index: 0, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, - index: 1, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, - index: 2, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, - index: 3, - }, - } - - for _, ins := range deposits { - assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) - } - - require.NoError(t, dc.PruneProofs(context.Background(), 1)) - - assert.DeepEqual(t, [][]byte(nil), dc.deposits[0].Deposit.Proof) - assert.DeepEqual(t, [][]byte(nil), dc.deposits[1].Deposit.Proof) - assert.NotNil(t, dc.deposits[2].Deposit.Proof) - assert.NotNil(t, dc.deposits[3].Deposit.Proof) -} - -func TestPruneProofs_SomeAlreadyPruned(t *testing.T) { - dc, err := New() - require.NoError(t, err) - - deposits := []struct { - blkNum uint64 - deposit *ethpb.Deposit - index int64 - }{ - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: nil, Data: ðpb.Deposit_Data{ - PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, - index: 0, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: nil, Data: ðpb.Deposit_Data{ - PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, index: 1, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, - index: 2, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, - index: 3, - }, - } - - for _, ins := range deposits { - assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) - } - - require.NoError(t, dc.PruneProofs(context.Background(), 2)) - - assert.DeepEqual(t, [][]byte(nil), dc.deposits[2].Deposit.Proof) -} - -func TestPruneProofs_PruneAllWhenDepositIndexTooBig(t *testing.T) { - dc, err := New() - require.NoError(t, err) - - deposits := []struct { - blkNum uint64 - deposit *ethpb.Deposit - index int64 - }{ - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, - index: 0, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, - index: 1, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, - index: 2, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, - index: 3, - }, - } - - for _, ins := range deposits { - assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) - } - - require.NoError(t, dc.PruneProofs(context.Background(), 99)) - - assert.DeepEqual(t, [][]byte(nil), dc.deposits[0].Deposit.Proof) - assert.DeepEqual(t, [][]byte(nil), dc.deposits[1].Deposit.Proof) - assert.DeepEqual(t, [][]byte(nil), dc.deposits[2].Deposit.Proof) - assert.DeepEqual(t, [][]byte(nil), dc.deposits[3].Deposit.Proof) -} - -func TestPruneProofs_CorrectlyHandleLastIndex(t *testing.T) { - dc, err := New() - require.NoError(t, err) - - deposits := []struct { - blkNum uint64 - deposit *ethpb.Deposit - index int64 - }{ - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, - index: 0, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, - index: 1, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, - index: 2, - }, - { - blkNum: 0, - deposit: ðpb.Deposit{Proof: makeDepositProof(), - Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, - index: 3, - }, - } - - for _, ins := range deposits { - assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) - } - - require.NoError(t, dc.PruneProofs(context.Background(), 4)) - - assert.DeepEqual(t, [][]byte(nil), dc.deposits[0].Deposit.Proof) - assert.DeepEqual(t, [][]byte(nil), dc.deposits[1].Deposit.Proof) - assert.DeepEqual(t, [][]byte(nil), dc.deposits[2].Deposit.Proof) - assert.DeepEqual(t, [][]byte(nil), dc.deposits[3].Deposit.Proof) -} - func TestDepositMap_WorksCorrectly(t *testing.T) { dc, err := New() require.NoError(t, err) diff --git a/beacon-chain/cache/depositsnapshot/deposit_fetcher.go b/beacon-chain/cache/depositsnapshot/deposit_fetcher.go index 2cf862765ea7..088e480bcf7f 100644 --- a/beacon-chain/cache/depositsnapshot/deposit_fetcher.go +++ b/beacon-chain/cache/depositsnapshot/deposit_fetcher.go @@ -10,10 +10,10 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/sirupsen/logrus" "github.com/wealdtech/go-bytesutil" - "go.opencensus.io/trace" ) var ( @@ -178,52 +178,6 @@ func (c *Cache) NonFinalizedDeposits(ctx context.Context, lastFinalizedIndex int return deposits } -// PruneProofs removes proofs from all deposits whose index is equal or less than untilDepositIndex. -func (c *Cache) PruneProofs(ctx context.Context, untilDepositIndex int64) error { - _, span := trace.StartSpan(ctx, "Cache.PruneProofs") - defer span.End() - c.depositsLock.Lock() - defer c.depositsLock.Unlock() - - if untilDepositIndex >= int64(len(c.deposits)) { - untilDepositIndex = int64(len(c.deposits) - 1) - } - - for i := untilDepositIndex; i >= 0; i-- { - // Finding a nil proof means that all proofs up to this deposit have been already pruned. - if c.deposits[i].Deposit.Proof == nil { - break - } - c.deposits[i].Deposit.Proof = nil - } - - return nil -} - -// PrunePendingDeposits removes any deposit which is older than the given deposit merkle tree index. -func (c *Cache) PrunePendingDeposits(ctx context.Context, merkleTreeIndex int64) { - _, span := trace.StartSpan(ctx, "Cache.PrunePendingDeposits") - defer span.End() - - if merkleTreeIndex == 0 { - log.Debug("Ignoring 0 deposit removal") - return - } - - c.depositsLock.Lock() - defer c.depositsLock.Unlock() - - cleanDeposits := make([]*ethpb.DepositContainer, 0, len(c.pendingDeposits)) - for _, dp := range c.pendingDeposits { - if dp.Index >= merkleTreeIndex { - cleanDeposits = append(cleanDeposits, dp) - } - } - - c.pendingDeposits = cleanDeposits - pendingDepositsCount.Set(float64(len(c.pendingDeposits))) -} - // InsertPendingDeposit into the database. If deposit or block number are nil // then this method does nothing. func (c *Cache) InsertPendingDeposit(ctx context.Context, d *ethpb.Deposit, blockNum uint64, index int64, depositRoot [32]byte) { @@ -241,7 +195,7 @@ func (c *Cache) InsertPendingDeposit(ctx context.Context, d *ethpb.Deposit, bloc c.pendingDeposits = append(c.pendingDeposits, ðpb.DepositContainer{Deposit: d, Eth1BlockHeight: blockNum, Index: index, DepositRoot: depositRoot[:]}) pendingDepositsCount.Set(float64(len(c.pendingDeposits))) - span.AddAttributes(trace.Int64Attribute("count", int64(len(c.pendingDeposits)))) + span.SetAttributes(trace.Int64Attribute("count", int64(len(c.pendingDeposits)))) } // Deposits returns the cached internal deposit tree. @@ -304,7 +258,7 @@ func (c *Cache) PendingContainers(ctx context.Context, untilBlk *big.Int) []*eth return depositCntrs[i].Index < depositCntrs[j].Index }) - span.AddAttributes(trace.Int64Attribute("count", int64(len(depositCntrs)))) + span.SetAttributes(trace.Int64Attribute("count", int64(len(depositCntrs)))) return depositCntrs } diff --git a/beacon-chain/cache/depositsnapshot/deposit_fetcher_test.go b/beacon-chain/cache/depositsnapshot/deposit_fetcher_test.go index 04c949355402..0c5fbf6ade5e 100644 --- a/beacon-chain/cache/depositsnapshot/deposit_fetcher_test.go +++ b/beacon-chain/cache/depositsnapshot/deposit_fetcher_test.go @@ -44,67 +44,3 @@ func TestPendingDeposits_OK(t *testing.T) { all := dc.PendingDeposits(context.Background(), nil) assert.Equal(t, len(dc.pendingDeposits), len(all), "PendingDeposits(ctx, nil) did not return all deposits") } - -func TestPrunePendingDeposits_ZeroMerkleIndex(t *testing.T) { - dc := Cache{} - - dc.pendingDeposits = []*ethpb.DepositContainer{ - {Eth1BlockHeight: 2, Index: 2}, - {Eth1BlockHeight: 4, Index: 4}, - {Eth1BlockHeight: 6, Index: 6}, - {Eth1BlockHeight: 8, Index: 8}, - {Eth1BlockHeight: 10, Index: 10}, - {Eth1BlockHeight: 12, Index: 12}, - } - - dc.PrunePendingDeposits(context.Background(), 0) - expected := []*ethpb.DepositContainer{ - {Eth1BlockHeight: 2, Index: 2}, - {Eth1BlockHeight: 4, Index: 4}, - {Eth1BlockHeight: 6, Index: 6}, - {Eth1BlockHeight: 8, Index: 8}, - {Eth1BlockHeight: 10, Index: 10}, - {Eth1BlockHeight: 12, Index: 12}, - } - assert.DeepEqual(t, expected, dc.pendingDeposits) -} - -func TestPrunePendingDeposits_OK(t *testing.T) { - dc := Cache{} - - dc.pendingDeposits = []*ethpb.DepositContainer{ - {Eth1BlockHeight: 2, Index: 2}, - {Eth1BlockHeight: 4, Index: 4}, - {Eth1BlockHeight: 6, Index: 6}, - {Eth1BlockHeight: 8, Index: 8}, - {Eth1BlockHeight: 10, Index: 10}, - {Eth1BlockHeight: 12, Index: 12}, - } - - dc.PrunePendingDeposits(context.Background(), 6) - expected := []*ethpb.DepositContainer{ - {Eth1BlockHeight: 6, Index: 6}, - {Eth1BlockHeight: 8, Index: 8}, - {Eth1BlockHeight: 10, Index: 10}, - {Eth1BlockHeight: 12, Index: 12}, - } - - assert.DeepEqual(t, expected, dc.pendingDeposits) - - dc.pendingDeposits = []*ethpb.DepositContainer{ - {Eth1BlockHeight: 2, Index: 2}, - {Eth1BlockHeight: 4, Index: 4}, - {Eth1BlockHeight: 6, Index: 6}, - {Eth1BlockHeight: 8, Index: 8}, - {Eth1BlockHeight: 10, Index: 10}, - {Eth1BlockHeight: 12, Index: 12}, - } - - dc.PrunePendingDeposits(context.Background(), 10) - expected = []*ethpb.DepositContainer{ - {Eth1BlockHeight: 10, Index: 10}, - {Eth1BlockHeight: 12, Index: 12}, - } - - assert.DeepEqual(t, expected, dc.pendingDeposits) -} diff --git a/beacon-chain/cache/depositsnapshot/deposit_inserter.go b/beacon-chain/cache/depositsnapshot/deposit_inserter.go index 990644e07d9a..59927bfe9e34 100644 --- a/beacon-chain/cache/depositsnapshot/deposit_inserter.go +++ b/beacon-chain/cache/depositsnapshot/deposit_inserter.go @@ -10,9 +10,9 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) var ( diff --git a/beacon-chain/cache/depositsnapshot/deposit_pruner.go b/beacon-chain/cache/depositsnapshot/deposit_pruner.go new file mode 100644 index 000000000000..904a3a1b1f47 --- /dev/null +++ b/beacon-chain/cache/depositsnapshot/deposit_pruner.go @@ -0,0 +1,88 @@ +package depositsnapshot + +import ( + "context" + + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" +) + +// PruneProofs removes proofs from all deposits whose index is equal or less than untilDepositIndex. +func (c *Cache) PruneProofs(ctx context.Context, untilDepositIndex int64) error { + _, span := trace.StartSpan(ctx, "Cache.PruneProofs") + defer span.End() + c.depositsLock.Lock() + defer c.depositsLock.Unlock() + + if untilDepositIndex >= int64(len(c.deposits)) { + untilDepositIndex = int64(len(c.deposits) - 1) + } + + for i := untilDepositIndex; i >= 0; i-- { + // Finding a nil proof means that all proofs up to this deposit have been already pruned. + if c.deposits[i].Deposit.Proof == nil { + break + } + c.deposits[i].Deposit.Proof = nil + } + + return nil +} + +// PruneAllProofs removes proofs from all deposits. +// As EIP-6110 applies and the legacy deposit mechanism is deprecated, +// proofs in deposit snapshot are no longer needed. +// See: https://eips.ethereum.org/EIPS/eip-6110#eth1data-poll-deprecation +func (c *Cache) PruneAllProofs(ctx context.Context) { + _, span := trace.StartSpan(ctx, "Cache.PruneAllProofs") + defer span.End() + + c.depositsLock.Lock() + defer c.depositsLock.Unlock() + + for i := len(c.deposits) - 1; i >= 0; i-- { + if c.deposits[i].Deposit.Proof == nil { + break + } + c.deposits[i].Deposit.Proof = nil + } +} + +// PrunePendingDeposits removes any deposit which is older than the given deposit merkle tree index. +func (c *Cache) PrunePendingDeposits(ctx context.Context, merkleTreeIndex int64) { + _, span := trace.StartSpan(ctx, "Cache.PrunePendingDeposits") + defer span.End() + + if merkleTreeIndex == 0 { + log.Debug("Ignoring 0 deposit removal") + return + } + + c.depositsLock.Lock() + defer c.depositsLock.Unlock() + + cleanDeposits := make([]*ethpb.DepositContainer, 0, len(c.pendingDeposits)) + for _, dp := range c.pendingDeposits { + if dp.Index >= merkleTreeIndex { + cleanDeposits = append(cleanDeposits, dp) + } + } + + c.pendingDeposits = cleanDeposits + pendingDepositsCount.Set(float64(len(c.pendingDeposits))) +} + +// PruneAllPendingDeposits removes all pending deposits from the cache. +// As EIP-6110 applies and the legacy deposit mechanism is deprecated, +// pending deposits in deposit snapshot are no longer needed. +// See: https://eips.ethereum.org/EIPS/eip-6110#eth1data-poll-deprecation +func (c *Cache) PruneAllPendingDeposits(ctx context.Context) { + _, span := trace.StartSpan(ctx, "Cache.PruneAllPendingDeposits") + defer span.End() + + c.depositsLock.Lock() + defer c.depositsLock.Unlock() + + c.pendingDeposits = make([]*ethpb.DepositContainer, 0) + pendingDepositsCount.Set(float64(0)) +} diff --git a/beacon-chain/cache/depositsnapshot/deposit_pruner_test.go b/beacon-chain/cache/depositsnapshot/deposit_pruner_test.go new file mode 100644 index 000000000000..64821f1a1467 --- /dev/null +++ b/beacon-chain/cache/depositsnapshot/deposit_pruner_test.go @@ -0,0 +1,323 @@ +package depositsnapshot + +import ( + "context" + "testing" + + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +func TestPrunePendingDeposits_ZeroMerkleIndex(t *testing.T) { + dc := Cache{} + + dc.pendingDeposits = []*ethpb.DepositContainer{ + {Eth1BlockHeight: 2, Index: 2}, + {Eth1BlockHeight: 4, Index: 4}, + {Eth1BlockHeight: 6, Index: 6}, + {Eth1BlockHeight: 8, Index: 8}, + {Eth1BlockHeight: 10, Index: 10}, + {Eth1BlockHeight: 12, Index: 12}, + } + + dc.PrunePendingDeposits(context.Background(), 0) + expected := []*ethpb.DepositContainer{ + {Eth1BlockHeight: 2, Index: 2}, + {Eth1BlockHeight: 4, Index: 4}, + {Eth1BlockHeight: 6, Index: 6}, + {Eth1BlockHeight: 8, Index: 8}, + {Eth1BlockHeight: 10, Index: 10}, + {Eth1BlockHeight: 12, Index: 12}, + } + assert.DeepEqual(t, expected, dc.pendingDeposits) +} + +func TestPrunePendingDeposits_OK(t *testing.T) { + dc := Cache{} + + dc.pendingDeposits = []*ethpb.DepositContainer{ + {Eth1BlockHeight: 2, Index: 2}, + {Eth1BlockHeight: 4, Index: 4}, + {Eth1BlockHeight: 6, Index: 6}, + {Eth1BlockHeight: 8, Index: 8}, + {Eth1BlockHeight: 10, Index: 10}, + {Eth1BlockHeight: 12, Index: 12}, + } + + dc.PrunePendingDeposits(context.Background(), 6) + expected := []*ethpb.DepositContainer{ + {Eth1BlockHeight: 6, Index: 6}, + {Eth1BlockHeight: 8, Index: 8}, + {Eth1BlockHeight: 10, Index: 10}, + {Eth1BlockHeight: 12, Index: 12}, + } + + assert.DeepEqual(t, expected, dc.pendingDeposits) + + dc.pendingDeposits = []*ethpb.DepositContainer{ + {Eth1BlockHeight: 2, Index: 2}, + {Eth1BlockHeight: 4, Index: 4}, + {Eth1BlockHeight: 6, Index: 6}, + {Eth1BlockHeight: 8, Index: 8}, + {Eth1BlockHeight: 10, Index: 10}, + {Eth1BlockHeight: 12, Index: 12}, + } + + dc.PrunePendingDeposits(context.Background(), 10) + expected = []*ethpb.DepositContainer{ + {Eth1BlockHeight: 10, Index: 10}, + {Eth1BlockHeight: 12, Index: 12}, + } + + assert.DeepEqual(t, expected, dc.pendingDeposits) +} + +func TestPruneAllPendingDeposits(t *testing.T) { + dc := Cache{} + + dc.pendingDeposits = []*ethpb.DepositContainer{ + {Eth1BlockHeight: 2, Index: 2}, + {Eth1BlockHeight: 4, Index: 4}, + {Eth1BlockHeight: 6, Index: 6}, + {Eth1BlockHeight: 8, Index: 8}, + {Eth1BlockHeight: 10, Index: 10}, + {Eth1BlockHeight: 12, Index: 12}, + } + + dc.PruneAllPendingDeposits(context.Background()) + expected := []*ethpb.DepositContainer{} + + assert.DeepEqual(t, expected, dc.pendingDeposits) +} + +func TestPruneProofs_Ok(t *testing.T) { + dc, err := New() + require.NoError(t, err) + + deposits := []struct { + blkNum uint64 + deposit *ethpb.Deposit + index int64 + }{ + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, + index: 0, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, + index: 1, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, + index: 2, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, + index: 3, + }, + } + + for _, ins := range deposits { + assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) + } + + require.NoError(t, dc.PruneProofs(context.Background(), 1)) + + assert.DeepEqual(t, [][]byte(nil), dc.deposits[0].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[1].Deposit.Proof) + assert.NotNil(t, dc.deposits[2].Deposit.Proof) + assert.NotNil(t, dc.deposits[3].Deposit.Proof) +} + +func TestPruneProofs_SomeAlreadyPruned(t *testing.T) { + dc, err := New() + require.NoError(t, err) + + deposits := []struct { + blkNum uint64 + deposit *ethpb.Deposit + index int64 + }{ + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: nil, Data: ðpb.Deposit_Data{ + PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, + index: 0, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: nil, Data: ðpb.Deposit_Data{ + PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, index: 1, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, + index: 2, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, + index: 3, + }, + } + + for _, ins := range deposits { + assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) + } + + require.NoError(t, dc.PruneProofs(context.Background(), 2)) + + assert.DeepEqual(t, [][]byte(nil), dc.deposits[2].Deposit.Proof) +} + +func TestPruneProofs_PruneAllWhenDepositIndexTooBig(t *testing.T) { + dc, err := New() + require.NoError(t, err) + + deposits := []struct { + blkNum uint64 + deposit *ethpb.Deposit + index int64 + }{ + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, + index: 0, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, + index: 1, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, + index: 2, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, + index: 3, + }, + } + + for _, ins := range deposits { + assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) + } + + require.NoError(t, dc.PruneProofs(context.Background(), 99)) + + assert.DeepEqual(t, [][]byte(nil), dc.deposits[0].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[1].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[2].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[3].Deposit.Proof) +} + +func TestPruneProofs_CorrectlyHandleLastIndex(t *testing.T) { + dc, err := New() + require.NoError(t, err) + + deposits := []struct { + blkNum uint64 + deposit *ethpb.Deposit + index int64 + }{ + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, + index: 0, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, + index: 1, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, + index: 2, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, + index: 3, + }, + } + + for _, ins := range deposits { + assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) + } + + require.NoError(t, dc.PruneProofs(context.Background(), 4)) + + assert.DeepEqual(t, [][]byte(nil), dc.deposits[0].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[1].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[2].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[3].Deposit.Proof) +} + +func TestPruneAllProofs(t *testing.T) { + dc, err := New() + require.NoError(t, err) + + deposits := []struct { + blkNum uint64 + deposit *ethpb.Deposit + index int64 + }{ + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk0"), 48)}}, + index: 0, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk1"), 48)}}, + index: 1, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk2"), 48)}}, + index: 2, + }, + { + blkNum: 0, + deposit: ðpb.Deposit{Proof: makeDepositProof(), + Data: ðpb.Deposit_Data{PublicKey: bytesutil.PadTo([]byte("pk3"), 48)}}, + index: 3, + }, + } + + for _, ins := range deposits { + assert.NoError(t, dc.InsertDeposit(context.Background(), ins.deposit, ins.blkNum, ins.index, [32]byte{})) + } + + dc.PruneAllProofs(context.Background()) + + assert.DeepEqual(t, [][]byte(nil), dc.deposits[0].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[1].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[2].Deposit.Proof) + assert.DeepEqual(t, [][]byte(nil), dc.deposits[3].Deposit.Proof) +} diff --git a/beacon-chain/cache/interfaces.go b/beacon-chain/cache/interfaces.go index 163dbd0ef777..338613e29636 100644 --- a/beacon-chain/cache/interfaces.go +++ b/beacon-chain/cache/interfaces.go @@ -12,6 +12,7 @@ import ( type DepositCache interface { DepositFetcher DepositInserter + DepositPruner } // DepositFetcher defines a struct which can retrieve deposit information from a store. @@ -23,8 +24,6 @@ type DepositFetcher interface { InsertPendingDeposit(ctx context.Context, d *ethpb.Deposit, blockNum uint64, index int64, depositRoot [32]byte) PendingDeposits(ctx context.Context, untilBlk *big.Int) []*ethpb.Deposit PendingContainers(ctx context.Context, untilBlk *big.Int) []*ethpb.DepositContainer - PrunePendingDeposits(ctx context.Context, merkleTreeIndex int64) - PruneProofs(ctx context.Context, untilDepositIndex int64) error FinalizedFetcher } @@ -42,6 +41,14 @@ type FinalizedFetcher interface { NonFinalizedDeposits(ctx context.Context, lastFinalizedIndex int64, untilBlk *big.Int) []*ethpb.Deposit } +// DepositPruner is an interface for pruning deposits and proofs. +type DepositPruner interface { + PrunePendingDeposits(ctx context.Context, merkleTreeIndex int64) + PruneAllPendingDeposits(ctx context.Context) + PruneProofs(ctx context.Context, untilDepositIndex int64) error + PruneAllProofs(ctx context.Context) +} + // FinalizedDeposits defines a method to access a merkle tree containing deposits and their indexes. type FinalizedDeposits interface { Deposits() MerkleTree diff --git a/beacon-chain/cache/registration.go b/beacon-chain/cache/registration.go index 217b850c9f37..5e1c907b383a 100644 --- a/beacon-chain/cache/registration.go +++ b/beacon-chain/cache/registration.go @@ -7,8 +7,8 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // RegistrationCache is used to store the cached results of an Validator Registration request. diff --git a/beacon-chain/cache/skip_slot_cache.go b/beacon-chain/cache/skip_slot_cache.go index 4e9538b197e1..41f79d1f446f 100644 --- a/beacon-chain/cache/skip_slot_cache.go +++ b/beacon-chain/cache/skip_slot_cache.go @@ -11,7 +11,7 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) var ( @@ -92,17 +92,17 @@ func (c *SkipSlotCache) Get(ctx context.Context, r [32]byte) (state.BeaconState, delay *= delayFactor delay = math.Min(delay, maxDelay) } - span.AddAttributes(trace.BoolAttribute("inProgress", inProgress)) + span.SetAttributes(trace.BoolAttribute("inProgress", inProgress)) item, exists := c.cache.Get(r) if exists && item != nil { skipSlotCacheHit.Inc() - span.AddAttributes(trace.BoolAttribute("hit", true)) + span.SetAttributes(trace.BoolAttribute("hit", true)) return item.(state.BeaconState).Copy(), nil } skipSlotCacheMiss.Inc() - span.AddAttributes(trace.BoolAttribute("hit", false)) + span.SetAttributes(trace.BoolAttribute("hit", false)) return nil, nil } diff --git a/beacon-chain/cache/tracked_validators.go b/beacon-chain/cache/tracked_validators.go index 1dd7725c048f..d3a86c0bdc1c 100644 --- a/beacon-chain/cache/tracked_validators.go +++ b/beacon-chain/cache/tracked_validators.go @@ -1,49 +1,139 @@ package cache import ( - "sync" + "strconv" + "time" + "github.com/patrickmn/go-cache" + "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/sirupsen/logrus" ) -type TrackedValidator struct { - Active bool - FeeRecipient primitives.ExecutionAddress - Index primitives.ValidatorIndex -} +const ( + defaultExpiration = 1 * time.Hour + cleanupInterval = 15 * time.Minute +) -type TrackedValidatorsCache struct { - sync.Mutex - trackedValidators map[primitives.ValidatorIndex]TrackedValidator -} +type ( + TrackedValidator struct { + Active bool + FeeRecipient primitives.ExecutionAddress + Index primitives.ValidatorIndex + } + + TrackedValidatorsCache struct { + trackedValidators cache.Cache + } +) + +var ( + // Metrics. + trackedValidatorsCacheMiss = promauto.NewCounter(prometheus.CounterOpts{ + Name: "tracked_validators_cache_miss", + Help: "The number of tracked validators requests that are not present in the cache.", + }) + + trackedValidatorsCacheTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "tracked_validators_cache_total", + Help: "The total number of tracked validators requests in the cache.", + }) + trackedValidatorsCacheCount = promauto.NewGauge(prometheus.GaugeOpts{ + Name: "tracked_validators_cache_count", + Help: "The number of tracked validators in the cache.", + }) +) + +// NewTrackedValidatorsCache creates a new cache for tracking validators. func NewTrackedValidatorsCache() *TrackedValidatorsCache { return &TrackedValidatorsCache{ - trackedValidators: make(map[primitives.ValidatorIndex]TrackedValidator), + trackedValidators: *cache.New(defaultExpiration, cleanupInterval), } } +// Validator retrieves a tracked validator from the cache (if present). func (t *TrackedValidatorsCache) Validator(index primitives.ValidatorIndex) (TrackedValidator, bool) { - t.Lock() - defer t.Unlock() - val, ok := t.trackedValidators[index] - return val, ok + trackedValidatorsCacheTotal.Inc() + + key := toCacheKey(index) + item, ok := t.trackedValidators.Get(key) + if !ok { + trackedValidatorsCacheMiss.Inc() + return TrackedValidator{}, false + } + + val, ok := item.(TrackedValidator) + if !ok { + logrus.Errorf("Failed to cast tracked validator from cache, got unexpected item type %T", item) + return TrackedValidator{}, false + } + + return val, true } +// Set adds a tracked validator to the cache. func (t *TrackedValidatorsCache) Set(val TrackedValidator) { - t.Lock() - defer t.Unlock() - t.trackedValidators[val.Index] = val + key := toCacheKey(val.Index) + t.trackedValidators.Set(key, val, cache.DefaultExpiration) } +// Delete removes a tracked validator from the cache. func (t *TrackedValidatorsCache) Prune() { - t.Lock() - defer t.Unlock() - t.trackedValidators = make(map[primitives.ValidatorIndex]TrackedValidator) + t.trackedValidators.Flush() + trackedValidatorsCacheCount.Set(0) } +// Validating returns true if there are at least one tracked validators in the cache. func (t *TrackedValidatorsCache) Validating() bool { - t.Lock() - defer t.Unlock() - return len(t.trackedValidators) > 0 + count := t.trackedValidators.ItemCount() + trackedValidatorsCacheCount.Set(float64(count)) + + return count > 0 +} + +// ItemCount returns the number of tracked validators in the cache. +func (t *TrackedValidatorsCache) ItemCount() int { + count := t.trackedValidators.ItemCount() + trackedValidatorsCacheCount.Set(float64(count)) + + return count +} + +// Indices returns a map of validator indices that are being tracked. +func (t *TrackedValidatorsCache) Indices() map[primitives.ValidatorIndex]bool { + items := t.trackedValidators.Items() + count := len(items) + trackedValidatorsCacheCount.Set(float64(count)) + + indices := make(map[primitives.ValidatorIndex]bool, count) + + for cacheKey := range items { + index, err := fromCacheKey(cacheKey) + if err != nil { + logrus.WithError(err).Error("Failed to get validator index from cache key") + continue + } + + indices[index] = true + } + + return indices +} + +// toCacheKey creates a cache key from the validator index. +func toCacheKey(validatorIndex primitives.ValidatorIndex) string { + return strconv.FormatUint(uint64(validatorIndex), 10) +} + +// fromCacheKey gets the validator index from the cache key. +func fromCacheKey(key string) (primitives.ValidatorIndex, error) { + validatorIndex, err := strconv.ParseUint(key, 10, 64) + if err != nil { + return 0, errors.Wrapf(err, "parse Uint: %s", key) + } + + return primitives.ValidatorIndex(validatorIndex), nil } diff --git a/beacon-chain/cache/tracked_validators_test.go b/beacon-chain/cache/tracked_validators_test.go new file mode 100644 index 000000000000..9f518f7e6ed8 --- /dev/null +++ b/beacon-chain/cache/tracked_validators_test.go @@ -0,0 +1,79 @@ +package cache + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +func mapEqual(a, b map[primitives.ValidatorIndex]bool) bool { + if len(a) != len(b) { + return false + } + + for k, v := range a { + if b[k] != v { + return false + } + } + + return true +} + +func TestTrackedValidatorsCache(t *testing.T) { + vc := NewTrackedValidatorsCache() + + // No validators in cache. + require.Equal(t, 0, vc.ItemCount()) + require.Equal(t, false, vc.Validating()) + require.Equal(t, 0, len(vc.Indices())) + + _, ok := vc.Validator(41) + require.Equal(t, false, ok) + + // Add some validators (one twice). + v42Expected := TrackedValidator{Active: true, FeeRecipient: [20]byte{1}, Index: 42} + v43Expected := TrackedValidator{Active: false, FeeRecipient: [20]byte{2}, Index: 43} + + vc.Set(v42Expected) + vc.Set(v43Expected) + vc.Set(v42Expected) + + // Check if they are in the cache. + v42Actual, ok := vc.Validator(42) + require.Equal(t, true, ok) + require.Equal(t, v42Expected, v42Actual) + + v43Actual, ok := vc.Validator(43) + require.Equal(t, true, ok) + require.Equal(t, v43Expected, v43Actual) + + expected := map[primitives.ValidatorIndex]bool{42: true, 43: true} + actual := vc.Indices() + require.Equal(t, true, mapEqual(expected, actual)) + + // Check the item count and if the cache is validating. + require.Equal(t, 2, vc.ItemCount()) + require.Equal(t, true, vc.Validating()) + + // Check if a non-existing validator is in the cache. + _, ok = vc.Validator(41) + require.Equal(t, false, ok) + + // Prune the cache and test it. + vc.Prune() + + _, ok = vc.Validator(41) + require.Equal(t, false, ok) + + _, ok = vc.Validator(42) + require.Equal(t, false, ok) + + _, ok = vc.Validator(43) + require.Equal(t, false, ok) + + require.Equal(t, 0, vc.ItemCount()) + require.Equal(t, false, vc.Validating()) + require.Equal(t, 0, len(vc.Indices())) +} diff --git a/beacon-chain/core/altair/BUILD.bazel b/beacon-chain/core/altair/BUILD.bazel index 37d83038eb83..e73e251e33d4 100644 --- a/beacon-chain/core/altair/BUILD.bazel +++ b/beacon-chain/core/altair/BUILD.bazel @@ -34,13 +34,13 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//math:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/core/altair/attestation.go b/beacon-chain/core/altair/attestation.go index 6c9c251e5f7b..7c11d68b7514 100644 --- a/beacon-chain/core/altair/attestation.go +++ b/beacon-chain/core/altair/attestation.go @@ -14,9 +14,9 @@ import ( consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" - "go.opencensus.io/trace" ) // ProcessAttestationsNoVerifySignature applies processing operations to a block's inner attestation diff --git a/beacon-chain/core/altair/deposit.go b/beacon-chain/core/altair/deposit.go index 9f3a0736c581..5aeb23c100c6 100644 --- a/beacon-chain/core/altair/deposit.go +++ b/beacon-chain/core/altair/deposit.go @@ -37,7 +37,7 @@ func ProcessDeposits( beaconState state.BeaconState, deposits []*ethpb.Deposit, ) (state.BeaconState, error) { - batchVerified, err := blocks.BatchVerifyDepositsSignatures(ctx, deposits) + allSignaturesVerified, err := blocks.BatchVerifyDepositsSignatures(ctx, deposits) if err != nil { return nil, err } @@ -46,7 +46,7 @@ func ProcessDeposits( if deposit == nil || deposit.Data == nil { return nil, errors.New("got a nil deposit in block") } - beaconState, err = ProcessDeposit(beaconState, deposit, batchVerified) + beaconState, err = ProcessDeposit(beaconState, deposit, allSignaturesVerified) if err != nil { return nil, errors.Wrapf(err, "could not process deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey)) } @@ -81,7 +81,7 @@ func ProcessDeposits( // amount=deposit.data.amount, // signature=deposit.data.signature, // ) -func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconState, error) { +func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, allSignaturesVerified bool) (state.BeaconState, error) { if err := blocks.VerifyDeposit(beaconState, deposit); err != nil { if deposit == nil || deposit.Data == nil { return nil, err @@ -92,7 +92,7 @@ func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verif return nil, err } - return ApplyDeposit(beaconState, deposit.Data, verifySignature) + return ApplyDeposit(beaconState, deposit.Data, allSignaturesVerified) } // ApplyDeposit @@ -115,13 +115,13 @@ func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verif // # Increase balance by deposit amount // index = ValidatorIndex(validator_pubkeys.index(pubkey)) // increase_balance(state, index, amount) -func ApplyDeposit(beaconState state.BeaconState, data *ethpb.Deposit_Data, verifySignature bool) (state.BeaconState, error) { +func ApplyDeposit(beaconState state.BeaconState, data *ethpb.Deposit_Data, allSignaturesVerified bool) (state.BeaconState, error) { pubKey := data.PublicKey amount := data.Amount withdrawalCredentials := data.WithdrawalCredentials index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey)) if !ok { - if verifySignature { + if !allSignaturesVerified { valid, err := blocks.IsValidDepositSignature(data) if err != nil { return nil, err @@ -187,11 +187,12 @@ func AddValidatorToRegistry(beaconState state.BeaconState, pubKey []byte, withdr // return Validator( // pubkey=pubkey, // withdrawal_credentials=withdrawal_credentials, +// effective_balance=effective_balance, +// slashed=False, // activation_eligibility_epoch=FAR_FUTURE_EPOCH, // activation_epoch=FAR_FUTURE_EPOCH, // exit_epoch=FAR_FUTURE_EPOCH, // withdrawable_epoch=FAR_FUTURE_EPOCH, -// effective_balance=effective_balance, // ) func GetValidatorFromDeposit(pubKey []byte, withdrawalCredentials []byte, amount uint64) *ethpb.Validator { effectiveBalance := amount - (amount % params.BeaconConfig().EffectiveBalanceIncrement) @@ -202,10 +203,11 @@ func GetValidatorFromDeposit(pubKey []byte, withdrawalCredentials []byte, amount return ðpb.Validator{ PublicKey: pubKey, WithdrawalCredentials: withdrawalCredentials, + EffectiveBalance: effectiveBalance, + Slashed: false, ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch, ActivationEpoch: params.BeaconConfig().FarFutureEpoch, ExitEpoch: params.BeaconConfig().FarFutureEpoch, WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch, - EffectiveBalance: effectiveBalance, } } diff --git a/beacon-chain/core/altair/deposit_test.go b/beacon-chain/core/altair/deposit_test.go index dda8b468d635..34dda460890f 100644 --- a/beacon-chain/core/altair/deposit_test.go +++ b/beacon-chain/core/altair/deposit_test.go @@ -199,7 +199,7 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) { }, }) require.NoError(t, err) - newState, err := altair.ProcessDeposit(beaconState, dep[0], true) + newState, err := altair.ProcessDeposit(beaconState, dep[0], false) require.NoError(t, err, "Expected invalid block deposit to be ignored without error") if newState.Eth1DepositIndex() != 1 { diff --git a/beacon-chain/core/altair/epoch_precompute.go b/beacon-chain/core/altair/epoch_precompute.go index dbe519830578..817650893afd 100644 --- a/beacon-chain/core/altair/epoch_precompute.go +++ b/beacon-chain/core/altair/epoch_precompute.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/math" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) // AttDelta contains rewards and penalties for a single attestation. diff --git a/beacon-chain/core/altair/epoch_spec_test.go b/beacon-chain/core/altair/epoch_spec_test.go index 4b2a4c427898..eca1f22cc449 100644 --- a/beacon-chain/core/altair/epoch_spec_test.go +++ b/beacon-chain/core/altair/epoch_spec_test.go @@ -105,10 +105,9 @@ func TestProcessSlashings_NotSlashed(t *testing.T) { } s, err := state_native.InitializeFromProtoAltair(base) require.NoError(t, err) - newState, err := epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplierAltair) - require.NoError(t, err) + require.NoError(t, epoch.ProcessSlashings(s)) wanted := params.BeaconConfig().MaxEffectiveBalance - assert.Equal(t, wanted, newState.Balances()[0], "Unexpected slashed balance") + assert.Equal(t, wanted, s.Balances()[0], "Unexpected slashed balance") } func TestProcessSlashings_SlashedLess(t *testing.T) { @@ -176,9 +175,8 @@ func TestProcessSlashings_SlashedLess(t *testing.T) { original := proto.Clone(tt.state) s, err := state_native.InitializeFromProtoAltair(tt.state) require.NoError(t, err) - newState, err := epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplierAltair) - require.NoError(t, err) - assert.Equal(t, tt.want, newState.Balances()[0], "ProcessSlashings({%v}) = newState; newState.Balances[0] = %d", original, newState.Balances()[0]) + require.NoError(t, epoch.ProcessSlashings(s)) + assert.Equal(t, tt.want, s.Balances()[0], "ProcessSlashings({%v}) = newState; newState.Balances[0] = %d", original, s.Balances()[0]) }) } } @@ -192,6 +190,5 @@ func TestProcessSlashings_BadValue(t *testing.T) { } s, err := state_native.InitializeFromProtoAltair(base) require.NoError(t, err) - _, err = epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplierAltair) - require.ErrorContains(t, "addition overflows", err) + require.ErrorContains(t, "addition overflows", epoch.ProcessSlashings(s)) } diff --git a/beacon-chain/core/altair/sync_committee.go b/beacon-chain/core/altair/sync_committee.go index 88ef8650763d..ee89c1755421 100644 --- a/beacon-chain/core/altair/sync_committee.go +++ b/beacon-chain/core/altair/sync_committee.go @@ -2,6 +2,7 @@ package altair import ( "context" + "encoding/binary" goErrors "errors" "fmt" "time" @@ -22,8 +23,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/time/slots" ) -const maxRandomByte = uint64(1<<8 - 1) - var ( ErrTooLate = errors.New("sync message is too late") ) @@ -91,19 +90,22 @@ func NextSyncCommittee(ctx context.Context, s state.BeaconState) (*ethpb.SyncCom // """ // epoch = Epoch(get_current_epoch(state) + 1) // -// MAX_RANDOM_BYTE = 2**8 - 1 +// MAX_RANDOM_VALUE = 2**16 - 1 # [Modified in Electra] // active_validator_indices = get_active_validator_indices(state, epoch) // active_validator_count = uint64(len(active_validator_indices)) // seed = get_seed(state, epoch, DOMAIN_SYNC_COMMITTEE) -// i = 0 +// i = uint64(0) // sync_committee_indices: List[ValidatorIndex] = [] // while len(sync_committee_indices) < SYNC_COMMITTEE_SIZE: // shuffled_index = compute_shuffled_index(uint64(i % active_validator_count), active_validator_count, seed) // candidate_index = active_validator_indices[shuffled_index] -// random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32] +// # [Modified in Electra] +// random_bytes = hash(seed + uint_to_bytes(i // 16)) +// offset = i % 16 * 2 +// random_value = bytes_to_uint64(random_bytes[offset:offset + 2]) // effective_balance = state.validators[candidate_index].effective_balance // # [Modified in Electra:EIP7251] -// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_byte: +// if effective_balance * MAX_RANDOM_VALUE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_value: // sync_committee_indices.append(candidate_index) // i += 1 // return sync_committee_indices @@ -123,12 +125,11 @@ func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconState) ([]primi cIndices := make([]primitives.ValidatorIndex, 0, syncCommitteeSize) hashFunc := hash.CustomSHA256Hasher() - maxEB := cfg.MaxEffectiveBalanceElectra - if s.Version() < version.Electra { - maxEB = cfg.MaxEffectiveBalance - } + // Preallocate buffers to avoid repeated allocations + seedBuffer := make([]byte, len(seed)+8) + copy(seedBuffer, seed[:]) - for i := primitives.ValidatorIndex(0); uint64(len(cIndices)) < params.BeaconConfig().SyncCommitteeSize; i++ { + for i := primitives.ValidatorIndex(0); uint64(len(cIndices)) < syncCommitteeSize; i++ { if ctx.Err() != nil { return nil, ctx.Err() } @@ -137,18 +138,30 @@ func NextSyncCommitteeIndices(ctx context.Context, s state.BeaconState) ([]primi if err != nil { return nil, err } - - b := append(seed[:], bytesutil.Bytes8(uint64(i.Div(32)))...) - randomByte := hashFunc(b)[i%32] cIndex := indices[sIndex] v, err := s.ValidatorAtIndexReadOnly(cIndex) if err != nil { return nil, err } - effectiveBal := v.EffectiveBalance() - if effectiveBal*maxRandomByte >= maxEB*uint64(randomByte) { - cIndices = append(cIndices, cIndex) + + if s.Version() >= version.Electra { + // Use the preallocated seed buffer + binary.LittleEndian.PutUint64(seedBuffer[len(seed):], uint64(i/16)) + randomByte := hashFunc(seedBuffer) + offset := (i % 16) * 2 + randomValue := uint64(randomByte[offset]) | uint64(randomByte[offset+1])<<8 + + if effectiveBal*fieldparams.MaxRandomValueElectra >= cfg.MaxEffectiveBalanceElectra*randomValue { + cIndices = append(cIndices, cIndex) + } + } else { + // Use the preallocated seed buffer + binary.LittleEndian.PutUint64(seedBuffer[len(seed):], uint64(i/32)) + randomByte := hashFunc(seedBuffer)[i%32] + if effectiveBal*fieldparams.MaxRandomByte >= cfg.MaxEffectiveBalance*uint64(randomByte) { + cIndices = append(cIndices, cIndex) + } } } diff --git a/beacon-chain/core/altair/transition.go b/beacon-chain/core/altair/transition.go index cc060d6203ee..4c8662128389 100644 --- a/beacon-chain/core/altair/transition.go +++ b/beacon-chain/core/altair/transition.go @@ -7,7 +7,7 @@ import ( e "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) // ProcessEpoch describes the per epoch operations that are performed on the beacon state. @@ -69,12 +69,7 @@ func ProcessEpoch(ctx context.Context, state state.BeaconState) error { } // Modified in Altair and Bellatrix. - proportionalSlashingMultiplier, err := state.ProportionalSlashingMultiplier() - if err != nil { - return err - } - state, err = e.ProcessSlashings(state, proportionalSlashingMultiplier) - if err != nil { + if err := e.ProcessSlashings(state); err != nil { return err } state, err = e.ProcessEth1DataReset(state) diff --git a/beacon-chain/core/blocks/BUILD.bazel b/beacon-chain/core/blocks/BUILD.bazel index 92e511ea1e27..64d5861acd63 100644 --- a/beacon-chain/core/blocks/BUILD.bazel +++ b/beacon-chain/core/blocks/BUILD.bazel @@ -40,6 +40,7 @@ go_library( "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", "//math:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/forks:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", @@ -49,7 +50,6 @@ go_library( "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/beacon-chain/core/blocks/attestation.go b/beacon-chain/core/blocks/attestation.go index fe71802126e1..aafcddffba7e 100644 --- a/beacon-chain/core/blocks/attestation.go +++ b/beacon-chain/core/blocks/attestation.go @@ -14,10 +14,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" ) // ProcessAttestationsNoVerifySignature applies processing operations to a block's inner attestation @@ -110,25 +110,7 @@ func VerifyAttestationNoVerifySignature( var indexedAtt ethpb.IndexedAtt - if att.Version() < version.Electra { - if uint64(att.GetData().CommitteeIndex) >= c { - return fmt.Errorf("committee index %d >= committee count %d", att.GetData().CommitteeIndex, c) - } - - if err = helpers.VerifyAttestationBitfieldLengths(ctx, beaconState, att); err != nil { - return errors.Wrap(err, "could not verify attestation bitfields") - } - - // Verify attesting indices are correct. - committee, err := helpers.BeaconCommitteeFromState(ctx, beaconState, att.GetData().Slot, att.GetData().CommitteeIndex) - if err != nil { - return err - } - indexedAtt, err = attestation.ConvertToIndexed(ctx, att, committee) - if err != nil { - return err - } - } else { + if att.Version() >= version.Electra { if att.GetData().CommitteeIndex != 0 { return errors.New("committee index must be 0 post-Electra") } @@ -154,6 +136,29 @@ func VerifyAttestationNoVerifySignature( if err != nil { return err } + } else { + if uint64(att.GetData().CommitteeIndex) >= c { + return fmt.Errorf("committee index %d >= committee count %d", att.GetData().CommitteeIndex, c) + } + + // Verify attesting indices are correct. + committee, err := helpers.BeaconCommitteeFromState(ctx, beaconState, att.GetData().Slot, att.GetData().CommitteeIndex) + if err != nil { + return err + } + + if committee == nil { + return errors.New("no committee exist for this attestation") + } + + if err := helpers.VerifyBitfieldLength(att.GetAggregationBits(), uint64(len(committee))); err != nil { + return errors.Wrap(err, "failed to verify aggregation bitfield") + } + + indexedAtt, err = attestation.ConvertToIndexed(ctx, att, committee) + if err != nil { + return err + } } return attestation.IsValidAttestationIndices(ctx, indexedAtt) diff --git a/beacon-chain/core/blocks/attestation_test.go b/beacon-chain/core/blocks/attestation_test.go index 361be04b5c0d..51467ddff545 100644 --- a/beacon-chain/core/blocks/attestation_test.go +++ b/beacon-chain/core/blocks/attestation_test.go @@ -448,6 +448,7 @@ func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) { Target: ðpb.Checkpoint{ Epoch: primitives.Epoch(i), }, + Source: ðpb.Checkpoint{}, } } @@ -489,6 +490,7 @@ func TestValidateIndexedAttestation_BadAttestationsSignatureSet(t *testing.T) { Target: ðpb.Checkpoint{ Root: []byte{}, }, + Source: ðpb.Checkpoint{}, }, Signature: sig.Marshal(), AggregationBits: list, diff --git a/beacon-chain/core/blocks/attester_slashing_test.go b/beacon-chain/core/blocks/attester_slashing_test.go index 75c5b7efa0cd..e6be851117f3 100644 --- a/beacon-chain/core/blocks/attester_slashing_test.go +++ b/beacon-chain/core/blocks/attester_slashing_test.go @@ -7,12 +7,14 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" v "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -105,293 +107,162 @@ func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T) } func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) { - beaconState, privKeys := util.DeterministicGenesisState(t, 100) - for _, vv := range beaconState.Validators() { - vv.WithdrawableEpoch = primitives.Epoch(params.BeaconConfig().SlotsPerEpoch) - } - - att1 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ + statePhase0, keysPhase0 := util.DeterministicGenesisState(t, 100) + stateAltair, keysAltair := util.DeterministicGenesisStateAltair(t, 100) + stateBellatrix, keysBellatrix := util.DeterministicGenesisStateBellatrix(t, 100) + stateCapella, keysCapella := util.DeterministicGenesisStateCapella(t, 100) + stateDeneb, keysDeneb := util.DeterministicGenesisStateDeneb(t, 100) + stateElectra, keysElectra := util.DeterministicGenesisStateElectra(t, 100) + + att1Phase0 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ Data: ðpb.AttestationData{ Source: ðpb.Checkpoint{Epoch: 1}, }, AttestingIndices: []uint64{0, 1}, }) - domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot()) - require.NoError(t, err) - signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) - assert.NoError(t, err, "Could not get signing root of beacon block header") - sig0 := privKeys[0].Sign(signingRoot[:]) - sig1 := privKeys[1].Sign(signingRoot[:]) - aggregateSig := bls.AggregateSignatures([]bls.Signature{sig0, sig1}) - att1.Signature = aggregateSig.Marshal() - - att2 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ + att2Phase0 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ AttestingIndices: []uint64{0, 1}, }) - signingRoot, err = signing.ComputeSigningRoot(att2.Data, domain) - assert.NoError(t, err, "Could not get signing root of beacon block header") - sig0 = privKeys[0].Sign(signingRoot[:]) - sig1 = privKeys[1].Sign(signingRoot[:]) - aggregateSig = bls.AggregateSignatures([]bls.Signature{sig0, sig1}) - att2.Signature = aggregateSig.Marshal() - - slashings := []*ethpb.AttesterSlashing{ - { - Attestation_1: att1, - Attestation_2: att2, - }, - } - - currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch - require.NoError(t, beaconState.SetSlot(currentSlot)) - - b := util.NewBeaconBlock() - b.Block = ðpb.BeaconBlock{ - Body: ðpb.BeaconBlockBody{ - AttesterSlashings: slashings, - }, - } - - ss := make([]ethpb.AttSlashing, len(b.Block.Body.AttesterSlashings)) - for i, s := range b.Block.Body.AttesterSlashings { - ss[i] = s - } - newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, ss, v.SlashValidator) - require.NoError(t, err) - newRegistry := newState.Validators() - - // Given the intersection of slashable indices is [1], only validator - // at index 1 should be slashed and exited. We confirm this below. - if newRegistry[1].ExitEpoch != beaconState.Validators()[1].ExitEpoch { - t.Errorf( - ` - Expected validator at index 1's exit epoch to match - %d, received %d instead - `, - beaconState.Validators()[1].ExitEpoch, - newRegistry[1].ExitEpoch, - ) - } - - require.Equal(t, uint64(31750000000), newState.Balances()[1]) - require.Equal(t, uint64(32000000000), newState.Balances()[2]) -} - -func TestProcessAttesterSlashings_AppliesCorrectStatusAltair(t *testing.T) { - beaconState, privKeys := util.DeterministicGenesisStateAltair(t, 100) - for _, vv := range beaconState.Validators() { - vv.WithdrawableEpoch = primitives.Epoch(params.BeaconConfig().SlotsPerEpoch) - } - - att1 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ + att1Electra := util.HydrateIndexedAttestationElectra(ðpb.IndexedAttestationElectra{ Data: ðpb.AttestationData{ Source: ðpb.Checkpoint{Epoch: 1}, }, AttestingIndices: []uint64{0, 1}, }) - domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot()) - require.NoError(t, err) - signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) - assert.NoError(t, err, "Could not get signing root of beacon block header") - sig0 := privKeys[0].Sign(signingRoot[:]) - sig1 := privKeys[1].Sign(signingRoot[:]) - aggregateSig := bls.AggregateSignatures([]bls.Signature{sig0, sig1}) - att1.Signature = aggregateSig.Marshal() - - att2 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ + att2Electra := util.HydrateIndexedAttestationElectra(ðpb.IndexedAttestationElectra{ AttestingIndices: []uint64{0, 1}, }) - signingRoot, err = signing.ComputeSigningRoot(att2.Data, domain) - assert.NoError(t, err, "Could not get signing root of beacon block header") - sig0 = privKeys[0].Sign(signingRoot[:]) - sig1 = privKeys[1].Sign(signingRoot[:]) - aggregateSig = bls.AggregateSignatures([]bls.Signature{sig0, sig1}) - att2.Signature = aggregateSig.Marshal() - - slashings := []*ethpb.AttesterSlashing{ - { - Attestation_1: att1, - Attestation_2: att2, - }, - } - - currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch - require.NoError(t, beaconState.SetSlot(currentSlot)) - - b := util.NewBeaconBlock() - b.Block = ðpb.BeaconBlock{ - Body: ðpb.BeaconBlockBody{ - AttesterSlashings: slashings, - }, - } - ss := make([]ethpb.AttSlashing, len(b.Block.Body.AttesterSlashings)) - for i, s := range b.Block.Body.AttesterSlashings { - ss[i] = s + slashingPhase0 := ðpb.AttesterSlashing{ + Attestation_1: att1Phase0, + Attestation_2: att2Phase0, } - newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, ss, v.SlashValidator) - require.NoError(t, err) - newRegistry := newState.Validators() - - // Given the intersection of slashable indices is [1], only validator - // at index 1 should be slashed and exited. We confirm this below. - if newRegistry[1].ExitEpoch != beaconState.Validators()[1].ExitEpoch { - t.Errorf( - ` - Expected validator at index 1's exit epoch to match - %d, received %d instead - `, - beaconState.Validators()[1].ExitEpoch, - newRegistry[1].ExitEpoch, - ) + slashingElectra := ðpb.AttesterSlashingElectra{ + Attestation_1: att1Electra, + Attestation_2: att2Electra, } - require.Equal(t, uint64(31500000000), newState.Balances()[1]) - require.Equal(t, uint64(32000000000), newState.Balances()[2]) -} - -func TestProcessAttesterSlashings_AppliesCorrectStatusBellatrix(t *testing.T) { - beaconState, privKeys := util.DeterministicGenesisStateBellatrix(t, 100) - for _, vv := range beaconState.Validators() { - vv.WithdrawableEpoch = primitives.Epoch(params.BeaconConfig().SlotsPerEpoch) + type testCase struct { + name string + st state.BeaconState + keys []bls.SecretKey + att1 ethpb.IndexedAtt + att2 ethpb.IndexedAtt + slashing ethpb.AttSlashing + slashedBalance uint64 } - att1 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ - Data: ðpb.AttestationData{ - Source: ðpb.Checkpoint{Epoch: 1}, + testCases := []testCase{ + { + name: "phase0", + st: statePhase0, + keys: keysPhase0, + att1: att1Phase0, + att2: att2Phase0, + slashing: slashingPhase0, + slashedBalance: 31750000000, }, - AttestingIndices: []uint64{0, 1}, - }) - domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot()) - require.NoError(t, err) - signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) - assert.NoError(t, err, "Could not get signing root of beacon block header") - sig0 := privKeys[0].Sign(signingRoot[:]) - sig1 := privKeys[1].Sign(signingRoot[:]) - aggregateSig := bls.AggregateSignatures([]bls.Signature{sig0, sig1}) - att1.Signature = aggregateSig.Marshal() - - att2 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ - AttestingIndices: []uint64{0, 1}, - }) - signingRoot, err = signing.ComputeSigningRoot(att2.Data, domain) - assert.NoError(t, err, "Could not get signing root of beacon block header") - sig0 = privKeys[0].Sign(signingRoot[:]) - sig1 = privKeys[1].Sign(signingRoot[:]) - aggregateSig = bls.AggregateSignatures([]bls.Signature{sig0, sig1}) - att2.Signature = aggregateSig.Marshal() - - slashings := []*ethpb.AttesterSlashing{ { - Attestation_1: att1, - Attestation_2: att2, + name: "altair", + st: stateAltair, + keys: keysAltair, + att1: att1Phase0, + att2: att2Phase0, + slashing: slashingPhase0, + slashedBalance: 31500000000, }, - } - - currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch - require.NoError(t, beaconState.SetSlot(currentSlot)) - - b := util.NewBeaconBlock() - b.Block = ðpb.BeaconBlock{ - Body: ðpb.BeaconBlockBody{ - AttesterSlashings: slashings, + { + name: "bellatrix", + st: stateBellatrix, + keys: keysBellatrix, + att1: att1Phase0, + att2: att2Phase0, + slashing: slashingPhase0, + slashedBalance: 31000000000, }, - } - - ss := make([]ethpb.AttSlashing, len(b.Block.Body.AttesterSlashings)) - for i, s := range b.Block.Body.AttesterSlashings { - ss[i] = s - } - newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, ss, v.SlashValidator) - require.NoError(t, err) - newRegistry := newState.Validators() - - // Given the intersection of slashable indices is [1], only validator - // at index 1 should be slashed and exited. We confirm this below. - if newRegistry[1].ExitEpoch != beaconState.Validators()[1].ExitEpoch { - t.Errorf( - ` - Expected validator at index 1's exit epoch to match - %d, received %d instead - `, - beaconState.Validators()[1].ExitEpoch, - newRegistry[1].ExitEpoch, - ) - } - - require.Equal(t, uint64(31000000000), newState.Balances()[1]) - require.Equal(t, uint64(32000000000), newState.Balances()[2]) -} - -func TestProcessAttesterSlashings_AppliesCorrectStatusCapella(t *testing.T) { - beaconState, privKeys := util.DeterministicGenesisStateCapella(t, 100) - for _, vv := range beaconState.Validators() { - vv.WithdrawableEpoch = primitives.Epoch(params.BeaconConfig().SlotsPerEpoch) - } - - att1 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ - Data: ðpb.AttestationData{ - Source: ðpb.Checkpoint{Epoch: 1}, + { + name: "capella", + st: stateCapella, + keys: keysCapella, + att1: att1Phase0, + att2: att2Phase0, + slashing: slashingPhase0, + slashedBalance: 31000000000, }, - AttestingIndices: []uint64{0, 1}, - }) - domain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot()) - require.NoError(t, err) - signingRoot, err := signing.ComputeSigningRoot(att1.Data, domain) - assert.NoError(t, err, "Could not get signing root of beacon block header") - sig0 := privKeys[0].Sign(signingRoot[:]) - sig1 := privKeys[1].Sign(signingRoot[:]) - aggregateSig := bls.AggregateSignatures([]bls.Signature{sig0, sig1}) - att1.Signature = aggregateSig.Marshal() - - att2 := util.HydrateIndexedAttestation(ðpb.IndexedAttestation{ - AttestingIndices: []uint64{0, 1}, - }) - signingRoot, err = signing.ComputeSigningRoot(att2.Data, domain) - assert.NoError(t, err, "Could not get signing root of beacon block header") - sig0 = privKeys[0].Sign(signingRoot[:]) - sig1 = privKeys[1].Sign(signingRoot[:]) - aggregateSig = bls.AggregateSignatures([]bls.Signature{sig0, sig1}) - att2.Signature = aggregateSig.Marshal() - - slashings := []*ethpb.AttesterSlashing{ { - Attestation_1: att1, - Attestation_2: att2, + name: "deneb", + st: stateDeneb, + keys: keysDeneb, + att1: att1Phase0, + att2: att2Phase0, + slashing: slashingPhase0, + slashedBalance: 31000000000, }, - } - - currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch - require.NoError(t, beaconState.SetSlot(currentSlot)) - - b := util.NewBeaconBlock() - b.Block = ðpb.BeaconBlock{ - Body: ðpb.BeaconBlockBody{ - AttesterSlashings: slashings, + { + name: "electra", + st: stateElectra, + keys: keysElectra, + att1: att1Electra, + att2: att2Electra, + slashing: slashingElectra, + slashedBalance: 31992187500, }, } - ss := make([]ethpb.AttSlashing, len(b.Block.Body.AttesterSlashings)) - for i, s := range b.Block.Body.AttesterSlashings { - ss[i] = s - } - newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, ss, v.SlashValidator) - require.NoError(t, err) - newRegistry := newState.Validators() - - // Given the intersection of slashable indices is [1], only validator - // at index 1 should be slashed and exited. We confirm this below. - if newRegistry[1].ExitEpoch != beaconState.Validators()[1].ExitEpoch { - t.Errorf( - ` + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for _, vv := range tc.st.Validators() { + vv.WithdrawableEpoch = primitives.Epoch(params.BeaconConfig().SlotsPerEpoch) + } + + domain, err := signing.Domain(tc.st.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, tc.st.GenesisValidatorsRoot()) + require.NoError(t, err) + signingRoot, err := signing.ComputeSigningRoot(tc.att1.GetData(), domain) + assert.NoError(t, err, "Could not get signing root of beacon block header") + sig0 := tc.keys[0].Sign(signingRoot[:]) + sig1 := tc.keys[1].Sign(signingRoot[:]) + aggregateSig := bls.AggregateSignatures([]bls.Signature{sig0, sig1}) + + if tc.att1.Version() >= version.Electra { + tc.att1.(*ethpb.IndexedAttestationElectra).Signature = aggregateSig.Marshal() + } else { + tc.att1.(*ethpb.IndexedAttestation).Signature = aggregateSig.Marshal() + } + + signingRoot, err = signing.ComputeSigningRoot(tc.att2.GetData(), domain) + assert.NoError(t, err, "Could not get signing root of beacon block header") + sig0 = tc.keys[0].Sign(signingRoot[:]) + sig1 = tc.keys[1].Sign(signingRoot[:]) + aggregateSig = bls.AggregateSignatures([]bls.Signature{sig0, sig1}) + + if tc.att2.Version() >= version.Electra { + tc.att2.(*ethpb.IndexedAttestationElectra).Signature = aggregateSig.Marshal() + } else { + tc.att2.(*ethpb.IndexedAttestation).Signature = aggregateSig.Marshal() + } + + currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch + require.NoError(t, tc.st.SetSlot(currentSlot)) + + newState, err := blocks.ProcessAttesterSlashings(context.Background(), tc.st, []ethpb.AttSlashing{tc.slashing}, v.SlashValidator) + require.NoError(t, err) + newRegistry := newState.Validators() + + // Given the intersection of slashable indices is [1], only validator + // at index 1 should be slashed and exited. We confirm this below. + if newRegistry[1].ExitEpoch != tc.st.Validators()[1].ExitEpoch { + t.Errorf( + ` Expected validator at index 1's exit epoch to match %d, received %d instead `, - beaconState.Validators()[1].ExitEpoch, - newRegistry[1].ExitEpoch, - ) + tc.st.Validators()[1].ExitEpoch, + newRegistry[1].ExitEpoch, + ) + } + + require.Equal(t, tc.slashedBalance, newState.Balances()[1]) + require.Equal(t, uint64(32000000000), newState.Balances()[2]) + }) } - - require.Equal(t, uint64(31000000000), newState.Balances()[1]) - require.Equal(t, uint64(32000000000), newState.Balances()[2]) } diff --git a/beacon-chain/core/blocks/deposit.go b/beacon-chain/core/blocks/deposit.go index 3b8b715ca1a8..af7a45b67b84 100644 --- a/beacon-chain/core/blocks/deposit.go +++ b/beacon-chain/core/blocks/deposit.go @@ -55,12 +55,26 @@ func BatchVerifyDepositsSignatures(ctx context.Context, deposits []*ethpb.Deposi return false, err } - verified := false if err := verifyDepositDataWithDomain(ctx, deposits, domain); err != nil { log.WithError(err).Debug("Failed to batch verify deposits signatures, will try individual verify") - verified = true + return false, nil + } + return true, nil +} + +// BatchVerifyPendingDepositsSignatures batch verifies pending deposit signatures. +func BatchVerifyPendingDepositsSignatures(ctx context.Context, deposits []*ethpb.PendingDeposit) (bool, error) { + var err error + domain, err := signing.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil) + if err != nil { + return false, err + } + + if err := verifyPendingDepositDataWithDomain(ctx, deposits, domain); err != nil { + log.WithError(err).Debug("Failed to batch verify deposits signatures, will try individual verify") + return false, nil } - return verified, nil + return true, nil } // IsValidDepositSignature returns whether deposit_data is valid @@ -159,3 +173,44 @@ func verifyDepositDataWithDomain(ctx context.Context, deps []*ethpb.Deposit, dom } return nil } + +func verifyPendingDepositDataWithDomain(ctx context.Context, deps []*ethpb.PendingDeposit, domain []byte) error { + if len(deps) == 0 { + return nil + } + pks := make([]bls.PublicKey, len(deps)) + sigs := make([][]byte, len(deps)) + msgs := make([][32]byte, len(deps)) + for i, dep := range deps { + if ctx.Err() != nil { + return ctx.Err() + } + if dep == nil { + return errors.New("nil deposit") + } + dpk, err := bls.PublicKeyFromBytes(dep.PublicKey) + if err != nil { + return err + } + pks[i] = dpk + sigs[i] = dep.Signature + depositMessage := ðpb.DepositMessage{ + PublicKey: dep.PublicKey, + WithdrawalCredentials: dep.WithdrawalCredentials, + Amount: dep.Amount, + } + sr, err := signing.ComputeSigningRoot(depositMessage, domain) + if err != nil { + return err + } + msgs[i] = sr + } + verify, err := bls.VerifyMultipleSignatures(sigs, msgs, pks) + if err != nil { + return errors.Errorf("could not verify multiple signatures: %v", err) + } + if !verify { + return errors.New("one or more deposit signatures did not verify") + } + return nil +} diff --git a/beacon-chain/core/blocks/deposit_test.go b/beacon-chain/core/blocks/deposit_test.go index 31ba22f23d17..480b4f5c1890 100644 --- a/beacon-chain/core/blocks/deposit_test.go +++ b/beacon-chain/core/blocks/deposit_test.go @@ -17,6 +17,41 @@ import ( ) func TestBatchVerifyDepositsSignatures_Ok(t *testing.T) { + sk, err := bls.RandKey() + require.NoError(t, err) + domain, err := signing.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil) + require.NoError(t, err) + deposit := ðpb.Deposit{ + Data: ðpb.Deposit_Data{ + PublicKey: sk.PublicKey().Marshal(), + WithdrawalCredentials: make([]byte, 32), + Amount: 3000, + }, + } + sr, err := signing.ComputeSigningRoot(ðpb.DepositMessage{ + PublicKey: deposit.Data.PublicKey, + WithdrawalCredentials: deposit.Data.WithdrawalCredentials, + Amount: 3000, + }, domain) + require.NoError(t, err) + sig := sk.Sign(sr[:]) + deposit.Data.Signature = sig.Marshal() + leaf, err := deposit.Data.HashTreeRoot() + require.NoError(t, err) + // We then create a merkle branch for the test. + depositTrie, err := trie.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth) + require.NoError(t, err, "Could not generate trie") + proof, err := depositTrie.MerkleProof(0) + require.NoError(t, err, "Could not generate proof") + + deposit.Proof = proof + require.NoError(t, err) + verified, err := blocks.BatchVerifyDepositsSignatures(context.Background(), []*ethpb.Deposit{deposit}) + require.NoError(t, err) + require.Equal(t, true, verified) +} + +func TestBatchVerifyDepositsSignatures_InvalidSignature(t *testing.T) { deposit := ðpb.Deposit{ Data: ðpb.Deposit_Data{ PublicKey: bytesutil.PadTo([]byte{1, 2, 3}, 48), @@ -34,9 +69,9 @@ func TestBatchVerifyDepositsSignatures_Ok(t *testing.T) { deposit.Proof = proof require.NoError(t, err) - ok, err := blocks.BatchVerifyDepositsSignatures(context.Background(), []*ethpb.Deposit{deposit}) + verified, err := blocks.BatchVerifyDepositsSignatures(context.Background(), []*ethpb.Deposit{deposit}) require.NoError(t, err) - require.Equal(t, true, ok) + require.Equal(t, false, verified) } func TestVerifyDeposit_MerkleBranchFailsVerification(t *testing.T) { @@ -93,3 +128,54 @@ func TestIsValidDepositSignature_Ok(t *testing.T) { require.NoError(t, err) require.Equal(t, true, valid) } + +func TestBatchVerifyPendingDepositsSignatures_Ok(t *testing.T) { + sk, err := bls.RandKey() + require.NoError(t, err) + domain, err := signing.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil) + require.NoError(t, err) + pendingDeposit := ðpb.PendingDeposit{ + PublicKey: sk.PublicKey().Marshal(), + WithdrawalCredentials: make([]byte, 32), + Amount: 3000, + } + sr, err := signing.ComputeSigningRoot(ðpb.DepositMessage{ + PublicKey: pendingDeposit.PublicKey, + WithdrawalCredentials: pendingDeposit.WithdrawalCredentials, + Amount: 3000, + }, domain) + require.NoError(t, err) + sig := sk.Sign(sr[:]) + pendingDeposit.Signature = sig.Marshal() + + sk2, err := bls.RandKey() + require.NoError(t, err) + pendingDeposit2 := ðpb.PendingDeposit{ + PublicKey: sk2.PublicKey().Marshal(), + WithdrawalCredentials: make([]byte, 32), + Amount: 4000, + } + sr2, err := signing.ComputeSigningRoot(ðpb.DepositMessage{ + PublicKey: pendingDeposit2.PublicKey, + WithdrawalCredentials: pendingDeposit2.WithdrawalCredentials, + Amount: 4000, + }, domain) + require.NoError(t, err) + sig2 := sk2.Sign(sr2[:]) + pendingDeposit2.Signature = sig2.Marshal() + + verified, err := blocks.BatchVerifyPendingDepositsSignatures(context.Background(), []*ethpb.PendingDeposit{pendingDeposit, pendingDeposit2}) + require.NoError(t, err) + require.Equal(t, true, verified) +} + +func TestBatchVerifyPendingDepositsSignatures_InvalidSignature(t *testing.T) { + pendingDeposit := ðpb.PendingDeposit{ + PublicKey: bytesutil.PadTo([]byte{1, 2, 3}, 48), + WithdrawalCredentials: make([]byte, 32), + Signature: make([]byte, 96), + } + verified, err := blocks.BatchVerifyPendingDepositsSignatures(context.Background(), []*ethpb.PendingDeposit{pendingDeposit}) + require.NoError(t, err) + require.Equal(t, false, verified) +} diff --git a/beacon-chain/core/blocks/exports_test.go b/beacon-chain/core/blocks/exports_test.go index 3d92819f3449..b3e1374b42e3 100644 --- a/beacon-chain/core/blocks/exports_test.go +++ b/beacon-chain/core/blocks/exports_test.go @@ -1,3 +1,5 @@ package blocks var ProcessBLSToExecutionChange = processBLSToExecutionChange +var ErrInvalidBLSPrefix = errInvalidBLSPrefix +var VerifyBlobCommitmentCount = verifyBlobCommitmentCount diff --git a/beacon-chain/core/blocks/genesis.go b/beacon-chain/core/blocks/genesis.go index 1099085cc2e9..2b140909c1d7 100644 --- a/beacon-chain/core/blocks/genesis.go +++ b/beacon-chain/core/blocks/genesis.go @@ -198,7 +198,7 @@ func NewGenesisBlockForState(ctx context.Context, st state.BeaconState) (interfa SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8), SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), }, - ExecutionPayload: &enginev1.ExecutionPayloadElectra{ + ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ ParentHash: make([]byte, 32), FeeRecipient: make([]byte, 20), StateRoot: make([]byte, 32), @@ -213,6 +213,11 @@ func NewGenesisBlockForState(ctx context.Context, st state.BeaconState) (interfa }, BlsToExecutionChanges: make([]*ethpb.SignedBLSToExecutionChange, 0), BlobKzgCommitments: make([][]byte, 0), + ExecutionRequests: &enginev1.ExecutionRequests{ + Withdrawals: make([]*enginev1.WithdrawalRequest, 0), + Deposits: make([]*enginev1.DepositRequest, 0), + Consolidations: make([]*enginev1.ConsolidationRequest, 0), + }, }, }, Signature: params.BeaconConfig().EmptySignature[:], diff --git a/beacon-chain/core/blocks/payload.go b/beacon-chain/core/blocks/payload.go index 9529aa087bad..27f0a6860f7f 100644 --- a/beacon-chain/core/blocks/payload.go +++ b/beacon-chain/core/blocks/payload.go @@ -2,14 +2,17 @@ package blocks import ( "bytes" + "fmt" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/params" consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" @@ -59,6 +62,9 @@ func IsExecutionBlock(body interfaces.ReadOnlyBeaconBlockBody) (bool, error) { if body == nil { return false, errors.New("nil block body") } + if body.Version() >= version.Capella { + return true, nil + } payload, err := body.Execution() switch { case errors.Is(err, consensus_types.ErrUnsupportedField): @@ -200,90 +206,41 @@ func ValidatePayload(st state.BeaconState, payload interfaces.ExecutionData) err // block_hash=payload.block_hash, // transactions_root=hash_tree_root(payload.transactions), // ) -func ProcessPayload(st state.BeaconState, payload interfaces.ExecutionData) (state.BeaconState, error) { - var err error - if st.Version() >= version.Capella { - st, err = ProcessWithdrawals(st, payload) - if err != nil { - return nil, errors.Wrap(err, "could not process withdrawals") - } +func ProcessPayload(st state.BeaconState, body interfaces.ReadOnlyBeaconBlockBody) error { + payload, err := body.Execution() + if err != nil { + return err + } + if err := verifyBlobCommitmentCount(st.Slot(), body); err != nil { + return err } if err := ValidatePayloadWhenMergeCompletes(st, payload); err != nil { - return nil, err + return err } if err := ValidatePayload(st, payload); err != nil { - return nil, err - } - if err := st.SetLatestExecutionPayloadHeader(payload); err != nil { - return nil, err - } - return st, nil -} - -// ValidatePayloadHeaderWhenMergeCompletes validates the payload header when the merge completes. -func ValidatePayloadHeaderWhenMergeCompletes(st state.BeaconState, header interfaces.ExecutionData) error { - // Skip validation if the state is not merge compatible. - complete, err := IsMergeTransitionComplete(st) - if err != nil { return err } - if !complete { - return nil - } - // Validate current header's parent hash matches state header's block hash. - h, err := st.LatestExecutionPayloadHeader() - if err != nil { + if err := st.SetLatestExecutionPayloadHeader(payload); err != nil { return err } - if !bytes.Equal(header.ParentHash(), h.BlockHash()) { - return ErrInvalidPayloadBlockHash - } return nil } -// ValidatePayloadHeader validates the payload header. -func ValidatePayloadHeader(st state.BeaconState, header interfaces.ExecutionData) error { - // Validate header's random mix matches with state in current epoch - random, err := helpers.RandaoMix(st, time.CurrentEpoch(st)) - if err != nil { - return err - } - if !bytes.Equal(header.PrevRandao(), random) { - return ErrInvalidPayloadPrevRandao +func verifyBlobCommitmentCount(slot primitives.Slot, body interfaces.ReadOnlyBeaconBlockBody) error { + if body.Version() < version.Deneb { + return nil } - - // Validate header's timestamp matches with state in current slot. - t, err := slots.ToTime(st.GenesisTime(), st.Slot()) + kzgs, err := body.BlobKzgCommitments() if err != nil { return err } - if header.Timestamp() != uint64(t.Unix()) { - return ErrInvalidPayloadTimeStamp + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(slot) + if len(kzgs) > maxBlobsPerBlock { + return fmt.Errorf("too many kzg commitments in block: %d", len(kzgs)) } return nil } -// ProcessPayloadHeader processes the payload header. -func ProcessPayloadHeader(st state.BeaconState, header interfaces.ExecutionData) (state.BeaconState, error) { - var err error - if st.Version() >= version.Capella { - st, err = ProcessWithdrawals(st, header) - if err != nil { - return nil, errors.Wrap(err, "could not process withdrawals") - } - } - if err := ValidatePayloadHeaderWhenMergeCompletes(st, header); err != nil { - return nil, err - } - if err := ValidatePayloadHeader(st, header); err != nil { - return nil, err - } - if err := st.SetLatestExecutionPayloadHeader(header); err != nil { - return nil, err - } - return st, nil -} - // GetBlockPayloadHash returns the hash of the execution payload of the block func GetBlockPayloadHash(blk interfaces.ReadOnlyBeaconBlock) ([32]byte, error) { var payloadHash [32]byte diff --git a/beacon-chain/core/blocks/payload_test.go b/beacon-chain/core/blocks/payload_test.go index 0da3e9b523ff..f93752e3a8d4 100644 --- a/beacon-chain/core/blocks/payload_test.go +++ b/beacon-chain/core/blocks/payload_test.go @@ -1,6 +1,7 @@ package blocks_test import ( + "fmt" "testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" @@ -8,11 +9,13 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/ssz" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" "github.com/prysmaticlabs/prysm/v5/time/slots" @@ -251,7 +254,8 @@ func Test_IsExecutionBlockCapella(t *testing.T) { require.NoError(t, err) got, err := blocks.IsExecutionBlock(wrappedBlock.Body()) require.NoError(t, err) - require.Equal(t, false, got) + // #14614 + require.Equal(t, true, got) } func Test_IsExecutionEnabled(t *testing.T) { @@ -581,14 +585,17 @@ func Test_ProcessPayload(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappedPayload, err := consensusblocks.WrappedExecutionPayload(tt.payload) + body, err := consensusblocks.NewBeaconBlockBody(ðpb.BeaconBlockBodyBellatrix{ + ExecutionPayload: tt.payload, + }) require.NoError(t, err) - st, err := blocks.ProcessPayload(st, wrappedPayload) - if err != nil { + if err := blocks.ProcessPayload(st, body); err != nil { require.Equal(t, tt.err.Error(), err.Error()) } else { require.Equal(t, tt.err, err) - want, err := consensusblocks.PayloadToHeader(wrappedPayload) + payload, err := body.Execution() + require.NoError(t, err) + want, err := consensusblocks.PayloadToHeader(payload) require.Equal(t, tt.err, err) h, err := st.LatestExecutionPayloadHeader() require.NoError(t, err) @@ -609,13 +616,14 @@ func Test_ProcessPayloadCapella(t *testing.T) { random, err := helpers.RandaoMix(st, time.CurrentEpoch(st)) require.NoError(t, err) payload.PrevRandao = random - wrapped, err := consensusblocks.WrappedExecutionPayloadCapella(payload) - require.NoError(t, err) - _, err = blocks.ProcessPayload(st, wrapped) + body, err := consensusblocks.NewBeaconBlockBody(ðpb.BeaconBlockBodyCapella{ + ExecutionPayload: payload, + }) require.NoError(t, err) + require.NoError(t, blocks.ProcessPayload(st, body)) } -func Test_ProcessPayloadHeader(t *testing.T) { +func Test_ProcessPayload_Blinded(t *testing.T) { st, _ := util.DeterministicGenesisStateBellatrix(t, 1) random, err := helpers.RandaoMix(st, time.CurrentEpoch(st)) require.NoError(t, err) @@ -663,8 +671,13 @@ func Test_ProcessPayloadHeader(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - st, err := blocks.ProcessPayloadHeader(st, tt.header) - if err != nil { + p, ok := tt.header.Proto().(*enginev1.ExecutionPayloadHeader) + require.Equal(t, true, ok) + body, err := consensusblocks.NewBeaconBlockBody(ðpb.BlindedBeaconBlockBodyBellatrix{ + ExecutionPayloadHeader: p, + }) + require.NoError(t, err) + if err := blocks.ProcessPayload(st, body); err != nil { require.Equal(t, tt.err.Error(), err.Error()) } else { require.Equal(t, tt.err, err) @@ -728,7 +741,7 @@ func Test_ValidatePayloadHeader(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err = blocks.ValidatePayloadHeader(st, tt.header) + err = blocks.ValidatePayload(st, tt.header) require.Equal(t, tt.err, err) }) } @@ -785,7 +798,7 @@ func Test_ValidatePayloadHeaderWhenMergeCompletes(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err = blocks.ValidatePayloadHeaderWhenMergeCompletes(tt.state, tt.header) + err = blocks.ValidatePayloadWhenMergeCompletes(tt.state, tt.header) require.Equal(t, tt.err, err) }) } @@ -906,3 +919,15 @@ func emptyPayloadCapella() *enginev1.ExecutionPayloadCapella { Withdrawals: make([]*enginev1.Withdrawal, 0), } } + +func TestVerifyBlobCommitmentCount(t *testing.T) { + b := ðpb.BeaconBlockDeneb{Body: ðpb.BeaconBlockBodyDeneb{}} + rb, err := consensusblocks.NewBeaconBlock(b) + require.NoError(t, err) + require.NoError(t, blocks.VerifyBlobCommitmentCount(rb.Slot(), rb.Body())) + + b = ðpb.BeaconBlockDeneb{Body: ðpb.BeaconBlockBodyDeneb{BlobKzgCommitments: make([][]byte, params.BeaconConfig().MaxBlobsPerBlock(rb.Slot())+1)}} + rb, err = consensusblocks.NewBeaconBlock(b) + require.NoError(t, err) + require.ErrorContains(t, fmt.Sprintf("too many kzg commitments in block: %d", params.BeaconConfig().MaxBlobsPerBlock(rb.Slot())+1), blocks.VerifyBlobCommitmentCount(rb.Slot(), rb.Body())) +} diff --git a/beacon-chain/core/blocks/withdrawals.go b/beacon-chain/core/blocks/withdrawals.go index e2f202ce9081..f51e916d6c1b 100644 --- a/beacon-chain/core/blocks/withdrawals.go +++ b/beacon-chain/core/blocks/withdrawals.go @@ -100,8 +100,11 @@ func ValidateBLSToExecutionChange(st state.ReadOnlyBeaconState, signed *ethpb.Si if err != nil { return nil, err } + if val == nil { + return nil, errors.Wrap(errInvalidWithdrawalCredentials, "validator is nil") // This should not be possible. + } cred := val.WithdrawalCredentials - if cred[0] != params.BeaconConfig().BLSWithdrawalPrefixByte { + if len(cred) < 2 || cred[0] != params.BeaconConfig().BLSWithdrawalPrefixByte { return nil, errInvalidBLSPrefix } @@ -120,35 +123,36 @@ func ValidateBLSToExecutionChange(st state.ReadOnlyBeaconState, signed *ethpb.Si // // Spec pseudocode definition: // -// def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: -// expected_withdrawals, partial_withdrawals_count = get_expected_withdrawals(state) # [Modified in Electra:EIP7251] +// def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: +// +// expected_withdrawals, processed_partial_withdrawals_count = get_expected_withdrawals(state) # [Modified in Electra:EIP7251] // -// assert len(payload.withdrawals) == len(expected_withdrawals) +// assert len(payload.withdrawals) == len(expected_withdrawals) // -// for expected_withdrawal, withdrawal in zip(expected_withdrawals, payload.withdrawals): -// assert withdrawal == expected_withdrawal -// decrease_balance(state, withdrawal.validator_index, withdrawal.amount) +// for expected_withdrawal, withdrawal in zip(expected_withdrawals, payload.withdrawals): +// assert withdrawal == expected_withdrawal +// decrease_balance(state, withdrawal.validator_index, withdrawal.amount) // -// # Update pending partial withdrawals [New in Electra:EIP7251] -// state.pending_partial_withdrawals = state.pending_partial_withdrawals[partial_withdrawals_count:] +// # Update pending partial withdrawals [New in Electra:EIP7251] +// state.pending_partial_withdrawals = state.pending_partial_withdrawals[processed_partial_withdrawals_count:] // -// # Update the next withdrawal index if this block contained withdrawals -// if len(expected_withdrawals) != 0: -// latest_withdrawal = expected_withdrawals[-1] -// state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1) +// # Update the next withdrawal index if this block contained withdrawals +// if len(expected_withdrawals) != 0: +// latest_withdrawal = expected_withdrawals[-1] +// state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1) // -// # Update the next validator index to start the next withdrawal sweep -// if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD: -// # Next sweep starts after the latest withdrawal's validator index -// next_validator_index = ValidatorIndex((expected_withdrawals[-1].validator_index + 1) % len(state.validators)) -// state.next_withdrawal_validator_index = next_validator_index -// else: -// # Advance sweep by the max length of the sweep if there was not a full set of withdrawals -// next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP -// next_validator_index = ValidatorIndex(next_index % len(state.validators)) -// state.next_withdrawal_validator_index = next_validator_index +// # Update the next validator index to start the next withdrawal sweep +// if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD: +// # Next sweep starts after the latest withdrawal's validator index +// next_validator_index = ValidatorIndex((expected_withdrawals[-1].validator_index + 1) % len(state.validators)) +// state.next_withdrawal_validator_index = next_validator_index +// else: +// # Advance sweep by the max length of the sweep if there was not a full set of withdrawals +// next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP +// next_validator_index = ValidatorIndex(next_index % len(state.validators)) +// state.next_withdrawal_validator_index = next_validator_index func ProcessWithdrawals(st state.BeaconState, executionData interfaces.ExecutionData) (state.BeaconState, error) { - expectedWithdrawals, partialWithdrawalsCount, err := st.ExpectedWithdrawals() + expectedWithdrawals, processedPartialWithdrawalsCount, err := st.ExpectedWithdrawals() if err != nil { return nil, errors.Wrap(err, "could not get expected withdrawals") } @@ -192,7 +196,7 @@ func ProcessWithdrawals(st state.BeaconState, executionData interfaces.Execution } if st.Version() >= version.Electra { - if err := st.DequeuePartialWithdrawals(partialWithdrawalsCount); err != nil { + if err := st.DequeuePendingPartialWithdrawals(processedPartialWithdrawalsCount); err != nil { return nil, fmt.Errorf("unable to dequeue partial withdrawals from state: %w", err) } } diff --git a/beacon-chain/core/blocks/withdrawals_test.go b/beacon-chain/core/blocks/withdrawals_test.go index 7d7dc5dc08f6..9a6f290d7556 100644 --- a/beacon-chain/core/blocks/withdrawals_test.go +++ b/beacon-chain/core/blocks/withdrawals_test.go @@ -113,7 +113,42 @@ func TestProcessBLSToExecutionChange(t *testing.T) { require.NoError(t, err) require.DeepEqual(t, digest[:], val.WithdrawalCredentials) }) + t.Run("nil validator does not panic", func(t *testing.T) { + priv, err := bls.RandKey() + require.NoError(t, err) + pubkey := priv.PublicKey().Marshal() + message := ðpb.BLSToExecutionChange{ + ToExecutionAddress: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13}, + ValidatorIndex: 0, + FromBlsPubkey: pubkey, + } + + registry := []*ethpb.Validator{ + nil, + } + st, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{ + Validators: registry, + Fork: ðpb.Fork{ + CurrentVersion: params.BeaconConfig().GenesisForkVersion, + PreviousVersion: params.BeaconConfig().GenesisForkVersion, + }, + Slot: params.BeaconConfig().SlotsPerEpoch * 5, + }) + require.NoError(t, err) + + signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, priv) + require.NoError(t, err) + + signed := ðpb.SignedBLSToExecutionChange{ + Message: message, + Signature: signature, + } + _, err = blocks.ValidateBLSToExecutionChange(st, signed) + // The state should return an empty validator, even when the validator object in the registry is + // nil. This error should return when the withdrawal credentials are invalid or too short. + require.ErrorIs(t, err, blocks.ErrInvalidBLSPrefix) + }) t.Run("non-existent validator", func(t *testing.T) { priv, err := bls.RandKey() require.NoError(t, err) @@ -1117,7 +1152,7 @@ func TestProcessWithdrawals(t *testing.T) { } st, err = state_native.InitializeFromProtoUnsafeElectra(spb) require.NoError(t, err) - p, err = consensusblocks.WrappedExecutionPayloadElectra(&enginev1.ExecutionPayloadElectra{Withdrawals: test.Args.Withdrawals}) + p, err = consensusblocks.WrappedExecutionPayloadDeneb(&enginev1.ExecutionPayloadDeneb{Withdrawals: test.Args.Withdrawals}) require.NoError(t, err) default: t.Fatalf("Add a beacon state setup for version %s", version.String(fork)) diff --git a/beacon-chain/core/electra/BUILD.bazel b/beacon-chain/core/electra/BUILD.bazel index 8e9da396597d..0cde0db8b1ef 100644 --- a/beacon-chain/core/electra/BUILD.bazel +++ b/beacon-chain/core/electra/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "consolidations.go", "deposits.go", "effective_balance_updates.go", + "error.go", "registry_updates.go", "transition.go", "transition_no_verify_sig.go", @@ -32,15 +33,18 @@ go_library( "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//contracts/deposit:go_default_library", + "//crypto/bls/common:go_default_library", "//encoding/bytesutil:go_default_library", "//math:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", + "@com_github_ethereum_go_ethereum//common/math:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -52,24 +56,30 @@ go_test( "deposit_fuzz_test.go", "deposits_test.go", "effective_balance_updates_test.go", + "error_test.go", + "export_test.go", "registry_updates_test.go", + "transition_no_verify_sig_test.go", "transition_test.go", "upgrade_test.go", "validator_test.go", "withdrawals_test.go", ], + data = glob(["testdata/**"]), + embed = [":go_default_library"], deps = [ - ":go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", + "//beacon-chain/state/testing:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", "//crypto/bls:go_default_library", + "//crypto/bls/common:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", @@ -80,6 +90,7 @@ go_test( "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_google_gofuzz//:go_default_library", + "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", ], diff --git a/beacon-chain/core/electra/churn_test.go b/beacon-chain/core/electra/churn_test.go index 4ce1731e7293..aede85646a81 100644 --- a/beacon-chain/core/electra/churn_test.go +++ b/beacon-chain/core/electra/churn_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -20,7 +21,7 @@ func createValidatorsWithTotalActiveBalance(totalBal primitives.Gwei) []*eth.Val vals := make([]*eth.Validator, num) for i := range vals { wd := make([]byte, 32) - wd[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wd[0] = params.BeaconConfig().CompoundingWithdrawalPrefixByte wd[31] = byte(i) vals[i] = ð.Validator{ @@ -129,6 +130,57 @@ func TestComputeConsolidationEpochAndUpdateChurn(t *testing.T) { expectedEpoch: 16, // Flows into another epoch. expectedConsolidationBalanceToConsume: 200000000000, // 200 ETH }, + { + name: "balance to consume is zero, consolidation balance at limit", + state: func(t *testing.T) state.BeaconState { + activeBal := 32000000000000000 // 32M ETH + s, err := state_native.InitializeFromProtoUnsafeElectra(ð.BeaconStateElectra{ + Slot: slots.UnsafeEpochStart(10), + EarliestConsolidationEpoch: 16, + ConsolidationBalanceToConsume: 0, + Validators: createValidatorsWithTotalActiveBalance(primitives.Gwei(activeBal)), + }) + require.NoError(t, err) + return s + }(t), + consolidationBalance: helpers.ConsolidationChurnLimit(32000000000000000), + expectedEpoch: 17, // Flows into another epoch. + expectedConsolidationBalanceToConsume: 0, + }, + { + name: "consolidation balance equals consolidation balance to consume", + state: func(t *testing.T) state.BeaconState { + activeBal := 32000000000000000 // 32M ETH + s, err := state_native.InitializeFromProtoUnsafeElectra(ð.BeaconStateElectra{ + Slot: slots.UnsafeEpochStart(10), + EarliestConsolidationEpoch: 16, + ConsolidationBalanceToConsume: helpers.ConsolidationChurnLimit(32000000000000000), + Validators: createValidatorsWithTotalActiveBalance(primitives.Gwei(activeBal)), + }) + require.NoError(t, err) + return s + }(t), + consolidationBalance: helpers.ConsolidationChurnLimit(32000000000000000), + expectedEpoch: 16, + expectedConsolidationBalanceToConsume: 0, + }, + { + name: "consolidation balance exceeds limit by one", + state: func(t *testing.T) state.BeaconState { + activeBal := 32000000000000000 // 32M ETH + s, err := state_native.InitializeFromProtoUnsafeElectra(ð.BeaconStateElectra{ + Slot: slots.UnsafeEpochStart(10), + EarliestConsolidationEpoch: 16, + ConsolidationBalanceToConsume: 0, + Validators: createValidatorsWithTotalActiveBalance(primitives.Gwei(activeBal)), + }) + require.NoError(t, err) + return s + }(t), + consolidationBalance: helpers.ConsolidationChurnLimit(32000000000000000) + 1, + expectedEpoch: 18, // Flows into another epoch. + expectedConsolidationBalanceToConsume: helpers.ConsolidationChurnLimit(32000000000000000) - 1, + }, } for _, tt := range tests { diff --git a/beacon-chain/core/electra/consolidations.go b/beacon-chain/core/electra/consolidations.go index 6fe9c69c5721..978b72ad1d0e 100644 --- a/beacon-chain/core/electra/consolidations.go +++ b/beacon-chain/core/electra/consolidations.go @@ -5,16 +5,19 @@ import ( "context" "fmt" + "github.com/ethereum/go-ethereum/common/math" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" + log "github.com/sirupsen/logrus" ) // ProcessPendingConsolidations implements the spec definition below. This method makes mutating @@ -22,25 +25,27 @@ import ( // // Spec definition: // -// def process_pending_consolidations(state: BeaconState) -> None: -// next_pending_consolidation = 0 -// for pending_consolidation in state.pending_consolidations: -// source_validator = state.validators[pending_consolidation.source_index] -// if source_validator.slashed: -// next_pending_consolidation += 1 -// continue -// if source_validator.withdrawable_epoch > get_current_epoch(state): -// break -// -// # Churn any target excess active balance of target and raise its max -// switch_to_compounding_validator(state, pending_consolidation.target_index) -// # Move active balance to target. Excess balance is withdrawable. -// active_balance = get_active_balance(state, pending_consolidation.source_index) -// decrease_balance(state, pending_consolidation.source_index, active_balance) -// increase_balance(state, pending_consolidation.target_index, active_balance) +// def process_pending_consolidations(state: BeaconState) -> None: +// +// next_epoch = Epoch(get_current_epoch(state) + 1) +// next_pending_consolidation = 0 +// for pending_consolidation in state.pending_consolidations: +// source_validator = state.validators[pending_consolidation.source_index] +// if source_validator.slashed: // next_pending_consolidation += 1 +// continue +// if source_validator.withdrawable_epoch > next_epoch: +// break +// +// # Calculate the consolidated balance +// source_effective_balance = min(state.balances[pending_consolidation.source_index], source_validator.effective_balance) +// +// # Move active balance to target. Excess balance is withdrawable. +// decrease_balance(state, pending_consolidation.source_index, source_effective_balance) +// increase_balance(state, pending_consolidation.target_index, source_effective_balance) +// next_pending_consolidation += 1 // -// state.pending_consolidations = state.pending_consolidations[next_pending_consolidation:] +// state.pending_consolidations = state.pending_consolidations[next_pending_consolidation:] func ProcessPendingConsolidations(ctx context.Context, st state.BeaconState) error { _, span := trace.StartSpan(ctx, "electra.ProcessPendingConsolidations") defer span.End() @@ -49,39 +54,36 @@ func ProcessPendingConsolidations(ctx context.Context, st state.BeaconState) err return errors.New("nil state") } - currentEpoch := slots.ToEpoch(st.Slot()) + nextEpoch := slots.ToEpoch(st.Slot()) + 1 - var nextPendingConsolidation uint64 pendingConsolidations, err := st.PendingConsolidations() if err != nil { return err } - + var nextPendingConsolidation uint64 for _, pc := range pendingConsolidations { - sourceValidator, err := st.ValidatorAtIndex(pc.SourceIndex) + sourceValidator, err := st.ValidatorAtIndexReadOnly(pc.SourceIndex) if err != nil { return err } - if sourceValidator.Slashed { + if sourceValidator.Slashed() { nextPendingConsolidation++ continue } - if sourceValidator.WithdrawableEpoch > currentEpoch { + if sourceValidator.WithdrawableEpoch() > nextEpoch { break } - if err := SwitchToCompoundingValidator(st, pc.TargetIndex); err != nil { - return err - } - - activeBalance, err := st.ActiveBalanceAtIndex(pc.SourceIndex) + validatorBalance, err := st.BalanceAtIndex(pc.SourceIndex) if err != nil { return err } - if err := helpers.DecreaseBalance(st, pc.SourceIndex, activeBalance); err != nil { + b := min(validatorBalance, sourceValidator.EffectiveBalance()) + + if err := helpers.DecreaseBalance(st, pc.SourceIndex, b); err != nil { return err } - if err := helpers.IncreaseBalance(st, pc.TargetIndex, activeBalance); err != nil { + if err := helpers.IncreaseBalance(st, pc.TargetIndex, b); err != nil { return err } nextPendingConsolidation++ @@ -101,6 +103,16 @@ func ProcessPendingConsolidations(ctx context.Context, st state.BeaconState) err // state: BeaconState, // consolidation_request: ConsolidationRequest // ) -> None: +// if is_valid_switch_to_compounding_request(state, consolidation_request): +// validator_pubkeys = [v.pubkey for v in state.validators] +// request_source_pubkey = consolidation_request.source_pubkey +// source_index = ValidatorIndex(validator_pubkeys.index(request_source_pubkey)) +// switch_to_compounding_validator(state, source_index) +// return +// +// # Verify that source != target, so a consolidation cannot be used as an exit. +// if consolidation_request.source_pubkey == consolidation_request.target_pubkey: +// return // # If the pending consolidations queue is full, consolidation requests are ignored // if len(state.pending_consolidations) == PENDING_CONSOLIDATIONS_LIMIT: // return @@ -121,10 +133,6 @@ func ProcessPendingConsolidations(ctx context.Context, st state.BeaconState) err // source_validator = state.validators[source_index] // target_validator = state.validators[target_index] // -// # Verify that source != target, so a consolidation cannot be used as an exit. -// if source_index == target_index: -// return -// // # Verify source withdrawal credentials // has_correct_credential = has_execution_withdrawal_credential(source_validator) // is_correct_source_address = ( @@ -133,8 +141,8 @@ func ProcessPendingConsolidations(ctx context.Context, st state.BeaconState) err // if not (has_correct_credential and is_correct_source_address): // return // -// # Verify that target has execution withdrawal credentials -// if not has_execution_withdrawal_credential(target_validator): +// # Verify that target has compounding withdrawal credentials +// if not has_compounding_withdrawal_credential(target_validator): // return // // # Verify the source and the target are active @@ -149,6 +157,13 @@ func ProcessPendingConsolidations(ctx context.Context, st state.BeaconState) err // if target_validator.exit_epoch != FAR_FUTURE_EPOCH: // return // +// # Verify the source has been active long enough +// if current_epoch < source_validator.activation_epoch + SHARD_COMMITTEE_PERIOD: +// return +// +// # Verify the source has no pending withdrawals in the queue +// if get_pending_balance_to_withdraw(state, source_index) > 0: +// return // # Initiate source validator exit and append pending consolidation // source_validator.exit_epoch = compute_consolidation_epoch_and_update_churn( // state, source_validator.effective_balance @@ -164,40 +179,56 @@ func ProcessConsolidationRequests(ctx context.Context, st state.BeaconState, req if len(reqs) == 0 || st == nil { return nil } - - activeBal, err := helpers.TotalActiveBalance(st) - if err != nil { - return err - } - churnLimit := helpers.ConsolidationChurnLimit(primitives.Gwei(activeBal)) - if churnLimit <= primitives.Gwei(params.BeaconConfig().MinActivationBalance) { - return nil - } curEpoch := slots.ToEpoch(st.Slot()) ffe := params.BeaconConfig().FarFutureEpoch minValWithdrawDelay := params.BeaconConfig().MinValidatorWithdrawabilityDelay pcLimit := params.BeaconConfig().PendingConsolidationsLimit for _, cr := range reqs { + if cr == nil { + return errors.New("nil consolidation request") + } if ctx.Err() != nil { return fmt.Errorf("cannot process consolidation requests: %w", ctx.Err()) } + if IsValidSwitchToCompoundingRequest(st, cr) { + srcIdx, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(cr.SourcePubkey)) + if !ok { + log.Error("failed to find source validator index") + continue + } + if err := SwitchToCompoundingValidator(st, srcIdx); err != nil { + log.WithError(err).Error("failed to switch to compounding validator") + } + continue + } + sourcePubkey := bytesutil.ToBytes48(cr.SourcePubkey) + targetPubkey := bytesutil.ToBytes48(cr.TargetPubkey) + if sourcePubkey == targetPubkey { + continue + } + if npc, err := st.NumPendingConsolidations(); err != nil { return fmt.Errorf("failed to fetch number of pending consolidations: %w", err) // This should never happen. } else if npc >= pcLimit { return nil } - srcIdx, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(cr.SourcePubkey)) - if !ok { - continue + activeBal, err := helpers.TotalActiveBalance(st) + if err != nil { + return err + } + churnLimit := helpers.ConsolidationChurnLimit(primitives.Gwei(activeBal)) + if churnLimit <= primitives.Gwei(params.BeaconConfig().MinActivationBalance) { + return nil } - tgtIdx, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(cr.TargetPubkey)) + + srcIdx, ok := st.ValidatorIndexByPubkey(sourcePubkey) if !ok { continue } - - if srcIdx == tgtIdx { + tgtIdx, ok := st.ValidatorIndexByPubkey(targetPubkey) + if !ok { continue } @@ -206,13 +237,18 @@ func ProcessConsolidationRequests(ctx context.Context, st state.BeaconState, req return fmt.Errorf("failed to fetch source validator: %w", err) // This should never happen. } + roSrcV, err := state_native.NewValidator(srcV) + if err != nil { + return err + } + tgtV, err := st.ValidatorAtIndexReadOnly(tgtIdx) if err != nil { return fmt.Errorf("failed to fetch target validator: %w", err) // This should never happen. } // Verify source withdrawal credentials - if !helpers.HasExecutionWithdrawalCredentials(srcV) { + if !roSrcV.HasExecutionWithdrawalCredentials() { continue } // Confirm source_validator.withdrawal_credentials[12:] == consolidation_request.source_address @@ -221,7 +257,7 @@ func ProcessConsolidationRequests(ctx context.Context, st state.BeaconState, req } // Target validator must have their withdrawal credentials set appropriately. - if !helpers.HasExecutionWithdrawalCredentials(tgtV) { + if !tgtV.HasCompoundingWithdrawalCredentials() { continue } @@ -229,15 +265,33 @@ func ProcessConsolidationRequests(ctx context.Context, st state.BeaconState, req if !helpers.IsActiveValidator(srcV, curEpoch) || !helpers.IsActiveValidatorUsingTrie(tgtV, curEpoch) { continue } - // Neither validator are exiting. + // Neither validator is exiting. if srcV.ExitEpoch != ffe || tgtV.ExitEpoch() != ffe { continue } + e, overflow := math.SafeAdd(uint64(srcV.ActivationEpoch), uint64(params.BeaconConfig().ShardCommitteePeriod)) + if overflow { + log.Error("Overflow when adding activation epoch and shard committee period") + continue + } + if uint64(curEpoch) < e { + continue + } + bal, err := st.PendingBalanceToWithdraw(srcIdx) + if err != nil { + log.WithError(err).Error("failed to fetch pending balance to withdraw") + continue + } + if bal > 0 { + continue + } + // Initiate the exit of the source validator. exitEpoch, err := ComputeConsolidationEpochAndUpdateChurn(ctx, st, primitives.Gwei(srcV.EffectiveBalance)) if err != nil { - return fmt.Errorf("failed to compute consolidaiton epoch: %w", err) + log.WithError(err).Error("failed to compute consolidation epoch") + continue } srcV.ExitEpoch = exitEpoch srcV.WithdrawableEpoch = exitEpoch + minValWithdrawDelay @@ -252,3 +306,84 @@ func ProcessConsolidationRequests(ctx context.Context, st state.BeaconState, req return nil } + +// IsValidSwitchToCompoundingRequest returns true if the given consolidation request is valid for switching to compounding. +// +// Spec code: +// +// def is_valid_switch_to_compounding_request( +// +// state: BeaconState, +// consolidation_request: ConsolidationRequest +// +// ) -> bool: +// +// # Switch to compounding requires source and target be equal +// if consolidation_request.source_pubkey != consolidation_request.target_pubkey: +// return False +// +// # Verify pubkey exists +// source_pubkey = consolidation_request.source_pubkey +// validator_pubkeys = [v.pubkey for v in state.validators] +// if source_pubkey not in validator_pubkeys: +// return False +// +// source_validator = state.validators[ValidatorIndex(validator_pubkeys.index(source_pubkey))] +// +// # Verify request has been authorized +// if source_validator.withdrawal_credentials[12:] != consolidation_request.source_address: +// return False +// +// # Verify source withdrawal credentials +// if not has_eth1_withdrawal_credential(source_validator): +// return False +// +// # Verify the source is active +// current_epoch = get_current_epoch(state) +// if not is_active_validator(source_validator, current_epoch): +// return False +// +// # Verify exit for source has not been initiated +// if source_validator.exit_epoch != FAR_FUTURE_EPOCH: +// return False +// +// return True +func IsValidSwitchToCompoundingRequest(st state.BeaconState, req *enginev1.ConsolidationRequest) bool { + if req.SourcePubkey == nil || req.TargetPubkey == nil { + return false + } + + if !bytes.Equal(req.SourcePubkey, req.TargetPubkey) { + return false + } + + srcIdx, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(req.SourcePubkey)) + if !ok { + return false + } + // As per the consensus specification, this error is not considered an assertion. + // Therefore, if the source_pubkey is not found in validator_pubkeys, we simply return false. + srcV, err := st.ValidatorAtIndexReadOnly(srcIdx) + if err != nil { + return false + } + sourceAddress := req.SourceAddress + withdrawalCreds := srcV.GetWithdrawalCredentials() + if len(withdrawalCreds) != 32 || len(sourceAddress) != 20 || !bytes.HasSuffix(withdrawalCreds, sourceAddress) { + return false + } + + if !srcV.HasETH1WithdrawalCredentials() { + return false + } + + curEpoch := slots.ToEpoch(st.Slot()) + if !helpers.IsActiveValidatorUsingTrie(srcV, curEpoch) { + return false + } + + if srcV.ExitEpoch() != params.BeaconConfig().FarFutureEpoch { + return false + } + return true +} diff --git a/beacon-chain/core/electra/consolidations_test.go b/beacon-chain/core/electra/consolidations_test.go index 98378fed3ca1..611dda2ed90e 100644 --- a/beacon-chain/core/electra/consolidations_test.go +++ b/beacon-chain/core/electra/consolidations_test.go @@ -13,6 +13,7 @@ import ( enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" ) func TestProcessPendingConsolidations(t *testing.T) { @@ -45,6 +46,7 @@ func TestProcessPendingConsolidations(t *testing.T) { Validators: []*eth.Validator{ { WithdrawalCredentials: []byte{0x01, 0xFF}, + EffectiveBalance: params.BeaconConfig().MinActivationBalance, }, { WithdrawalCredentials: []byte{0x01, 0xAB}, @@ -80,10 +82,10 @@ func TestProcessPendingConsolidations(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(0), num) - // v1 is switched to compounding validator. + // v1 withdrawal credentials should not be updated. v1, err := st.ValidatorAtIndex(1) require.NoError(t, err) - require.Equal(t, params.BeaconConfig().CompoundingWithdrawalPrefixByte, v1.WithdrawalCredentials[0]) + require.Equal(t, params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, v1.WithdrawalCredentials[0]) }, wantErr: false, }, @@ -201,58 +203,48 @@ func TestProcessPendingConsolidations(t *testing.T) { } } -func stateWithActiveBalanceETH(t *testing.T, balETH uint64) state.BeaconState { - gwei := balETH * 1_000_000_000 - balPerVal := params.BeaconConfig().MinActivationBalance - numVals := gwei / balPerVal - - vals := make([]*eth.Validator, numVals) - bals := make([]uint64, numVals) - for i := uint64(0); i < numVals; i++ { - wc := make([]byte, 32) - wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte - wc[31] = byte(i) - vals[i] = ð.Validator{ - ActivationEpoch: 0, - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - EffectiveBalance: balPerVal, - WithdrawalCredentials: wc, - } - bals[i] = balPerVal - } - st, err := state_native.InitializeFromProtoUnsafeElectra(ð.BeaconStateElectra{ - Slot: 10 * params.BeaconConfig().SlotsPerEpoch, - Validators: vals, - Balances: bals, - Fork: ð.Fork{ - CurrentVersion: params.BeaconConfig().ElectraForkVersion, - }, - }) - require.NoError(t, err) - - return st -} - func TestProcessConsolidationRequests(t *testing.T) { tests := []struct { name string state state.BeaconState reqs []*enginev1.ConsolidationRequest validate func(*testing.T, state.BeaconState) + wantErr bool }{ + { + name: "nil request", + state: func() state.BeaconState { + st := ð.BeaconStateElectra{} + s, err := state_native.InitializeFromProtoElectra(st) + require.NoError(t, err) + return s + }(), + reqs: []*enginev1.ConsolidationRequest{nil}, + validate: func(t *testing.T, st state.BeaconState) { + require.DeepEqual(t, st, st) + }, + wantErr: true, + }, { name: "one valid request", state: func() state.BeaconState { st := ð.BeaconStateElectra{ + Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)), Validators: createValidatorsWithTotalActiveBalance(32000000000000000), // 32M ETH } // Validator scenario setup. See comments in reqs section. st.Validators[3].WithdrawalCredentials = bytesutil.Bytes32(0) - st.Validators[8].WithdrawalCredentials = bytesutil.Bytes32(0) + st.Validators[8].WithdrawalCredentials = bytesutil.Bytes32(1) st.Validators[9].ActivationEpoch = params.BeaconConfig().FarFutureEpoch st.Validators[12].ActivationEpoch = params.BeaconConfig().FarFutureEpoch st.Validators[13].ExitEpoch = 10 st.Validators[16].ExitEpoch = 10 + st.PendingPartialWithdrawals = []*eth.PendingPartialWithdrawal{ + { + Index: 17, + Amount: 100, + }, + } s, err := state_native.InitializeFromProtoElectra(st) require.NoError(t, err) return s @@ -270,7 +262,7 @@ func TestProcessConsolidationRequests(t *testing.T) { SourcePubkey: []byte("val_5"), TargetPubkey: []byte("val_6"), }, - // Target does not have their withdrawal credentials set appropriately. + // Target does not have their withdrawal credentials set appropriately. (Using eth1 address prefix) { SourceAddress: append(bytesutil.PadTo(nil, 19), byte(7)), SourcePubkey: []byte("val_7"), @@ -318,6 +310,12 @@ func TestProcessConsolidationRequests(t *testing.T) { SourcePubkey: []byte("val_0"), TargetPubkey: []byte("val_0"), }, + // Has pending partial withdrawal + { + SourceAddress: append(bytesutil.PadTo(nil, 19), byte(0)), + SourcePubkey: []byte("val_17"), + TargetPubkey: []byte("val_1"), + }, // Valid consolidation request. This should be last to ensure invalid requests do // not end the processing early. { @@ -378,6 +376,7 @@ func TestProcessConsolidationRequests(t *testing.T) { name: "pending consolidations limit reached during processing", state: func() state.BeaconState { st := ð.BeaconStateElectra{ + Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)), Validators: createValidatorsWithTotalActiveBalance(32000000000000000), // 32M ETH PendingConsolidations: make([]*eth.PendingConsolidation, params.BeaconConfig().PendingConsolidationsLimit-1), } @@ -421,10 +420,100 @@ func TestProcessConsolidationRequests(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := electra.ProcessConsolidationRequests(context.TODO(), tt.state, tt.reqs) - require.NoError(t, err) + if (err != nil) != tt.wantErr { + t.Errorf("ProcessWithdrawalRequests() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !tt.wantErr { + require.NoError(t, err) + } if tt.validate != nil { tt.validate(t, tt.state) } }) } } + +func TestIsValidSwitchToCompoundingRequest(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, 1) + t.Run("nil source pubkey", func(t *testing.T) { + ok := electra.IsValidSwitchToCompoundingRequest(st, &enginev1.ConsolidationRequest{ + SourcePubkey: nil, + TargetPubkey: []byte{'a'}, + }) + require.Equal(t, false, ok) + }) + t.Run("nil target pubkey", func(t *testing.T) { + ok := electra.IsValidSwitchToCompoundingRequest(st, &enginev1.ConsolidationRequest{ + TargetPubkey: nil, + SourcePubkey: []byte{'a'}, + }) + require.Equal(t, false, ok) + }) + t.Run("different source and target pubkey", func(t *testing.T) { + ok := electra.IsValidSwitchToCompoundingRequest(st, &enginev1.ConsolidationRequest{ + TargetPubkey: []byte{'a'}, + SourcePubkey: []byte{'b'}, + }) + require.Equal(t, false, ok) + }) + t.Run("source validator not found in state", func(t *testing.T) { + ok := electra.IsValidSwitchToCompoundingRequest(st, &enginev1.ConsolidationRequest{ + SourceAddress: make([]byte, 20), + TargetPubkey: []byte{'a'}, + SourcePubkey: []byte{'a'}, + }) + require.Equal(t, false, ok) + }) + t.Run("incorrect source address", func(t *testing.T) { + v, err := st.ValidatorAtIndex(0) + require.NoError(t, err) + pubkey := v.PublicKey + ok := electra.IsValidSwitchToCompoundingRequest(st, &enginev1.ConsolidationRequest{ + SourceAddress: make([]byte, 20), + TargetPubkey: pubkey, + SourcePubkey: pubkey, + }) + require.Equal(t, false, ok) + }) + t.Run("incorrect eth1 withdrawal credential", func(t *testing.T) { + v, err := st.ValidatorAtIndex(0) + require.NoError(t, err) + pubkey := v.PublicKey + wc := v.WithdrawalCredentials + ok := electra.IsValidSwitchToCompoundingRequest(st, &enginev1.ConsolidationRequest{ + SourceAddress: wc[12:], + TargetPubkey: pubkey, + SourcePubkey: pubkey, + }) + require.Equal(t, false, ok) + }) + t.Run("is valid compounding request", func(t *testing.T) { + v, err := st.ValidatorAtIndex(0) + require.NoError(t, err) + pubkey := v.PublicKey + wc := v.WithdrawalCredentials + v.WithdrawalCredentials[0] = 1 + require.NoError(t, st.UpdateValidatorAtIndex(0, v)) + ok := electra.IsValidSwitchToCompoundingRequest(st, &enginev1.ConsolidationRequest{ + SourceAddress: wc[12:], + TargetPubkey: pubkey, + SourcePubkey: pubkey, + }) + require.Equal(t, true, ok) + }) + t.Run("already has an exit epoch", func(t *testing.T) { + v, err := st.ValidatorAtIndex(0) + require.NoError(t, err) + pubkey := v.PublicKey + wc := v.WithdrawalCredentials + v.ExitEpoch = 100 + require.NoError(t, st.UpdateValidatorAtIndex(0, v)) + ok := electra.IsValidSwitchToCompoundingRequest(st, &enginev1.ConsolidationRequest{ + SourceAddress: wc[12:], + TargetPubkey: pubkey, + SourcePubkey: pubkey, + }) + require.Equal(t, false, ok) + }) +} diff --git a/beacon-chain/core/electra/deposits.go b/beacon-chain/core/electra/deposits.go index aab787b4f2dd..c0baaf3cf0b7 100644 --- a/beacon-chain/core/electra/deposits.go +++ b/beacon-chain/core/electra/deposits.go @@ -2,23 +2,23 @@ package electra import ( "context" - "fmt" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/contracts/deposit" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" - eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" log "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // ProcessDeposits is one of the operations performed on each processed @@ -38,7 +38,7 @@ func ProcessDeposits( defer span.End() // Attempt to verify all deposit signatures at once, if this fails then fall back to processing // individual deposits with signature verification enabled. - batchVerified, err := blocks.BatchVerifyDepositsSignatures(ctx, deposits) + allSignaturesVerified, err := blocks.BatchVerifyDepositsSignatures(ctx, deposits) if err != nil { return nil, errors.Wrap(err, "could not verify deposit signatures in batch") } @@ -47,7 +47,7 @@ func ProcessDeposits( if d == nil || d.Data == nil { return nil, errors.New("got a nil deposit in block") } - beaconState, err = ProcessDeposit(beaconState, d, batchVerified) + beaconState, err = ProcessDeposit(beaconState, d, allSignaturesVerified) if err != nil { return nil, errors.Wrapf(err, "could not process deposit from %#x", bytesutil.Trunc(d.Data.PublicKey)) } @@ -82,7 +82,7 @@ func ProcessDeposits( // amount=deposit.data.amount, // signature=deposit.data.signature, // ) -func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconState, error) { +func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, allSignaturesVerified bool) (state.BeaconState, error) { if err := blocks.VerifyDeposit(beaconState, deposit); err != nil { if deposit == nil || deposit.Data == nil { return nil, err @@ -92,37 +92,49 @@ func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verif if err := beaconState.SetEth1DepositIndex(beaconState.Eth1DepositIndex() + 1); err != nil { return nil, err } - return ApplyDeposit(beaconState, deposit.Data, verifySignature) + return ApplyDeposit(beaconState, deposit.Data, allSignaturesVerified) } -// ApplyDeposit -// def apply_deposit(state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64, signature: BLSSignature) -> None: -// validator_pubkeys = [v.pubkey for v in state.validators] -// if pubkey not in validator_pubkeys: +// ApplyDeposit adds the incoming deposit as a pending deposit on the state // -// # Verify the deposit signature (proof of possession) which is not checked by the deposit contract -// if is_valid_deposit_signature(pubkey, withdrawal_credentials, amount, signature): -// add_validator_to_registry(state, pubkey, withdrawal_credentials, amount) -// -// else: -// -// # Increase balance by deposit amount -// index = ValidatorIndex(validator_pubkeys.index(pubkey)) -// state.pending_balance_deposits.append(PendingBalanceDeposit(index=index, amount=amount)) # [Modified in Electra:EIP-7251] -// # Check if valid deposit switch to compounding credentials -// -// if ( is_compounding_withdrawal_credential(withdrawal_credentials) and has_eth1_withdrawal_credential(state.validators[index]) +// Spec pseudocode definition: +// def apply_deposit(state: BeaconState, // -// and is_valid_deposit_signature(pubkey, withdrawal_credentials, amount, signature) -// ): -// switch_to_compounding_validator(state, index) -func ApplyDeposit(beaconState state.BeaconState, data *ethpb.Deposit_Data, verifySignature bool) (state.BeaconState, error) { +// pubkey: BLSPubkey, +// withdrawal_credentials: Bytes32, +// amount: uint64, +// signature: BLSSignature) -> None: +// validator_pubkeys = [v.pubkey for v in state.validators] +// if pubkey not in validator_pubkeys: +// # Verify the deposit signature (proof of possession) which is not checked by the deposit contract +// if is_valid_deposit_signature(pubkey, withdrawal_credentials, amount, signature): +// add_validator_to_registry(state, pubkey, withdrawal_credentials, Gwei(0)) # [Modified in Electra:EIP7251] +// # [New in Electra:EIP7251] +// state.pending_deposits.append(PendingDeposit( +// pubkey=pubkey, +// withdrawal_credentials=withdrawal_credentials, +// amount=amount, +// signature=signature, +// slot=GENESIS_SLOT, # Use GENESIS_SLOT to distinguish from a pending deposit request +// )) +// else: +// # Increase balance by deposit amount +// # [Modified in Electra:EIP7251] +// state.pending_deposits.append(PendingDeposit( +// pubkey=pubkey, +// withdrawal_credentials=withdrawal_credentials, +// amount=amount, +// signature=signature, +// slot=GENESIS_SLOT # Use GENESIS_SLOT to distinguish from a pending deposit request +// )) +func ApplyDeposit(beaconState state.BeaconState, data *ethpb.Deposit_Data, allSignaturesVerified bool) (state.BeaconState, error) { pubKey := data.PublicKey amount := data.Amount withdrawalCredentials := data.WithdrawalCredentials - index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey)) + signature := data.Signature + _, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey)) if !ok { - if verifySignature { + if !allSignaturesVerified { valid, err := IsValidDepositSignature(data) if err != nil { return nil, errors.Wrap(err, "could not verify deposit signature") @@ -131,32 +143,20 @@ func ApplyDeposit(beaconState state.BeaconState, data *ethpb.Deposit_Data, verif return beaconState, nil } } - if err := AddValidatorToRegistry(beaconState, pubKey, withdrawalCredentials, amount); err != nil { + + if err := AddValidatorToRegistry(beaconState, pubKey, withdrawalCredentials, 0); err != nil { // # [Modified in Electra:EIP7251] return nil, errors.Wrap(err, "could not add validator to registry") } - } else { - // no validation on top-ups (phase0 feature). no validation before state change - if err := beaconState.AppendPendingBalanceDeposit(index, amount); err != nil { - return nil, err - } - val, err := beaconState.ValidatorAtIndex(index) - if err != nil { - return nil, err - } - if helpers.IsCompoundingWithdrawalCredential(withdrawalCredentials) && helpers.HasETH1WithdrawalCredential(val) { - if verifySignature { - valid, err := IsValidDepositSignature(data) - if err != nil { - return nil, errors.Wrap(err, "could not verify deposit signature") - } - if !valid { - return beaconState, nil - } - } - if err := SwitchToCompoundingValidator(beaconState, index); err != nil { - return nil, errors.Wrap(err, "could not switch to compound validator") - } - } + } + // no validation on top-ups (phase0 feature). no validation before state change + if err := beaconState.AppendPendingDeposit(ðpb.PendingDeposit{ + PublicKey: pubKey, + WithdrawalCredentials: withdrawalCredentials, + Amount: amount, + Signature: signature, + Slot: params.BeaconConfig().GenesisSlot, + }); err != nil { + return nil, err } return beaconState, nil } @@ -185,152 +185,381 @@ func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, domain []byte) error return deposit.VerifyDepositSignature(obj, domain) } -// ProcessPendingBalanceDeposits implements the spec definition below. This method mutates the state. +// ProcessPendingDeposits implements the spec definition below. This method mutates the state. +// Iterating over `pending_deposits` queue this function runs the following checks before applying pending deposit: +// 1. All Eth1 bridge deposits are processed before the first deposit request gets processed. +// 2. Deposit position in the queue is finalized. +// 3. Deposit does not exceed the `MAX_PENDING_DEPOSITS_PER_EPOCH` limit. +// 4. Deposit does not exceed the activation churn limit. // // Spec definition: // -// def process_pending_balance_deposits(state: BeaconState) -> None: -// available_for_processing = state.deposit_balance_to_consume + get_activation_exit_churn_limit(state) -// processed_amount = 0 -// next_deposit_index = 0 -// deposits_to_postpone = [] +// def process_pending_deposits(state: BeaconState) -> None: // -// for deposit in state.pending_balance_deposits: -// validator = state.validators[deposit.index] -// # Validator is exiting, postpone the deposit until after withdrawable epoch -// if validator.exit_epoch < FAR_FUTURE_EPOCH: -// if get_current_epoch(state) <= validator.withdrawable_epoch: -// deposits_to_postpone.append(deposit) -// # Deposited balance will never become active. Increase balance but do not consume churn -// else: -// increase_balance(state, deposit.index, deposit.amount) -// # Validator is not exiting, attempt to process deposit -// else: -// # Deposit does not fit in the churn, no more deposit processing in this epoch. -// if processed_amount + deposit.amount > available_for_processing: -// break -// # Deposit fits in the churn, process it. Increase balance and consume churn. -// else: -// increase_balance(state, deposit.index, deposit.amount) -// processed_amount += deposit.amount -// # Regardless of how the deposit was handled, we move on in the queue. -// next_deposit_index += 1 +// next_epoch = Epoch(get_current_epoch(state) + 1) +// available_for_processing = state.deposit_balance_to_consume + get_activation_exit_churn_limit(state) +// processed_amount = 0 +// next_deposit_index = 0 +// deposits_to_postpone = [] +// is_churn_limit_reached = False +// finalized_slot = compute_start_slot_at_epoch(state.finalized_checkpoint.epoch) +// +// for deposit in state.pending_deposits: +// # Do not process deposit requests if Eth1 bridge deposits are not yet applied. +// if ( +// # Is deposit request +// deposit.slot > GENESIS_SLOT and +// # There are pending Eth1 bridge deposits +// state.eth1_deposit_index < state.deposit_requests_start_index +// ): +// break // -// state.pending_balance_deposits = state.pending_balance_deposits[next_deposit_index:] +// # Check if deposit has been finalized, otherwise, stop processing. +// if deposit.slot > finalized_slot: +// break // -// if len(state.pending_balance_deposits) == 0: -// state.deposit_balance_to_consume = Gwei(0) +// # Check if number of processed deposits has not reached the limit, otherwise, stop processing. +// if next_deposit_index >= MAX_PENDING_DEPOSITS_PER_EPOCH: +// break +// +// # Read validator state +// is_validator_exited = False +// is_validator_withdrawn = False +// validator_pubkeys = [v.pubkey for v in state.validators] +// if deposit.pubkey in validator_pubkeys: +// validator = state.validators[ValidatorIndex(validator_pubkeys.index(deposit.pubkey))] +// is_validator_exited = validator.exit_epoch < FAR_FUTURE_EPOCH +// is_validator_withdrawn = validator.withdrawable_epoch < next_epoch +// +// if is_validator_withdrawn: +// # Deposited balance will never become active. Increase balance but do not consume churn +// apply_pending_deposit(state, deposit) +// elif is_validator_exited: +// # Validator is exiting, postpone the deposit until after withdrawable epoch +// deposits_to_postpone.append(deposit) // else: -// state.deposit_balance_to_consume = available_for_processing - processed_amount +// # Check if deposit fits in the churn, otherwise, do no more deposit processing in this epoch. +// is_churn_limit_reached = processed_amount + deposit.amount > available_for_processing +// if is_churn_limit_reached: +// break +// +// # Consume churn and apply deposit. +// processed_amount += deposit.amount +// apply_pending_deposit(state, deposit) // -// state.pending_balance_deposits += deposits_to_postpone -func ProcessPendingBalanceDeposits(ctx context.Context, st state.BeaconState, activeBalance primitives.Gwei) error { - _, span := trace.StartSpan(ctx, "electra.ProcessPendingBalanceDeposits") +// # Regardless of how the deposit was handled, we move on in the queue. +// next_deposit_index += 1 +// +// state.pending_deposits = state.pending_deposits[next_deposit_index:] + deposits_to_postpone +// +// # Accumulate churn only if the churn limit has been hit. +// if is_churn_limit_reached: +// state.deposit_balance_to_consume = available_for_processing - processed_amount +// else: +// state.deposit_balance_to_consume = Gwei(0) +func ProcessPendingDeposits(ctx context.Context, st state.BeaconState, activeBalance primitives.Gwei) error { + _, span := trace.StartSpan(ctx, "electra.ProcessPendingDeposits") defer span.End() if st == nil || st.IsNil() { return errors.New("nil state") } + // constants & initializations + nextEpoch := slots.ToEpoch(st.Slot()) + 1 + processedAmount := uint64(0) + nextDepositIndex := uint64(0) + isChurnLimitReached := false + + var pendingDepositsToBatchVerify []*ethpb.PendingDeposit + var pendingDepositsToPostpone []*ethpb.PendingDeposit + depBalToConsume, err := st.DepositBalanceToConsume() if err != nil { - return err + return errors.Wrap(err, "could not get deposit balance to consume") } availableForProcessing := depBalToConsume + helpers.ActivationExitChurnLimit(activeBalance) - processedAmount := uint64(0) - nextDepositIndex := 0 - var depositsToPostpone []*eth.PendingBalanceDeposit - deposits, err := st.PendingBalanceDeposits() + finalizedSlot, err := slots.EpochStart(st.FinalizedCheckpoint().Epoch) + if err != nil { + return errors.Wrap(err, "could not get finalized slot") + } + + startIndex, err := st.DepositRequestsStartIndex() + if err != nil { + return errors.Wrap(err, "could not get starting pendingDeposit index") + } + + pendingDeposits, err := st.PendingDeposits() if err != nil { return err } + for _, pendingDeposit := range pendingDeposits { + // Do not process pendingDeposit requests if Eth1 bridge deposits are not yet applied. + if pendingDeposit.Slot > params.BeaconConfig().GenesisSlot && st.Eth1DepositIndex() < startIndex { + break + } - // constants - ffe := params.BeaconConfig().FarFutureEpoch - curEpoch := slots.ToEpoch(st.Slot()) + // Check if pendingDeposit has been finalized, otherwise, stop processing. + if pendingDeposit.Slot > finalizedSlot { + break + } - for _, balanceDeposit := range deposits { - v, err := st.ValidatorAtIndexReadOnly(balanceDeposit.Index) - if err != nil { - return fmt.Errorf("failed to fetch validator at index: %w", err) + // Check if number of processed deposits has not reached the limit, otherwise, stop processing. + if nextDepositIndex >= params.BeaconConfig().MaxPendingDepositsPerEpoch { + break } - // If the validator is currently exiting, postpone the deposit until after the withdrawable - // epoch. - if v.ExitEpoch() < ffe { - if curEpoch <= v.WithdrawableEpoch() { - depositsToPostpone = append(depositsToPostpone, balanceDeposit) - } else { - // The deposited balance will never become active. Therefore, we increase the balance but do - // not consume the churn. - if err := helpers.IncreaseBalance(st, balanceDeposit.Index, balanceDeposit.Amount); err != nil { - return err - } + var isValidatorExited bool + var isValidatorWithdrawn bool + index, found := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(pendingDeposit.PublicKey)) + if found { + val, err := st.ValidatorAtIndexReadOnly(index) + if err != nil { + return errors.Wrap(err, "could not get validator") + } + isValidatorExited = val.ExitEpoch() < params.BeaconConfig().FarFutureEpoch + isValidatorWithdrawn = val.WithdrawableEpoch() < nextEpoch + } + + if isValidatorWithdrawn { + // note: the validator will never be active, just increase the balance + if err := helpers.IncreaseBalance(st, index, pendingDeposit.Amount); err != nil { + return errors.Wrap(err, "could not increase balance") } + } else if isValidatorExited { + pendingDepositsToPostpone = append(pendingDepositsToPostpone, pendingDeposit) } else { - // Validator is not exiting, attempt to process deposit. - if primitives.Gwei(processedAmount+balanceDeposit.Amount) > availableForProcessing { + isChurnLimitReached = primitives.Gwei(processedAmount+pendingDeposit.Amount) > availableForProcessing + if isChurnLimitReached { break } - // Deposit fits in churn, process it. Increase balance and consume churn. - if err := helpers.IncreaseBalance(st, balanceDeposit.Index, balanceDeposit.Amount); err != nil { - return err + processedAmount += pendingDeposit.Amount + + // note: the following code deviates from the spec in order to perform batch signature verification + if found { + if err := helpers.IncreaseBalance(st, index, pendingDeposit.Amount); err != nil { + return errors.Wrap(err, "could not increase balance") + } + } else { + // Collect deposit for batch signature verification + pendingDepositsToBatchVerify = append(pendingDepositsToBatchVerify, pendingDeposit) } - processedAmount += balanceDeposit.Amount } - // Regardless of how the deposit was handled, we move on in the queue. + // Regardless of how the pendingDeposit was handled, we move on in the queue. nextDepositIndex++ } + // Perform batch signature verification on pending deposits that require validator registration + if err = batchProcessNewPendingDeposits(ctx, st, pendingDepositsToBatchVerify); err != nil { + return errors.Wrap(err, "could not process pending deposits with new public keys") + } + // Combined operation: - // - state.pending_balance_deposits = state.pending_balance_deposits[next_deposit_index:] - // - state.pending_balance_deposits += deposits_to_postpone - // However, the number of remaining deposits must be maintained to properly update the deposit + // - state.pending_deposits = state.pending_deposits[next_deposit_index:] + // - state.pending_deposits += deposits_to_postpone + // However, the number of remaining deposits must be maintained to properly update the pendingDeposit // balance to consume. - numRemainingDeposits := len(deposits[nextDepositIndex:]) - deposits = append(deposits[nextDepositIndex:], depositsToPostpone...) - if err := st.SetPendingBalanceDeposits(deposits); err != nil { + pendingDeposits = append(pendingDeposits[nextDepositIndex:], pendingDepositsToPostpone...) + if err := st.SetPendingDeposits(pendingDeposits); err != nil { + return errors.Wrap(err, "could not set pending deposits") + } + // Accumulate churn only if the churn limit has been hit. + if isChurnLimitReached { + return st.SetDepositBalanceToConsume(availableForProcessing - primitives.Gwei(processedAmount)) + } + return st.SetDepositBalanceToConsume(0) +} + +// batchProcessNewPendingDeposits should only be used to process new deposits that require validator registration +func batchProcessNewPendingDeposits(ctx context.Context, state state.BeaconState, pendingDeposits []*ethpb.PendingDeposit) error { + // Return early if there are no deposits to process + if len(pendingDeposits) == 0 { + return nil + } + + // Try batch verification of all deposit signatures + allSignaturesVerified, err := blocks.BatchVerifyPendingDepositsSignatures(ctx, pendingDeposits) + if err != nil { + return errors.Wrap(err, "batch signature verification failed") + } + + // Process each deposit individually + for _, pendingDeposit := range pendingDeposits { + validSignature := allSignaturesVerified + + // If batch verification failed, check the individual deposit signature + if !allSignaturesVerified { + validSignature, err = blocks.IsValidDepositSignature(ðpb.Deposit_Data{ + PublicKey: bytesutil.SafeCopyBytes(pendingDeposit.PublicKey), + WithdrawalCredentials: bytesutil.SafeCopyBytes(pendingDeposit.WithdrawalCredentials), + Amount: pendingDeposit.Amount, + Signature: bytesutil.SafeCopyBytes(pendingDeposit.Signature), + }) + if err != nil { + return errors.Wrap(err, "individual deposit signature verification failed") + } + } + + // Add validator to the registry if the signature is valid + if validSignature { + _, has := state.ValidatorIndexByPubkey(bytesutil.ToBytes48(pendingDeposit.PublicKey)) + if has { + index, _ := state.ValidatorIndexByPubkey(bytesutil.ToBytes48(pendingDeposit.PublicKey)) + if err := helpers.IncreaseBalance(state, index, pendingDeposit.Amount); err != nil { + return errors.Wrap(err, "could not increase balance") + } + } else { + err = AddValidatorToRegistry(state, pendingDeposit.PublicKey, pendingDeposit.WithdrawalCredentials, pendingDeposit.Amount) + if err != nil { + return errors.Wrap(err, "failed to add validator to registry") + } + } + } + } + + return nil +} + +// ApplyPendingDeposit implements the spec definition below. +// Note : This function is NOT used by ProcessPendingDeposits due to simplified logic for more readable batch processing +// +// Spec Definition: +// +// def apply_pending_deposit(state: BeaconState, deposit: PendingDeposit) -> None: +// +// """ +// Applies ``deposit`` to the ``state``. +// """ +// validator_pubkeys = [v.pubkey for v in state.validators] +// if deposit.pubkey not in validator_pubkeys: +// # Verify the deposit signature (proof of possession) which is not checked by the deposit contract +// if is_valid_deposit_signature( +// deposit.pubkey, +// deposit.withdrawal_credentials, +// deposit.amount, +// deposit.signature +// ): +// add_validator_to_registry(state, deposit.pubkey, deposit.withdrawal_credentials, deposit.amount) +// else: +// validator_index = ValidatorIndex(validator_pubkeys.index(deposit.pubkey)) +// # Increase balance +// increase_balance(state, validator_index, deposit.amount) +func ApplyPendingDeposit(ctx context.Context, st state.BeaconState, deposit *ethpb.PendingDeposit) error { + _, span := trace.StartSpan(ctx, "electra.ApplyPendingDeposit") + defer span.End() + index, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(deposit.PublicKey)) + if !ok { + verified, err := blocks.IsValidDepositSignature(ðpb.Deposit_Data{ + PublicKey: bytesutil.SafeCopyBytes(deposit.PublicKey), + WithdrawalCredentials: bytesutil.SafeCopyBytes(deposit.WithdrawalCredentials), + Amount: deposit.Amount, + Signature: bytesutil.SafeCopyBytes(deposit.Signature), + }) + if err != nil { + return errors.Wrap(err, "could not verify deposit signature") + } + + if verified { + if err := AddValidatorToRegistry(st, deposit.PublicKey, deposit.WithdrawalCredentials, deposit.Amount); err != nil { + return errors.Wrap(err, "could not add validator to registry") + } + } + return nil + } + return helpers.IncreaseBalance(st, index, deposit.Amount) +} + +// AddValidatorToRegistry updates the beacon state with validator information +// def add_validator_to_registry(state: BeaconState, pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64) -> None: +// +// index = get_index_for_new_validator(state) +// validator = get_validator_from_deposit(pubkey, withdrawal_credentials, amount) # [Modified in Electra:EIP7251] +// set_or_append_list(state.validators, index, validator) +// set_or_append_list(state.balances, index, amount) +// set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) +// set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) +// set_or_append_list(state.inactivity_scores, index, uint64(0)) +func AddValidatorToRegistry(beaconState state.BeaconState, pubKey []byte, withdrawalCredentials []byte, amount uint64) error { + val, err := GetValidatorFromDeposit(pubKey, withdrawalCredentials, amount) + if err != nil { + return errors.Wrap(err, "could not get validator from deposit") + } + if err := beaconState.AppendValidator(val); err != nil { + return err + } + if err := beaconState.AppendBalance(amount); err != nil { return err } - if numRemainingDeposits == 0 { - return st.SetDepositBalanceToConsume(0) - } else { - return st.SetDepositBalanceToConsume(availableForProcessing - primitives.Gwei(processedAmount)) + // only active in altair and only when it's a new validator (after append balance) + if beaconState.Version() >= version.Altair { + if err := beaconState.AppendInactivityScore(0); err != nil { + return err + } + if err := beaconState.AppendPreviousParticipationBits(0); err != nil { + return err + } + if err := beaconState.AppendCurrentParticipationBits(0); err != nil { + return err + } + } + return nil +} + +// GetValidatorFromDeposit gets a new validator object with provided parameters +// +// def get_validator_from_deposit(pubkey: BLSPubkey, withdrawal_credentials: Bytes32, amount: uint64) -> Validator: +// +// validator = Validator( +// pubkey=pubkey, +// withdrawal_credentials=withdrawal_credentials, +// effective_balance=Gwei(0), +// slashed=False, +// activation_eligibility_epoch=FAR_FUTURE_EPOCH, +// activation_epoch=FAR_FUTURE_EPOCH, +// exit_epoch=FAR_FUTURE_EPOCH, +// withdrawable_epoch=FAR_FUTURE_EPOCH, +// ) +// +// # [Modified in Electra:EIP7251] +// max_effective_balance = get_max_effective_balance(validator) +// validator.effective_balance = min(amount - amount % EFFECTIVE_BALANCE_INCREMENT, max_effective_balance) +// +// return validator +func GetValidatorFromDeposit(pubKey []byte, withdrawalCredentials []byte, amount uint64) (*ethpb.Validator, error) { + validator := ðpb.Validator{ + PublicKey: pubKey, + WithdrawalCredentials: withdrawalCredentials, + EffectiveBalance: 0, + Slashed: false, + ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch, + ActivationEpoch: params.BeaconConfig().FarFutureEpoch, + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch, } + v, err := state_native.NewValidator(validator) + if err != nil { + return nil, err + } + maxEffectiveBalance := helpers.ValidatorMaxEffectiveBalance(v) + validator.EffectiveBalance = min(amount-(amount%params.BeaconConfig().EffectiveBalanceIncrement), maxEffectiveBalance) + return validator, nil } // ProcessDepositRequests is a function as part of electra to process execution layer deposits func ProcessDepositRequests(ctx context.Context, beaconState state.BeaconState, requests []*enginev1.DepositRequest) (state.BeaconState, error) { - ctx, span := trace.StartSpan(ctx, "electra.ProcessDepositRequests") + _, span := trace.StartSpan(ctx, "electra.ProcessDepositRequests") defer span.End() if len(requests) == 0 { return beaconState, nil } - deposits := make([]*ethpb.Deposit, 0) - for _, req := range requests { - if req == nil { - return nil, errors.New("got a nil DepositRequest") - } - deposits = append(deposits, ðpb.Deposit{ - Data: ðpb.Deposit_Data{ - PublicKey: req.Pubkey, - WithdrawalCredentials: req.WithdrawalCredentials, - Amount: req.Amount, - Signature: req.Signature, - }, - }) - } - batchVerified, err := blocks.BatchVerifyDepositsSignatures(ctx, deposits) - if err != nil { - return nil, errors.Wrap(err, "could not verify deposit signatures in batch") - } + var err error for _, receipt := range requests { - beaconState, err = processDepositRequest(beaconState, receipt, batchVerified) + beaconState, err = processDepositRequest(beaconState, receipt) if err != nil { return nil, errors.Wrap(err, "could not apply deposit request") } @@ -338,34 +567,42 @@ func ProcessDepositRequests(ctx context.Context, beaconState state.BeaconState, return beaconState, nil } -// processDepositRequest processes the specific deposit receipt +// processDepositRequest processes the specific deposit request // def process_deposit_request(state: BeaconState, deposit_request: DepositRequest) -> None: // // # Set deposit request start index -// if state.deposit_requests_start_index == UNSET_DEPOSIT_REQUEST_START_INDEX: +// if state.deposit_requests_start_index == UNSET_DEPOSIT_REQUESTS_START_INDEX: // state.deposit_requests_start_index = deposit_request.index // -// apply_deposit( -// state=state, +// # Create pending deposit +// state.pending_deposits.append(PendingDeposit( // pubkey=deposit_request.pubkey, // withdrawal_credentials=deposit_request.withdrawal_credentials, // amount=deposit_request.amount, // signature=deposit_request.signature, -// ) -func processDepositRequest(beaconState state.BeaconState, request *enginev1.DepositRequest, verifySignature bool) (state.BeaconState, error) { +// slot=state.slot, +// )) +func processDepositRequest(beaconState state.BeaconState, request *enginev1.DepositRequest) (state.BeaconState, error) { requestsStartIndex, err := beaconState.DepositRequestsStartIndex() if err != nil { return nil, errors.Wrap(err, "could not get deposit requests start index") } + if request == nil { + return nil, errors.New("nil deposit request") + } if requestsStartIndex == params.BeaconConfig().UnsetDepositRequestsStartIndex { if err := beaconState.SetDepositRequestsStartIndex(request.Index); err != nil { return nil, errors.Wrap(err, "could not set deposit requests start index") } } - return ApplyDeposit(beaconState, ðpb.Deposit_Data{ + if err := beaconState.AppendPendingDeposit(ðpb.PendingDeposit{ PublicKey: bytesutil.SafeCopyBytes(request.Pubkey), - Amount: request.Amount, WithdrawalCredentials: bytesutil.SafeCopyBytes(request.WithdrawalCredentials), + Amount: request.Amount, Signature: bytesutil.SafeCopyBytes(request.Signature), - }, verifySignature) + Slot: beaconState.Slot(), + }); err != nil { + return nil, errors.Wrap(err, "could not append deposit request") + } + return beaconState, nil } diff --git a/beacon-chain/core/electra/deposits_test.go b/beacon-chain/core/electra/deposits_test.go index e498ea613119..484c3297a005 100644 --- a/beacon-chain/core/electra/deposits_test.go +++ b/beacon-chain/core/electra/deposits_test.go @@ -9,10 +9,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" + stateTesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/testing" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" + "github.com/prysmaticlabs/prysm/v5/crypto/bls/common" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -20,7 +22,41 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func TestProcessPendingBalanceDeposits(t *testing.T) { +func TestProcessPendingDepositsMultiplesSameDeposits(t *testing.T) { + st := stateWithActiveBalanceETH(t, 1000) + deps := make([]*eth.PendingDeposit, 2) // Make same deposit twice + validators := st.Validators() + sk, err := bls.RandKey() + require.NoError(t, err) + for i := 0; i < len(deps); i += 1 { + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(i) + validators[i].PublicKey = sk.PublicKey().Marshal() + validators[i].WithdrawalCredentials = wc + deps[i] = stateTesting.GeneratePendingDeposit(t, sk, 32, bytesutil.ToBytes32(wc), 0) + } + require.NoError(t, st.SetPendingDeposits(deps)) + + err = electra.ProcessPendingDeposits(context.TODO(), st, 10000) + require.NoError(t, err) + + val := st.Validators() + seenPubkeys := make(map[string]struct{}) + for i := 0; i < len(val); i += 1 { + if len(val[i].PublicKey) == 0 { + continue + } + _, ok := seenPubkeys[string(val[i].PublicKey)] + if ok { + t.Fatalf("duplicated pubkeys") + } else { + seenPubkeys[string(val[i].PublicKey)] = struct{}{} + } + } +} + +func TestProcessPendingDeposits(t *testing.T) { tests := []struct { name string state state.BeaconState @@ -48,17 +84,10 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { { name: "more deposits than balance to consume processes partial deposits", state: func() state.BeaconState { - st := stateWithActiveBalanceETH(t, 1_000) - require.NoError(t, st.SetDepositBalanceToConsume(100)) amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9) - deps := make([]*eth.PendingBalanceDeposit, 20) - for i := 0; i < len(deps); i += 1 { - deps[i] = ð.PendingBalanceDeposit{ - Amount: uint64(amountAvailForProcessing) / 10, - Index: primitives.ValidatorIndex(i), - } - } - require.NoError(t, st.SetPendingBalanceDeposits(deps)) + depositAmount := uint64(amountAvailForProcessing) / 10 + st := stateWithPendingDeposits(t, 1_000, 20, depositAmount) + require.NoError(t, st.SetDepositBalanceToConsume(100)) return st }(), check: func(t *testing.T, st state.BeaconState) { @@ -74,25 +103,45 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { } // Half of the balance deposits should have been processed. - remaining, err := st.PendingBalanceDeposits() + remaining, err := st.PendingDeposits() require.NoError(t, err) require.Equal(t, 10, len(remaining)) }, }, { - name: "less deposits than balance to consume processes all deposits", + name: "withdrawn validators should not consume churn", state: func() state.BeaconState { - st := stateWithActiveBalanceETH(t, 1_000) - require.NoError(t, st.SetDepositBalanceToConsume(0)) amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9) - deps := make([]*eth.PendingBalanceDeposit, 5) - for i := 0; i < len(deps); i += 1 { - deps[i] = ð.PendingBalanceDeposit{ - Amount: uint64(amountAvailForProcessing) / 5, - Index: primitives.ValidatorIndex(i), - } + depositAmount := uint64(amountAvailForProcessing) + // set the pending deposits to the maximum churn limit + st := stateWithPendingDeposits(t, 1_000, 2, depositAmount) + vals := st.Validators() + vals[1].WithdrawableEpoch = 0 + require.NoError(t, st.SetValidators(vals)) + return st + }(), + check: func(t *testing.T, st state.BeaconState) { + amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9) + // Validators 0..9 should have their balance increased + for i := primitives.ValidatorIndex(0); i < 2; i++ { + b, err := st.BalanceAtIndex(i) + require.NoError(t, err) + require.Equal(t, params.BeaconConfig().MinActivationBalance+uint64(amountAvailForProcessing), b) } - require.NoError(t, st.SetPendingBalanceDeposits(deps)) + + // All pending deposits should have been processed + remaining, err := st.PendingDeposits() + require.NoError(t, err) + require.Equal(t, 0, len(remaining)) + }, + }, + { + name: "less deposits than balance to consume processes all deposits", + state: func() state.BeaconState { + amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9) + depositAmount := uint64(amountAvailForProcessing) / 5 + st := stateWithPendingDeposits(t, 1_000, 5, depositAmount) + require.NoError(t, st.SetDepositBalanceToConsume(0)) return st }(), check: func(t *testing.T, st state.BeaconState) { @@ -108,7 +157,73 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { } // All of the balance deposits should have been processed. - remaining, err := st.PendingBalanceDeposits() + remaining, err := st.PendingDeposits() + require.NoError(t, err) + require.Equal(t, 0, len(remaining)) + }, + }, + { + name: "process pending deposit for unknown key, activates new key", + state: func() state.BeaconState { + st := stateWithActiveBalanceETH(t, 0) + sk, err := bls.RandKey() + require.NoError(t, err) + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(0) + dep := stateTesting.GeneratePendingDeposit(t, sk, params.BeaconConfig().MinActivationBalance, bytesutil.ToBytes32(wc), 0) + require.NoError(t, st.SetPendingDeposits([]*eth.PendingDeposit{dep})) + require.Equal(t, 0, len(st.Validators())) + require.Equal(t, 0, len(st.Balances())) + return st + }(), + check: func(t *testing.T, st state.BeaconState) { + res, err := st.DepositBalanceToConsume() + require.NoError(t, err) + require.Equal(t, primitives.Gwei(0), res) + b, err := st.BalanceAtIndex(0) + require.NoError(t, err) + require.Equal(t, params.BeaconConfig().MinActivationBalance, b) + + // All of the balance deposits should have been processed. + remaining, err := st.PendingDeposits() + require.NoError(t, err) + require.Equal(t, 0, len(remaining)) + + // validator becomes active + require.Equal(t, 1, len(st.Validators())) + require.Equal(t, 1, len(st.Balances())) + }, + }, + { + name: "process excess balance that uses a point to infinity signature, processed as a topup", + state: func() state.BeaconState { + excessBalance := uint64(100) + st := stateWithActiveBalanceETH(t, 32) + validators := st.Validators() + sk, err := bls.RandKey() + require.NoError(t, err) + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(0) + validators[0].PublicKey = sk.PublicKey().Marshal() + validators[0].WithdrawalCredentials = wc + dep := stateTesting.GeneratePendingDeposit(t, sk, excessBalance, bytesutil.ToBytes32(wc), 0) + dep.Signature = common.InfiniteSignature[:] + require.NoError(t, st.SetValidators(validators)) + require.NoError(t, st.SetPendingDeposits([]*eth.PendingDeposit{dep})) + return st + }(), + check: func(t *testing.T, st state.BeaconState) { + res, err := st.DepositBalanceToConsume() + require.NoError(t, err) + require.Equal(t, primitives.Gwei(0), res) + b, err := st.BalanceAtIndex(0) + require.NoError(t, err) + require.Equal(t, params.BeaconConfig().MinActivationBalance+uint64(100), b) + + // All of the balance deposits should have been processed. + remaining, err := st.PendingDeposits() require.NoError(t, err) require.Equal(t, 0, len(remaining)) }, @@ -116,17 +231,10 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { { name: "exiting validator deposit postponed", state: func() state.BeaconState { - st := stateWithActiveBalanceETH(t, 1_000) - require.NoError(t, st.SetDepositBalanceToConsume(0)) amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9) - deps := make([]*eth.PendingBalanceDeposit, 5) - for i := 0; i < len(deps); i += 1 { - deps[i] = ð.PendingBalanceDeposit{ - Amount: uint64(amountAvailForProcessing) / 5, - Index: primitives.ValidatorIndex(i), - } - } - require.NoError(t, st.SetPendingBalanceDeposits(deps)) + depositAmount := uint64(amountAvailForProcessing) / 5 + st := stateWithPendingDeposits(t, 1_000, 5, depositAmount) + require.NoError(t, st.SetDepositBalanceToConsume(0)) v, err := st.ValidatorAtIndex(0) require.NoError(t, err) v.ExitEpoch = 10 @@ -148,7 +256,7 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { // All of the balance deposits should have been processed, except validator index 0 was // added back to the pending deposits queue. - remaining, err := st.PendingBalanceDeposits() + remaining, err := st.PendingDeposits() require.NoError(t, err) require.Equal(t, 1, len(remaining)) }, @@ -156,15 +264,7 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { { name: "exited validator balance increased", state: func() state.BeaconState { - st := stateWithActiveBalanceETH(t, 1_000) - deps := make([]*eth.PendingBalanceDeposit, 1) - for i := 0; i < len(deps); i += 1 { - deps[i] = ð.PendingBalanceDeposit{ - Amount: 1_000_000, - Index: primitives.ValidatorIndex(i), - } - } - require.NoError(t, st.SetPendingBalanceDeposits(deps)) + st := stateWithPendingDeposits(t, 1_000, 1, 1_000_000) v, err := st.ValidatorAtIndex(0) require.NoError(t, err) v.ExitEpoch = 2 @@ -182,7 +282,7 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { require.Equal(t, uint64(1_100_000), b) // All of the balance deposits should have been processed. - remaining, err := st.PendingBalanceDeposits() + remaining, err := st.PendingDeposits() require.NoError(t, err) require.Equal(t, 0, len(remaining)) }, @@ -199,7 +299,7 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { tab, err = helpers.TotalActiveBalance(tt.state) } require.NoError(t, err) - err = electra.ProcessPendingBalanceDeposits(context.TODO(), tt.state, primitives.Gwei(tab)) + err = electra.ProcessPendingDeposits(context.TODO(), tt.state, primitives.Gwei(tab)) require.Equal(t, tt.wantErr, err != nil, "wantErr=%v, got err=%s", tt.wantErr, err) if tt.check != nil { tt.check(t, tt.state) @@ -208,10 +308,32 @@ func TestProcessPendingBalanceDeposits(t *testing.T) { } } +func TestBatchProcessNewPendingDeposits(t *testing.T) { + t.Run("invalid batch initiates correct individual validation", func(t *testing.T) { + st := stateWithActiveBalanceETH(t, 0) + require.Equal(t, 0, len(st.Validators())) + require.Equal(t, 0, len(st.Balances())) + sk, err := bls.RandKey() + require.NoError(t, err) + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(0) + validDep := stateTesting.GeneratePendingDeposit(t, sk, params.BeaconConfig().MinActivationBalance, bytesutil.ToBytes32(wc), 0) + invalidDep := ð.PendingDeposit{PublicKey: make([]byte, 48)} + // have a combination of valid and invalid deposits + deps := []*eth.PendingDeposit{validDep, invalidDep} + require.NoError(t, electra.BatchProcessNewPendingDeposits(context.Background(), st, deps)) + // successfully added to register + require.Equal(t, 1, len(st.Validators())) + require.Equal(t, 1, len(st.Balances())) + }) +} + func TestProcessDepositRequests(t *testing.T) { st, _ := util.DeterministicGenesisStateElectra(t, 1) sk, err := bls.RandKey() require.NoError(t, err) + require.NoError(t, st.SetDepositRequestsStartIndex(1)) t.Run("empty requests continues", func(t *testing.T) { newSt, err := electra.ProcessDepositRequests(context.Background(), st, []*enginev1.DepositRequest{}) @@ -220,7 +342,7 @@ func TestProcessDepositRequests(t *testing.T) { }) t.Run("nil request errors", func(t *testing.T) { _, err = electra.ProcessDepositRequests(context.Background(), st, []*enginev1.DepositRequest{nil}) - require.ErrorContains(t, "got a nil DepositRequest", err) + require.ErrorContains(t, "nil deposit request", err) }) vals := st.Validators() @@ -230,7 +352,7 @@ func TestProcessDepositRequests(t *testing.T) { bals := st.Balances() bals[0] = params.BeaconConfig().MinActivationBalance + 2000 require.NoError(t, st.SetBalances(bals)) - require.NoError(t, st.SetPendingBalanceDeposits(make([]*eth.PendingBalanceDeposit, 0))) // reset pbd as the determinitstic state populates this already + require.NoError(t, st.SetPendingDeposits(make([]*eth.PendingDeposit, 0))) // reset pbd as the determinitstic state populates this already withdrawalCred := make([]byte, 32) withdrawalCred[0] = params.BeaconConfig().CompoundingWithdrawalPrefixByte depositMessage := ð.DepositMessage{ @@ -255,11 +377,10 @@ func TestProcessDepositRequests(t *testing.T) { st, err = electra.ProcessDepositRequests(context.Background(), st, requests) require.NoError(t, err) - pbd, err := st.PendingBalanceDeposits() + pbd, err := st.PendingDeposits() require.NoError(t, err) - require.Equal(t, 2, len(pbd)) + require.Equal(t, 1, len(pbd)) require.Equal(t, uint64(1000), pbd[0].Amount) - require.Equal(t, uint64(2000), pbd[1].Amount) } func TestProcessDeposit_Electra_Simple(t *testing.T) { @@ -286,7 +407,7 @@ func TestProcessDeposit_Electra_Simple(t *testing.T) { require.NoError(t, err) pdSt, err := electra.ProcessDeposits(context.Background(), st, deps) require.NoError(t, err) - pbd, err := pdSt.PendingBalanceDeposits() + pbd, err := pdSt.PendingDeposits() require.NoError(t, err) require.Equal(t, params.BeaconConfig().MinActivationBalance, pbd[2].Amount) require.Equal(t, 3, len(pbd)) @@ -322,7 +443,7 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) { }, }) require.NoError(t, err) - newState, err := electra.ProcessDeposit(beaconState, dep[0], true) + newState, err := electra.ProcessDeposit(beaconState, dep[0], false) require.NoError(t, err, "Expected invalid block deposit to be ignored without error") if newState.Eth1DepositIndex() != 1 { @@ -359,42 +480,128 @@ func TestApplyDeposit_TopUps_WithBadSignature(t *testing.T) { vals[0].PublicKey = sk.PublicKey().Marshal() vals[0].WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte require.NoError(t, st.SetValidators(vals)) - adSt, err := electra.ApplyDeposit(st, depositData, true) + adSt, err := electra.ApplyDeposit(st, depositData, false) require.NoError(t, err) - pbd, err := adSt.PendingBalanceDeposits() + pbd, err := adSt.PendingDeposits() require.NoError(t, err) require.Equal(t, 1, len(pbd)) require.Equal(t, topUpAmount, pbd[0].Amount) } -func TestApplyDeposit_Electra_SwitchToCompoundingValidator(t *testing.T) { - st, _ := util.DeterministicGenesisStateElectra(t, 3) - sk, err := bls.RandKey() +// stateWithActiveBalanceETH generates a mock beacon state given a balance in eth +func stateWithActiveBalanceETH(t *testing.T, balETH uint64) state.BeaconState { + gwei := balETH * 1_000_000_000 + balPerVal := params.BeaconConfig().MinActivationBalance + numVals := gwei / balPerVal + + vals := make([]*eth.Validator, numVals) + bals := make([]uint64, numVals) + for i := uint64(0); i < numVals; i++ { + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(i) + vals[i] = ð.Validator{ + ActivationEpoch: 0, + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + EffectiveBalance: balPerVal, + WithdrawalCredentials: wc, + WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch, + } + bals[i] = balPerVal + } + st, err := state_native.InitializeFromProtoUnsafeElectra(ð.BeaconStateElectra{ + Slot: 10 * params.BeaconConfig().SlotsPerEpoch, + Validators: vals, + Balances: bals, + Fork: ð.Fork{ + CurrentVersion: params.BeaconConfig().ElectraForkVersion, + }, + }) require.NoError(t, err) - withdrawalCred := make([]byte, 32) - withdrawalCred[0] = params.BeaconConfig().CompoundingWithdrawalPrefixByte - depositData := ð.Deposit_Data{ - PublicKey: sk.PublicKey().Marshal(), - Amount: 1000, - WithdrawalCredentials: withdrawalCred, - Signature: make([]byte, fieldparams.BLSSignatureLength), + // set some fake finalized checkpoint + require.NoError(t, st.SetFinalizedCheckpoint(ð.Checkpoint{ + Epoch: 0, + Root: make([]byte, 32), + })) + return st +} + +// stateWithPendingDeposits with pending deposits and existing ethbalance +func stateWithPendingDeposits(t *testing.T, balETH uint64, numDeposits, amount uint64) state.BeaconState { + st := stateWithActiveBalanceETH(t, balETH) + deps := make([]*eth.PendingDeposit, numDeposits) + validators := st.Validators() + for i := 0; i < len(deps); i += 1 { + sk, err := bls.RandKey() + require.NoError(t, err) + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(i) + validators[i].PublicKey = sk.PublicKey().Marshal() + validators[i].WithdrawalCredentials = wc + deps[i] = stateTesting.GeneratePendingDeposit(t, sk, amount, bytesutil.ToBytes32(wc), 0) } - vals := st.Validators() - vals[0].PublicKey = sk.PublicKey().Marshal() - vals[0].WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte - require.NoError(t, st.SetValidators(vals)) - bals := st.Balances() - bals[0] = params.BeaconConfig().MinActivationBalance + 2000 - require.NoError(t, st.SetBalances(bals)) - sr, err := signing.ComputeSigningRoot(depositData, bytesutil.ToBytes(3, 32)) + require.NoError(t, st.SetValidators(validators)) + require.NoError(t, st.SetPendingDeposits(deps)) + return st +} + +func TestApplyPendingDeposit_TopUp(t *testing.T) { + excessBalance := uint64(100) + st := stateWithActiveBalanceETH(t, 32) + validators := st.Validators() + sk, err := bls.RandKey() require.NoError(t, err) - sig := sk.Sign(sr[:]) - depositData.Signature = sig.Marshal() - adSt, err := electra.ApplyDeposit(st, depositData, false) + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(0) + validators[0].PublicKey = sk.PublicKey().Marshal() + validators[0].WithdrawalCredentials = wc + dep := stateTesting.GeneratePendingDeposit(t, sk, excessBalance, bytesutil.ToBytes32(wc), 0) + dep.Signature = common.InfiniteSignature[:] + require.NoError(t, st.SetValidators(validators)) + + require.NoError(t, electra.ApplyPendingDeposit(context.Background(), st, dep)) + + b, err := st.BalanceAtIndex(0) + require.NoError(t, err) + require.Equal(t, params.BeaconConfig().MinActivationBalance+uint64(excessBalance), b) +} + +func TestApplyPendingDeposit_UnknownKey(t *testing.T) { + st := stateWithActiveBalanceETH(t, 0) + sk, err := bls.RandKey() require.NoError(t, err) - pbd, err := adSt.PendingBalanceDeposits() + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(0) + dep := stateTesting.GeneratePendingDeposit(t, sk, params.BeaconConfig().MinActivationBalance, bytesutil.ToBytes32(wc), 0) + require.Equal(t, 0, len(st.Validators())) + require.NoError(t, electra.ApplyPendingDeposit(context.Background(), st, dep)) + // activates new validator + require.Equal(t, 1, len(st.Validators())) + b, err := st.BalanceAtIndex(0) require.NoError(t, err) - require.Equal(t, 2, len(pbd)) - require.Equal(t, uint64(1000), pbd[0].Amount) - require.Equal(t, uint64(2000), pbd[1].Amount) + require.Equal(t, params.BeaconConfig().MinActivationBalance, b) +} + +func TestApplyPendingDeposit_InvalidSignature(t *testing.T) { + st := stateWithActiveBalanceETH(t, 0) + + sk, err := bls.RandKey() + require.NoError(t, err) + wc := make([]byte, 32) + wc[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + wc[31] = byte(0) + dep := ð.PendingDeposit{ + PublicKey: sk.PublicKey().Marshal(), + WithdrawalCredentials: wc, + Amount: 100, + } + require.Equal(t, 0, len(st.Validators())) + require.NoError(t, electra.ApplyPendingDeposit(context.Background(), st, dep)) + // no validator added + require.Equal(t, 0, len(st.Validators())) + // no topup either + require.Equal(t, 0, len(st.Balances())) } diff --git a/beacon-chain/core/electra/effective_balance_updates.go b/beacon-chain/core/electra/effective_balance_updates.go index 60627d378ad1..a16515faeb50 100644 --- a/beacon-chain/core/electra/effective_balance_updates.go +++ b/beacon-chain/core/electra/effective_balance_updates.go @@ -3,7 +3,6 @@ package electra import ( "fmt" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -30,36 +29,36 @@ import ( // or validator.effective_balance + UPWARD_THRESHOLD < balance // ): // validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, EFFECTIVE_BALANCE_LIMIT) -func ProcessEffectiveBalanceUpdates(state state.BeaconState) error { +func ProcessEffectiveBalanceUpdates(st state.BeaconState) error { effBalanceInc := params.BeaconConfig().EffectiveBalanceIncrement hysteresisInc := effBalanceInc / params.BeaconConfig().HysteresisQuotient downwardThreshold := hysteresisInc * params.BeaconConfig().HysteresisDownwardMultiplier upwardThreshold := hysteresisInc * params.BeaconConfig().HysteresisUpwardMultiplier - bals := state.Balances() + bals := st.Balances() // Update effective balances with hysteresis. - validatorFunc := func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - if val == nil { - return false, nil, fmt.Errorf("validator %d is nil in state", idx) + validatorFunc := func(idx int, val state.ReadOnlyValidator) (newVal *ethpb.Validator, err error) { + if val.IsNil() { + return nil, fmt.Errorf("validator %d is nil in state", idx) } if idx >= len(bals) { - return false, nil, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances())) + return nil, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(st.Balances())) } balance := bals[idx] effectiveBalanceLimit := params.BeaconConfig().MinActivationBalance - if helpers.HasCompoundingWithdrawalCredential(val) { + if val.HasCompoundingWithdrawalCredentials() { effectiveBalanceLimit = params.BeaconConfig().MaxEffectiveBalanceElectra } - if balance+downwardThreshold < val.EffectiveBalance || val.EffectiveBalance+upwardThreshold < balance { + if balance+downwardThreshold < val.EffectiveBalance() || val.EffectiveBalance()+upwardThreshold < balance { effectiveBal := min(balance-balance%effBalanceInc, effectiveBalanceLimit) - val.EffectiveBalance = effectiveBal - return true, val, nil + newVal = val.Copy() + newVal.EffectiveBalance = effectiveBal } - return false, val, nil + return newVal, nil } - return state.ApplyToEveryValidator(validatorFunc) + return st.ApplyToEveryValidator(validatorFunc) } diff --git a/beacon-chain/core/electra/effective_balance_updates_test.go b/beacon-chain/core/electra/effective_balance_updates_test.go index 8d3350fb4d7d..765f417d6b95 100644 --- a/beacon-chain/core/electra/effective_balance_updates_test.go +++ b/beacon-chain/core/electra/effective_balance_updates_test.go @@ -11,6 +11,29 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/require" ) +func TestProcessEffectiveBalanceUpdates_SafeCopy(t *testing.T) { + pb := ð.BeaconStateElectra{ + Validators: []*eth.Validator{ + { + EffectiveBalance: params.BeaconConfig().MinActivationBalance, + WithdrawalCredentials: []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte, 0x11}, + }, + }, + Balances: []uint64{ + params.BeaconConfig().MaxEffectiveBalanceElectra * 2, + }, + } + st, err := state_native.InitializeFromProtoElectra(pb) + require.NoError(t, err) + copiedState := st.Copy() + + err = electra.ProcessEffectiveBalanceUpdates(copiedState) + require.NoError(t, err) + + require.Equal(t, st.Validators()[0].EffectiveBalance, params.BeaconConfig().MinActivationBalance) + require.Equal(t, copiedState.Validators()[0].EffectiveBalance, params.BeaconConfig().MaxEffectiveBalanceElectra) +} + func TestProcessEffectiveBalnceUpdates(t *testing.T) { effBalanceInc := params.BeaconConfig().EffectiveBalanceIncrement hysteresisInc := effBalanceInc / params.BeaconConfig().HysteresisQuotient @@ -54,7 +77,7 @@ func TestProcessEffectiveBalnceUpdates(t *testing.T) { Validators: []*eth.Validator{ { EffectiveBalance: params.BeaconConfig().MinActivationBalance / 2, - WithdrawalCredentials: nil, + WithdrawalCredentials: make([]byte, 32), }, }, Balances: []uint64{ diff --git a/beacon-chain/core/electra/error.go b/beacon-chain/core/electra/error.go new file mode 100644 index 000000000000..522b75696a59 --- /dev/null +++ b/beacon-chain/core/electra/error.go @@ -0,0 +1,16 @@ +package electra + +import "github.com/pkg/errors" + +type execReqErr struct { + error +} + +// IsExecutionRequestError returns true if the error has `execReqErr`. +func IsExecutionRequestError(e error) bool { + if e == nil { + return false + } + var d execReqErr + return errors.As(e, &d) +} diff --git a/beacon-chain/core/electra/error_test.go b/beacon-chain/core/electra/error_test.go new file mode 100644 index 000000000000..808117fba22d --- /dev/null +++ b/beacon-chain/core/electra/error_test.go @@ -0,0 +1,45 @@ +package electra + +import ( + "testing" + + "github.com/pkg/errors" +) + +func TestIsExecutionRequestError(t *testing.T) { + tests := []struct { + name string + err error + want bool + }{ + { + name: "nil error", + err: nil, + want: false, + }, + { + name: "random error", + err: errors.New("some error"), + want: false, + }, + { + name: "execution request error", + err: execReqErr{errors.New("execution request failed")}, + want: true, + }, + { + name: "wrapped execution request error", + err: errors.Wrap(execReqErr{errors.New("execution request failed")}, "wrapped"), + want: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := IsExecutionRequestError(tt.err) + if got != tt.want { + t.Errorf("IsExecutionRequestError(%v) = %v, want %v", tt.err, got, tt.want) + } + }) + } +} diff --git a/beacon-chain/core/electra/export_test.go b/beacon-chain/core/electra/export_test.go new file mode 100644 index 000000000000..599926f2a4cd --- /dev/null +++ b/beacon-chain/core/electra/export_test.go @@ -0,0 +1,3 @@ +package electra + +var BatchProcessNewPendingDeposits = batchProcessNewPendingDeposits diff --git a/beacon-chain/core/electra/registry_updates.go b/beacon-chain/core/electra/registry_updates.go index 5a85f41cb1be..07424568e1af 100644 --- a/beacon-chain/core/electra/registry_updates.go +++ b/beacon-chain/core/electra/registry_updates.go @@ -18,23 +18,24 @@ import ( // // Spec pseudocode definition: // -// def process_registry_updates(state: BeaconState) -> None: -// # Process activation eligibility and ejections -// for index, validator in enumerate(state.validators): -// if is_eligible_for_activation_queue(validator): -// validator.activation_eligibility_epoch = get_current_epoch(state) + 1 +// def process_registry_updates(state: BeaconState) -> None: +// # Process activation eligibility and ejections +// for index, validator in enumerate(state.validators): +// if is_eligible_for_activation_queue(validator): # [Modified in Electra:EIP7251] +// validator.activation_eligibility_epoch = get_current_epoch(state) + 1 // -// if ( -// is_active_validator(validator, get_current_epoch(state)) -// and validator.effective_balance <= EJECTION_BALANCE -// ): -// initiate_validator_exit(state, ValidatorIndex(index)) +// if ( +// is_active_validator(validator, get_current_epoch(state)) +// and validator.effective_balance <= EJECTION_BALANCE +// ): +// initiate_validator_exit(state, ValidatorIndex(index)) # [Modified in Electra:EIP7251] // -// # Activate all eligible validators -// activation_epoch = compute_activation_exit_epoch(get_current_epoch(state)) -// for validator in state.validators: -// if is_eligible_for_activation(state, validator): -// validator.activation_epoch = activation_epoch +// # Activate all eligible validators +// # [Modified in Electra:EIP7251] +// activation_epoch = compute_activation_exit_epoch(get_current_epoch(state)) +// for validator in state.validators: +// if is_eligible_for_activation(state, validator): +// validator.activation_epoch = activation_epoch func ProcessRegistryUpdates(ctx context.Context, st state.BeaconState) error { currentEpoch := time.CurrentEpoch(st) ejectionBal := params.BeaconConfig().EjectionBalance @@ -90,8 +91,8 @@ func ProcessRegistryUpdates(ctx context.Context, st state.BeaconState) error { } } + // Activate all eligible validators. for _, idx := range eligibleForActivation { - // Activate all eligible validators. v, err := st.ValidatorAtIndex(idx) if err != nil { return err diff --git a/beacon-chain/core/electra/transition.go b/beacon-chain/core/electra/transition.go index 97388eba7bcc..c269fe686bc9 100644 --- a/beacon-chain/core/electra/transition.go +++ b/beacon-chain/core/electra/transition.go @@ -12,7 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) // Re-exports for methods that haven't changed in Electra. @@ -29,7 +29,6 @@ var ( ProcessParticipationFlagUpdates = altair.ProcessParticipationFlagUpdates ProcessSyncCommitteeUpdates = altair.ProcessSyncCommitteeUpdates AttestationsDelta = altair.AttestationsDelta - ProcessSyncAggregate = altair.ProcessSyncAggregate ) // ProcessEpoch describes the per epoch operations that are performed on the beacon state. @@ -41,14 +40,17 @@ var ( // process_justification_and_finalization(state) // process_inactivity_updates(state) // process_rewards_and_penalties(state) -// process_registry_updates(state) -// process_slashings(state) +// process_registry_updates(state) # [Modified in Electra:EIP7251] +// process_slashings(state) # [Modified in Electra:EIP7251] // process_eth1_data_reset(state) -// process_pending_balance_deposits(state) # New in EIP7251 -// process_pending_consolidations(state) # New in EIP7251 -// process_effective_balance_updates(state) +// process_pending_deposits(state) # [New in Electra:EIP7251] +// process_pending_consolidations(state) # [New in Electra:EIP7251] +// process_effective_balance_updates(state) # [Modified in Electra:EIP7251] // process_slashings_reset(state) // process_randao_mixes_reset(state) +// process_historical_summaries_update(state) +// process_participation_flag_updates(state) +// process_sync_committee_updates(state) func ProcessEpoch(ctx context.Context, state state.BeaconState) error { _, span := trace.StartSpan(ctx, "electra.ProcessEpoch") defer span.End() @@ -76,25 +78,17 @@ func ProcessEpoch(ctx context.Context, state state.BeaconState) error { if err != nil { return errors.Wrap(err, "could not process rewards and penalties") } - if err := ProcessRegistryUpdates(ctx, state); err != nil { return errors.Wrap(err, "could not process registry updates") } - - proportionalSlashingMultiplier, err := state.ProportionalSlashingMultiplier() - if err != nil { - return err - } - state, err = ProcessSlashings(state, proportionalSlashingMultiplier) - if err != nil { + if err := ProcessSlashings(state); err != nil { return err } state, err = ProcessEth1DataReset(state) if err != nil { return err } - - if err = ProcessPendingBalanceDeposits(ctx, state, primitives.Gwei(bp.ActiveCurrentEpoch)); err != nil { + if err = ProcessPendingDeposits(ctx, state, primitives.Gwei(bp.ActiveCurrentEpoch)); err != nil { return err } if err = ProcessPendingConsolidations(ctx, state); err != nil { @@ -103,7 +97,6 @@ func ProcessEpoch(ctx context.Context, state state.BeaconState) error { if err = ProcessEffectiveBalanceUpdates(state); err != nil { return err } - state, err = ProcessSlashingsReset(state) if err != nil { return err @@ -116,17 +109,14 @@ func ProcessEpoch(ctx context.Context, state state.BeaconState) error { if err != nil { return err } - state, err = ProcessParticipationFlagUpdates(state) if err != nil { return err } - _, err = ProcessSyncCommitteeUpdates(ctx, state) if err != nil { return err } - return nil } diff --git a/beacon-chain/core/electra/transition_no_verify_sig.go b/beacon-chain/core/electra/transition_no_verify_sig.go index 4f417f18ade0..018e519abc2a 100644 --- a/beacon-chain/core/electra/transition_no_verify_sig.go +++ b/beacon-chain/core/electra/transition_no_verify_sig.go @@ -2,7 +2,6 @@ package electra import ( "context" - "fmt" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" @@ -78,24 +77,35 @@ func ProcessOperations( return nil, errors.Wrap(err, "could not process bls-to-execution changes") } // new in electra - e, err := bb.Execution() + requests, err := bb.ExecutionRequests() if err != nil { - return nil, errors.Wrap(err, "could not get execution data from block") + return nil, errors.Wrap(err, "could not get execution requests") } - exe, ok := e.(interfaces.ExecutionDataElectra) - if !ok { - return nil, errors.New("could not cast execution data to electra execution data") + for _, d := range requests.Deposits { + if d == nil { + return nil, errors.New("nil deposit request") + } } - st, err = ProcessDepositRequests(ctx, st, exe.DepositRequests()) + st, err = ProcessDepositRequests(ctx, st, requests.Deposits) if err != nil { - return nil, errors.Wrap(err, "could not process deposit receipts") + return nil, execReqErr{errors.Wrap(err, "could not process deposit requests")} } - st, err = ProcessWithdrawalRequests(ctx, st, exe.WithdrawalRequests()) + for _, w := range requests.Withdrawals { + if w == nil { + return nil, errors.New("nil withdrawal request") + } + } + st, err = ProcessWithdrawalRequests(ctx, st, requests.Withdrawals) if err != nil { - return nil, errors.Wrap(err, "could not process execution layer withdrawal requests") + return nil, execReqErr{errors.Wrap(err, "could not process withdrawal requests")} + } + for _, c := range requests.Consolidations { + if c == nil { + return nil, errors.New("nil consolidation request") + } } - if err := ProcessConsolidationRequests(ctx, st, exe.ConsolidationRequests()); err != nil { - return nil, fmt.Errorf("could not process consolidation requests: %w", err) + if err := ProcessConsolidationRequests(ctx, st, requests.Consolidations); err != nil { + return nil, execReqErr{errors.Wrap(err, "could not process consolidation requests")} } return st, nil } diff --git a/beacon-chain/core/electra/transition_no_verify_sig_test.go b/beacon-chain/core/electra/transition_no_verify_sig_test.go new file mode 100644 index 000000000000..3eee062d8038 --- /dev/null +++ b/beacon-chain/core/electra/transition_no_verify_sig_test.go @@ -0,0 +1,61 @@ +package electra_test + +import ( + "context" + "testing" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func TestProcessOperationsWithNilRequests(t *testing.T) { + tests := []struct { + name string + modifyBlk func(blockElectra *ethpb.SignedBeaconBlockElectra) + errMsg string + }{ + { + name: "Nil deposit request", + modifyBlk: func(blk *ethpb.SignedBeaconBlockElectra) { + blk.Block.Body.ExecutionRequests.Deposits = []*enginev1.DepositRequest{nil} + }, + errMsg: "nil deposit request", + }, + { + name: "Nil withdrawal request", + modifyBlk: func(blk *ethpb.SignedBeaconBlockElectra) { + blk.Block.Body.ExecutionRequests.Withdrawals = []*enginev1.WithdrawalRequest{nil} + }, + errMsg: "nil withdrawal request", + }, + { + name: "Nil consolidation request", + modifyBlk: func(blk *ethpb.SignedBeaconBlockElectra) { + blk.Block.Body.ExecutionRequests.Consolidations = []*enginev1.ConsolidationRequest{nil} + }, + errMsg: "nil consolidation request", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + st, ks := util.DeterministicGenesisStateElectra(t, 128) + blk, err := util.GenerateFullBlockElectra(st, ks, util.DefaultBlockGenConfig(), 1) + require.NoError(t, err) + + tc.modifyBlk(blk) + + b, err := blocks.NewSignedBeaconBlock(blk) + require.NoError(t, err) + + require.NoError(t, st.SetSlot(1)) + + _, err = electra.ProcessOperations(context.Background(), st, b.Block()) + require.ErrorContains(t, tc.errMsg, err) + }) + } +} diff --git a/beacon-chain/core/electra/transition_test.go b/beacon-chain/core/electra/transition_test.go index b94fb21611ec..e03ee7ab9e22 100644 --- a/beacon-chain/core/electra/transition_test.go +++ b/beacon-chain/core/electra/transition_test.go @@ -57,14 +57,17 @@ func TestProcessEpoch_CanProcessElectra(t *testing.T) { require.NoError(t, st.SetSlot(10*params.BeaconConfig().SlotsPerEpoch)) require.NoError(t, st.SetDepositBalanceToConsume(100)) amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9) - deps := make([]*ethpb.PendingBalanceDeposit, 20) + validators := st.Validators() + deps := make([]*ethpb.PendingDeposit, 20) for i := 0; i < len(deps); i += 1 { - deps[i] = ðpb.PendingBalanceDeposit{ - Amount: uint64(amountAvailForProcessing) / 10, - Index: primitives.ValidatorIndex(i), + deps[i] = ðpb.PendingDeposit{ + PublicKey: validators[i].PublicKey, + WithdrawalCredentials: validators[i].WithdrawalCredentials, + Amount: uint64(amountAvailForProcessing) / 10, + Slot: 0, } } - require.NoError(t, st.SetPendingBalanceDeposits(deps)) + require.NoError(t, st.SetPendingDeposits(deps)) require.NoError(t, st.SetPendingConsolidations([]*ethpb.PendingConsolidation{ { SourceIndex: 2, @@ -108,7 +111,7 @@ func TestProcessEpoch_CanProcessElectra(t *testing.T) { require.Equal(t, primitives.Gwei(100), res) // Half of the balance deposits should have been processed. - remaining, err := st.PendingBalanceDeposits() + remaining, err := st.PendingDeposits() require.NoError(t, err) require.Equal(t, 10, len(remaining)) diff --git a/beacon-chain/core/electra/upgrade.go b/beacon-chain/core/electra/upgrade.go index f5cb4eb5c429..a815461b4246 100644 --- a/beacon-chain/core/electra/upgrade.go +++ b/beacon-chain/core/electra/upgrade.go @@ -10,42 +10,26 @@ import ( state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" ) // UpgradeToElectra updates inputs a generic state to return the version Electra state. +// +// nolint:dupword +// Spec code: // def upgrade_to_electra(pre: deneb.BeaconState) -> BeaconState: // // epoch = deneb.get_current_epoch(pre) -// latest_execution_payload_header = ExecutionPayloadHeader( -// parent_hash=pre.latest_execution_payload_header.parent_hash, -// fee_recipient=pre.latest_execution_payload_header.fee_recipient, -// state_root=pre.latest_execution_payload_header.state_root, -// receipts_root=pre.latest_execution_payload_header.receipts_root, -// logs_bloom=pre.latest_execution_payload_header.logs_bloom, -// prev_randao=pre.latest_execution_payload_header.prev_randao, -// block_number=pre.latest_execution_payload_header.block_number, -// gas_limit=pre.latest_execution_payload_header.gas_limit, -// gas_used=pre.latest_execution_payload_header.gas_used, -// timestamp=pre.latest_execution_payload_header.timestamp, -// extra_data=pre.latest_execution_payload_header.extra_data, -// base_fee_per_gas=pre.latest_execution_payload_header.base_fee_per_gas, -// block_hash=pre.latest_execution_payload_header.block_hash, -// transactions_root=pre.latest_execution_payload_header.transactions_root, -// withdrawals_root=pre.latest_execution_payload_header.withdrawals_root, -// blob_gas_used=pre.latest_execution_payload_header.blob_gas_used, -// excess_blob_gas=pre.latest_execution_payload_header.excess_blob_gas, -// deposit_requests_root=Root(), # [New in Electra:EIP6110] -// withdrawal_requests_root=Root(), # [New in Electra:EIP7002], -// ) +// latest_execution_payload_header = pre.latest_execution_payload_header // -// exit_epochs = [v.exit_epoch for v in pre.validators if v.exit_epoch != FAR_FUTURE_EPOCH] -// if not exit_epochs: -// exit_epochs = [get_current_epoch(pre)] -// earliest_exit_epoch = max(exit_epochs) + 1 +// earliest_exit_epoch = compute_activation_exit_epoch(get_current_epoch(pre)) +// for validator in pre.validators: +// if validator.exit_epoch != FAR_FUTURE_EPOCH: +// if validator.exit_epoch > earliest_exit_epoch: +// earliest_exit_epoch = validator.exit_epoch +// earliest_exit_epoch += Epoch(1) // // post = BeaconState( // # Versioning @@ -101,7 +85,7 @@ import ( // earliest_exit_epoch=earliest_exit_epoch, // consolidation_balance_to_consume=0, // earliest_consolidation_epoch=compute_activation_exit_epoch(get_current_epoch(pre)), -// pending_balance_deposits=[], +// pending_deposits=[], // pending_partial_withdrawals=[], // pending_consolidations=[], // ) @@ -120,7 +104,20 @@ import ( // )) // // for index in pre_activation: -// queue_entire_balance_and_reset_validator(post, ValidatorIndex(index)) +// balance = post.balances[index] +// post.balances[index] = 0 +// validator = post.validators[index] +// validator.effective_balance = 0 +// validator.activation_eligibility_epoch = FAR_FUTURE_EPOCH +// # Use bls.G2_POINT_AT_INFINITY as a signature field placeholder +// # and GENESIS_SLOT to distinguish from a pending deposit request +// post.pending_deposits.append(PendingDeposit( +// pubkey=validator.pubkey, +// withdrawal_credentials=validator.withdrawal_credentials, +// amount=balance, +// signature=bls.G2_POINT_AT_INFINITY, +// slot=GENESIS_SLOT, +// )) // // # Ensure early adopters of compounding credentials go through the activation churn // for index, validator in enumerate(post.validators): @@ -187,7 +184,7 @@ func UpgradeToElectra(beaconState state.BeaconState) (state.BeaconState, error) } // [New in Electra:EIP7251] - earliestExitEpoch := time.CurrentEpoch(beaconState) + earliestExitEpoch := helpers.ActivationExitEpoch(time.CurrentEpoch(beaconState)) preActivationIndices := make([]primitives.ValidatorIndex, 0) compoundWithdrawalIndices := make([]primitives.ValidatorIndex, 0) if err = beaconState.ReadFromEveryValidator(func(index int, val state.ReadOnlyValidator) error { @@ -197,7 +194,7 @@ func UpgradeToElectra(beaconState state.BeaconState) (state.BeaconState, error) if val.ActivationEpoch() == params.BeaconConfig().FarFutureEpoch { preActivationIndices = append(preActivationIndices, primitives.ValidatorIndex(index)) } - if helpers.HasCompoundingWithdrawalCredential(val) { + if val.HasCompoundingWithdrawalCredentials() { compoundWithdrawalIndices = append(compoundWithdrawalIndices, primitives.ValidatorIndex(index)) } return nil @@ -243,27 +240,24 @@ func UpgradeToElectra(beaconState state.BeaconState) (state.BeaconState, error) InactivityScores: inactivityScores, CurrentSyncCommittee: currentSyncCommittee, NextSyncCommittee: nextSyncCommittee, - LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderElectra{ - ParentHash: payloadHeader.ParentHash(), - FeeRecipient: payloadHeader.FeeRecipient(), - StateRoot: payloadHeader.StateRoot(), - ReceiptsRoot: payloadHeader.ReceiptsRoot(), - LogsBloom: payloadHeader.LogsBloom(), - PrevRandao: payloadHeader.PrevRandao(), - BlockNumber: payloadHeader.BlockNumber(), - GasLimit: payloadHeader.GasLimit(), - GasUsed: payloadHeader.GasUsed(), - Timestamp: payloadHeader.Timestamp(), - ExtraData: payloadHeader.ExtraData(), - BaseFeePerGas: payloadHeader.BaseFeePerGas(), - BlockHash: payloadHeader.BlockHash(), - TransactionsRoot: txRoot, - WithdrawalsRoot: wdRoot, - ExcessBlobGas: excessBlobGas, - BlobGasUsed: blobGasUsed, - DepositRequestsRoot: bytesutil.Bytes32(0), // [New in Electra:EIP6110] - WithdrawalRequestsRoot: bytesutil.Bytes32(0), // [New in Electra:EIP7002] - ConsolidationRequestsRoot: bytesutil.Bytes32(0), // [New in Electra:EIP7251] + LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadHeader.ParentHash(), + FeeRecipient: payloadHeader.FeeRecipient(), + StateRoot: payloadHeader.StateRoot(), + ReceiptsRoot: payloadHeader.ReceiptsRoot(), + LogsBloom: payloadHeader.LogsBloom(), + PrevRandao: payloadHeader.PrevRandao(), + BlockNumber: payloadHeader.BlockNumber(), + GasLimit: payloadHeader.GasLimit(), + GasUsed: payloadHeader.GasUsed(), + Timestamp: payloadHeader.Timestamp(), + ExtraData: payloadHeader.ExtraData(), + BaseFeePerGas: payloadHeader.BaseFeePerGas(), + BlockHash: payloadHeader.BlockHash(), + TransactionsRoot: txRoot, + WithdrawalsRoot: wdRoot, + ExcessBlobGas: excessBlobGas, + BlobGasUsed: blobGasUsed, }, NextWithdrawalIndex: wi, NextWithdrawalValidatorIndex: vi, @@ -275,7 +269,7 @@ func UpgradeToElectra(beaconState state.BeaconState) (state.BeaconState, error) EarliestExitEpoch: earliestExitEpoch, ConsolidationBalanceToConsume: helpers.ConsolidationChurnLimit(primitives.Gwei(tab)), EarliestConsolidationEpoch: helpers.ActivationExitEpoch(slots.ToEpoch(beaconState.Slot())), - PendingBalanceDeposits: make([]*ethpb.PendingBalanceDeposit, 0), + PendingDeposits: make([]*ethpb.PendingDeposit, 0), PendingPartialWithdrawals: make([]*ethpb.PendingPartialWithdrawal, 0), PendingConsolidations: make([]*ethpb.PendingConsolidation, 0), } diff --git a/beacon-chain/core/electra/upgrade_test.go b/beacon-chain/core/electra/upgrade_test.go index 9e6e20c8dff0..4c6ab89ef838 100644 --- a/beacon-chain/core/electra/upgrade_test.go +++ b/beacon-chain/core/electra/upgrade_test.go @@ -8,7 +8,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -103,7 +102,7 @@ func TestUpgradeToElectra(t *testing.T) { header, err := mSt.LatestExecutionPayloadHeader() require.NoError(t, err) - protoHeader, ok := header.Proto().(*enginev1.ExecutionPayloadHeaderElectra) + protoHeader, ok := header.Proto().(*enginev1.ExecutionPayloadHeaderDeneb) require.Equal(t, true, ok) prevHeader, err := preForkState.LatestExecutionPayloadHeader() require.NoError(t, err) @@ -112,25 +111,22 @@ func TestUpgradeToElectra(t *testing.T) { wdRoot, err := prevHeader.WithdrawalsRoot() require.NoError(t, err) - wanted := &enginev1.ExecutionPayloadHeaderElectra{ - ParentHash: prevHeader.ParentHash(), - FeeRecipient: prevHeader.FeeRecipient(), - StateRoot: prevHeader.StateRoot(), - ReceiptsRoot: prevHeader.ReceiptsRoot(), - LogsBloom: prevHeader.LogsBloom(), - PrevRandao: prevHeader.PrevRandao(), - BlockNumber: prevHeader.BlockNumber(), - GasLimit: prevHeader.GasLimit(), - GasUsed: prevHeader.GasUsed(), - Timestamp: prevHeader.Timestamp(), - ExtraData: prevHeader.ExtraData(), - BaseFeePerGas: prevHeader.BaseFeePerGas(), - BlockHash: prevHeader.BlockHash(), - TransactionsRoot: txRoot, - WithdrawalsRoot: wdRoot, - DepositRequestsRoot: bytesutil.Bytes32(0), - WithdrawalRequestsRoot: bytesutil.Bytes32(0), - ConsolidationRequestsRoot: bytesutil.Bytes32(0), + wanted := &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: prevHeader.ParentHash(), + FeeRecipient: prevHeader.FeeRecipient(), + StateRoot: prevHeader.StateRoot(), + ReceiptsRoot: prevHeader.ReceiptsRoot(), + LogsBloom: prevHeader.LogsBloom(), + PrevRandao: prevHeader.PrevRandao(), + BlockNumber: prevHeader.BlockNumber(), + GasLimit: prevHeader.GasLimit(), + GasUsed: prevHeader.GasUsed(), + Timestamp: prevHeader.Timestamp(), + ExtraData: prevHeader.ExtraData(), + BaseFeePerGas: prevHeader.BaseFeePerGas(), + BlockHash: prevHeader.BlockHash(), + TransactionsRoot: txRoot, + WithdrawalsRoot: wdRoot, } require.DeepEqual(t, wanted, protoHeader) @@ -163,7 +159,7 @@ func TestUpgradeToElectra(t *testing.T) { eee, err := mSt.EarliestExitEpoch() require.NoError(t, err) - require.Equal(t, primitives.Epoch(1), eee) + require.Equal(t, helpers.ActivationExitEpoch(primitives.Epoch(1)), eee) cbtc, err := mSt.ConsolidationBalanceToConsume() require.NoError(t, err) @@ -173,10 +169,10 @@ func TestUpgradeToElectra(t *testing.T) { require.NoError(t, err) require.Equal(t, helpers.ActivationExitEpoch(slots.ToEpoch(preForkState.Slot())), earliestConsolidationEpoch) - pendingBalanceDeposits, err := mSt.PendingBalanceDeposits() + pendingDeposits, err := mSt.PendingDeposits() require.NoError(t, err) - require.Equal(t, 2, len(pendingBalanceDeposits)) - require.Equal(t, uint64(1000), pendingBalanceDeposits[1].Amount) + require.Equal(t, 2, len(pendingDeposits)) + require.Equal(t, uint64(1000), pendingDeposits[1].Amount) numPendingPartialWithdrawals, err := mSt.NumPendingPartialWithdrawals() require.NoError(t, err) diff --git a/beacon-chain/core/electra/validator.go b/beacon-chain/core/electra/validator.go index 82b41fd8d7b4..501e75e7d738 100644 --- a/beacon-chain/core/electra/validator.go +++ b/beacon-chain/core/electra/validator.go @@ -3,87 +3,22 @@ package electra import ( "errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/crypto/bls/common" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) -// AddValidatorToRegistry updates the beacon state with validator information -// def add_validator_to_registry(state: BeaconState, -// -// pubkey: BLSPubkey, -// withdrawal_credentials: Bytes32, -// amount: uint64) -> None: -// index = get_index_for_new_validator(state) -// validator = get_validator_from_deposit(pubkey, withdrawal_credentials) -// set_or_append_list(state.validators, index, validator) -// set_or_append_list(state.balances, index, 0) # [Modified in Electra:EIP7251] -// set_or_append_list(state.previous_epoch_participation, index, ParticipationFlags(0b0000_0000)) -// set_or_append_list(state.current_epoch_participation, index, ParticipationFlags(0b0000_0000)) -// set_or_append_list(state.inactivity_scores, index, uint64(0)) -// state.pending_balance_deposits.append(PendingBalanceDeposit(index=index, amount=amount)) # [New in Electra:EIP7251] -func AddValidatorToRegistry(beaconState state.BeaconState, pubKey []byte, withdrawalCredentials []byte, amount uint64) error { - val := ValidatorFromDeposit(pubKey, withdrawalCredentials) - if err := beaconState.AppendValidator(val); err != nil { - return err - } - index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey)) - if !ok { - return errors.New("could not find validator in registry") - } - if err := beaconState.AppendBalance(0); err != nil { - return err - } - if err := beaconState.AppendPendingBalanceDeposit(index, amount); err != nil { - return err - } - if err := beaconState.AppendInactivityScore(0); err != nil { - return err - } - if err := beaconState.AppendPreviousParticipationBits(0); err != nil { - return err - } - return beaconState.AppendCurrentParticipationBits(0) -} - -// ValidatorFromDeposit gets a new validator object with provided parameters -// -// def get_validator_from_deposit(pubkey: BLSPubkey, withdrawal_credentials: Bytes32) -> Validator: -// -// return Validator( -// pubkey=pubkey, -// withdrawal_credentials=withdrawal_credentials, -// activation_eligibility_epoch=FAR_FUTURE_EPOCH, -// activation_epoch=FAR_FUTURE_EPOCH, -// exit_epoch=FAR_FUTURE_EPOCH, -// withdrawable_epoch=FAR_FUTURE_EPOCH, -// effective_balance=0, # [Modified in Electra:EIP7251] -// -// ) -func ValidatorFromDeposit(pubKey []byte, withdrawalCredentials []byte) *ethpb.Validator { - return ðpb.Validator{ - PublicKey: pubKey, - WithdrawalCredentials: withdrawalCredentials, - ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch, - ActivationEpoch: params.BeaconConfig().FarFutureEpoch, - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch, - EffectiveBalance: 0, // [Modified in Electra:EIP7251] - } -} - // SwitchToCompoundingValidator // // Spec definition: // -// def switch_to_compounding_validator(state: BeaconState, index: ValidatorIndex) -> None: -// validator = state.validators[index] -// if has_eth1_withdrawal_credential(validator): -// validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:] -// queue_excess_active_balance(state, index) +// def switch_to_compounding_validator(state: BeaconState, index: ValidatorIndex) -> None: +// +// validator = state.validators[index] +// validator.withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX + validator.withdrawal_credentials[1:] +// queue_excess_active_balance(state, index) func SwitchToCompoundingValidator(s state.BeaconState, idx primitives.ValidatorIndex) error { v, err := s.ValidatorAtIndex(idx) if err != nil { @@ -92,28 +27,32 @@ func SwitchToCompoundingValidator(s state.BeaconState, idx primitives.ValidatorI if len(v.WithdrawalCredentials) == 0 { return errors.New("validator has no withdrawal credentials") } - if helpers.HasETH1WithdrawalCredential(v) { - v.WithdrawalCredentials[0] = params.BeaconConfig().CompoundingWithdrawalPrefixByte - if err := s.UpdateValidatorAtIndex(idx, v); err != nil { - return err - } - return QueueExcessActiveBalance(s, idx) + + v.WithdrawalCredentials[0] = params.BeaconConfig().CompoundingWithdrawalPrefixByte + if err := s.UpdateValidatorAtIndex(idx, v); err != nil { + return err } - return nil + return QueueExcessActiveBalance(s, idx) } -// QueueExcessActiveBalance queues validators with balances above the min activation balance and adds to pending balance deposit. +// QueueExcessActiveBalance queues validators with balances above the min activation balance and adds to pending deposit. // // Spec definition: // -// def queue_excess_active_balance(state: BeaconState, index: ValidatorIndex) -> None: -// balance = state.balances[index] -// if balance > MIN_ACTIVATION_BALANCE: -// excess_balance = balance - MIN_ACTIVATION_BALANCE -// state.balances[index] = MIN_ACTIVATION_BALANCE -// state.pending_balance_deposits.append( -// PendingBalanceDeposit(index=index, amount=excess_balance) -// ) +// def queue_excess_active_balance(state: BeaconState, index: ValidatorIndex) -> None: +// +// balance = state.balances[index] +// if balance > MIN_ACTIVATION_BALANCE: +// excess_balance = balance - MIN_ACTIVATION_BALANCE +// state.balances[index] = MIN_ACTIVATION_BALANCE +// validator = state.validators[index] +// state.pending_deposits.append(PendingDeposit( +// pubkey=validator.pubkey, +// withdrawal_credentials=validator.withdrawal_credentials, +// amount=excess_balance, +// signature=bls.G2_POINT_AT_INFINITY, +// slot=GENESIS_SLOT, +// )) func QueueExcessActiveBalance(s state.BeaconState, idx primitives.ValidatorIndex) error { bal, err := s.BalanceAtIndex(idx) if err != nil { @@ -121,11 +60,22 @@ func QueueExcessActiveBalance(s state.BeaconState, idx primitives.ValidatorIndex } if bal > params.BeaconConfig().MinActivationBalance { - excessBalance := bal - params.BeaconConfig().MinActivationBalance if err := s.UpdateBalancesAtIndex(idx, params.BeaconConfig().MinActivationBalance); err != nil { return err } - return s.AppendPendingBalanceDeposit(idx, excessBalance) + excessBalance := bal - params.BeaconConfig().MinActivationBalance + val, err := s.ValidatorAtIndexReadOnly(idx) + if err != nil { + return err + } + pk := val.PublicKey() + return s.AppendPendingDeposit(ðpb.PendingDeposit{ + PublicKey: pk[:], + WithdrawalCredentials: val.GetWithdrawalCredentials(), + Amount: excessBalance, + Signature: common.InfiniteSignature[:], + Slot: params.BeaconConfig().GenesisSlot, + }) } return nil } @@ -134,15 +84,21 @@ func QueueExcessActiveBalance(s state.BeaconState, idx primitives.ValidatorIndex // // Spec definition: // -// def queue_entire_balance_and_reset_validator(state: BeaconState, index: ValidatorIndex) -> None: -// balance = state.balances[index] -// state.balances[index] = 0 -// validator = state.validators[index] -// validator.effective_balance = 0 -// validator.activation_eligibility_epoch = FAR_FUTURE_EPOCH -// state.pending_balance_deposits.append( -// PendingBalanceDeposit(index=index, amount=balance) -// ) +// def queue_entire_balance_and_reset_validator(state: BeaconState, index: ValidatorIndex) -> None: +// +// balance = state.balances[index] +// state.balances[index] = 0 +// validator = state.validators[index] +// validator.effective_balance = 0 +// validator.activation_eligibility_epoch = FAR_FUTURE_EPOCH +// state.pending_deposits.append(PendingDeposit( +// pubkey=validator.pubkey, +// withdrawal_credentials=validator.withdrawal_credentials, +// amount=balance, +// signature=bls.G2_POINT_AT_INFINITY, +// slot=GENESIS_SLOT, +// +// )) // //nolint:dupword func QueueEntireBalanceAndResetValidator(s state.BeaconState, idx primitives.ValidatorIndex) error { @@ -166,5 +122,11 @@ func QueueEntireBalanceAndResetValidator(s state.BeaconState, idx primitives.Val return err } - return s.AppendPendingBalanceDeposit(idx, bal) + return s.AppendPendingDeposit(ðpb.PendingDeposit{ + PublicKey: v.PublicKey, + WithdrawalCredentials: v.WithdrawalCredentials, + Amount: bal, + Signature: common.InfiniteSignature[:], + Slot: params.BeaconConfig().GenesisSlot, + }) } diff --git a/beacon-chain/core/electra/validator_test.go b/beacon-chain/core/electra/validator_test.go index a1fa8308ba22..8cdfa2c53406 100644 --- a/beacon-chain/core/electra/validator_test.go +++ b/beacon-chain/core/electra/validator_test.go @@ -6,7 +6,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -14,20 +13,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func TestAddValidatorToRegistry(t *testing.T) { - st, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{}) - require.NoError(t, err) - require.NoError(t, electra.AddValidatorToRegistry(st, make([]byte, fieldparams.BLSPubkeyLength), make([]byte, fieldparams.RootLength), 100)) - balances := st.Balances() - require.Equal(t, 1, len(balances)) - require.Equal(t, uint64(0), balances[0]) - pbds, err := st.PendingBalanceDeposits() - require.NoError(t, err) - require.Equal(t, 1, len(pbds)) - require.Equal(t, uint64(100), pbds[0].Amount) - require.Equal(t, primitives.ValidatorIndex(0), pbds[0].Index) -} - func TestSwitchToCompoundingValidator(t *testing.T) { s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{ Validators: []*eth.Validator{ @@ -60,7 +45,7 @@ func TestSwitchToCompoundingValidator(t *testing.T) { b, err := s.BalanceAtIndex(1) require.NoError(t, err) require.Equal(t, params.BeaconConfig().MinActivationBalance, b, "balance was changed") - pbd, err := s.PendingBalanceDeposits() + pbd, err := s.PendingDeposits() require.NoError(t, err) require.Equal(t, 0, len(pbd), "pending balance deposits should be empty") @@ -69,11 +54,10 @@ func TestSwitchToCompoundingValidator(t *testing.T) { b, err = s.BalanceAtIndex(2) require.NoError(t, err) require.Equal(t, params.BeaconConfig().MinActivationBalance, b, "balance was not changed") - pbd, err = s.PendingBalanceDeposits() + pbd, err = s.PendingDeposits() require.NoError(t, err) require.Equal(t, 1, len(pbd), "pending balance deposits should have one element") require.Equal(t, uint64(100_000), pbd[0].Amount, "pending balance deposit amount is incorrect") - require.Equal(t, primitives.ValidatorIndex(2), pbd[0].Index, "pending balance deposit index is incorrect") } func TestQueueEntireBalanceAndResetValidator(t *testing.T) { @@ -97,11 +81,10 @@ func TestQueueEntireBalanceAndResetValidator(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(0), v.EffectiveBalance, "effective balance was not reset") require.Equal(t, params.BeaconConfig().FarFutureEpoch, v.ActivationEligibilityEpoch, "activation eligibility epoch was not reset") - pbd, err := s.PendingBalanceDeposits() + pbd, err := s.PendingDeposits() require.NoError(t, err) require.Equal(t, 1, len(pbd), "pending balance deposits should have one element") require.Equal(t, params.BeaconConfig().MinActivationBalance+100_000, pbd[0].Amount, "pending balance deposit amount is incorrect") - require.Equal(t, primitives.ValidatorIndex(0), pbd[0].Index, "pending balance deposit index is incorrect") } func TestSwitchToCompoundingValidator_Ok(t *testing.T) { @@ -114,7 +97,7 @@ func TestSwitchToCompoundingValidator_Ok(t *testing.T) { require.NoError(t, st.SetBalances(bals)) require.NoError(t, electra.SwitchToCompoundingValidator(st, 0)) - pbd, err := st.PendingBalanceDeposits() + pbd, err := st.PendingDeposits() require.NoError(t, err) require.Equal(t, uint64(1010), pbd[0].Amount) // appends it at the end val, err := st.ValidatorAtIndex(0) @@ -132,7 +115,7 @@ func TestQueueExcessActiveBalance_Ok(t *testing.T) { err := electra.QueueExcessActiveBalance(st, 0) require.NoError(t, err) - pbd, err := st.PendingBalanceDeposits() + pbd, err := st.PendingDeposits() require.NoError(t, err) require.Equal(t, uint64(1000), pbd[0].Amount) // appends it at the end @@ -149,7 +132,7 @@ func TestQueueEntireBalanceAndResetValidator_Ok(t *testing.T) { err := electra.QueueEntireBalanceAndResetValidator(st, 0) require.NoError(t, err) - pbd, err := st.PendingBalanceDeposits() + pbd, err := st.PendingDeposits() require.NoError(t, err) require.Equal(t, 1, len(pbd)) require.Equal(t, params.BeaconConfig().MinActivationBalance-1000, pbd[0].Amount) diff --git a/beacon-chain/core/electra/withdrawals.go b/beacon-chain/core/electra/withdrawals.go index 13ccbc08f204..62156188ccd8 100644 --- a/beacon-chain/core/electra/withdrawals.go +++ b/beacon-chain/core/electra/withdrawals.go @@ -12,11 +12,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" log "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // ProcessWithdrawalRequests processes the validator withdrawals from the provided execution payload @@ -111,30 +111,31 @@ func ProcessWithdrawalRequests(ctx context.Context, st state.BeaconState, wrs [] log.Debugf("Skipping execution layer withdrawal request, validator index for %s not found\n", hexutil.Encode(wr.ValidatorPubkey)) continue } - validator, err := st.ValidatorAtIndex(vIdx) + validator, err := st.ValidatorAtIndexReadOnly(vIdx) if err != nil { return nil, err } // Verify withdrawal credentials - hasCorrectCredential := helpers.HasExecutionWithdrawalCredentials(validator) - isCorrectSourceAddress := bytes.Equal(validator.WithdrawalCredentials[12:], wr.SourceAddress) + hasCorrectCredential := validator.HasExecutionWithdrawalCredentials() + wc := validator.GetWithdrawalCredentials() + isCorrectSourceAddress := bytes.Equal(wc[12:], wr.SourceAddress) if !hasCorrectCredential || !isCorrectSourceAddress { log.Debugln("Skipping execution layer withdrawal request, wrong withdrawal credentials") continue } // Verify the validator is active. - if !helpers.IsActiveValidator(validator, currentEpoch) { + if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) { log.Debugln("Skipping execution layer withdrawal request, validator not active") continue } // Verify the validator has not yet submitted an exit. - if validator.ExitEpoch != params.BeaconConfig().FarFutureEpoch { + if validator.ExitEpoch() != params.BeaconConfig().FarFutureEpoch { log.Debugln("Skipping execution layer withdrawal request, validator has submitted an exit already") continue } // Verify the validator has been active long enough. - if currentEpoch < validator.ActivationEpoch.AddEpoch(params.BeaconConfig().ShardCommitteePeriod) { + if currentEpoch < validator.ActivationEpoch().AddEpoch(params.BeaconConfig().ShardCommitteePeriod) { log.Debugln("Skipping execution layer withdrawal request, validator has not been active long enough") continue } @@ -156,7 +157,7 @@ func ProcessWithdrawalRequests(ctx context.Context, st state.BeaconState, wrs [] continue } - hasSufficientEffectiveBalance := validator.EffectiveBalance >= params.BeaconConfig().MinActivationBalance + hasSufficientEffectiveBalance := validator.EffectiveBalance() >= params.BeaconConfig().MinActivationBalance vBal, err := st.BalanceAtIndex(vIdx) if err != nil { return nil, err @@ -164,7 +165,7 @@ func ProcessWithdrawalRequests(ctx context.Context, st state.BeaconState, wrs [] hasExcessBalance := vBal > params.BeaconConfig().MinActivationBalance+pendingBalanceToWithdraw // Only allow partial withdrawals with compounding withdrawal credentials - if helpers.HasCompoundingWithdrawalCredential(validator) && hasSufficientEffectiveBalance && hasExcessBalance { + if validator.HasCompoundingWithdrawalCredentials() && hasSufficientEffectiveBalance && hasExcessBalance { // Spec definition: // to_withdraw = min( // state.balances[index] - MIN_ACTIVATION_BALANCE - pending_balance_to_withdraw, diff --git a/beacon-chain/core/electra/withdrawals_test.go b/beacon-chain/core/electra/withdrawals_test.go index da00cdd9cb77..b13d28839f6f 100644 --- a/beacon-chain/core/electra/withdrawals_test.go +++ b/beacon-chain/core/electra/withdrawals_test.go @@ -38,6 +38,17 @@ func TestProcessWithdrawRequests(t *testing.T) { wantFn func(t *testing.T, got state.BeaconState) wantErr bool }{ + { + name: "nil request", + args: args{ + st: func() state.BeaconState { return st }(), + wrs: []*enginev1.WithdrawalRequest{nil}, + }, + wantErr: true, + wantFn: func(t *testing.T, got state.BeaconState) { + require.DeepEqual(t, got, nil) + }, + }, { name: "happy path exit and withdrawal only", args: args{ diff --git a/beacon-chain/core/epoch/BUILD.bazel b/beacon-chain/core/epoch/BUILD.bazel index e6f559e55916..3a3ea5c5eec5 100644 --- a/beacon-chain/core/epoch/BUILD.bazel +++ b/beacon-chain/core/epoch/BUILD.bazel @@ -22,7 +22,6 @@ go_library( "//consensus-types/primitives:go_default_library", "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//proto/prysm/v1alpha1/attestation:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", ], @@ -53,7 +52,6 @@ go_test( "//testing/util:go_default_library", "@com_github_google_go_cmp//cmp:go_default_library", "@com_github_google_gofuzz//:go_default_library", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/beacon-chain/core/epoch/epoch_processing.go b/beacon-chain/core/epoch/epoch_processing.go index 7856b83d45dc..720e1ac9d42a 100644 --- a/beacon-chain/core/epoch/epoch_processing.go +++ b/beacon-chain/core/epoch/epoch_processing.go @@ -20,32 +20,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/math" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/runtime/version" ) -// AttestingBalance returns the total balance from all the attesting indices. -// -// WARNING: This method allocates a new copy of the attesting validator indices set and is -// considered to be very memory expensive. Avoid using this unless you really -// need to get attesting balance from attestations. -// -// Spec pseudocode definition: -// -// def get_attesting_balance(state: BeaconState, attestations: Sequence[PendingAttestation]) -> Gwei: -// """ -// Return the combined effective balance of the set of unslashed validators participating in ``attestations``. -// Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero. -// """ -// return get_total_balance(state, get_unslashed_attesting_indices(state, attestations)) -func AttestingBalance(ctx context.Context, state state.ReadOnlyBeaconState, atts []*ethpb.PendingAttestation) (uint64, error) { - indices, err := UnslashedAttestingIndices(ctx, state, atts) - if err != nil { - return 0, errors.Wrap(err, "could not get attesting indices") - } - return helpers.TotalBalance(state, indices), nil -} - // ProcessRegistryUpdates rotates validators in and out of active pool. // the amount to rotate is determined churn limit. // @@ -164,35 +141,88 @@ func ProcessRegistryUpdates(ctx context.Context, st state.BeaconState) (state.Be return st, nil } -// ProcessSlashings processes the slashed validators during epoch processing, +// ProcessSlashings processes the slashed validators during epoch processing. This is a state mutating method. +// +// Electra spec definition: // // def process_slashings(state: BeaconState) -> None: -// epoch = get_current_epoch(state) -// total_balance = get_total_active_balance(state) -// adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER, total_balance) -// for index, validator in enumerate(state.validators): -// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: -// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow -// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance -// penalty = penalty_numerator // total_balance * increment -// decrease_balance(state, ValidatorIndex(index), penalty) -func ProcessSlashings(state state.BeaconState, slashingMultiplier uint64) (state.BeaconState, error) { - currentEpoch := time.CurrentEpoch(state) - totalBalance, err := helpers.TotalActiveBalance(state) +// epoch = get_current_epoch(state) +// total_balance = get_total_active_balance(state) +// adjusted_total_slashing_balance = min( +// sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX, +// total_balance +// ) +// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from total balance to avoid uint64 overflow +// penalty_per_effective_balance_increment = adjusted_total_slashing_balance // (total_balance // increment) +// for index, validator in enumerate(state.validators): +// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: +// effective_balance_increments = validator.effective_balance // increment +// # [Modified in Electra:EIP7251] +// penalty = penalty_per_effective_balance_increment * effective_balance_increments +// decrease_balance(state, ValidatorIndex(index), penalty) +// +// Bellatrix spec definition: +// +// def process_slashings(state: BeaconState) -> None: +// epoch = get_current_epoch(state) +// total_balance = get_total_active_balance(state) +// adjusted_total_slashing_balance = min( +// sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX, # [Modified in Bellatrix] +// total_balance +// ) +// for index, validator in enumerate(state.validators): +// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: +// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow +// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance +// penalty = penalty_numerator // total_balance * increment +// decrease_balance(state, ValidatorIndex(index), penalty) +// +// Altair spec definition: +// +// def process_slashings(state: BeaconState) -> None: +// epoch = get_current_epoch(state) +// total_balance = get_total_active_balance(state) +// adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR, total_balance) +// for index, validator in enumerate(state.validators): +// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: +// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow +// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance +// penalty = penalty_numerator // total_balance * increment +// decrease_balance(state, ValidatorIndex(index), penalty) +// +// Phase0 spec definition: +// +// def process_slashings(state: BeaconState) -> None: +// epoch = get_current_epoch(state) +// total_balance = get_total_active_balance(state) +// adjusted_total_slashing_balance = min(sum(state.slashings) * PROPORTIONAL_SLASHING_MULTIPLIER, total_balance) +// for index, validator in enumerate(state.validators): +// if validator.slashed and epoch + EPOCHS_PER_SLASHINGS_VECTOR // 2 == validator.withdrawable_epoch: +// increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from penalty numerator to avoid uint64 overflow +// penalty_numerator = validator.effective_balance // increment * adjusted_total_slashing_balance +// penalty = penalty_numerator // total_balance * increment +// decrease_balance(state, ValidatorIndex(index), penalty) +func ProcessSlashings(st state.BeaconState) error { + slashingMultiplier, err := st.ProportionalSlashingMultiplier() if err != nil { - return nil, errors.Wrap(err, "could not get total active balance") + return errors.Wrap(err, "could not get proportional slashing multiplier") + } + currentEpoch := time.CurrentEpoch(st) + totalBalance, err := helpers.TotalActiveBalance(st) + if err != nil { + return errors.Wrap(err, "could not get total active balance") } // Compute slashed balances in the current epoch exitLength := params.BeaconConfig().EpochsPerSlashingsVector // Compute the sum of state slashings - slashings := state.Slashings() + slashings := st.Slashings() totalSlashing := uint64(0) for _, slashing := range slashings { totalSlashing, err = math.Add64(totalSlashing, slashing) if err != nil { - return nil, err + return err } } @@ -200,19 +230,40 @@ func ProcessSlashings(state state.BeaconState, slashingMultiplier uint64) (state // below equally. increment := params.BeaconConfig().EffectiveBalanceIncrement minSlashing := math.Min(totalSlashing*slashingMultiplier, totalBalance) - err = state.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - correctEpoch := (currentEpoch + exitLength/2) == val.WithdrawableEpoch - if val.Slashed && correctEpoch { - penaltyNumerator := val.EffectiveBalance / increment * minSlashing - penalty := penaltyNumerator / totalBalance * increment - if err := helpers.DecreaseBalance(state, primitives.ValidatorIndex(idx), penalty); err != nil { - return false, val, err + + // Modified in Electra:EIP7251 + var penaltyPerEffectiveBalanceIncrement uint64 + if st.Version() >= version.Electra { + penaltyPerEffectiveBalanceIncrement = minSlashing / (totalBalance / increment) + } + + bals := st.Balances() + changed := false + err = st.ReadFromEveryValidator(func(idx int, val state.ReadOnlyValidator) error { + correctEpoch := (currentEpoch + exitLength/2) == val.WithdrawableEpoch() + if val.Slashed() && correctEpoch { + var penalty uint64 + if st.Version() >= version.Electra { + effectiveBalanceIncrements := val.EffectiveBalance() / increment + penalty = penaltyPerEffectiveBalanceIncrement * effectiveBalanceIncrements + } else { + penaltyNumerator := val.EffectiveBalance() / increment * minSlashing + penalty = penaltyNumerator / totalBalance * increment } - return true, val, nil + bals[idx] = helpers.DecreaseBalanceWithVal(bals[idx], penalty) + changed = true } - return false, val, nil + return nil }) - return state, err + if err != nil { + return err + } + if changed { + if err := st.SetBalances(bals); err != nil { + return err + } + } + return nil } // ProcessEth1DataReset processes updates to ETH1 data votes during epoch processing. @@ -254,45 +305,43 @@ func ProcessEth1DataReset(state state.BeaconState) (state.BeaconState, error) { // or validator.effective_balance + UPWARD_THRESHOLD < balance // ): // validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) -func ProcessEffectiveBalanceUpdates(state state.BeaconState) (state.BeaconState, error) { +func ProcessEffectiveBalanceUpdates(st state.BeaconState) (state.BeaconState, error) { effBalanceInc := params.BeaconConfig().EffectiveBalanceIncrement maxEffBalance := params.BeaconConfig().MaxEffectiveBalance hysteresisInc := effBalanceInc / params.BeaconConfig().HysteresisQuotient downwardThreshold := hysteresisInc * params.BeaconConfig().HysteresisDownwardMultiplier upwardThreshold := hysteresisInc * params.BeaconConfig().HysteresisUpwardMultiplier - bals := state.Balances() + bals := st.Balances() // Update effective balances with hysteresis. - validatorFunc := func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { + validatorFunc := func(idx int, val state.ReadOnlyValidator) (newVal *ethpb.Validator, err error) { if val == nil { - return false, nil, fmt.Errorf("validator %d is nil in state", idx) + return nil, fmt.Errorf("validator %d is nil in state", idx) } if idx >= len(bals) { - return false, nil, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(state.Balances())) + return nil, fmt.Errorf("validator index exceeds validator length in state %d >= %d", idx, len(st.Balances())) } balance := bals[idx] - if balance+downwardThreshold < val.EffectiveBalance || val.EffectiveBalance+upwardThreshold < balance { + if balance+downwardThreshold < val.EffectiveBalance() || val.EffectiveBalance()+upwardThreshold < balance { effectiveBal := maxEffBalance if effectiveBal > balance-balance%effBalanceInc { effectiveBal = balance - balance%effBalanceInc } - if effectiveBal != val.EffectiveBalance { - newVal := ethpb.CopyValidator(val) + if effectiveBal != val.EffectiveBalance() { + newVal = val.Copy() newVal.EffectiveBalance = effectiveBal - return true, newVal, nil } - return false, val, nil } - return false, val, nil + return } - if err := state.ApplyToEveryValidator(validatorFunc); err != nil { + if err := st.ApplyToEveryValidator(validatorFunc); err != nil { return nil, err } - return state, nil + return st, nil } // ProcessSlashingsReset processes the total slashing balances updates during epoch processing. @@ -455,51 +504,3 @@ func ProcessFinalUpdates(state state.BeaconState) (state.BeaconState, error) { return state, nil } - -// UnslashedAttestingIndices returns all the attesting indices from a list of attestations, -// it sorts the indices and filters out the slashed ones. -// -// Spec pseudocode definition: -// -// def get_unslashed_attesting_indices(state: BeaconState, -// attestations: Sequence[PendingAttestation]) -> Set[ValidatorIndex]: -// output = set() # type: Set[ValidatorIndex] -// for a in attestations: -// output = output.union(get_attesting_indices(state, a.data, a.aggregation_bits)) -// return set(filter(lambda index: not state.validators[index].slashed, output)) -func UnslashedAttestingIndices(ctx context.Context, state state.ReadOnlyBeaconState, atts []*ethpb.PendingAttestation) ([]primitives.ValidatorIndex, error) { - var setIndices []primitives.ValidatorIndex - seen := make(map[uint64]bool) - - for _, att := range atts { - committee, err := helpers.BeaconCommitteeFromState(ctx, state, att.GetData().Slot, att.GetData().CommitteeIndex) - if err != nil { - return nil, err - } - attestingIndices, err := attestation.AttestingIndices(att, committee) - if err != nil { - return nil, err - } - // Create a set for attesting indices - for _, index := range attestingIndices { - if !seen[index] { - setIndices = append(setIndices, primitives.ValidatorIndex(index)) - } - seen[index] = true - } - } - // Sort the attesting set indices by increasing order. - sort.Slice(setIndices, func(i, j int) bool { return setIndices[i] < setIndices[j] }) - // Remove the slashed validator indices. - for i := 0; i < len(setIndices); i++ { - v, err := state.ValidatorAtIndexReadOnly(setIndices[i]) - if err != nil { - return nil, errors.Wrap(err, "failed to look up validator") - } - if !v.IsNil() && v.Slashed() { - setIndices = append(setIndices[:i], setIndices[i+1:]...) - } - } - - return setIndices, nil -} diff --git a/beacon-chain/core/epoch/epoch_processing_test.go b/beacon-chain/core/epoch/epoch_processing_test.go index dd78dd5ca626..074367146dc2 100644 --- a/beacon-chain/core/epoch/epoch_processing_test.go +++ b/beacon-chain/core/epoch/epoch_processing_test.go @@ -6,7 +6,6 @@ import ( "math" "testing" - "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" @@ -24,131 +23,6 @@ import ( "google.golang.org/protobuf/proto" ) -func TestUnslashedAttestingIndices_CanSortAndFilter(t *testing.T) { - // Generate 2 attestations. - atts := make([]*ethpb.PendingAttestation, 2) - for i := 0; i < len(atts); i++ { - atts[i] = ðpb.PendingAttestation{ - Data: ðpb.AttestationData{Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - Target: ðpb.Checkpoint{Epoch: 0, Root: make([]byte, fieldparams.RootLength)}, - }, - AggregationBits: bitfield.Bitlist{0x00, 0xFF, 0xFF, 0xFF}, - } - } - - // Generate validators and state for the 2 attestations. - validatorCount := 1000 - validators := make([]*ethpb.Validator, validatorCount) - for i := 0; i < len(validators); i++ { - validators[i] = ðpb.Validator{ - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - } - } - base := ðpb.BeaconState{ - Validators: validators, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - } - beaconState, err := state_native.InitializeFromProtoPhase0(base) - require.NoError(t, err) - - indices, err := epoch.UnslashedAttestingIndices(context.Background(), beaconState, atts) - require.NoError(t, err) - for i := 0; i < len(indices)-1; i++ { - if indices[i] >= indices[i+1] { - t.Error("sorted indices not sorted or duplicated") - } - } - - // Verify the slashed validator is filtered. - slashedValidator := indices[0] - validators = beaconState.Validators() - validators[slashedValidator].Slashed = true - require.NoError(t, beaconState.SetValidators(validators)) - indices, err = epoch.UnslashedAttestingIndices(context.Background(), beaconState, atts) - require.NoError(t, err) - for i := 0; i < len(indices); i++ { - assert.NotEqual(t, slashedValidator, indices[i], "Slashed validator %d is not filtered", slashedValidator) - } -} - -func TestUnslashedAttestingIndices_DuplicatedAttestations(t *testing.T) { - // Generate 5 of the same attestations. - atts := make([]*ethpb.PendingAttestation, 5) - for i := 0; i < len(atts); i++ { - atts[i] = ðpb.PendingAttestation{ - Data: ðpb.AttestationData{Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - Target: ðpb.Checkpoint{Epoch: 0}}, - AggregationBits: bitfield.Bitlist{0x00, 0xFF, 0xFF, 0xFF}, - } - } - - // Generate validators and state for the 5 attestations. - validatorCount := 1000 - validators := make([]*ethpb.Validator, validatorCount) - for i := 0; i < len(validators); i++ { - validators[i] = ðpb.Validator{ - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - } - } - base := ðpb.BeaconState{ - Validators: validators, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - } - beaconState, err := state_native.InitializeFromProtoPhase0(base) - require.NoError(t, err) - - indices, err := epoch.UnslashedAttestingIndices(context.Background(), beaconState, atts) - require.NoError(t, err) - - for i := 0; i < len(indices)-1; i++ { - if indices[i] >= indices[i+1] { - t.Error("sorted indices not sorted or duplicated") - } - } -} - -func TestAttestingBalance_CorrectBalance(t *testing.T) { - helpers.ClearCache() - // Generate 2 attestations. - atts := make([]*ethpb.PendingAttestation, 2) - for i := 0; i < len(atts); i++ { - atts[i] = ðpb.PendingAttestation{ - Data: ðpb.AttestationData{ - Target: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, - Slot: primitives.Slot(i), - }, - AggregationBits: bitfield.Bitlist{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01}, - } - } - - // Generate validators with balances and state for the 2 attestations. - validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount) - balances := make([]uint64, params.BeaconConfig().MinGenesisActiveValidatorCount) - for i := 0; i < len(validators); i++ { - validators[i] = ðpb.Validator{ - ExitEpoch: params.BeaconConfig().FarFutureEpoch, - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - } - balances[i] = params.BeaconConfig().MaxEffectiveBalance - } - base := ðpb.BeaconState{ - Slot: 2, - RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), - - Validators: validators, - Balances: balances, - } - beaconState, err := state_native.InitializeFromProtoPhase0(base) - require.NoError(t, err) - - balance, err := epoch.AttestingBalance(context.Background(), beaconState, atts) - require.NoError(t, err) - wanted := 256 * params.BeaconConfig().MaxEffectiveBalance - assert.Equal(t, wanted, balance) -} - func TestProcessSlashings_NotSlashed(t *testing.T) { base := ðpb.BeaconState{ Slot: 0, @@ -158,10 +32,9 @@ func TestProcessSlashings_NotSlashed(t *testing.T) { } s, err := state_native.InitializeFromProtoPhase0(base) require.NoError(t, err) - newState, err := epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplier) - require.NoError(t, err) + require.NoError(t, epoch.ProcessSlashings(s)) wanted := params.BeaconConfig().MaxEffectiveBalance - assert.Equal(t, wanted, newState.Balances()[0], "Unexpected slashed balance") + assert.Equal(t, wanted, s.Balances()[0], "Unexpected slashed balance") } func TestProcessSlashings_SlashedLess(t *testing.T) { @@ -237,9 +110,8 @@ func TestProcessSlashings_SlashedLess(t *testing.T) { s, err := state_native.InitializeFromProtoPhase0(tt.state) require.NoError(t, err) helpers.ClearCache() - newState, err := epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplier) - require.NoError(t, err) - assert.Equal(t, tt.want, newState.Balances()[0], "ProcessSlashings({%v}) = newState; newState.Balances[0] = %d", original, newState.Balances()[0]) + require.NoError(t, epoch.ProcessSlashings(s)) + assert.Equal(t, tt.want, s.Balances()[0], "ProcessSlashings({%v}) = newState; newState.Balances[0] = %d", original, s.Balances()[0]) }) } } @@ -491,8 +363,7 @@ func TestProcessSlashings_BadValue(t *testing.T) { } s, err := state_native.InitializeFromProtoPhase0(base) require.NoError(t, err) - _, err = epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplier) - require.ErrorContains(t, "addition overflows", err) + require.ErrorContains(t, "addition overflows", epoch.ProcessSlashings(s)) } func TestProcessHistoricalDataUpdate(t *testing.T) { @@ -574,3 +445,74 @@ func TestProcessHistoricalDataUpdate(t *testing.T) { }) } } + +func TestProcessSlashings_SlashedElectra(t *testing.T) { + tests := []struct { + state *ethpb.BeaconStateElectra + want uint64 + }{ + { + state: ðpb.BeaconStateElectra{ + Validators: []*ethpb.Validator{ + {Slashed: true, + WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}}, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance}, + Slashings: []uint64{0, 1e9}, + }, + want: uint64(29000000000), + }, + { + state: ðpb.BeaconStateElectra{ + Validators: []*ethpb.Validator{ + {Slashed: true, + WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance}, + }, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance, params.BeaconConfig().MaxEffectiveBalance}, + Slashings: []uint64{0, 1e9}, + }, + want: uint64(30500000000), + }, + { + state: ðpb.BeaconStateElectra{ + Validators: []*ethpb.Validator{ + {Slashed: true, + WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra}, + }, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalance * 10, params.BeaconConfig().MaxEffectiveBalance * 20}, + Slashings: []uint64{0, 2 * 1e9}, + }, + want: uint64(317000001536), + }, + { + state: ðpb.BeaconStateElectra{ + Validators: []*ethpb.Validator{ + {Slashed: true, + WithdrawableEpoch: params.BeaconConfig().EpochsPerSlashingsVector / 2, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra - params.BeaconConfig().EffectiveBalanceIncrement}, + {ExitEpoch: params.BeaconConfig().FarFutureEpoch, EffectiveBalance: params.BeaconConfig().MaxEffectiveBalanceElectra - params.BeaconConfig().EffectiveBalanceIncrement}}, + Balances: []uint64{params.BeaconConfig().MaxEffectiveBalanceElectra - params.BeaconConfig().EffectiveBalanceIncrement, params.BeaconConfig().MaxEffectiveBalanceElectra - params.BeaconConfig().EffectiveBalanceIncrement}, + Slashings: []uint64{0, 1e9}, + }, + want: uint64(2044000000727), + }, + } + + for i, tt := range tests { + t.Run(fmt.Sprint(i), func(t *testing.T) { + original := proto.Clone(tt.state) + s, err := state_native.InitializeFromProtoElectra(tt.state) + require.NoError(t, err) + helpers.ClearCache() + require.NoError(t, epoch.ProcessSlashings(s)) + assert.Equal(t, tt.want, s.Balances()[0], "ProcessSlashings({%v}); s.Balances[0] = %d", original, s.Balances()[0]) + }) + } +} diff --git a/beacon-chain/core/epoch/precompute/BUILD.bazel b/beacon-chain/core/epoch/precompute/BUILD.bazel index 18a12269b84a..d16cd58091bd 100644 --- a/beacon-chain/core/epoch/precompute/BUILD.bazel +++ b/beacon-chain/core/epoch/precompute/BUILD.bazel @@ -24,13 +24,13 @@ go_library( "//consensus-types/primitives:go_default_library", "//math:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -47,7 +47,6 @@ go_test( embed = [":go_default_library"], deps = [ "//beacon-chain/core/altair:go_default_library", - "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/state:go_default_library", diff --git a/beacon-chain/core/epoch/precompute/attestation.go b/beacon-chain/core/epoch/precompute/attestation.go index a510fbb83e6f..45daa1f9b847 100644 --- a/beacon-chain/core/epoch/precompute/attestation.go +++ b/beacon-chain/core/epoch/precompute/attestation.go @@ -11,10 +11,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" ) // ProcessAttestations process the attestations in state and update individual validator's pre computes, diff --git a/beacon-chain/core/epoch/precompute/new.go b/beacon-chain/core/epoch/precompute/new.go index b4f74900e352..2f77e82d8990 100644 --- a/beacon-chain/core/epoch/precompute/new.go +++ b/beacon-chain/core/epoch/precompute/new.go @@ -11,7 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) // New gets called at the beginning of process epoch cycle to return diff --git a/beacon-chain/core/epoch/precompute/reward_penalty_test.go b/beacon-chain/core/epoch/precompute/reward_penalty_test.go index 4c4e3c40911f..9ab32f65a9da 100644 --- a/beacon-chain/core/epoch/precompute/reward_penalty_test.go +++ b/beacon-chain/core/epoch/precompute/reward_penalty_test.go @@ -6,7 +6,6 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" @@ -59,90 +58,6 @@ func TestProcessRewardsAndPenaltiesPrecompute(t *testing.T) { assert.Equal(t, wanted, beaconState.Balances()[0], "Unexpected balance") } -func TestAttestationDeltaPrecompute(t *testing.T) { - e := params.BeaconConfig().SlotsPerEpoch - validatorCount := uint64(2048) - base := buildState(e+2, validatorCount) - atts := make([]*ethpb.PendingAttestation, 3) - var emptyRoot [32]byte - for i := 0; i < len(atts); i++ { - atts[i] = ðpb.PendingAttestation{ - Data: ðpb.AttestationData{ - Target: ðpb.Checkpoint{ - Root: emptyRoot[:], - }, - Source: ðpb.Checkpoint{ - Root: emptyRoot[:], - }, - BeaconBlockRoot: emptyRoot[:], - }, - AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01}, - InclusionDelay: 1, - } - } - base.PreviousEpochAttestations = atts - beaconState, err := state_native.InitializeFromProtoPhase0(base) - require.NoError(t, err) - slashedAttestedIndices := []primitives.ValidatorIndex{1413} - for _, i := range slashedAttestedIndices { - vs := beaconState.Validators() - vs[i].Slashed = true - require.Equal(t, nil, beaconState.SetValidators(vs)) - } - - vp, bp, err := New(context.Background(), beaconState) - require.NoError(t, err) - vp, bp, err = ProcessAttestations(context.Background(), beaconState, vp, bp) - require.NoError(t, err) - - // Add some variances to target and head balances. - // See: https://github.com/prysmaticlabs/prysm/issues/5593 - bp.PrevEpochTargetAttested /= 2 - bp.PrevEpochHeadAttested = bp.PrevEpochHeadAttested * 2 / 3 - rewards, penalties, err := AttestationsDelta(beaconState, bp, vp) - require.NoError(t, err) - attestedBalance, err := epoch.AttestingBalance(context.Background(), beaconState, atts) - require.NoError(t, err) - totalBalance, err := helpers.TotalActiveBalance(beaconState) - require.NoError(t, err) - - attestedIndices := []primitives.ValidatorIndex{55, 1339, 1746, 1811, 1569} - for _, i := range attestedIndices { - base, err := baseReward(beaconState, i) - require.NoError(t, err, "Could not get base reward") - - // Base rewards for getting source right - wanted := attestedBalance*base/totalBalance + - bp.PrevEpochTargetAttested*base/totalBalance + - bp.PrevEpochHeadAttested*base/totalBalance - // Base rewards for proposer and attesters working together getting attestation - // on chain in the fatest manner - proposerReward := base / params.BeaconConfig().ProposerRewardQuotient - wanted += (base-proposerReward)*uint64(params.BeaconConfig().MinAttestationInclusionDelay) - 1 - assert.Equal(t, wanted, rewards[i], "Unexpected reward balance for validator with index %d", i) - // Since all these validators attested, they shouldn't get penalized. - assert.Equal(t, uint64(0), penalties[i], "Unexpected penalty balance") - } - - for _, i := range slashedAttestedIndices { - base, err := baseReward(beaconState, i) - assert.NoError(t, err, "Could not get base reward") - assert.Equal(t, uint64(0), rewards[i], "Unexpected slashed indices reward balance") - assert.Equal(t, 3*base, penalties[i], "Unexpected slashed indices penalty balance") - } - - nonAttestedIndices := []primitives.ValidatorIndex{434, 677, 872, 791} - for _, i := range nonAttestedIndices { - base, err := baseReward(beaconState, i) - assert.NoError(t, err, "Could not get base reward") - wanted := 3 * base - // Since all these validators did not attest, they shouldn't get rewarded. - assert.Equal(t, uint64(0), rewards[i], "Unexpected reward balance") - // Base penalties for not attesting. - assert.Equal(t, wanted, penalties[i], "Unexpected penalty balance") - } -} - func TestAttestationDeltas_ZeroEpoch(t *testing.T) { e := params.BeaconConfig().SlotsPerEpoch validatorCount := uint64(2048) diff --git a/beacon-chain/core/epoch/precompute/slashing.go b/beacon-chain/core/epoch/precompute/slashing.go index 03e0cd6ef99b..02458f4a905b 100644 --- a/beacon-chain/core/epoch/precompute/slashing.go +++ b/beacon-chain/core/epoch/precompute/slashing.go @@ -5,9 +5,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/math" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) // ProcessSlashingsPrecompute processes the slashed validators during epoch processing. @@ -44,18 +42,18 @@ func ProcessSlashingsPrecompute(s state.BeaconState, pBal *Balance) error { } increment := params.BeaconConfig().EffectiveBalanceIncrement - validatorFunc := func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - correctEpoch := epochToWithdraw == val.WithdrawableEpoch - if val.Slashed && correctEpoch { - penaltyNumerator := val.EffectiveBalance / increment * minSlashing + bals := s.Balances() + validatorFunc := func(idx int, val state.ReadOnlyValidator) error { + correctEpoch := epochToWithdraw == val.WithdrawableEpoch() + if val.Slashed() && correctEpoch { + penaltyNumerator := val.EffectiveBalance() / increment * minSlashing penalty := penaltyNumerator / pBal.ActiveCurrentEpoch * increment - if err := helpers.DecreaseBalance(s, primitives.ValidatorIndex(idx), penalty); err != nil { - return false, val, err - } - return true, val, nil + bals[idx] = helpers.DecreaseBalanceWithVal(bals[idx], penalty) } - return false, val, nil + return nil } - - return s.ApplyToEveryValidator(validatorFunc) + if err := s.ReadFromEveryValidator(validatorFunc); err != nil { + return err + } + return s.SetBalances(bals) } diff --git a/beacon-chain/core/feed/operation/events.go b/beacon-chain/core/feed/operation/events.go index 86287da922e5..4244253acc0c 100644 --- a/beacon-chain/core/feed/operation/events.go +++ b/beacon-chain/core/feed/operation/events.go @@ -32,6 +32,9 @@ const ( // AttesterSlashingReceived is sent after an attester slashing is received from gossip or rpc AttesterSlashingReceived = 8 + + // SingleAttReceived is sent after a single attestation object is received from gossip or rpc + SingleAttReceived = 9 ) // UnAggregatedAttReceivedData is the data sent with UnaggregatedAttReceived events. @@ -43,7 +46,7 @@ type UnAggregatedAttReceivedData struct { // AggregatedAttReceivedData is the data sent with AggregatedAttReceived events. type AggregatedAttReceivedData struct { // Attestation is the aggregated attestation object. - Attestation *ethpb.AggregateAttestationAndProof + Attestation ethpb.AggregateAttAndProof } // ExitReceivedData is the data sent with ExitReceived events. @@ -77,3 +80,8 @@ type ProposerSlashingReceivedData struct { type AttesterSlashingReceivedData struct { AttesterSlashing ethpb.AttSlashing } + +// SingleAttReceivedData is the data sent with SingleAttReceived events. +type SingleAttReceivedData struct { + Attestation ethpb.Att +} diff --git a/beacon-chain/core/feed/operation/notifier.go b/beacon-chain/core/feed/operation/notifier.go index 798519ee848c..acfd5cf68c3b 100644 --- a/beacon-chain/core/feed/operation/notifier.go +++ b/beacon-chain/core/feed/operation/notifier.go @@ -4,5 +4,5 @@ import "github.com/prysmaticlabs/prysm/v5/async/event" // Notifier interface defines the methods of the service that provides beacon block operation updates to consumers. type Notifier interface { - OperationFeed() *event.Feed + OperationFeed() event.SubscriberSender } diff --git a/beacon-chain/core/feed/state/events.go b/beacon-chain/core/feed/state/events.go index 1a31d10cfee3..cc6f7f126249 100644 --- a/beacon-chain/core/feed/state/events.go +++ b/beacon-chain/core/feed/state/events.go @@ -31,6 +31,8 @@ const ( LightClientFinalityUpdate // LightClientOptimisticUpdate event LightClientOptimisticUpdate + // PayloadAttributes events are fired upon a missed slot or new head. + PayloadAttributes ) // BlockProcessedData is the data sent with BlockProcessed events. diff --git a/beacon-chain/core/feed/state/notifier.go b/beacon-chain/core/feed/state/notifier.go index 6ba795e73aee..f3487279ab78 100644 --- a/beacon-chain/core/feed/state/notifier.go +++ b/beacon-chain/core/feed/state/notifier.go @@ -4,5 +4,5 @@ import "github.com/prysmaticlabs/prysm/v5/async/event" // Notifier interface defines the methods of the service that provides state updates to consumers. type Notifier interface { - StateFeed() *event.Feed + StateFeed() event.SubscriberSender } diff --git a/beacon-chain/core/fulu/BUILD.bazel b/beacon-chain/core/fulu/BUILD.bazel new file mode 100644 index 000000000000..cc08879cd78c --- /dev/null +++ b/beacon-chain/core/fulu/BUILD.bazel @@ -0,0 +1,32 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["upgrade.go"], + importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/fulu", + visibility = ["//visibility:public"], + deps = [ + "//beacon-chain/core/time:go_default_library", + "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native:go_default_library", + "//config/params:go_default_library", + "//proto/engine/v1:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "@com_github_pkg_errors//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["upgrade_test.go"], + deps = [ + ":go_default_library", + "//beacon-chain/core/time:go_default_library", + "//config/params:go_default_library", + "//consensus-types/primitives:go_default_library", + "//proto/engine/v1:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + ], +) diff --git a/beacon-chain/core/fulu/upgrade.go b/beacon-chain/core/fulu/upgrade.go new file mode 100644 index 000000000000..5b26f218d7f6 --- /dev/null +++ b/beacon-chain/core/fulu/upgrade.go @@ -0,0 +1,175 @@ +package fulu + +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" + "github.com/prysmaticlabs/prysm/v5/config/params" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" +) + +// UpgradeToFulu updates inputs a generic state to return the version Fulu state. +// https://github.com/ethereum/consensus-specs/blob/dev/specs/fulu/fork.md#upgrading-the-state +func UpgradeToFulu(beaconState state.BeaconState) (state.BeaconState, error) { + currentSyncCommittee, err := beaconState.CurrentSyncCommittee() + if err != nil { + return nil, err + } + nextSyncCommittee, err := beaconState.NextSyncCommittee() + if err != nil { + return nil, err + } + prevEpochParticipation, err := beaconState.PreviousEpochParticipation() + if err != nil { + return nil, err + } + currentEpochParticipation, err := beaconState.CurrentEpochParticipation() + if err != nil { + return nil, err + } + inactivityScores, err := beaconState.InactivityScores() + if err != nil { + return nil, err + } + payloadHeader, err := beaconState.LatestExecutionPayloadHeader() + if err != nil { + return nil, err + } + txRoot, err := payloadHeader.TransactionsRoot() + if err != nil { + return nil, err + } + wdRoot, err := payloadHeader.WithdrawalsRoot() + if err != nil { + return nil, err + } + wi, err := beaconState.NextWithdrawalIndex() + if err != nil { + return nil, err + } + vi, err := beaconState.NextWithdrawalValidatorIndex() + if err != nil { + return nil, err + } + summaries, err := beaconState.HistoricalSummaries() + if err != nil { + return nil, err + } + historicalRoots, err := beaconState.HistoricalRoots() + if err != nil { + return nil, err + } + excessBlobGas, err := payloadHeader.ExcessBlobGas() + if err != nil { + return nil, err + } + blobGasUsed, err := payloadHeader.BlobGasUsed() + if err != nil { + return nil, err + } + depositBalanceToConsume, err := beaconState.DepositBalanceToConsume() + if err != nil { + return nil, err + } + exitBalanceToConsume, err := beaconState.ExitBalanceToConsume() + if err != nil { + return nil, err + } + earliestExitEpoch, err := beaconState.EarliestExitEpoch() + if err != nil { + return nil, err + } + consolidationBalanceToConsume, err := beaconState.ConsolidationBalanceToConsume() + if err != nil { + return nil, err + } + earliestConsolidationEpoch, err := beaconState.EarliestConsolidationEpoch() + if err != nil { + return nil, err + } + pendingDeposits, err := beaconState.PendingDeposits() + if err != nil { + return nil, err + } + pendingPartialWithdrawals, err := beaconState.PendingPartialWithdrawals() + if err != nil { + return nil, err + } + pendingConsolidations, err := beaconState.PendingConsolidations() + if err != nil { + return nil, err + } + + s := ðpb.BeaconStateElectra{ + GenesisTime: beaconState.GenesisTime(), + GenesisValidatorsRoot: beaconState.GenesisValidatorsRoot(), + Slot: beaconState.Slot(), + Fork: ðpb.Fork{ + PreviousVersion: beaconState.Fork().CurrentVersion, + CurrentVersion: params.BeaconConfig().FuluForkVersion, + Epoch: time.CurrentEpoch(beaconState), + }, + LatestBlockHeader: beaconState.LatestBlockHeader(), + BlockRoots: beaconState.BlockRoots(), + StateRoots: beaconState.StateRoots(), + HistoricalRoots: historicalRoots, + Eth1Data: beaconState.Eth1Data(), + Eth1DataVotes: beaconState.Eth1DataVotes(), + Eth1DepositIndex: beaconState.Eth1DepositIndex(), + Validators: beaconState.Validators(), + Balances: beaconState.Balances(), + RandaoMixes: beaconState.RandaoMixes(), + Slashings: beaconState.Slashings(), + PreviousEpochParticipation: prevEpochParticipation, + CurrentEpochParticipation: currentEpochParticipation, + JustificationBits: beaconState.JustificationBits(), + PreviousJustifiedCheckpoint: beaconState.PreviousJustifiedCheckpoint(), + CurrentJustifiedCheckpoint: beaconState.CurrentJustifiedCheckpoint(), + FinalizedCheckpoint: beaconState.FinalizedCheckpoint(), + InactivityScores: inactivityScores, + CurrentSyncCommittee: currentSyncCommittee, + NextSyncCommittee: nextSyncCommittee, + LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadHeader.ParentHash(), + FeeRecipient: payloadHeader.FeeRecipient(), + StateRoot: payloadHeader.StateRoot(), + ReceiptsRoot: payloadHeader.ReceiptsRoot(), + LogsBloom: payloadHeader.LogsBloom(), + PrevRandao: payloadHeader.PrevRandao(), + BlockNumber: payloadHeader.BlockNumber(), + GasLimit: payloadHeader.GasLimit(), + GasUsed: payloadHeader.GasUsed(), + Timestamp: payloadHeader.Timestamp(), + ExtraData: payloadHeader.ExtraData(), + BaseFeePerGas: payloadHeader.BaseFeePerGas(), + BlockHash: payloadHeader.BlockHash(), + TransactionsRoot: txRoot, + WithdrawalsRoot: wdRoot, + ExcessBlobGas: excessBlobGas, + BlobGasUsed: blobGasUsed, + }, + NextWithdrawalIndex: wi, + NextWithdrawalValidatorIndex: vi, + HistoricalSummaries: summaries, + + DepositRequestsStartIndex: params.BeaconConfig().UnsetDepositRequestsStartIndex, + DepositBalanceToConsume: depositBalanceToConsume, + ExitBalanceToConsume: exitBalanceToConsume, + EarliestExitEpoch: earliestExitEpoch, + ConsolidationBalanceToConsume: consolidationBalanceToConsume, + EarliestConsolidationEpoch: earliestConsolidationEpoch, + PendingDeposits: pendingDeposits, + PendingPartialWithdrawals: pendingPartialWithdrawals, + PendingConsolidations: pendingConsolidations, + } + + // Need to cast the beaconState to use in helper functions + post, err := state_native.InitializeFromProtoUnsafeFulu(s) + if err != nil { + return nil, errors.Wrap(err, "failed to initialize post fulu beaconState") + } + + return post, nil +} diff --git a/beacon-chain/core/fulu/upgrade_test.go b/beacon-chain/core/fulu/upgrade_test.go new file mode 100644 index 000000000000..005bddba200b --- /dev/null +++ b/beacon-chain/core/fulu/upgrade_test.go @@ -0,0 +1,185 @@ +package fulu_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/fulu" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func TestUpgradeToFulu(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, params.BeaconConfig().MaxValidatorsPerCommittee) + require.NoError(t, st.SetHistoricalRoots([][]byte{{1}})) + vals := st.Validators() + vals[0].ActivationEpoch = params.BeaconConfig().FarFutureEpoch + vals[1].WithdrawalCredentials = []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte} + require.NoError(t, st.SetValidators(vals)) + bals := st.Balances() + bals[1] = params.BeaconConfig().MinActivationBalance + 1000 + require.NoError(t, st.SetBalances(bals)) + + preForkState := st.Copy() + mSt, err := fulu.UpgradeToFulu(st) + require.NoError(t, err) + + require.Equal(t, preForkState.GenesisTime(), mSt.GenesisTime()) + require.DeepSSZEqual(t, preForkState.GenesisValidatorsRoot(), mSt.GenesisValidatorsRoot()) + require.Equal(t, preForkState.Slot(), mSt.Slot()) + + f := mSt.Fork() + require.DeepSSZEqual(t, ðpb.Fork{ + PreviousVersion: st.Fork().CurrentVersion, + CurrentVersion: params.BeaconConfig().FuluForkVersion, + Epoch: time.CurrentEpoch(st), + }, f) + + require.DeepSSZEqual(t, preForkState.LatestBlockHeader(), mSt.LatestBlockHeader()) + require.DeepSSZEqual(t, preForkState.BlockRoots(), mSt.BlockRoots()) + require.DeepSSZEqual(t, preForkState.StateRoots(), mSt.StateRoots()) + + hr1, err := preForkState.HistoricalRoots() + require.NoError(t, err) + hr2, err := mSt.HistoricalRoots() + require.NoError(t, err) + require.DeepEqual(t, hr1, hr2) + + require.DeepSSZEqual(t, preForkState.Eth1Data(), mSt.Eth1Data()) + require.DeepSSZEqual(t, preForkState.Eth1DataVotes(), mSt.Eth1DataVotes()) + require.DeepSSZEqual(t, preForkState.Eth1DepositIndex(), mSt.Eth1DepositIndex()) + require.DeepSSZEqual(t, preForkState.Validators(), mSt.Validators()) + require.DeepSSZEqual(t, preForkState.Balances(), mSt.Balances()) + require.DeepSSZEqual(t, preForkState.RandaoMixes(), mSt.RandaoMixes()) + require.DeepSSZEqual(t, preForkState.Slashings(), mSt.Slashings()) + + numValidators := mSt.NumValidators() + + p, err := mSt.PreviousEpochParticipation() + require.NoError(t, err) + require.DeepSSZEqual(t, make([]byte, numValidators), p) + + p, err = mSt.CurrentEpochParticipation() + require.NoError(t, err) + require.DeepSSZEqual(t, make([]byte, numValidators), p) + + require.DeepSSZEqual(t, preForkState.JustificationBits(), mSt.JustificationBits()) + require.DeepSSZEqual(t, preForkState.PreviousJustifiedCheckpoint(), mSt.PreviousJustifiedCheckpoint()) + require.DeepSSZEqual(t, preForkState.CurrentJustifiedCheckpoint(), mSt.CurrentJustifiedCheckpoint()) + require.DeepSSZEqual(t, preForkState.FinalizedCheckpoint(), mSt.FinalizedCheckpoint()) + + s, err := mSt.InactivityScores() + require.NoError(t, err) + require.DeepSSZEqual(t, make([]uint64, numValidators), s) + + csc, err := mSt.CurrentSyncCommittee() + require.NoError(t, err) + psc, err := preForkState.CurrentSyncCommittee() + require.NoError(t, err) + require.DeepSSZEqual(t, psc, csc) + + nsc, err := mSt.NextSyncCommittee() + require.NoError(t, err) + psc, err = preForkState.NextSyncCommittee() + require.NoError(t, err) + require.DeepSSZEqual(t, psc, nsc) + + header, err := mSt.LatestExecutionPayloadHeader() + require.NoError(t, err) + protoHeader, ok := header.Proto().(*enginev1.ExecutionPayloadHeaderDeneb) + require.Equal(t, true, ok) + prevHeader, err := preForkState.LatestExecutionPayloadHeader() + require.NoError(t, err) + txRoot, err := prevHeader.TransactionsRoot() + require.NoError(t, err) + wdRoot, err := prevHeader.WithdrawalsRoot() + require.NoError(t, err) + wanted := &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: prevHeader.ParentHash(), + FeeRecipient: prevHeader.FeeRecipient(), + StateRoot: prevHeader.StateRoot(), + ReceiptsRoot: prevHeader.ReceiptsRoot(), + LogsBloom: prevHeader.LogsBloom(), + PrevRandao: prevHeader.PrevRandao(), + BlockNumber: prevHeader.BlockNumber(), + GasLimit: prevHeader.GasLimit(), + GasUsed: prevHeader.GasUsed(), + Timestamp: prevHeader.Timestamp(), + ExtraData: prevHeader.ExtraData(), + BaseFeePerGas: prevHeader.BaseFeePerGas(), + BlockHash: prevHeader.BlockHash(), + TransactionsRoot: txRoot, + WithdrawalsRoot: wdRoot, + } + require.DeepEqual(t, wanted, protoHeader) + + nwi, err := mSt.NextWithdrawalIndex() + require.NoError(t, err) + require.Equal(t, uint64(0), nwi) + + lwvi, err := mSt.NextWithdrawalValidatorIndex() + require.NoError(t, err) + require.Equal(t, primitives.ValidatorIndex(0), lwvi) + + summaries, err := mSt.HistoricalSummaries() + require.NoError(t, err) + require.Equal(t, 0, len(summaries)) + + preDepositRequestsStartIndex, err := preForkState.DepositRequestsStartIndex() + require.NoError(t, err) + postDepositRequestsStartIndex, err := mSt.DepositRequestsStartIndex() + require.NoError(t, err) + require.Equal(t, preDepositRequestsStartIndex, postDepositRequestsStartIndex) + + preDepositBalanceToConsume, err := preForkState.DepositBalanceToConsume() + require.NoError(t, err) + postDepositBalanceToConsume, err := mSt.DepositBalanceToConsume() + require.NoError(t, err) + require.Equal(t, preDepositBalanceToConsume, postDepositBalanceToConsume) + + preExitBalanceToConsume, err := preForkState.ExitBalanceToConsume() + require.NoError(t, err) + postExitBalanceToConsume, err := mSt.ExitBalanceToConsume() + require.NoError(t, err) + require.Equal(t, preExitBalanceToConsume, postExitBalanceToConsume) + + preEarliestExitEpoch, err := preForkState.EarliestExitEpoch() + require.NoError(t, err) + postEarliestExitEpoch, err := mSt.EarliestExitEpoch() + require.NoError(t, err) + require.Equal(t, preEarliestExitEpoch, postEarliestExitEpoch) + + preConsolidationBalanceToConsume, err := preForkState.ConsolidationBalanceToConsume() + require.NoError(t, err) + postConsolidationBalanceToConsume, err := mSt.ConsolidationBalanceToConsume() + require.NoError(t, err) + require.Equal(t, preConsolidationBalanceToConsume, postConsolidationBalanceToConsume) + + preEarliesConsolidationEoch, err := preForkState.EarliestConsolidationEpoch() + require.NoError(t, err) + postEarliestConsolidationEpoch, err := mSt.EarliestConsolidationEpoch() + require.NoError(t, err) + require.Equal(t, preEarliesConsolidationEoch, postEarliestConsolidationEpoch) + + prePendingDeposits, err := preForkState.PendingDeposits() + require.NoError(t, err) + postPendingDeposits, err := mSt.PendingDeposits() + require.NoError(t, err) + require.DeepSSZEqual(t, prePendingDeposits, postPendingDeposits) + + prePendingPartialWithdrawals, err := preForkState.PendingPartialWithdrawals() + require.NoError(t, err) + postPendingPartialWithdrawals, err := mSt.PendingPartialWithdrawals() + require.NoError(t, err) + require.DeepSSZEqual(t, prePendingPartialWithdrawals, postPendingPartialWithdrawals) + + prePendingConsolidations, err := preForkState.PendingConsolidations() + require.NoError(t, err) + postPendingConsolidations, err := mSt.PendingConsolidations() + require.NoError(t, err) + require.DeepSSZEqual(t, prePendingConsolidations, postPendingConsolidations) +} diff --git a/beacon-chain/core/helpers/BUILD.bazel b/beacon-chain/core/helpers/BUILD.bazel index c33980c260f3..1e65375ede71 100644 --- a/beacon-chain/core/helpers/BUILD.bazel +++ b/beacon-chain/core/helpers/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "beacon_committee.go", "block.go", "genesis.go", + "legacy.go", "metrics.go", "randao.go", "rewards_penalties.go", @@ -25,7 +26,6 @@ go_library( "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", - "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//container/slice:go_default_library", "//container/trie:go_default_library", @@ -33,6 +33,7 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//math:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "//time:go_default_library", @@ -42,7 +43,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -53,6 +53,7 @@ go_test( "attestation_test.go", "beacon_committee_test.go", "block_test.go", + "legacy_test.go", "private_access_fuzz_noop_test.go", # keep "private_access_test.go", "randao_test.go", @@ -63,6 +64,7 @@ go_test( "validators_test.go", "weak_subjectivity_test.go", ], + data = glob(["testdata/**"]), embed = [":go_default_library"], shard_count = 2, tags = ["CI_race_detection"], @@ -86,5 +88,6 @@ go_test( "//time:go_default_library", "//time/slots:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", ], ) diff --git a/beacon-chain/core/helpers/attestation.go b/beacon-chain/core/helpers/attestation.go index 807743e4f893..0dc7d845be19 100644 --- a/beacon-chain/core/helpers/attestation.go +++ b/beacon-chain/core/helpers/attestation.go @@ -23,11 +23,8 @@ var ( // Access to these nil fields will result in run time panic, // it is recommended to run these checks as first line of defense. func ValidateNilAttestation(attestation ethpb.Att) error { - if attestation == nil { - return errors.New("attestation can't be nil") - } - if attestation.GetData() == nil { - return errors.New("attestation's data can't be nil") + if attestation == nil || attestation.IsNil() { + return errors.New("attestation is nil") } if attestation.GetData().Source == nil { return errors.New("attestation's source can't be nil") @@ -35,6 +32,9 @@ func ValidateNilAttestation(attestation ethpb.Att) error { if attestation.GetData().Target == nil { return errors.New("attestation's target can't be nil") } + if attestation.IsSingle() { + return nil + } if attestation.GetAggregationBits() == nil { return errors.New("attestation's bitfield can't be nil") } @@ -70,12 +70,6 @@ func IsAggregator(committeeCount uint64, slotSig []byte) (bool, error) { return binary.LittleEndian.Uint64(b[:8])%modulo == 0, nil } -// IsAggregated returns true if the attestation is an aggregated attestation, -// false otherwise. -func IsAggregated(attestation ethpb.Att) bool { - return attestation.GetAggregationBits().Count() > 1 -} - // ComputeSubnetForAttestation returns the subnet for which the provided attestation will be broadcasted to. // This differs from the spec definition by instead passing in the active validators indices in the attestation's // given epoch. diff --git a/beacon-chain/core/helpers/attestation_test.go b/beacon-chain/core/helpers/attestation_test.go index 7004c9510aa2..e936abdddb40 100644 --- a/beacon-chain/core/helpers/attestation_test.go +++ b/beacon-chain/core/helpers/attestation_test.go @@ -260,12 +260,12 @@ func TestValidateNilAttestation(t *testing.T) { { name: "nil attestation", attestation: nil, - errString: "attestation can't be nil", + errString: "attestation is nil", }, { name: "nil attestation data", attestation: ðpb.Attestation{}, - errString: "attestation's data can't be nil", + errString: "attestation is nil", }, { name: "nil attestation source", @@ -308,6 +308,16 @@ func TestValidateNilAttestation(t *testing.T) { }, errString: "", }, + { + name: "single attestation", + attestation: ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + Target: ðpb.Checkpoint{}, + Source: ðpb.Checkpoint{}, + }, + }, + errString: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/beacon-chain/core/helpers/beacon_committee.go b/beacon-chain/core/helpers/beacon_committee.go index e8443630a7ee..2e70cf5f0fd4 100644 --- a/beacon-chain/core/helpers/beacon_committee.go +++ b/beacon-chain/core/helpers/beacon_committee.go @@ -337,24 +337,6 @@ func VerifyBitfieldLength(bf bitfield.Bitfield, committeeSize uint64) error { return nil } -// VerifyAttestationBitfieldLengths verifies that an attestations aggregation bitfields is -// a valid length matching the size of the committee. -func VerifyAttestationBitfieldLengths(ctx context.Context, state state.ReadOnlyBeaconState, att ethpb.Att) error { - committee, err := BeaconCommitteeFromState(ctx, state, att.GetData().Slot, att.GetData().CommitteeIndex) - if err != nil { - return errors.Wrap(err, "could not retrieve beacon committees") - } - - if committee == nil { - return errors.New("no committee exist for this attestation") - } - - if err := VerifyBitfieldLength(att.GetAggregationBits(), uint64(len(committee))); err != nil { - return errors.Wrap(err, "failed to verify aggregation bitfield") - } - return nil -} - // ShuffledIndices uses input beacon state and returns the shuffled indices of the input epoch, // the shuffled indices then can be used to break up into committees. func ShuffledIndices(s state.ReadOnlyBeaconState, epoch primitives.Epoch) ([]primitives.ValidatorIndex, error) { diff --git a/beacon-chain/core/helpers/beacon_committee_test.go b/beacon-chain/core/helpers/beacon_committee_test.go index 9604ede6f596..a9a95facc43c 100644 --- a/beacon-chain/core/helpers/beacon_committee_test.go +++ b/beacon-chain/core/helpers/beacon_committee_test.go @@ -97,6 +97,13 @@ func TestVerifyBitfieldLength_OK(t *testing.T) { assert.NoError(t, helpers.VerifyBitfieldLength(bf, committeeSize), "Bitfield is not validated when it was supposed to be") } +func TestVerifyBitfieldLength_Incorrect(t *testing.T) { + helpers.ClearCache() + + bf := bitfield.NewBitlist(1) + require.ErrorContains(t, "wanted participants bitfield length 2, got: 1", helpers.VerifyBitfieldLength(bf, 2)) +} + func TestCommitteeAssignments_CannotRetrieveFutureEpoch(t *testing.T) { helpers.ClearCache() @@ -403,7 +410,12 @@ func TestVerifyAttestationBitfieldLengths_OK(t *testing.T) { helpers.ClearCache() require.NoError(t, state.SetSlot(tt.stateSlot)) - err := helpers.VerifyAttestationBitfieldLengths(context.Background(), state, tt.attestation) + att := tt.attestation + // Verify attesting indices are correct. + committee, err := helpers.BeaconCommitteeFromState(context.Background(), state, att.GetData().Slot, att.GetData().CommitteeIndex) + require.NoError(t, err) + require.NotNil(t, committee) + err = helpers.VerifyBitfieldLength(att.GetAggregationBits(), uint64(len(committee))) if tt.verificationFailure { assert.NotNil(t, err, "Verification succeeded when it was supposed to fail") } else { diff --git a/beacon-chain/core/helpers/legacy.go b/beacon-chain/core/helpers/legacy.go new file mode 100644 index 000000000000..1e6a470a254d --- /dev/null +++ b/beacon-chain/core/helpers/legacy.go @@ -0,0 +1,20 @@ +package helpers + +import ( + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/runtime/version" +) + +// DepositRequestsStarted determines if the deposit requests have started. +func DepositRequestsStarted(beaconState state.BeaconState) bool { + if beaconState.Version() < version.Electra { + return false + } + + requestsStartIndex, err := beaconState.DepositRequestsStartIndex() + if err != nil { + return false + } + + return beaconState.Eth1DepositIndex() == requestsStartIndex +} diff --git a/beacon-chain/core/helpers/legacy_test.go b/beacon-chain/core/helpers/legacy_test.go new file mode 100644 index 000000000000..e9429aa48b11 --- /dev/null +++ b/beacon-chain/core/helpers/legacy_test.go @@ -0,0 +1,33 @@ +package helpers_test + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/stretchr/testify/require" +) + +// TestDepositRequestHaveStarted contains several test cases for depositRequestHaveStarted. +func TestDepositRequestHaveStarted(t *testing.T) { + t.Run("Version below Electra returns false", func(t *testing.T) { + st, _ := util.DeterministicGenesisStateBellatrix(t, 1) + result := helpers.DepositRequestsStarted(st) + require.False(t, result) + }) + + t.Run("Version is Electra or higher, no error, but Eth1DepositIndex != requestsStartIndex returns false", func(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, 1) + require.NoError(t, st.SetEth1DepositIndex(1)) + result := helpers.DepositRequestsStarted(st) + require.False(t, result) + }) + + t.Run("Version is Electra or higher, no error, and Eth1DepositIndex == requestsStartIndex returns true", func(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, 1) + require.NoError(t, st.SetEth1DepositIndex(33)) + require.NoError(t, st.SetDepositRequestsStartIndex(33)) + result := helpers.DepositRequestsStarted(st) + require.True(t, result) + }) +} diff --git a/beacon-chain/core/helpers/sync_committee.go b/beacon-chain/core/helpers/sync_committee.go index c28926f062b3..d012af07aed3 100644 --- a/beacon-chain/core/helpers/sync_committee.go +++ b/beacon-chain/core/helpers/sync_committee.go @@ -69,15 +69,16 @@ func IsNextPeriodSyncCommittee( } indices, err := syncCommitteeCache.NextPeriodIndexPosition(root, valIdx) if errors.Is(err, cache.ErrNonExistingSyncCommitteeKey) { - val, err := st.ValidatorAtIndex(valIdx) + val, err := st.ValidatorAtIndexReadOnly(valIdx) if err != nil { return false, err } + pk := val.PublicKey() committee, err := st.NextSyncCommittee() if err != nil { return false, err } - return len(findSubCommitteeIndices(val.PublicKey, committee.Pubkeys)) > 0, nil + return len(findSubCommitteeIndices(pk[:], committee.Pubkeys)) > 0, nil } if err != nil { return false, err @@ -96,10 +97,11 @@ func CurrentPeriodSyncSubcommitteeIndices( } indices, err := syncCommitteeCache.CurrentPeriodIndexPosition(root, valIdx) if errors.Is(err, cache.ErrNonExistingSyncCommitteeKey) { - val, err := st.ValidatorAtIndex(valIdx) + val, err := st.ValidatorAtIndexReadOnly(valIdx) if err != nil { return nil, err } + pk := val.PublicKey() committee, err := st.CurrentSyncCommittee() if err != nil { return nil, err @@ -112,7 +114,7 @@ func CurrentPeriodSyncSubcommitteeIndices( } }() - return findSubCommitteeIndices(val.PublicKey, committee.Pubkeys), nil + return findSubCommitteeIndices(pk[:], committee.Pubkeys), nil } if err != nil { return nil, err @@ -130,15 +132,16 @@ func NextPeriodSyncSubcommitteeIndices( } indices, err := syncCommitteeCache.NextPeriodIndexPosition(root, valIdx) if errors.Is(err, cache.ErrNonExistingSyncCommitteeKey) { - val, err := st.ValidatorAtIndex(valIdx) + val, err := st.ValidatorAtIndexReadOnly(valIdx) if err != nil { return nil, err } + pk := val.PublicKey() committee, err := st.NextSyncCommittee() if err != nil { return nil, err } - return findSubCommitteeIndices(val.PublicKey, committee.Pubkeys), nil + return findSubCommitteeIndices(pk[:], committee.Pubkeys), nil } if err != nil { return nil, err diff --git a/beacon-chain/core/helpers/validator_churn.go b/beacon-chain/core/helpers/validator_churn.go index a038e32b7db8..d6a2e55b7c22 100644 --- a/beacon-chain/core/helpers/validator_churn.go +++ b/beacon-chain/core/helpers/validator_churn.go @@ -22,7 +22,7 @@ import ( func BalanceChurnLimit(activeBalance primitives.Gwei) primitives.Gwei { churn := max( params.BeaconConfig().MinPerEpochChurnLimitElectra, - (uint64(activeBalance) / params.BeaconConfig().ChurnLimitQuotient), + uint64(activeBalance)/params.BeaconConfig().ChurnLimitQuotient, ) return primitives.Gwei(churn - churn%params.BeaconConfig().EffectiveBalanceIncrement) } diff --git a/beacon-chain/core/helpers/validators.go b/beacon-chain/core/helpers/validators.go index d896fe2de7f5..be387d2bc92d 100644 --- a/beacon-chain/core/helpers/validators.go +++ b/beacon-chain/core/helpers/validators.go @@ -3,6 +3,7 @@ package helpers import ( "bytes" "context" + "encoding/binary" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" @@ -11,16 +12,16 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" - "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/hash" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" log "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) var ( @@ -347,27 +348,33 @@ func BeaconProposerIndexAtSlot(ctx context.Context, state state.ReadOnlyBeaconSt // Spec pseudocode definition: // // def compute_proposer_index(state: BeaconState, indices: Sequence[ValidatorIndex], seed: Bytes32) -> ValidatorIndex: -// """ -// Return from ``indices`` a random index sampled by effective balance. -// """ -// assert len(indices) > 0 -// MAX_RANDOM_BYTE = 2**8 - 1 -// i = uint64(0) -// total = uint64(len(indices)) -// while True: -// candidate_index = indices[compute_shuffled_index(i % total, total, seed)] -// random_byte = hash(seed + uint_to_bytes(uint64(i // 32)))[i % 32] -// effective_balance = state.validators[candidate_index].effective_balance -// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_byte: #[Modified in Electra:EIP7251] -// return candidate_index -// i += 1 +// """ +// Return from ``indices`` a random index sampled by effective balance. +// """ +// assert len(indices) > 0 +// MAX_RANDOM_VALUE = 2**16 - 1 # [Modified in Electra] +// i = uint64(0) +// total = uint64(len(indices)) +// while True: +// candidate_index = indices[compute_shuffled_index(i % total, total, seed)] +// # [Modified in Electra] +// random_bytes = hash(seed + uint_to_bytes(i // 16)) +// offset = i % 16 * 2 +// random_value = bytes_to_uint64(random_bytes[offset:offset + 2]) +// effective_balance = state.validators[candidate_index].effective_balance +// # [Modified in Electra:EIP7251] +// if effective_balance * MAX_RANDOM_VALUE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_value: +// return candidate_index +// i += 1 func ComputeProposerIndex(bState state.ReadOnlyBeaconState, activeIndices []primitives.ValidatorIndex, seed [32]byte) (primitives.ValidatorIndex, error) { length := uint64(len(activeIndices)) if length == 0 { return 0, errors.New("empty active indices list") } - maxRandomByte := uint64(1<<8 - 1) hashFunc := hash.CustomSHA256Hasher() + beaconConfig := params.BeaconConfig() + seedBuffer := make([]byte, len(seed)+8) + copy(seedBuffer, seed[:]) for i := uint64(0); ; i++ { candidateIndex, err := ComputeShuffledIndex(primitives.ValidatorIndex(i%length), length, seed, true /* shuffle */) @@ -378,21 +385,28 @@ func ComputeProposerIndex(bState state.ReadOnlyBeaconState, activeIndices []prim if uint64(candidateIndex) >= uint64(bState.NumValidators()) { return 0, errors.New("active index out of range") } - b := append(seed[:], bytesutil.Bytes8(i/32)...) - randomByte := hashFunc(b)[i%32] + v, err := bState.ValidatorAtIndexReadOnly(candidateIndex) if err != nil { return 0, err } effectiveBal := v.EffectiveBalance() - - maxEB := params.BeaconConfig().MaxEffectiveBalance if bState.Version() >= version.Electra { - maxEB = params.BeaconConfig().MaxEffectiveBalanceElectra - } + binary.LittleEndian.PutUint64(seedBuffer[len(seed):], i/16) + randomBytes := hashFunc(seedBuffer) + offset := (i % 16) * 2 + randomValue := uint64(randomBytes[offset]) | uint64(randomBytes[offset+1])<<8 - if effectiveBal*maxRandomByte >= maxEB*uint64(randomByte) { - return candidateIndex, nil + if effectiveBal*fieldparams.MaxRandomValueElectra >= beaconConfig.MaxEffectiveBalanceElectra*randomValue { + return candidateIndex, nil + } + } else { + binary.LittleEndian.PutUint64(seedBuffer[len(seed):], i/32) + randomByte := hashFunc(seedBuffer)[i%32] + + if effectiveBal*fieldparams.MaxRandomByte >= beaconConfig.MaxEffectiveBalance*uint64(randomByte) { + return candidateIndex, nil + } } } } @@ -500,63 +514,6 @@ func LastActivatedValidatorIndex(ctx context.Context, st state.ReadOnlyBeaconSta return lastActivatedvalidatorIndex, nil } -// hasETH1WithdrawalCredential returns whether the validator has an ETH1 -// Withdrawal prefix. It assumes that the caller has a lock on the state -func HasETH1WithdrawalCredential(val interfaces.WithWithdrawalCredentials) bool { - if val == nil { - return false - } - return isETH1WithdrawalCredential(val.GetWithdrawalCredentials()) -} - -func isETH1WithdrawalCredential(creds []byte) bool { - return bytes.HasPrefix(creds, []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte}) -} - -// HasCompoundingWithdrawalCredential checks if the validator has a compounding withdrawal credential. -// New in Electra EIP-7251: https://eips.ethereum.org/EIPS/eip-7251 -// -// Spec definition: -// -// def has_compounding_withdrawal_credential(validator: Validator) -> bool: -// """ -// Check if ``validator`` has an 0x02 prefixed "compounding" withdrawal credential. -// """ -// return is_compounding_withdrawal_credential(validator.withdrawal_credentials) -func HasCompoundingWithdrawalCredential(v interfaces.WithWithdrawalCredentials) bool { - if v == nil { - return false - } - return IsCompoundingWithdrawalCredential(v.GetWithdrawalCredentials()) -} - -// IsCompoundingWithdrawalCredential checks if the credentials are a compounding withdrawal credential. -// -// Spec definition: -// -// def is_compounding_withdrawal_credential(withdrawal_credentials: Bytes32) -> bool: -// return withdrawal_credentials[:1] == COMPOUNDING_WITHDRAWAL_PREFIX -func IsCompoundingWithdrawalCredential(creds []byte) bool { - return bytes.HasPrefix(creds, []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte}) -} - -// HasExecutionWithdrawalCredentials checks if the validator has an execution withdrawal credential or compounding credential. -// New in Electra EIP-7251: https://eips.ethereum.org/EIPS/eip-7251 -// -// Spec definition: -// -// def has_execution_withdrawal_credential(validator: Validator) -> bool: -// """ -// Check if ``validator`` has a 0x01 or 0x02 prefixed withdrawal credential. -// """ -// return has_compounding_withdrawal_credential(validator) or has_eth1_withdrawal_credential(validator) -func HasExecutionWithdrawalCredentials(v interfaces.WithWithdrawalCredentials) bool { - if v == nil { - return false - } - return HasCompoundingWithdrawalCredential(v) || HasETH1WithdrawalCredential(v) -} - // IsSameWithdrawalCredentials returns true if both validators have the same withdrawal credentials. // // return a.withdrawal_credentials[12:] == b.withdrawal_credentials[12:] @@ -584,23 +541,23 @@ func IsSameWithdrawalCredentials(a, b *ethpb.Validator) bool { // and validator.withdrawable_epoch <= epoch // and balance > 0 // ) -func IsFullyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoch primitives.Epoch, fork int) bool { +func IsFullyWithdrawableValidator(val state.ReadOnlyValidator, balance uint64, epoch primitives.Epoch, fork int) bool { if val == nil || balance <= 0 { return false } // Electra / EIP-7251 logic if fork >= version.Electra { - return HasExecutionWithdrawalCredentials(val) && val.WithdrawableEpoch <= epoch + return val.HasExecutionWithdrawalCredentials() && val.WithdrawableEpoch() <= epoch } - return HasETH1WithdrawalCredential(val) && val.WithdrawableEpoch <= epoch + return val.HasETH1WithdrawalCredentials() && val.WithdrawableEpoch() <= epoch } // IsPartiallyWithdrawableValidator returns whether the validator is able to perform a // partial withdrawal. This function assumes that the caller has a lock on the state. // This method conditionally calls the fork appropriate implementation based on the epoch argument. -func IsPartiallyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoch primitives.Epoch, fork int) bool { +func IsPartiallyWithdrawableValidator(val state.ReadOnlyValidator, balance uint64, epoch primitives.Epoch, fork int) bool { if val == nil { return false } @@ -622,7 +579,7 @@ func IsPartiallyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoc // """ // Check if ``validator`` is partially withdrawable. // """ -// max_effective_balance = get_validator_max_effective_balance(validator) +// max_effective_balance = get_max_effective_balance(validator) // has_max_effective_balance = validator.effective_balance == max_effective_balance # [Modified in Electra:EIP7251] // has_excess_balance = balance > max_effective_balance # [Modified in Electra:EIP7251] // return ( @@ -630,12 +587,12 @@ func IsPartiallyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoc // and has_max_effective_balance // and has_excess_balance // ) -func isPartiallyWithdrawableValidatorElectra(val *ethpb.Validator, balance uint64, epoch primitives.Epoch) bool { +func isPartiallyWithdrawableValidatorElectra(val state.ReadOnlyValidator, balance uint64, epoch primitives.Epoch) bool { maxEB := ValidatorMaxEffectiveBalance(val) - hasMaxBalance := val.EffectiveBalance == maxEB + hasMaxBalance := val.EffectiveBalance() == maxEB hasExcessBalance := balance > maxEB - return HasExecutionWithdrawalCredentials(val) && + return val.HasExecutionWithdrawalCredentials() && hasMaxBalance && hasExcessBalance } @@ -652,17 +609,17 @@ func isPartiallyWithdrawableValidatorElectra(val *ethpb.Validator, balance uint6 // has_max_effective_balance = validator.effective_balance == MAX_EFFECTIVE_BALANCE // has_excess_balance = balance > MAX_EFFECTIVE_BALANCE // return has_eth1_withdrawal_credential(validator) and has_max_effective_balance and has_excess_balance -func isPartiallyWithdrawableValidatorCapella(val *ethpb.Validator, balance uint64, epoch primitives.Epoch) bool { - hasMaxBalance := val.EffectiveBalance == params.BeaconConfig().MaxEffectiveBalance +func isPartiallyWithdrawableValidatorCapella(val state.ReadOnlyValidator, balance uint64, epoch primitives.Epoch) bool { + hasMaxBalance := val.EffectiveBalance() == params.BeaconConfig().MaxEffectiveBalance hasExcessBalance := balance > params.BeaconConfig().MaxEffectiveBalance - return HasETH1WithdrawalCredential(val) && hasExcessBalance && hasMaxBalance + return val.HasETH1WithdrawalCredentials() && hasExcessBalance && hasMaxBalance } // ValidatorMaxEffectiveBalance returns the maximum effective balance for a validator. // // Spec definition: // -// def get_validator_max_effective_balance(validator: Validator) -> Gwei: +// def get_max_effective_balance(validator: Validator) -> Gwei: // """ // Get max effective balance for ``validator``. // """ @@ -670,8 +627,8 @@ func isPartiallyWithdrawableValidatorCapella(val *ethpb.Validator, balance uint6 // return MAX_EFFECTIVE_BALANCE_ELECTRA // else: // return MIN_ACTIVATION_BALANCE -func ValidatorMaxEffectiveBalance(val *ethpb.Validator) uint64 { - if HasCompoundingWithdrawalCredential(val) { +func ValidatorMaxEffectiveBalance(val state.ReadOnlyValidator) uint64 { + if val.HasCompoundingWithdrawalCredentials() { return params.BeaconConfig().MaxEffectiveBalanceElectra } return params.BeaconConfig().MinActivationBalance diff --git a/beacon-chain/core/helpers/validators_test.go b/beacon-chain/core/helpers/validators_test.go index 3d10c711db43..7374d3498def 100644 --- a/beacon-chain/core/helpers/validators_test.go +++ b/beacon-chain/core/helpers/validators_test.go @@ -841,7 +841,6 @@ func computeProposerIndexWithValidators(validators []*ethpb.Validator, activeInd if length == 0 { return 0, errors.New("empty active indices list") } - maxRandomByte := uint64(1<<8 - 1) hashFunc := hash.CustomSHA256Hasher() for i := uint64(0); ; i++ { @@ -860,7 +859,7 @@ func computeProposerIndexWithValidators(validators []*ethpb.Validator, activeInd if v != nil { effectiveBal = v.EffectiveBalance } - if effectiveBal*maxRandomByte >= params.BeaconConfig().MaxEffectiveBalance*uint64(randomByte) { + if effectiveBal*fieldparams.MaxRandomByte >= params.BeaconConfig().MaxEffectiveBalance*uint64(randomByte) { return candidateIndex, nil } } @@ -911,13 +910,15 @@ func TestProposerIndexFromCheckpoint(t *testing.T) { func TestHasETH1WithdrawalCredentials(t *testing.T) { creds := []byte{0xFA, 0xCC} v := ðpb.Validator{WithdrawalCredentials: creds} - require.Equal(t, false, helpers.HasETH1WithdrawalCredential(v)) + roV, err := state_native.NewValidator(v) + require.NoError(t, err) + require.Equal(t, false, roV.HasETH1WithdrawalCredentials()) creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC} v = ðpb.Validator{WithdrawalCredentials: creds} - require.Equal(t, true, helpers.HasETH1WithdrawalCredential(v)) + roV, err = state_native.NewValidator(v) + require.NoError(t, err) + require.Equal(t, true, roV.HasETH1WithdrawalCredentials()) // No Withdrawal cred - v = ðpb.Validator{} - require.Equal(t, false, helpers.HasETH1WithdrawalCredential(v)) } func TestHasCompoundingWithdrawalCredential(t *testing.T) { @@ -932,11 +933,12 @@ func TestHasCompoundingWithdrawalCredential(t *testing.T) { {"Does not have compounding withdrawal credential", ðpb.Validator{WithdrawalCredentials: bytesutil.PadTo([]byte{0x00}, 32)}, false}, - {"Handles nil case", nil, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, helpers.HasCompoundingWithdrawalCredential(tt.validator)) + roV, err := state_native.NewValidator(tt.validator) + require.NoError(t, err) + assert.Equal(t, tt.want, roV.HasCompoundingWithdrawalCredentials()) }) } } @@ -956,11 +958,12 @@ func TestHasExecutionWithdrawalCredentials(t *testing.T) { {"Does not have compounding withdrawal credential or eth1 withdrawal credential", ðpb.Validator{WithdrawalCredentials: bytesutil.PadTo([]byte{0x00}, 32)}, false}, - {"Handles nil case", nil, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, helpers.HasExecutionWithdrawalCredentials(tt.validator)) + roV, err := state_native.NewValidator(tt.validator) + require.NoError(t, err) + assert.Equal(t, tt.want, roV.HasExecutionWithdrawalCredentials()) }) } } @@ -974,13 +977,6 @@ func TestIsFullyWithdrawableValidator(t *testing.T) { fork int want bool }{ - { - name: "Handles nil case", - validator: nil, - balance: 0, - epoch: 0, - want: false, - }, { name: "No ETH1 prefix", validator: ðpb.Validator{ @@ -1036,7 +1032,9 @@ func TestIsFullyWithdrawableValidator(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, helpers.IsFullyWithdrawableValidator(tt.validator, tt.balance, tt.epoch, tt.fork)) + v, err := state_native.NewValidator(tt.validator) + require.NoError(t, err) + assert.Equal(t, tt.want, helpers.IsFullyWithdrawableValidator(v, tt.balance, tt.epoch, tt.fork)) }) } } @@ -1050,13 +1048,6 @@ func TestIsPartiallyWithdrawableValidator(t *testing.T) { fork int want bool }{ - { - name: "Handles nil case", - validator: nil, - balance: 0, - epoch: 0, - want: false, - }, { name: "No ETH1 prefix", validator: ðpb.Validator{ @@ -1113,7 +1104,9 @@ func TestIsPartiallyWithdrawableValidator(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, helpers.IsPartiallyWithdrawableValidator(tt.validator, tt.balance, tt.epoch, tt.fork)) + v, err := state_native.NewValidator(tt.validator) + require.NoError(t, err) + assert.Equal(t, tt.want, helpers.IsPartiallyWithdrawableValidator(v, tt.balance, tt.epoch, tt.fork)) }) } } @@ -1167,15 +1160,12 @@ func TestValidatorMaxEffectiveBalance(t *testing.T) { validator: ðpb.Validator{WithdrawalCredentials: []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}}, want: params.BeaconConfig().MinActivationBalance, }, - { - "Handles nil case", - nil, - params.BeaconConfig().MinActivationBalance, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, helpers.ValidatorMaxEffectiveBalance(tt.validator)) + v, err := state_native.NewValidator(tt.validator) + require.NoError(t, err) + assert.Equal(t, tt.want, helpers.ValidatorMaxEffectiveBalance(v)) }) } // Sanity check that MinActivationBalance equals (pre-electra) MaxEffectiveBalance diff --git a/beacon-chain/core/light-client/BUILD.bazel b/beacon-chain/core/light-client/BUILD.bazel new file mode 100644 index 000000000000..25bfc44320a1 --- /dev/null +++ b/beacon-chain/core/light-client/BUILD.bazel @@ -0,0 +1,46 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["lightclient.go"], + importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client", + visibility = ["//visibility:public"], + deps = [ + "//beacon-chain/execution:go_default_library", + "//beacon-chain/state:go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//consensus-types:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/interfaces:go_default_library", + "//consensus-types/light-client:go_default_library", + "//consensus-types/primitives:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/engine/v1:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", + "//time/slots:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["lightclient_test.go"], + deps = [ + ":go_default_library", + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//consensus-types:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/light-client:go_default_library", + "//consensus-types/primitives:go_default_library", + "//encoding/ssz:go_default_library", + "//proto/engine/v1:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "@com_github_pkg_errors//:go_default_library", + ], +) diff --git a/beacon-chain/core/light-client/lightclient.go b/beacon-chain/core/light-client/lightclient.go new file mode 100644 index 000000000000..c5518aecc4a1 --- /dev/null +++ b/beacon-chain/core/light-client/lightclient.go @@ -0,0 +1,1015 @@ +package light_client + +import ( + "bytes" + "context" + "fmt" + "reflect" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" + consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/encoding/ssz" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/time/slots" + "google.golang.org/protobuf/proto" +) + +const ErrNotEnoughSyncCommitteeBits = "sync committee bits count is less than required" + +func NewLightClientFinalityUpdateFromBeaconState( + ctx context.Context, + currentSlot primitives.Slot, + state state.BeaconState, + block interfaces.ReadOnlySignedBeaconBlock, + attestedState state.BeaconState, + attestedBlock interfaces.ReadOnlySignedBeaconBlock, + finalizedBlock interfaces.ReadOnlySignedBeaconBlock, +) (interfaces.LightClientFinalityUpdate, error) { + update, err := NewLightClientUpdateFromBeaconState(ctx, currentSlot, state, block, attestedState, attestedBlock, finalizedBlock) + if err != nil { + return nil, err + } + + return light_client.NewFinalityUpdateFromUpdate(update) +} + +func NewLightClientOptimisticUpdateFromBeaconState( + ctx context.Context, + currentSlot primitives.Slot, + state state.BeaconState, + block interfaces.ReadOnlySignedBeaconBlock, + attestedState state.BeaconState, + attestedBlock interfaces.ReadOnlySignedBeaconBlock, +) (interfaces.LightClientOptimisticUpdate, error) { + update, err := NewLightClientUpdateFromBeaconState(ctx, currentSlot, state, block, attestedState, attestedBlock, nil) + if err != nil { + return nil, err + } + + return light_client.NewOptimisticUpdateFromUpdate(update) +} + +// To form a LightClientUpdate, the following historical states and blocks are needed: +// - state: the post state of any block with a post-Altair parent block +// - block: the corresponding block +// - attested_state: the post state of attested_block +// - attested_block: the block referred to by block.parent_root +// - finalized_block: the block referred to by attested_state.finalized_checkpoint.root, +// if locally available (may be unavailable, e.g., when using checkpoint sync, or if it was pruned locally) +func NewLightClientUpdateFromBeaconState( + ctx context.Context, + currentSlot primitives.Slot, + state state.BeaconState, + block interfaces.ReadOnlySignedBeaconBlock, + attestedState state.BeaconState, + attestedBlock interfaces.ReadOnlySignedBeaconBlock, + finalizedBlock interfaces.ReadOnlySignedBeaconBlock) (interfaces.LightClientUpdate, error) { + // assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH + attestedEpoch := slots.ToEpoch(attestedState.Slot()) + if attestedEpoch < params.BeaconConfig().AltairForkEpoch { + return nil, fmt.Errorf("invalid attested epoch %d", attestedEpoch) + } + + // assert sum(block.message.body.sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS + syncAggregate, err := block.Block().Body().SyncAggregate() + if err != nil { + return nil, errors.Wrap(err, "could not get sync aggregate") + } + if syncAggregate.SyncCommitteeBits.Count() < params.BeaconConfig().MinSyncCommitteeParticipants { + return nil, fmt.Errorf( + "%s (got %d, need %d)", + ErrNotEnoughSyncCommitteeBits, + syncAggregate.SyncCommitteeBits.Count(), + params.BeaconConfig().MinSyncCommitteeParticipants, + ) + } + + // assert state.slot == state.latest_block_header.slot + if state.Slot() != state.LatestBlockHeader().Slot { + return nil, fmt.Errorf("state slot %d not equal to latest block header slot %d", state.Slot(), state.LatestBlockHeader().Slot) + } + + // assert hash_tree_root(header) == hash_tree_root(block.message) + header := state.LatestBlockHeader() + stateRoot, err := state.HashTreeRoot(ctx) + if err != nil { + return nil, errors.Wrap(err, "could not get state root") + } + header.StateRoot = stateRoot[:] + headerRoot, err := header.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get header root") + } + blockRoot, err := block.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get block root") + } + if headerRoot != blockRoot { + return nil, fmt.Errorf("header root %#x not equal to block root %#x", headerRoot, blockRoot) + } + + // update_signature_period = compute_sync_committee_period(compute_epoch_at_slot(block.message.slot)) + updateSignaturePeriod := slots.SyncCommitteePeriod(slots.ToEpoch(block.Block().Slot())) + + // assert attested_state.slot == attested_state.latest_block_header.slot + if attestedState.Slot() != attestedState.LatestBlockHeader().Slot { + return nil, fmt.Errorf( + "attested state slot %d not equal to attested latest block header slot %d", + attestedState.Slot(), + attestedState.LatestBlockHeader().Slot, + ) + } + + // attested_header = attested_state.latest_block_header.copy() + attestedHeader := attestedState.LatestBlockHeader() + + // attested_header.state_root = hash_tree_root(attested_state) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + if err != nil { + return nil, errors.Wrap(err, "could not get attested state root") + } + attestedHeader.StateRoot = attestedStateRoot[:] + + // assert hash_tree_root(attested_header) == block.message.parent_root + attestedHeaderRoot, err := attestedHeader.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get attested header root") + } + attestedBlockRoot, err := attestedBlock.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get attested block root") + } + // assert hash_tree_root(attested_header) == hash_tree_root(attested_block.message) == block.message.parent_root + if attestedHeaderRoot != block.Block().ParentRoot() || attestedHeaderRoot != attestedBlockRoot { + return nil, fmt.Errorf( + "attested header root %#x not equal to block parent root %#x or attested block root %#x", + attestedHeaderRoot, + block.Block().ParentRoot(), + attestedBlockRoot, + ) + } + + // update_attested_period = compute_sync_committee_period_at_slot(attested_block.message.slot) + updateAttestedPeriod := slots.SyncCommitteePeriod(slots.ToEpoch(attestedBlock.Block().Slot())) + + // update = LightClientUpdate() + result, err := CreateDefaultLightClientUpdate(currentSlot, attestedState) + if err != nil { + return nil, errors.Wrap(err, "could not create default light client update") + } + + // update.attested_header = block_to_light_client_header(attested_block) + attestedLightClientHeader, err := BlockToLightClientHeader(ctx, currentSlot, attestedBlock) + if err != nil { + return nil, errors.Wrap(err, "could not get attested light client header") + } + if err = result.SetAttestedHeader(attestedLightClientHeader); err != nil { + return nil, errors.Wrap(err, "could not set attested header") + } + + // if update_attested_period == update_signature_period + if updateAttestedPeriod == updateSignaturePeriod { + // update.next_sync_committee = attested_state.next_sync_committee + tempNextSyncCommittee, err := attestedState.NextSyncCommittee() + if err != nil { + return nil, errors.Wrap(err, "could not get next sync committee") + } + nextSyncCommittee := &pb.SyncCommittee{ + Pubkeys: tempNextSyncCommittee.Pubkeys, + AggregatePubkey: tempNextSyncCommittee.AggregatePubkey, + } + result.SetNextSyncCommittee(nextSyncCommittee) + + // update.next_sync_committee_branch = NextSyncCommitteeBranch( + // compute_merkle_proof(attested_state, next_sync_committee_gindex_at_slot(attested_state.slot))) + nextSyncCommitteeBranch, err := attestedState.NextSyncCommitteeProof(ctx) + if err != nil { + return nil, errors.Wrap(err, "could not get next sync committee proof") + } + if attestedBlock.Version() >= version.Electra { + if err = result.SetNextSyncCommitteeBranch(nextSyncCommitteeBranch); err != nil { + return nil, errors.Wrap(err, "could not set next sync committee branch") + } + } else if err = result.SetNextSyncCommitteeBranch(nextSyncCommitteeBranch); err != nil { + return nil, errors.Wrap(err, "could not set next sync committee branch") + } + } + + // if finalized_block is not None + if finalizedBlock != nil && !finalizedBlock.IsNil() { + // if finalized_block.message.slot != GENESIS_SLOT + if finalizedBlock.Block().Slot() != 0 { + // update.finalized_header = block_to_light_client_header(finalized_block) + finalizedLightClientHeader, err := BlockToLightClientHeader(ctx, currentSlot, finalizedBlock) + if err != nil { + return nil, errors.Wrap(err, "could not get finalized light client header") + } + if err = result.SetFinalizedHeader(finalizedLightClientHeader); err != nil { + return nil, errors.Wrap(err, "could not set finalized header") + } + } else { + // assert attested_state.finalized_checkpoint.root == Bytes32() + if !bytes.Equal(attestedState.FinalizedCheckpoint().Root, make([]byte, 32)) { + return nil, fmt.Errorf("invalid finalized header root %v", attestedState.FinalizedCheckpoint().Root) + } + } + + // update.finality_branch = FinalityBranch( + // compute_merkle_proof(attested_state, finalized_root_gindex_at_slot(attested_state.slot))) + finalityBranch, err := attestedState.FinalizedRootProof(ctx) + if err != nil { + return nil, errors.Wrap(err, "could not get finalized root proof") + } + if err = result.SetFinalityBranch(finalityBranch); err != nil { + return nil, errors.Wrap(err, "could not set finality branch") + } + } + + // update.sync_aggregate = block.message.body.sync_aggregate + result.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: syncAggregate.SyncCommitteeBits, + SyncCommitteeSignature: syncAggregate.SyncCommitteeSignature, + }) + + // update.signature_slot = block.message.slot + result.SetSignatureSlot(block.Block().Slot()) + + return result, nil +} + +func CreateDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState state.BeaconState) (interfaces.LightClientUpdate, error) { + currentEpoch := slots.ToEpoch(currentSlot) + + syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize + pubKeys := make([][]byte, syncCommitteeSize) + for i := uint64(0); i < syncCommitteeSize; i++ { + pubKeys[i] = make([]byte, fieldparams.BLSPubkeyLength) + } + nextSyncCommittee := &pb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), + } + + var nextSyncCommitteeBranch [][]byte + if attestedState.Version() >= version.Electra { + nextSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepthElectra) + } else { + nextSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepth) + } + for i := 0; i < len(nextSyncCommitteeBranch); i++ { + nextSyncCommitteeBranch[i] = make([]byte, fieldparams.RootLength) + } + + executionBranch := make([][]byte, fieldparams.ExecutionBranchDepth) + for i := 0; i < fieldparams.ExecutionBranchDepth; i++ { + executionBranch[i] = make([]byte, 32) + } + + var finalityBranch [][]byte + if attestedState.Version() >= version.Electra { + finalityBranch = make([][]byte, fieldparams.FinalityBranchDepthElectra) + } else { + finalityBranch = make([][]byte, fieldparams.FinalityBranchDepth) + } + for i := 0; i < len(finalityBranch); i++ { + finalityBranch[i] = make([]byte, 32) + } + + var m proto.Message + if currentEpoch < params.BeaconConfig().CapellaForkEpoch { + m = &pb.LightClientUpdateAltair{ + AttestedHeader: &pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + FinalizedHeader: &pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + }, + SyncAggregate: &pb.SyncAggregate{ + SyncCommitteeBits: make([]byte, 64), + SyncCommitteeSignature: make([]byte, 96), + }, + } + } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { + m = &pb.LightClientUpdateCapella{ + AttestedHeader: &pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + FinalizedHeader: &pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: executionBranch, + }, + SyncAggregate: &pb.SyncAggregate{ + SyncCommitteeBits: make([]byte, 64), + SyncCommitteeSignature: make([]byte, 96), + }, + } + } else if currentEpoch < params.BeaconConfig().ElectraForkEpoch { + m = &pb.LightClientUpdateDeneb{ + AttestedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, + }, + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + FinalizedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, + }, + ExecutionBranch: executionBranch, + }, + SyncAggregate: &pb.SyncAggregate{ + SyncCommitteeBits: make([]byte, 64), + SyncCommitteeSignature: make([]byte, 96), + }, + } + } else { + if attestedState.Version() >= version.Electra { + m = &pb.LightClientUpdateElectra{ + AttestedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, + }, + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + FinalizedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, + }, + ExecutionBranch: executionBranch, + }, + SyncAggregate: &pb.SyncAggregate{ + SyncCommitteeBits: make([]byte, 64), + SyncCommitteeSignature: make([]byte, 96), + }, + } + } else { + m = &pb.LightClientUpdateDeneb{ + AttestedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, + }, + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + FinalizedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, + }, + ExecutionBranch: executionBranch, + }, + SyncAggregate: &pb.SyncAggregate{ + SyncCommitteeBits: make([]byte, 64), + SyncCommitteeSignature: make([]byte, 96), + }, + } + } + } + + return light_client.NewWrappedUpdate(m) +} + +func ComputeTransactionsRoot(payload interfaces.ExecutionData) ([]byte, error) { + transactionsRoot, err := payload.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payload.Transactions() + if err != nil { + return nil, errors.Wrap(err, "could not get transactions") + } + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + transactionsRoot = transactionsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + return transactionsRoot, nil +} + +func ComputeWithdrawalsRoot(payload interfaces.ExecutionData) ([]byte, error) { + withdrawalsRoot, err := payload.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals") + } + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + withdrawalsRoot = withdrawalsRootArray[:] + } else if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + return withdrawalsRoot, nil +} + +func BlockToLightClientHeader( + ctx context.Context, + currentSlot primitives.Slot, + block interfaces.ReadOnlySignedBeaconBlock, +) (interfaces.LightClientHeader, error) { + var m proto.Message + currentEpoch := slots.ToEpoch(currentSlot) + blockEpoch := slots.ToEpoch(block.Block().Slot()) + parentRoot := block.Block().ParentRoot() + stateRoot := block.Block().StateRoot() + bodyRoot, err := block.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get body root") + } + + if currentEpoch < params.BeaconConfig().CapellaForkEpoch { + m = &pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: block.Block().Slot(), + ProposerIndex: block.Block().ProposerIndex(), + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + BodyRoot: bodyRoot[:], + }, + } + } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { + var payloadHeader *enginev1.ExecutionPayloadHeaderCapella + var payloadProof [][]byte + + if blockEpoch < params.BeaconConfig().CapellaForkEpoch { + var ok bool + + p, err := execution.EmptyExecutionPayloadHeader(version.Capella) + if err != nil { + return nil, errors.Wrap(err, "could not get payload header") + } + payloadHeader, ok = p.(*enginev1.ExecutionPayloadHeaderCapella) + if !ok { + return nil, fmt.Errorf("payload header type %T is not %T", p, &enginev1.ExecutionPayloadHeaderCapella{}) + } + payloadProof = emptyPayloadProof() + } else { + payload, err := block.Block().Body().Execution() + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload") + } + transactionsRoot, err := ComputeTransactionsRoot(payload) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + + payloadHeader = &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + payloadProof, err = blocks.PayloadProof(ctx, block.Block()) + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload proof") + } + } + + m = &pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{ + Slot: block.Block().Slot(), + ProposerIndex: block.Block().ProposerIndex(), + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + BodyRoot: bodyRoot[:], + }, + Execution: payloadHeader, + ExecutionBranch: payloadProof, + } + } else { + var payloadHeader *enginev1.ExecutionPayloadHeaderDeneb + var payloadProof [][]byte + + if blockEpoch < params.BeaconConfig().CapellaForkEpoch { + var ok bool + + p, err := execution.EmptyExecutionPayloadHeader(version.Deneb) + if err != nil { + return nil, errors.Wrap(err, "could not get payload header") + } + payloadHeader, ok = p.(*enginev1.ExecutionPayloadHeaderDeneb) + if !ok { + return nil, fmt.Errorf("payload header type %T is not %T", p, &enginev1.ExecutionPayloadHeaderDeneb{}) + } + payloadProof = emptyPayloadProof() + } else { + payload, err := block.Block().Body().Execution() + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload") + } + transactionsRoot, err := ComputeTransactionsRoot(payload) + if err != nil { + return nil, errors.Wrap(err, "could not get transactions root") + } + withdrawalsRoot, err := ComputeWithdrawalsRoot(payload) + if err != nil { + return nil, errors.Wrap(err, "could not get withdrawals root") + } + + var blobGasUsed uint64 + var excessBlobGas uint64 + + if blockEpoch >= params.BeaconConfig().DenebForkEpoch { + blobGasUsed, err = payload.BlobGasUsed() + if err != nil { + return nil, errors.Wrap(err, "could not get blob gas used") + } + excessBlobGas, err = payload.ExcessBlobGas() + if err != nil { + return nil, errors.Wrap(err, "could not get excess blob gas") + } + } + + payloadHeader = &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: blobGasUsed, + ExcessBlobGas: excessBlobGas, + } + + payloadProof, err = blocks.PayloadProof(ctx, block.Block()) + if err != nil { + return nil, errors.Wrap(err, "could not get execution payload proof") + } + } + + m = &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + Slot: block.Block().Slot(), + ProposerIndex: block.Block().ProposerIndex(), + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + BodyRoot: bodyRoot[:], + }, + Execution: payloadHeader, + ExecutionBranch: payloadProof, + } + } + + return light_client.NewWrappedHeader(m) +} + +func emptyPayloadProof() [][]byte { + branch := interfaces.LightClientExecutionBranch{} + proof := make([][]byte, len(branch)) + for i, b := range branch { + proof[i] = b[:] + } + return proof +} + +func HasRelevantSyncCommittee(update interfaces.LightClientUpdate) (bool, error) { + if update.Version() >= version.Electra { + branch, err := update.NextSyncCommitteeBranchElectra() + if err != nil { + return false, err + } + return !reflect.DeepEqual(branch, interfaces.LightClientSyncCommitteeBranchElectra{}), nil + } + branch, err := update.NextSyncCommitteeBranch() + if err != nil { + return false, err + } + return !reflect.DeepEqual(branch, interfaces.LightClientSyncCommitteeBranch{}), nil +} + +func HasFinality(update interfaces.LightClientUpdate) (bool, error) { + if update.Version() >= version.Electra { + b, err := update.FinalityBranchElectra() + if err != nil { + return false, err + } + return !reflect.DeepEqual(b, interfaces.LightClientFinalityBranchElectra{}), nil + } + + b, err := update.FinalityBranch() + if err != nil { + return false, err + } + return !reflect.DeepEqual(b, interfaces.LightClientFinalityBranch{}), nil +} + +func IsBetterUpdate(newUpdate, oldUpdate interfaces.LightClientUpdate) (bool, error) { + maxActiveParticipants := newUpdate.SyncAggregate().SyncCommitteeBits.Len() + newNumActiveParticipants := newUpdate.SyncAggregate().SyncCommitteeBits.Count() + oldNumActiveParticipants := oldUpdate.SyncAggregate().SyncCommitteeBits.Count() + newHasSupermajority := newNumActiveParticipants*3 >= maxActiveParticipants*2 + oldHasSupermajority := oldNumActiveParticipants*3 >= maxActiveParticipants*2 + + if newHasSupermajority != oldHasSupermajority { + return newHasSupermajority, nil + } + if !newHasSupermajority && newNumActiveParticipants != oldNumActiveParticipants { + return newNumActiveParticipants > oldNumActiveParticipants, nil + } + + newUpdateAttestedHeaderBeacon := newUpdate.AttestedHeader().Beacon() + oldUpdateAttestedHeaderBeacon := oldUpdate.AttestedHeader().Beacon() + + // Compare presence of relevant sync committee + newHasRelevantSyncCommittee, err := HasRelevantSyncCommittee(newUpdate) + if err != nil { + return false, err + } + newHasRelevantSyncCommittee = newHasRelevantSyncCommittee && + (slots.SyncCommitteePeriod(slots.ToEpoch(newUpdateAttestedHeaderBeacon.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(newUpdate.SignatureSlot()))) + oldHasRelevantSyncCommittee, err := HasRelevantSyncCommittee(oldUpdate) + if err != nil { + return false, err + } + oldHasRelevantSyncCommittee = oldHasRelevantSyncCommittee && + (slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdateAttestedHeaderBeacon.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdate.SignatureSlot()))) + + if newHasRelevantSyncCommittee != oldHasRelevantSyncCommittee { + return newHasRelevantSyncCommittee, nil + } + + // Compare indication of any finality + newHasFinality, err := HasFinality(newUpdate) + if err != nil { + return false, err + } + oldHasFinality, err := HasFinality(oldUpdate) + if err != nil { + return false, err + } + if newHasFinality != oldHasFinality { + return newHasFinality, nil + } + + newUpdateFinalizedHeaderBeacon := newUpdate.FinalizedHeader().Beacon() + oldUpdateFinalizedHeaderBeacon := oldUpdate.FinalizedHeader().Beacon() + + // Compare sync committee finality + if newHasFinality { + newHasSyncCommitteeFinality := + slots.SyncCommitteePeriod(slots.ToEpoch(newUpdateFinalizedHeaderBeacon.Slot)) == + slots.SyncCommitteePeriod(slots.ToEpoch(newUpdateAttestedHeaderBeacon.Slot)) + oldHasSyncCommitteeFinality := + slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdateFinalizedHeaderBeacon.Slot)) == + slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdateAttestedHeaderBeacon.Slot)) + + if newHasSyncCommitteeFinality != oldHasSyncCommitteeFinality { + return newHasSyncCommitteeFinality, nil + } + } + + // Tiebreaker 1: Sync committee participation beyond supermajority + if newNumActiveParticipants != oldNumActiveParticipants { + return newNumActiveParticipants > oldNumActiveParticipants, nil + } + + // Tiebreaker 2: Prefer older data (fewer changes to best) + if newUpdateAttestedHeaderBeacon.Slot != oldUpdateAttestedHeaderBeacon.Slot { + return newUpdateAttestedHeaderBeacon.Slot < oldUpdateAttestedHeaderBeacon.Slot, nil + } + + return newUpdate.SignatureSlot() < oldUpdate.SignatureSlot(), nil +} + +func NewLightClientBootstrapFromBeaconState( + ctx context.Context, + currentSlot primitives.Slot, + state state.BeaconState, + block interfaces.ReadOnlySignedBeaconBlock, +) (interfaces.LightClientBootstrap, error) { + // assert compute_epoch_at_slot(state.slot) >= ALTAIR_FORK_EPOCH + if slots.ToEpoch(state.Slot()) < params.BeaconConfig().AltairForkEpoch { + return nil, fmt.Errorf("light client bootstrap is not supported before Altair, invalid slot %d", state.Slot()) + } + + // assert state.slot == state.latest_block_header.slot + latestBlockHeader := state.LatestBlockHeader() + if state.Slot() != latestBlockHeader.Slot { + return nil, fmt.Errorf("state slot %d not equal to latest block header slot %d", state.Slot(), latestBlockHeader.Slot) + } + + // header.state_root = hash_tree_root(state) + stateRoot, err := state.HashTreeRoot(ctx) + if err != nil { + return nil, errors.Wrap(err, "could not get state root") + } + latestBlockHeader.StateRoot = stateRoot[:] + + // assert hash_tree_root(header) == hash_tree_root(block.message) + latestBlockHeaderRoot, err := latestBlockHeader.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get latest block header root") + } + beaconBlockRoot, err := block.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get block root") + } + if latestBlockHeaderRoot != beaconBlockRoot { + return nil, fmt.Errorf("latest block header root %#x not equal to block root %#x", latestBlockHeaderRoot, beaconBlockRoot) + } + + bootstrap, err := createDefaultLightClientBootstrap(currentSlot) + if err != nil { + return nil, errors.Wrap(err, "could not create default light client bootstrap") + } + + lightClientHeader, err := BlockToLightClientHeader(ctx, currentSlot, block) + if err != nil { + return nil, errors.Wrap(err, "could not convert block to light client header") + } + + err = bootstrap.SetHeader(lightClientHeader) + if err != nil { + return nil, errors.Wrap(err, "could not set header") + } + + currentSyncCommittee, err := state.CurrentSyncCommittee() + if err != nil { + return nil, errors.Wrap(err, "could not get current sync committee") + } + + err = bootstrap.SetCurrentSyncCommittee(currentSyncCommittee) + if err != nil { + return nil, errors.Wrap(err, "could not set current sync committee") + } + + currentSyncCommitteeProof, err := state.CurrentSyncCommitteeProof(ctx) + if err != nil { + return nil, errors.Wrap(err, "could not get current sync committee proof") + } + + err = bootstrap.SetCurrentSyncCommitteeBranch(currentSyncCommitteeProof) + if err != nil { + return nil, errors.Wrap(err, "could not set current sync committee proof") + } + + return bootstrap, nil +} + +func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces.LightClientBootstrap, error) { + currentEpoch := slots.ToEpoch(currentSlot) + syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize + pubKeys := make([][]byte, syncCommitteeSize) + for i := uint64(0); i < syncCommitteeSize; i++ { + pubKeys[i] = make([]byte, fieldparams.BLSPubkeyLength) + } + currentSyncCommittee := &pb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), + } + + var currentSyncCommitteeBranch [][]byte + if currentEpoch >= params.BeaconConfig().ElectraForkEpoch { + currentSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepthElectra) + } else { + currentSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepth) + } + for i := 0; i < len(currentSyncCommitteeBranch); i++ { + currentSyncCommitteeBranch[i] = make([]byte, fieldparams.RootLength) + } + + executionBranch := make([][]byte, fieldparams.ExecutionBranchDepth) + for i := 0; i < fieldparams.ExecutionBranchDepth; i++ { + executionBranch[i] = make([]byte, 32) + } + + // TODO: can this be based on the current epoch? + var m proto.Message + if currentEpoch < params.BeaconConfig().CapellaForkEpoch { + m = &pb.LightClientBootstrapAltair{ + Header: &pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{}, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { + m = &pb.LightClientBootstrapCapella{ + Header: &pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderCapella{}, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else if currentEpoch < params.BeaconConfig().ElectraForkEpoch { + m = &pb.LightClientBootstrapDeneb{ + Header: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else { + m = &pb.LightClientBootstrapElectra{ + Header: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } + + return light_client.NewWrappedBootstrap(m) +} diff --git a/beacon-chain/core/light-client/lightclient_test.go b/beacon-chain/core/light-client/lightclient_test.go new file mode 100644 index 000000000000..2916b77e7e1f --- /dev/null +++ b/beacon-chain/core/light-client/lightclient_test.go @@ -0,0 +1,1823 @@ +package light_client_test + +import ( + "reflect" + "strings" + "testing" + + "github.com/prysmaticlabs/prysm/v5/config/params" + light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + + "github.com/pkg/errors" + lightClient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/encoding/ssz" + v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + cfg.AltairForkEpoch = 1 + cfg.BellatrixForkEpoch = 2 + cfg.CapellaForkEpoch = 3 + cfg.DenebForkEpoch = 4 + cfg.ElectraForkEpoch = 5 + params.OverrideBeaconConfig(cfg) + + t.Run("Altair", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + }) + + t.Run("Capella", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) + + update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + }) + + t.Run("Deneb", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) + + update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + }) + + t.Run("Electra", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestElectra(false) + + update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + }) +} + +func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + cfg.AltairForkEpoch = 1 + cfg.BellatrixForkEpoch = 2 + cfg.CapellaForkEpoch = 3 + cfg.DenebForkEpoch = 4 + cfg.ElectraForkEpoch = 5 + params.OverrideBeaconConfig(cfg) + + t.Run("Altair", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + t.Run("FinalizedBlock Not Nil", func(t *testing.T) { + update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + + finalizedBlockHeader, err := l.FinalizedBlock.Header() + require.NoError(t, err) + + //zeroHash := params.BeaconConfig().ZeroHash[:] + require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil") + require.Equal(t, reflect.TypeOf(update.FinalizedHeader().Proto()), reflect.TypeOf(&pb.LightClientHeaderAltair{}), "Finalized header is not Altair") + updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon() + require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal") + require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal") + fb, err := update.FinalityBranch() + require.NoError(t, err) + proof, err := l.AttestedState.FinalizedRootProof(l.Ctx) + require.NoError(t, err) + for i, leaf := range fb { + require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal") + } + }) + }) + + t.Run("Capella", func(t *testing.T) { + + t.Run("FinalizedBlock Not Nil", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) + update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + + finalizedBlockHeader, err := l.FinalizedBlock.Header() + require.NoError(t, err) + require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil") + require.Equal(t, reflect.TypeOf(update.FinalizedHeader().Proto()), reflect.TypeOf(&pb.LightClientHeaderCapella{}), "Finalized header is not Capella") + updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon() + require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal") + require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal") + fb, err := update.FinalityBranch() + require.NoError(t, err) + proof, err := l.AttestedState.FinalizedRootProof(l.Ctx) + require.NoError(t, err) + for i, leaf := range fb { + require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal") + } + + // Check Execution BlockHash + payloadInterface, err := l.FinalizedBlock.Block().Body().Execution() + require.NoError(t, err) + transactionsRoot, err := payloadInterface.TransactionsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + transactions, err := payloadInterface.Transactions() + require.NoError(t, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(t, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(t, err) + } + withdrawalsRoot, err := payloadInterface.WithdrawalsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + withdrawals, err := payloadInterface.Withdrawals() + require.NoError(t, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(t, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(t, err) + } + execution := &v11.ExecutionPayloadHeaderCapella{ + ParentHash: payloadInterface.ParentHash(), + FeeRecipient: payloadInterface.FeeRecipient(), + StateRoot: payloadInterface.StateRoot(), + ReceiptsRoot: payloadInterface.ReceiptsRoot(), + LogsBloom: payloadInterface.LogsBloom(), + PrevRandao: payloadInterface.PrevRandao(), + BlockNumber: payloadInterface.BlockNumber(), + GasLimit: payloadInterface.GasLimit(), + GasUsed: payloadInterface.GasUsed(), + Timestamp: payloadInterface.Timestamp(), + ExtraData: payloadInterface.ExtraData(), + BaseFeePerGas: payloadInterface.BaseFeePerGas(), + BlockHash: payloadInterface.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + updateExecution, err := update.FinalizedHeader().Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, execution, updateExecution.Proto(), "Finalized Block Execution is not equal") + }) + + t.Run("FinalizedBlock In Previous Fork", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapellaFinalizedBlockAltair(false) + update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + + finalizedBlockHeader, err := l.FinalizedBlock.Header() + require.NoError(t, err) + require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil") + require.Equal(t, reflect.TypeOf(update.FinalizedHeader().Proto()), reflect.TypeOf(&pb.LightClientHeaderCapella{}), "Finalized header is not Capella") + updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon() + require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal") + require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal") + fb, err := update.FinalityBranch() + require.NoError(t, err) + proof, err := l.AttestedState.FinalizedRootProof(l.Ctx) + require.NoError(t, err) + for i, leaf := range fb { + require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal") + } + }) + }) + + t.Run("Deneb", func(t *testing.T) { + + t.Run("FinalizedBlock Not Nil", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) + + update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + + //zeroHash := params.BeaconConfig().ZeroHash[:] + finalizedBlockHeader, err := l.FinalizedBlock.Header() + require.NoError(t, err) + require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil") + updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon() + require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal") + require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal") + fb, err := update.FinalityBranch() + require.NoError(t, err) + proof, err := l.AttestedState.FinalizedRootProof(l.Ctx) + require.NoError(t, err) + for i, leaf := range fb { + require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal") + } + + // Check Execution BlockHash + payloadInterface, err := l.FinalizedBlock.Block().Body().Execution() + require.NoError(t, err) + transactionsRoot, err := payloadInterface.TransactionsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + transactions, err := payloadInterface.Transactions() + require.NoError(t, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(t, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(t, err) + } + withdrawalsRoot, err := payloadInterface.WithdrawalsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + withdrawals, err := payloadInterface.Withdrawals() + require.NoError(t, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(t, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(t, err) + } + execution := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadInterface.ParentHash(), + FeeRecipient: payloadInterface.FeeRecipient(), + StateRoot: payloadInterface.StateRoot(), + ReceiptsRoot: payloadInterface.ReceiptsRoot(), + LogsBloom: payloadInterface.LogsBloom(), + PrevRandao: payloadInterface.PrevRandao(), + BlockNumber: payloadInterface.BlockNumber(), + GasLimit: payloadInterface.GasLimit(), + GasUsed: payloadInterface.GasUsed(), + Timestamp: payloadInterface.Timestamp(), + ExtraData: payloadInterface.ExtraData(), + BaseFeePerGas: payloadInterface.BaseFeePerGas(), + BlockHash: payloadInterface.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + updateExecution, err := update.FinalizedHeader().Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, execution, updateExecution.Proto(), "Finalized Block Execution is not equal") + }) + + t.Run("FinalizedBlock In Previous Fork", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDenebFinalizedBlockCapella(false) + + update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + + finalizedBlockHeader, err := l.FinalizedBlock.Header() + require.NoError(t, err) + require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil") + updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon() + require.Equal(t, reflect.TypeOf(update.FinalizedHeader().Proto()), reflect.TypeOf(&pb.LightClientHeaderDeneb{}), "Finalized header is not Deneb") + require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal") + require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal") + fb, err := update.FinalityBranch() + require.NoError(t, err) + proof, err := l.AttestedState.FinalizedRootProof(l.Ctx) + require.NoError(t, err) + for i, leaf := range fb { + require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal") + } + + // Check Execution BlockHash + payloadInterface, err := l.FinalizedBlock.Block().Body().Execution() + require.NoError(t, err) + transactionsRoot, err := payloadInterface.TransactionsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + transactions, err := payloadInterface.Transactions() + require.NoError(t, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(t, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(t, err) + } + withdrawalsRoot, err := payloadInterface.WithdrawalsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + withdrawals, err := payloadInterface.Withdrawals() + require.NoError(t, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(t, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(t, err) + } + execution := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadInterface.ParentHash(), + FeeRecipient: payloadInterface.FeeRecipient(), + StateRoot: payloadInterface.StateRoot(), + ReceiptsRoot: payloadInterface.ReceiptsRoot(), + LogsBloom: payloadInterface.LogsBloom(), + PrevRandao: payloadInterface.PrevRandao(), + BlockNumber: payloadInterface.BlockNumber(), + GasLimit: payloadInterface.GasLimit(), + GasUsed: payloadInterface.GasUsed(), + Timestamp: payloadInterface.Timestamp(), + ExtraData: payloadInterface.ExtraData(), + BaseFeePerGas: payloadInterface.BaseFeePerGas(), + BlockHash: payloadInterface.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + updateExecution, err := update.FinalizedHeader().Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, execution, updateExecution.Proto(), "Finalized Block Execution is not equal") + }) + }) + + t.Run("Electra", func(t *testing.T) { + t.Run("FinalizedBlock Not Nil", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestElectra(false) + + update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + + //zeroHash := params.BeaconConfig().ZeroHash[:] + finalizedBlockHeader, err := l.FinalizedBlock.Header() + require.NoError(t, err) + require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil") + updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon() + require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal") + require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal") + fb, err := update.FinalityBranchElectra() + require.NoError(t, err) + proof, err := l.AttestedState.FinalizedRootProof(l.Ctx) + require.NoError(t, err) + for i, leaf := range fb { + require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal") + } + + // Check Execution BlockHash + payloadInterface, err := l.FinalizedBlock.Block().Body().Execution() + require.NoError(t, err) + transactionsRoot, err := payloadInterface.TransactionsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + transactions, err := payloadInterface.Transactions() + require.NoError(t, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(t, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(t, err) + } + withdrawalsRoot, err := payloadInterface.WithdrawalsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + withdrawals, err := payloadInterface.Withdrawals() + require.NoError(t, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(t, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(t, err) + } + execution := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadInterface.ParentHash(), + FeeRecipient: payloadInterface.FeeRecipient(), + StateRoot: payloadInterface.StateRoot(), + ReceiptsRoot: payloadInterface.ReceiptsRoot(), + LogsBloom: payloadInterface.LogsBloom(), + PrevRandao: payloadInterface.PrevRandao(), + BlockNumber: payloadInterface.BlockNumber(), + GasLimit: payloadInterface.GasLimit(), + GasUsed: payloadInterface.GasUsed(), + Timestamp: payloadInterface.Timestamp(), + ExtraData: payloadInterface.ExtraData(), + BaseFeePerGas: payloadInterface.BaseFeePerGas(), + BlockHash: payloadInterface.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + updateExecution, err := update.FinalizedHeader().Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, execution, updateExecution.Proto(), "Finalized Block Execution is not equal") + }) + + t.Run("FinalizedBlock In Previous Fork", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestElectraFinalizedBlockDeneb(false) + + update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State.Slot(), l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock) + require.NoError(t, err) + require.NotNil(t, update, "update is nil") + + require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal") + + l.CheckSyncAggregate(update.SyncAggregate()) + l.CheckAttestedHeader(update.AttestedHeader()) + + finalizedBlockHeader, err := l.FinalizedBlock.Header() + require.NoError(t, err) + require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil") + updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon() + require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal") + require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal") + require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal") + fb, err := update.FinalityBranchElectra() + require.NoError(t, err) + proof, err := l.AttestedState.FinalizedRootProof(l.Ctx) + require.NoError(t, err) + for i, leaf := range fb { + require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal") + } + + // Check Execution BlockHash + payloadInterface, err := l.FinalizedBlock.Block().Body().Execution() + require.NoError(t, err) + transactionsRoot, err := payloadInterface.TransactionsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + transactions, err := payloadInterface.Transactions() + require.NoError(t, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(t, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(t, err) + } + withdrawalsRoot, err := payloadInterface.WithdrawalsRoot() + if errors.Is(err, consensustypes.ErrUnsupportedField) { + withdrawals, err := payloadInterface.Withdrawals() + require.NoError(t, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(t, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(t, err) + } + execution := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadInterface.ParentHash(), + FeeRecipient: payloadInterface.FeeRecipient(), + StateRoot: payloadInterface.StateRoot(), + ReceiptsRoot: payloadInterface.ReceiptsRoot(), + LogsBloom: payloadInterface.LogsBloom(), + PrevRandao: payloadInterface.PrevRandao(), + BlockNumber: payloadInterface.BlockNumber(), + GasLimit: payloadInterface.GasLimit(), + GasUsed: payloadInterface.GasUsed(), + Timestamp: payloadInterface.Timestamp(), + ExtraData: payloadInterface.ExtraData(), + BaseFeePerGas: payloadInterface.BaseFeePerGas(), + BlockHash: payloadInterface.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + updateExecution, err := update.FinalizedHeader().Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, execution, updateExecution.Proto(), "Finalized Block Execution is not equal") + }) + }) +} + +func TestLightClient_BlockToLightClientHeader(t *testing.T) { + t.Run("Altair", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().AltairForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block, + ) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + }) + + t.Run("Bellatrix", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestBellatrix() + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().BellatrixForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block, + ) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + }) + + t.Run("Capella", func(t *testing.T) { + t.Run("Non-Blinded Beacon Block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().CapellaForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block, + ) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := lightClient.ComputeTransactionsRoot(payload) + require.NoError(t, err) + + withdrawalsRoot, err := lightClient.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderCapella{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + + headerExecution, err := header.Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal") + + headerExecutionBranch, err := header.ExecutionBranch() + require.NoError(t, err) + require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal") + }) + + t.Run("Blinded Beacon Block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(true) + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().CapellaForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block, + ) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := payload.TransactionsRoot() + require.NoError(t, err) + + withdrawalsRoot, err := payload.WithdrawalsRoot() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderCapella{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + + headerExecution, err := header.Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal") + + headerExecutionBranch, err := header.ExecutionBranch() + require.NoError(t, err) + require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal") + }) + }) + + t.Run("Deneb", func(t *testing.T) { + t.Run("Non-Blinded Beacon Block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block, + ) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := lightClient.ComputeTransactionsRoot(payload) + require.NoError(t, err) + + withdrawalsRoot, err := lightClient.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) + + blobGasUsed, err := payload.BlobGasUsed() + require.NoError(t, err) + + excessBlobGas, err := payload.ExcessBlobGas() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: blobGasUsed, + ExcessBlobGas: excessBlobGas, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + + headerExecution, err := header.Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal") + + headerExecutionBranch, err := header.ExecutionBranch() + require.NoError(t, err) + require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal") + }) + + t.Run("Blinded Beacon Block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(true) + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block, + ) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := payload.TransactionsRoot() + require.NoError(t, err) + + withdrawalsRoot, err := payload.WithdrawalsRoot() + require.NoError(t, err) + + blobGasUsed, err := payload.BlobGasUsed() + require.NoError(t, err) + + excessBlobGas, err := payload.ExcessBlobGas() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: blobGasUsed, + ExcessBlobGas: excessBlobGas, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + + headerExecution, err := header.Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal") + + headerExecutionBranch, err := header.ExecutionBranch() + require.NoError(t, err) + require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal") + }) + }) + + t.Run("Electra", func(t *testing.T) { + t.Run("Non-Blinded Beacon Block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestElectra(false) + + header, err := lightClient.BlockToLightClientHeader(l.Ctx, l.State.Slot(), l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := lightClient.ComputeTransactionsRoot(payload) + require.NoError(t, err) + + withdrawalsRoot, err := lightClient.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) + + blobGasUsed, err := payload.BlobGasUsed() + require.NoError(t, err) + + excessBlobGas, err := payload.ExcessBlobGas() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: blobGasUsed, + ExcessBlobGas: excessBlobGas, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + + headerExecution, err := header.Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal") + + headerExecutionBranch, err := header.ExecutionBranch() + require.NoError(t, err) + require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal") + }) + + t.Run("Blinded Beacon Block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestElectra(true) + + header, err := lightClient.BlockToLightClientHeader(l.Ctx, l.State.Slot(), l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := payload.TransactionsRoot() + require.NoError(t, err) + + withdrawalsRoot, err := payload.WithdrawalsRoot() + require.NoError(t, err) + + blobGasUsed, err := payload.BlobGasUsed() + require.NoError(t, err) + + excessBlobGas, err := payload.ExcessBlobGas() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + BlobGasUsed: blobGasUsed, + ExcessBlobGas: excessBlobGas, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + + headerExecution, err := header.Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal") + + headerExecutionBranch, err := header.ExecutionBranch() + require.NoError(t, err) + require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal") + }) + }) + + t.Run("Capella fork with Altair block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().CapellaForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + }) + + t.Run("Deneb fork with Altair block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + }) + + t.Run("Deneb fork with Capella block", func(t *testing.T) { + t.Run("Non-Blinded Beacon Block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := lightClient.ComputeTransactionsRoot(payload) + require.NoError(t, err) + + withdrawalsRoot, err := lightClient.ComputeWithdrawalsRoot(payload) + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + + headerExecution, err := header.Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal") + + headerExecutionBranch, err := header.ExecutionBranch() + require.NoError(t, err) + require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal") + }) + + t.Run("Blinded Beacon Block", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(true) + + header, err := lightClient.BlockToLightClientHeader( + l.Ctx, + primitives.Slot(params.BeaconConfig().DenebForkEpoch)*params.BeaconConfig().SlotsPerEpoch, + l.Block) + require.NoError(t, err) + require.NotNil(t, header, "header is nil") + + parentRoot := l.Block.Block().ParentRoot() + stateRoot := l.Block.Block().StateRoot() + bodyRoot, err := l.Block.Block().Body().HashTreeRoot() + require.NoError(t, err) + + payload, err := l.Block.Block().Body().Execution() + require.NoError(t, err) + + transactionsRoot, err := payload.TransactionsRoot() + require.NoError(t, err) + + withdrawalsRoot, err := payload.WithdrawalsRoot() + require.NoError(t, err) + + executionHeader := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payload.ParentHash(), + FeeRecipient: payload.FeeRecipient(), + StateRoot: payload.StateRoot(), + ReceiptsRoot: payload.ReceiptsRoot(), + LogsBloom: payload.LogsBloom(), + PrevRandao: payload.PrevRandao(), + BlockNumber: payload.BlockNumber(), + GasLimit: payload.GasLimit(), + GasUsed: payload.GasUsed(), + Timestamp: payload.Timestamp(), + ExtraData: payload.ExtraData(), + BaseFeePerGas: payload.BaseFeePerGas(), + BlockHash: payload.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block()) + require.NoError(t, err) + + require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal") + require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal") + require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal") + require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal") + require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal") + + headerExecution, err := header.Execution() + require.NoError(t, err) + require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal") + + headerExecutionBranch, err := header.ExecutionBranch() + require.NoError(t, err) + require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal") + }) + }) +} + +func convertArrayToSlice(arr [4][32]uint8) [][]uint8 { + slice := make([][]uint8, len(arr)) + for i := range arr { + slice[i] = arr[i][:] + } + return slice +} + +// When the update has relevant sync committee +func createNonEmptySyncCommitteeBranch() [][]byte { + res := make([][]byte, fieldparams.SyncCommitteeBranchDepth) + res[0] = []byte(strings.Repeat("x", 32)) + for i := 1; i < len(res); i++ { + res[i] = make([]byte, fieldparams.RootLength) + } + return res +} + +// When the update has finality +func createNonEmptyFinalityBranch() [][]byte { + res := make([][]byte, fieldparams.FinalityBranchDepth) + res[0] = []byte(strings.Repeat("x", 32)) + for i := 1; i < fieldparams.FinalityBranchDepth; i++ { + res[i] = make([]byte, 32) + } + return res +} + +func TestIsBetterUpdate(t *testing.T) { + config := params.BeaconConfig() + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + + t.Run("new has supermajority but old doesn't", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] + }) + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1] + }) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, true, result) + }) + + t.Run("old has supermajority but new doesn't", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1] + }) + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] + }) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, false, result) + }) + + t.Run("new doesn't have supermajority and newNumActiveParticipants is greater than oldNumActiveParticipants", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] + }) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, true, result) + }) + + t.Run("new doesn't have supermajority and newNumActiveParticipants is lesser than oldNumActiveParticipants", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] + }) + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, false, result) + }) + + t.Run("new has relevant sync committee but old doesn't", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(9999) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000001, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(1000000) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, true, result) + }) + + t.Run("old has relevant sync committee but new doesn't", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000001, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(1000000) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + newUpdate.SetSignatureSlot(9999) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, false, result) + }) + + t.Run("new has finality but old doesn't", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(9999) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(9999) + err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, true, result) + }) + + t.Run("old has finality but new doesn't", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(9999) + err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(9999) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, false, result) + }) + + t.Run("new has finality and sync committee finality both but old doesn't have sync committee finality", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(9999) + oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader) + require.NoError(t, err) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(999999) + err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 999999, + }, + }) + require.NoError(t, err) + err = newUpdate.SetFinalizedHeader(newFinalizedHeader) + require.NoError(t, err) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, true, result) + }) + + t.Run("new has finality but doesn't have sync committee finality and old has sync committee finality", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(999999) + oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 999999, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader) + require.NoError(t, err) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(9999) + err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = newUpdate.SetFinalizedHeader(newFinalizedHeader) + require.NoError(t, err) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, false, result) + }) + + t.Run("new has more active participants than old", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0] + }) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, true, result) + }) + + t.Run("new has less active participants than old", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0] + }) + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, false, result) + }) + + t.Run("new's attested header's slot is lesser than old's attested header's slot", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(9999) + oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader) + require.NoError(t, err) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 999999, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(9999) + err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = newUpdate.SetFinalizedHeader(newFinalizedHeader) + require.NoError(t, err) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, true, result) + }) + + t.Run("new's attested header's slot is greater than old's attested header's slot", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 999999, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(9999) + oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader) + require.NoError(t, err) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(9999) + err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = newUpdate.SetFinalizedHeader(newFinalizedHeader) + require.NoError(t, err) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, false, result) + }) + + t.Run("none of the above conditions are met and new signature's slot is less than old signature's slot", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(9999) + oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader) + require.NoError(t, err) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(9998) + err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = newUpdate.SetFinalizedHeader(newFinalizedHeader) + require.NoError(t, err) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, true, result) + }) + + t.Run("none of the above conditions are met and new signature's slot is greater than old signature's slot", func(t *testing.T) { + oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st) + require.NoError(t, err) + newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st) + require.NoError(t, err) + + oldUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetAttestedHeader(oldAttestedHeader) + require.NoError(t, err) + err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + oldUpdate.SetSignatureSlot(9998) + oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader) + require.NoError(t, err) + + newUpdate.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] + }) + newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1000000, + }, + }) + require.NoError(t, err) + err = newUpdate.SetAttestedHeader(newAttestedHeader) + require.NoError(t, err) + err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch()) + require.NoError(t, err) + newUpdate.SetSignatureSlot(9999) + err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch()) + require.NoError(t, err) + newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 9999, + }, + }) + require.NoError(t, err) + err = newUpdate.SetFinalizedHeader(newFinalizedHeader) + require.NoError(t, err) + + result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate) + require.NoError(t, err) + require.Equal(t, false, result) + }) +} diff --git a/beacon-chain/core/time/slot_epoch.go b/beacon-chain/core/time/slot_epoch.go index 9ffa1561a3bf..9acb54c5fa29 100644 --- a/beacon-chain/core/time/slot_epoch.go +++ b/beacon-chain/core/time/slot_epoch.go @@ -99,6 +99,15 @@ func CanUpgradeToElectra(slot primitives.Slot) bool { return epochStart && electraEpoch } +// CanUpgradeToFulu returns true if the input `slot` can upgrade to Fulu. +// Spec code: +// If state.slot % SLOTS_PER_EPOCH == 0 and compute_epoch_at_slot(state.slot) == FULU_FORK_EPOCH +func CanUpgradeToFulu(slot primitives.Slot) bool { + epochStart := slots.IsEpochStart(slot) + fuluEpoch := slots.ToEpoch(slot) == params.BeaconConfig().FuluForkEpoch + return epochStart && fuluEpoch +} + // CanProcessEpoch checks the eligibility to process epoch. // The epoch can be processed at the end of the last slot of every epoch. // diff --git a/beacon-chain/core/time/slot_epoch_test.go b/beacon-chain/core/time/slot_epoch_test.go index 69fd32603267..8456b3a1643e 100644 --- a/beacon-chain/core/time/slot_epoch_test.go +++ b/beacon-chain/core/time/slot_epoch_test.go @@ -1,6 +1,7 @@ package time_test import ( + "fmt" "testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" @@ -83,76 +84,6 @@ func TestNextEpoch_OK(t *testing.T) { } } -func TestCanUpgradeToAltair(t *testing.T) { - params.SetupTestConfigCleanup(t) - bc := params.BeaconConfig() - bc.AltairForkEpoch = 5 - params.OverrideBeaconConfig(bc) - tests := []struct { - name string - slot primitives.Slot - want bool - }{ - { - name: "not epoch start", - slot: 1, - want: false, - }, - { - name: "not altair epoch", - slot: params.BeaconConfig().SlotsPerEpoch, - want: false, - }, - { - name: "altair epoch", - slot: primitives.Slot(params.BeaconConfig().AltairForkEpoch) * params.BeaconConfig().SlotsPerEpoch, - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := time.CanUpgradeToAltair(tt.slot); got != tt.want { - t.Errorf("canUpgradeToAltair() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestCanUpgradeBellatrix(t *testing.T) { - params.SetupTestConfigCleanup(t) - bc := params.BeaconConfig() - bc.BellatrixForkEpoch = 5 - params.OverrideBeaconConfig(bc) - tests := []struct { - name string - slot primitives.Slot - want bool - }{ - { - name: "not epoch start", - slot: 1, - want: false, - }, - { - name: "not bellatrix epoch", - slot: params.BeaconConfig().SlotsPerEpoch, - want: false, - }, - { - name: "bellatrix epoch", - slot: primitives.Slot(params.BeaconConfig().BellatrixForkEpoch) * params.BeaconConfig().SlotsPerEpoch, - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := time.CanUpgradeToBellatrix(tt.slot); got != tt.want { - t.Errorf("CanUpgradeToBellatrix() = %v, want %v", got, tt.want) - } - }) - } -} - func TestCanProcessEpoch_TrueOnEpochsLastSlot(t *testing.T) { tests := []struct { slot primitives.Slot @@ -264,107 +195,79 @@ func TestAltairCompatible(t *testing.T) { } } -func TestCanUpgradeToCapella(t *testing.T) { - params.SetupTestConfigCleanup(t) - bc := params.BeaconConfig() - bc.CapellaForkEpoch = 5 - params.OverrideBeaconConfig(bc) - tests := []struct { - name string - slot primitives.Slot - want bool - }{ - { - name: "not epoch start", - slot: 1, - want: false, - }, - { - name: "not capella epoch", - slot: params.BeaconConfig().SlotsPerEpoch, - want: false, - }, - { - name: "capella epoch", - slot: primitives.Slot(params.BeaconConfig().CapellaForkEpoch) * params.BeaconConfig().SlotsPerEpoch, - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := time.CanUpgradeToCapella(tt.slot); got != tt.want { - t.Errorf("CanUpgradeToCapella() = %v, want %v", got, tt.want) - } - }) - } -} +func TestCanUpgradeTo(t *testing.T) { + beaconConfig := params.BeaconConfig() -func TestCanUpgradeToDeneb(t *testing.T) { - params.SetupTestConfigCleanup(t) - bc := params.BeaconConfig() - bc.DenebForkEpoch = 5 - params.OverrideBeaconConfig(bc) - tests := []struct { - name string - slot primitives.Slot - want bool + outerTestCases := []struct { + name string + forkEpoch *primitives.Epoch + upgradeFunc func(primitives.Slot) bool }{ { - name: "not epoch start", - slot: 1, - want: false, + name: "Altair", + forkEpoch: &beaconConfig.AltairForkEpoch, + upgradeFunc: time.CanUpgradeToAltair, }, { - name: "not deneb epoch", - slot: params.BeaconConfig().SlotsPerEpoch, - want: false, + name: "Bellatrix", + forkEpoch: &beaconConfig.BellatrixForkEpoch, + upgradeFunc: time.CanUpgradeToBellatrix, }, { - name: "deneb epoch", - slot: primitives.Slot(params.BeaconConfig().DenebForkEpoch) * params.BeaconConfig().SlotsPerEpoch, - want: true, + name: "Capella", + forkEpoch: &beaconConfig.CapellaForkEpoch, + upgradeFunc: time.CanUpgradeToCapella, }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := time.CanUpgradeToDeneb(tt.slot); got != tt.want { - t.Errorf("CanUpgradeToDeneb() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestCanUpgradeToElectra(t *testing.T) { - params.SetupTestConfigCleanup(t) - bc := params.BeaconConfig() - bc.ElectraForkEpoch = 5 - params.OverrideBeaconConfig(bc) - tests := []struct { - name string - slot primitives.Slot - want bool - }{ { - name: "not epoch start", - slot: 1, - want: false, + name: "Deneb", + forkEpoch: &beaconConfig.DenebForkEpoch, + upgradeFunc: time.CanUpgradeToDeneb, }, { - name: "not electra epoch", - slot: params.BeaconConfig().SlotsPerEpoch, - want: false, + name: "Electra", + forkEpoch: &beaconConfig.ElectraForkEpoch, + upgradeFunc: time.CanUpgradeToElectra, }, { - name: "electra epoch", - slot: primitives.Slot(params.BeaconConfig().ElectraForkEpoch) * params.BeaconConfig().SlotsPerEpoch, - want: true, + name: "Fulu", + forkEpoch: &beaconConfig.FuluForkEpoch, + upgradeFunc: time.CanUpgradeToFulu, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := time.CanUpgradeToElectra(tt.slot); got != tt.want { - t.Errorf("CanUpgradeToElectra() = %v, want %v", got, tt.want) - } - }) + + for _, otc := range outerTestCases { + params.SetupTestConfigCleanup(t) + *otc.forkEpoch = 5 + params.OverrideBeaconConfig(beaconConfig) + + innerTestCases := []struct { + name string + slot primitives.Slot + want bool + }{ + { + name: "not epoch start", + slot: 1, + want: false, + }, + { + name: fmt.Sprintf("not %s epoch", otc.name), + slot: params.BeaconConfig().SlotsPerEpoch, + want: false, + }, + { + name: fmt.Sprintf("%s epoch", otc.name), + slot: primitives.Slot(*otc.forkEpoch) * params.BeaconConfig().SlotsPerEpoch, + want: true, + }, + } + + for _, itc := range innerTestCases { + t.Run(fmt.Sprintf("%s-%s", otc.name, itc.name), func(t *testing.T) { + if got := otc.upgradeFunc(itc.slot); got != itc.want { + t.Errorf("CanUpgradeTo%s() = %v, want %v", otc.name, got, itc.want) + } + }) + } } } diff --git a/beacon-chain/core/transition/BUILD.bazel b/beacon-chain/core/transition/BUILD.bazel index 0f5bb260b4b8..50fd99050778 100644 --- a/beacon-chain/core/transition/BUILD.bazel +++ b/beacon-chain/core/transition/BUILD.bazel @@ -23,6 +23,7 @@ go_library( "//beacon-chain/core/epoch:go_default_library", "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/core/execution:go_default_library", + "//beacon-chain/core/fulu:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/core/transition/interop:go_default_library", @@ -41,6 +42,7 @@ go_library( "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", @@ -48,7 +50,7 @@ go_library( "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@io_opentelemetry_go_otel_trace//:go_default_library", ], ) diff --git a/beacon-chain/core/transition/transition.go b/beacon-chain/core/transition/transition.go index fa64765bc404..dc0cc3ef53d9 100644 --- a/beacon-chain/core/transition/transition.go +++ b/beacon-chain/core/transition/transition.go @@ -17,6 +17,7 @@ import ( e "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/execution" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/fulu" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/features" @@ -25,8 +26,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + prysmTrace "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" + "go.opentelemetry.io/otel/trace" ) type customProcessingFn func(context.Context, state.BeaconState) error @@ -62,7 +64,7 @@ func ExecuteStateTransition( return nil, err } - ctx, span := trace.StartSpan(ctx, "core.state.ExecuteStateTransition") + ctx, span := prysmTrace.StartSpan(ctx, "core.state.ExecuteStateTransition") defer span.End() var err error @@ -102,9 +104,9 @@ func ExecuteStateTransition( // previous_block_root = hash_tree_root(state.latest_block_header) // state.block_roots[state.slot % SLOTS_PER_HISTORICAL_ROOT] = previous_block_root func ProcessSlot(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { - ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlot") + ctx, span := prysmTrace.StartSpan(ctx, "core.state.ProcessSlot") defer span.End() - span.AddAttributes(trace.Int64Attribute("slot", int64(state.Slot()))) // lint:ignore uintcast -- This is OK for tracing. + span.SetAttributes(prysmTrace.Int64Attribute("slot", int64(state.Slot()))) // lint:ignore uintcast -- This is OK for tracing. prevStateRoot, err := state.HashTreeRoot(ctx) if err != nil { @@ -147,7 +149,7 @@ func ProcessSlotsUsingNextSlotCache( parentState state.BeaconState, parentRoot []byte, slot primitives.Slot) (state.BeaconState, error) { - ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlotsUsingNextSlotCache") + ctx, span := prysmTrace.StartSpan(ctx, "core.state.ProcessSlotsUsingNextSlotCache") defer span.End() nextSlotState := NextSlotState(parentRoot, slot) @@ -177,12 +179,12 @@ func ProcessSlotsIfPossible(ctx context.Context, state state.BeaconState, target // ProcessSlots includes core slot processing as well as a cache func ProcessSlots(ctx context.Context, state state.BeaconState, slot primitives.Slot) (state.BeaconState, error) { - ctx, span := trace.StartSpan(ctx, "core.state.ProcessSlots") + ctx, span := prysmTrace.StartSpan(ctx, "core.state.ProcessSlots") defer span.End() if state == nil || state.IsNil() { return nil, errors.New("nil state") } - span.AddAttributes(trace.Int64Attribute("slots", int64(slot)-int64(state.Slot()))) // lint:ignore uintcast -- This is OK for tracing. + span.SetAttributes(prysmTrace.Int64Attribute("slots", int64(slot)-int64(state.Slot()))) // lint:ignore uintcast -- This is OK for tracing. // The block must have a higher slot than parent state. if state.Slot() >= slot { @@ -258,7 +260,7 @@ func cacheBestBeaconStateOnErrFn(highestSlot primitives.Slot, key [32]byte) cust // if (state.slot + 1) % SLOTS_PER_EPOCH == 0: // process_epoch(state) // state.slot = Slot(state.slot + 1) -func ProcessSlotsCore(ctx context.Context, span *trace.Span, state state.BeaconState, slot primitives.Slot, fn customProcessingFn) (state.BeaconState, error) { +func ProcessSlotsCore(ctx context.Context, span trace.Span, state state.BeaconState, slot primitives.Slot, fn customProcessingFn) (state.BeaconState, error) { var err error for state.Slot() < slot { if fn != nil { @@ -297,7 +299,7 @@ func ProcessSlotsCore(ctx context.Context, span *trace.Span, state state.BeaconS func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { var err error if time.CanProcessEpoch(state) { - if state.Version() == version.Electra { + if state.Version() >= version.Electra { if err = electra.ProcessEpoch(ctx, state); err != nil { return nil, errors.Wrap(err, fmt.Sprintf("could not process %s epoch", version.String(state.Version()))) } @@ -317,50 +319,72 @@ func ProcessEpoch(ctx context.Context, state state.BeaconState) (state.BeaconSta // UpgradeState upgrades the state to the next version if possible. func UpgradeState(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { - ctx, span := trace.StartSpan(ctx, "core.state.UpgradeState") + ctx, span := prysmTrace.StartSpan(ctx, "core.state.UpgradeState") defer span.End() + var err error - if time.CanUpgradeToAltair(state.Slot()) { + + slot := state.Slot() + upgraded := false + + if time.CanUpgradeToAltair(slot) { state, err = altair.UpgradeToAltair(ctx, state) if err != nil { tracing.AnnotateError(span, err) return nil, err } + upgraded = true } - if time.CanUpgradeToBellatrix(state.Slot()) { + if time.CanUpgradeToBellatrix(slot) { state, err = execution.UpgradeToBellatrix(state) if err != nil { tracing.AnnotateError(span, err) return nil, err } + upgraded = true } - if time.CanUpgradeToCapella(state.Slot()) { + if time.CanUpgradeToCapella(slot) { state, err = capella.UpgradeToCapella(state) if err != nil { tracing.AnnotateError(span, err) return nil, err } + upgraded = true } - if time.CanUpgradeToDeneb(state.Slot()) { + if time.CanUpgradeToDeneb(slot) { state, err = deneb.UpgradeToDeneb(state) if err != nil { tracing.AnnotateError(span, err) return nil, err } + upgraded = true } - if time.CanUpgradeToElectra(state.Slot()) { + if time.CanUpgradeToElectra(slot) { state, err = electra.UpgradeToElectra(state) if err != nil { tracing.AnnotateError(span, err) return nil, err } + upgraded = true + } + + if time.CanUpgradeToFulu(slot) { + state, err = fulu.UpgradeToFulu(state) + if err != nil { + tracing.AnnotateError(span, err) + return nil, err + } + upgraded = true + } + + if upgraded { + log.WithField("version", version.String(state.Version())).Info("Upgraded state to") } - log.Debugf("upgraded state to %s", version.String(state.Version())) return state, nil } @@ -379,11 +403,15 @@ func VerifyOperationLengths(_ context.Context, state state.BeaconState, b interf ) } - if uint64(len(body.AttesterSlashings())) > params.BeaconConfig().MaxAttesterSlashings { + maxSlashings := params.BeaconConfig().MaxAttesterSlashings + if body.Version() >= version.Electra { + maxSlashings = params.BeaconConfig().MaxAttesterSlashingsElectra + } + if uint64(len(body.AttesterSlashings())) > maxSlashings { return nil, fmt.Errorf( "number of attester slashings (%d) in block body exceeds allowed threshold of %d", len(body.AttesterSlashings()), - params.BeaconConfig().MaxAttesterSlashings, + maxSlashings, ) } @@ -433,9 +461,9 @@ func VerifyOperationLengths(_ context.Context, state state.BeaconState, b interf // ProcessEpochPrecompute describes the per epoch operations that are performed on the beacon state. // It's optimized by pre computing validator attested info and epoch total/attested balances upfront. func ProcessEpochPrecompute(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { - ctx, span := trace.StartSpan(ctx, "core.state.ProcessEpochPrecompute") + ctx, span := prysmTrace.StartSpan(ctx, "core.state.ProcessEpochPrecompute") defer span.End() - span.AddAttributes(trace.Int64Attribute("epoch", int64(time.CurrentEpoch(state)))) // lint:ignore uintcast -- This is OK for tracing. + span.SetAttributes(prysmTrace.Int64Attribute("epoch", int64(time.CurrentEpoch(state)))) // lint:ignore uintcast -- This is OK for tracing. if state == nil || state.IsNil() { return nil, errors.New("nil state") diff --git a/beacon-chain/core/transition/transition_no_verify_sig.go b/beacon-chain/core/transition/transition_no_verify_sig.go index 17bc3b7d435d..e633c844d35b 100644 --- a/beacon-chain/core/transition/transition_no_verify_sig.go +++ b/beacon-chain/core/transition/transition_no_verify_sig.go @@ -12,13 +12,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition/interop" v "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" ) // ExecuteStateTransitionNoVerifyAnySig defines the procedure for a state transition function. @@ -328,20 +327,17 @@ func ProcessBlockForStateRoot( if err != nil { return nil, err } - if blk.IsBlinded() { - state, err = b.ProcessPayloadHeader(state, executionData) - } else { - state, err = b.ProcessPayload(state, executionData) + if state.Version() >= version.Capella { + state, err = b.ProcessWithdrawals(state, executionData) + if err != nil { + return nil, errors.Wrap(err, "could not process withdrawals") + } } - if err != nil { + if err = b.ProcessPayload(state, blk.Body()); err != nil { return nil, errors.Wrap(err, "could not process execution data") } } - if err := VerifyBlobCommitmentCount(blk); err != nil { - return nil, err - } - randaoReveal := signed.Block().Body().RandaoReveal() state, err = b.ProcessRandaoNoVerify(state, randaoReveal[:]) if err != nil { @@ -377,20 +373,6 @@ func ProcessBlockForStateRoot( return state, nil } -func VerifyBlobCommitmentCount(blk interfaces.ReadOnlyBeaconBlock) error { - if blk.Version() < version.Deneb { - return nil - } - kzgs, err := blk.Body().BlobKzgCommitments() - if err != nil { - return err - } - if len(kzgs) > field_params.MaxBlobsPerBlock { - return fmt.Errorf("too many kzg commitments in block: %d", len(kzgs)) - } - return nil -} - // This calls altair block operations. func altairOperations( ctx context.Context, diff --git a/beacon-chain/core/transition/transition_no_verify_sig_test.go b/beacon-chain/core/transition/transition_no_verify_sig_test.go index 5c5b786a2bb1..03472fd4a272 100644 --- a/beacon-chain/core/transition/transition_no_verify_sig_test.go +++ b/beacon-chain/core/transition/transition_no_verify_sig_test.go @@ -2,13 +2,11 @@ package transition_test import ( "context" - "fmt" "testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" - field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" @@ -212,15 +210,3 @@ func TestProcessBlockDifferentVersion(t *testing.T) { _, _, err = transition.ProcessBlockNoVerifyAnySig(context.Background(), beaconState, wsb) require.ErrorContains(t, "state and block are different version. 0 != 1", err) } - -func TestVerifyBlobCommitmentCount(t *testing.T) { - b := ðpb.BeaconBlockDeneb{Body: ðpb.BeaconBlockBodyDeneb{}} - rb, err := blocks.NewBeaconBlock(b) - require.NoError(t, err) - require.NoError(t, transition.VerifyBlobCommitmentCount(rb)) - - b = ðpb.BeaconBlockDeneb{Body: ðpb.BeaconBlockBodyDeneb{BlobKzgCommitments: make([][]byte, field_params.MaxBlobsPerBlock+1)}} - rb, err = blocks.NewBeaconBlock(b) - require.NoError(t, err) - require.ErrorContains(t, fmt.Sprintf("too many kzg commitments in block: %d", field_params.MaxBlobsPerBlock+1), transition.VerifyBlobCommitmentCount(rb)) -} diff --git a/beacon-chain/core/transition/transition_test.go b/beacon-chain/core/transition/transition_test.go index 9000afeee603..37561e699b46 100644 --- a/beacon-chain/core/transition/transition_test.go +++ b/beacon-chain/core/transition/transition_test.go @@ -437,6 +437,25 @@ func TestProcessBlock_OverMaxAttesterSlashings(t *testing.T) { assert.ErrorContains(t, want, err) } +func TestProcessBlock_OverMaxAttesterSlashingsElectra(t *testing.T) { + maxSlashings := params.BeaconConfig().MaxAttesterSlashingsElectra + b := ðpb.SignedBeaconBlockElectra{ + Block: ðpb.BeaconBlockElectra{ + Body: ðpb.BeaconBlockBodyElectra{ + AttesterSlashings: make([]*ethpb.AttesterSlashingElectra, maxSlashings+1), + }, + }, + } + want := fmt.Sprintf("number of attester slashings (%d) in block body exceeds allowed threshold of %d", + len(b.Block.Body.AttesterSlashings), params.BeaconConfig().MaxAttesterSlashingsElectra) + s, err := state_native.InitializeFromProtoUnsafeElectra(ðpb.BeaconStateElectra{}) + require.NoError(t, err) + wsb, err := consensusblocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + _, err = transition.VerifyOperationLengths(context.Background(), s, wsb.Block()) + assert.ErrorContains(t, want, err) +} + func TestProcessBlock_OverMaxAttestations(t *testing.T) { b := ðpb.SignedBeaconBlock{ Block: ðpb.BeaconBlock{ @@ -665,6 +684,20 @@ func TestProcessSlots_ThroughElectraEpoch(t *testing.T) { require.Equal(t, params.BeaconConfig().SlotsPerEpoch*10, st.Slot()) } +func TestProcessSlots_ThroughFuluEpoch(t *testing.T) { + transition.SkipSlotCache.Disable() + params.SetupTestConfigCleanup(t) + conf := params.BeaconConfig() + conf.FuluForkEpoch = 5 + params.OverrideBeaconConfig(conf) + + st, _ := util.DeterministicGenesisStateElectra(t, params.BeaconConfig().MaxValidatorsPerCommittee) + st, err := transition.ProcessSlots(context.Background(), st, params.BeaconConfig().SlotsPerEpoch*10) + require.NoError(t, err) + require.Equal(t, version.Fulu, st.Version()) + require.Equal(t, params.BeaconConfig().SlotsPerEpoch*10, st.Slot()) +} + func TestProcessSlotsUsingNextSlotCache(t *testing.T) { s, _ := util.DeterministicGenesisState(t, 1) r := []byte{'a'} @@ -698,3 +731,45 @@ func TestProcessSlotsConditionally(t *testing.T) { assert.Equal(t, primitives.Slot(6), s.Slot()) }) } + +func BenchmarkProcessSlots_Capella(b *testing.B) { + st, _ := util.DeterministicGenesisStateCapella(b, params.BeaconConfig().MaxValidatorsPerCommittee) + + var err error + + b.ResetTimer() + for i := 0; i < b.N; i++ { + st, err = transition.ProcessSlots(context.Background(), st, st.Slot()+1) + if err != nil { + b.Fatalf("Failed to process slot %v", err) + } + } +} + +func BenchmarkProcessSlots_Deneb(b *testing.B) { + st, _ := util.DeterministicGenesisStateDeneb(b, params.BeaconConfig().MaxValidatorsPerCommittee) + + var err error + + b.ResetTimer() + for i := 0; i < b.N; i++ { + st, err = transition.ProcessSlots(context.Background(), st, st.Slot()+1) + if err != nil { + b.Fatalf("Failed to process slot %v", err) + } + } +} + +func BenchmarkProcessSlots_Electra(b *testing.B) { + st, _ := util.DeterministicGenesisStateElectra(b, params.BeaconConfig().MaxValidatorsPerCommittee) + + var err error + + b.ResetTimer() + for i := 0; i < b.N; i++ { + st, err = transition.ProcessSlots(context.Background(), st, st.Slot()+1) + if err != nil { + b.Fatalf("Failed to process slot %v", err) + } + } +} diff --git a/beacon-chain/core/validators/slashing.go b/beacon-chain/core/validators/slashing.go index 1149ac78773a..8951026f256b 100644 --- a/beacon-chain/core/validators/slashing.go +++ b/beacon-chain/core/validators/slashing.go @@ -9,25 +9,35 @@ import ( // SlashingParamsPerVersion returns the slashing parameters for the given state version. func SlashingParamsPerVersion(v int) (slashingQuotient, proposerRewardQuotient, whistleblowerRewardQuotient uint64, err error) { cfg := params.BeaconConfig() - switch v { - case version.Phase0: - slashingQuotient = cfg.MinSlashingPenaltyQuotient + + if v >= version.Electra { + slashingQuotient = cfg.MinSlashingPenaltyQuotientElectra + proposerRewardQuotient = cfg.ProposerRewardQuotient + whistleblowerRewardQuotient = cfg.WhistleBlowerRewardQuotientElectra + return + } + + if v >= version.Bellatrix { + slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix proposerRewardQuotient = cfg.ProposerRewardQuotient whistleblowerRewardQuotient = cfg.WhistleBlowerRewardQuotient - case version.Altair: + return + } + + if v >= version.Altair { slashingQuotient = cfg.MinSlashingPenaltyQuotientAltair proposerRewardQuotient = cfg.ProposerRewardQuotient whistleblowerRewardQuotient = cfg.WhistleBlowerRewardQuotient - case version.Bellatrix, version.Capella, version.Deneb: - slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix + return + } + + if v >= version.Phase0 { + slashingQuotient = cfg.MinSlashingPenaltyQuotient proposerRewardQuotient = cfg.ProposerRewardQuotient whistleblowerRewardQuotient = cfg.WhistleBlowerRewardQuotient - case version.Electra: - slashingQuotient = cfg.MinSlashingPenaltyQuotientElectra - proposerRewardQuotient = cfg.ProposerRewardQuotient - whistleblowerRewardQuotient = cfg.WhistleBlowerRewardQuotientElectra - default: - err = errors.New("unknown state version") + return } + + err = errors.Errorf("unknown state version %s", version.String(v)) return } diff --git a/beacon-chain/core/validators/validator.go b/beacon-chain/core/validators/validator.go index 33f4c57b1ed3..a68264d9c962 100644 --- a/beacon-chain/core/validators/validator.go +++ b/beacon-chain/core/validators/validator.go @@ -75,7 +75,7 @@ func InitiateValidatorExit(ctx context.Context, s state.BeaconState, idx primiti // Compute exit queue epoch. if s.Version() < version.Electra { - // Relevant spec code from deneb: + // Relevant spec code from phase0: // // exit_epochs = [v.exit_epoch for v in state.validators if v.exit_epoch != FAR_FUTURE_EPOCH] // exit_queue_epoch = max(exit_epochs + [compute_activation_exit_epoch(get_current_epoch(state))]) @@ -241,76 +241,35 @@ func SlashedValidatorIndices(epoch primitives.Epoch, validators []*ethpb.Validat return slashed } -// ExitedValidatorIndices determines the indices exited during the current epoch. -func ExitedValidatorIndices(epoch primitives.Epoch, validators []*ethpb.Validator, activeValidatorCount uint64) ([]primitives.ValidatorIndex, error) { +// ExitedValidatorIndices returns the indices of validators who exited during the specified epoch. +// +// A validator is considered to have exited during an epoch if their ExitEpoch equals the epoch and +// excludes validators that have been ejected. +// This function simplifies the exit determination by directly checking the validator's ExitEpoch, +// avoiding the complexities and potential inaccuracies of calculating withdrawable epochs. +func ExitedValidatorIndices(epoch primitives.Epoch, validators []*ethpb.Validator) ([]primitives.ValidatorIndex, error) { exited := make([]primitives.ValidatorIndex, 0) - exitEpochs := make([]primitives.Epoch, 0) - for i := 0; i < len(validators); i++ { - val := validators[i] - if val.ExitEpoch != params.BeaconConfig().FarFutureEpoch { - exitEpochs = append(exitEpochs, val.ExitEpoch) - } - } - exitQueueEpoch := primitives.Epoch(0) - for _, i := range exitEpochs { - if exitQueueEpoch < i { - exitQueueEpoch = i - } - } - - // We use the exit queue churn to determine if we have passed a churn limit. - exitQueueChurn := uint64(0) - for _, val := range validators { - if val.ExitEpoch == exitQueueEpoch { - exitQueueChurn++ - } - } - churn := helpers.ValidatorExitChurnLimit(activeValidatorCount) - if churn < exitQueueChurn { - exitQueueEpoch++ - } - withdrawableEpoch := exitQueueEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay for i, val := range validators { - if val.ExitEpoch == epoch && val.WithdrawableEpoch == withdrawableEpoch && - val.EffectiveBalance > params.BeaconConfig().EjectionBalance { + if val.ExitEpoch == epoch && val.EffectiveBalance > params.BeaconConfig().EjectionBalance { exited = append(exited, primitives.ValidatorIndex(i)) } } return exited, nil } -// EjectedValidatorIndices determines the indices ejected during the given epoch. -func EjectedValidatorIndices(epoch primitives.Epoch, validators []*ethpb.Validator, activeValidatorCount uint64) ([]primitives.ValidatorIndex, error) { +// EjectedValidatorIndices returns the indices of validators who were ejected during the specified epoch. +// +// A validator is considered ejected during an epoch if: +// - Their ExitEpoch equals the epoch. +// - Their EffectiveBalance is less than or equal to the EjectionBalance threshold. +// +// This function simplifies the ejection determination by directly checking the validator's ExitEpoch +// and EffectiveBalance, avoiding the complexities and potential inaccuracies of calculating +// withdrawable epochs. +func EjectedValidatorIndices(epoch primitives.Epoch, validators []*ethpb.Validator) ([]primitives.ValidatorIndex, error) { ejected := make([]primitives.ValidatorIndex, 0) - exitEpochs := make([]primitives.Epoch, 0) - for i := 0; i < len(validators); i++ { - val := validators[i] - if val.ExitEpoch != params.BeaconConfig().FarFutureEpoch { - exitEpochs = append(exitEpochs, val.ExitEpoch) - } - } - exitQueueEpoch := primitives.Epoch(0) - for _, i := range exitEpochs { - if exitQueueEpoch < i { - exitQueueEpoch = i - } - } - - // We use the exit queue churn to determine if we have passed a churn limit. - exitQueueChurn := uint64(0) - for _, val := range validators { - if val.ExitEpoch == exitQueueEpoch { - exitQueueChurn++ - } - } - churn := helpers.ValidatorExitChurnLimit(activeValidatorCount) - if churn < exitQueueChurn { - exitQueueEpoch++ - } - withdrawableEpoch := exitQueueEpoch + params.BeaconConfig().MinValidatorWithdrawabilityDelay for i, val := range validators { - if val.ExitEpoch == epoch && val.WithdrawableEpoch == withdrawableEpoch && - val.EffectiveBalance <= params.BeaconConfig().EjectionBalance { + if val.ExitEpoch == epoch && val.EffectiveBalance <= params.BeaconConfig().EjectionBalance { ejected = append(ejected, primitives.ValidatorIndex(i)) } } diff --git a/beacon-chain/core/validators/validator_test.go b/beacon-chain/core/validators/validator_test.go index f68634541255..3c05b0599e1a 100644 --- a/beacon-chain/core/validators/validator_test.go +++ b/beacon-chain/core/validators/validator_test.go @@ -217,6 +217,7 @@ func TestSlashValidator_OK(t *testing.T) { } func TestSlashValidator_Electra(t *testing.T) { + helpers.ClearCache() validatorCount := 100 registry := make([]*ethpb.Validator, 0, validatorCount) balances := make([]uint64, 0, validatorCount) @@ -389,19 +390,16 @@ func TestExitedValidatorIndices(t *testing.T) { state: ðpb.BeaconState{ Validators: []*ethpb.Validator{ { - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - ExitEpoch: 0, - WithdrawableEpoch: params.BeaconConfig().MinValidatorWithdrawabilityDelay, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + ExitEpoch: 0, }, { - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - ExitEpoch: 0, - WithdrawableEpoch: 10, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + ExitEpoch: 10, }, { - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - ExitEpoch: 0, - WithdrawableEpoch: params.BeaconConfig().MinValidatorWithdrawabilityDelay, + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + ExitEpoch: 0, }, }, }, @@ -433,11 +431,7 @@ func TestExitedValidatorIndices(t *testing.T) { }, } for _, tt := range tests { - s, err := state_native.InitializeFromProtoPhase0(tt.state) - require.NoError(t, err) - activeCount, err := helpers.ActiveValidatorCount(context.Background(), s, time.PrevEpoch(s)) - require.NoError(t, err) - exitedIndices, err := validators.ExitedValidatorIndices(0, tt.state.Validators, activeCount) + exitedIndices, err := validators.ExitedValidatorIndices(0, tt.state.Validators) require.NoError(t, err) assert.DeepEqual(t, tt.wanted, exitedIndices) } diff --git a/beacon-chain/das/BUILD.bazel b/beacon-chain/das/BUILD.bazel index aa288ca4fecc..09d761fee830 100644 --- a/beacon-chain/das/BUILD.bazel +++ b/beacon-chain/das/BUILD.bazel @@ -13,7 +13,6 @@ go_library( deps = [ "//beacon-chain/db/filesystem:go_default_library", "//beacon-chain/verification:go_default_library", - "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", @@ -35,7 +34,6 @@ go_test( deps = [ "//beacon-chain/db/filesystem:go_default_library", "//beacon-chain/verification:go_default_library", - "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", diff --git a/beacon-chain/das/availability.go b/beacon-chain/das/availability.go index 7a8a2105838a..e18f075822d3 100644 --- a/beacon-chain/das/availability.go +++ b/beacon-chain/das/availability.go @@ -83,10 +83,10 @@ func (s *LazilyPersistentStore) Persist(current primitives.Slot, sc ...blocks.RO func (s *LazilyPersistentStore) IsDataAvailable(ctx context.Context, current primitives.Slot, b blocks.ROBlock) error { blockCommitments, err := commitmentsToCheck(b, current) if err != nil { - return errors.Wrapf(err, "could check data availability for block %#x", b.Root()) + return errors.Wrapf(err, "could not check data availability for block %#x", b.Root()) } // Return early for blocks that are pre-deneb or which do not have any commitments. - if blockCommitments.count() == 0 { + if len(blockCommitments) == 0 { return nil } @@ -94,19 +94,12 @@ func (s *LazilyPersistentStore) IsDataAvailable(ctx context.Context, current pri entry := s.cache.ensure(key) defer s.cache.delete(key) root := b.Root() - sumz, err := s.store.WaitForSummarizer(ctx) - if err != nil { - log.WithField("root", fmt.Sprintf("%#x", b.Root())). - WithError(err). - Debug("Failed to receive BlobStorageSummarizer within IsDataAvailable") - } else { - entry.setDiskSummary(sumz.Summary(root)) - } + entry.setDiskSummary(s.store.Summary(root)) // Verify we have all the expected sidecars, and fail fast if any are missing or inconsistent. // We don't try to salvage problematic batches because this indicates a misbehaving peer and we'd rather // ignore their response and decrease their peer score. - sidecars, err := entry.filter(root, blockCommitments) + sidecars, err := entry.filter(root, blockCommitments, b.Block().Slot()) if err != nil { return errors.Wrap(err, "incomplete BlobSidecar batch") } @@ -137,22 +130,28 @@ func (s *LazilyPersistentStore) IsDataAvailable(ctx context.Context, current pri return nil } -func commitmentsToCheck(b blocks.ROBlock, current primitives.Slot) (safeCommitmentArray, error) { - var ar safeCommitmentArray +func commitmentsToCheck(b blocks.ROBlock, current primitives.Slot) ([][]byte, error) { if b.Version() < version.Deneb { - return ar, nil + return nil, nil } - // We are only required to check within MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS + + // We are only required to check within MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUEST if !params.WithinDAPeriod(slots.ToEpoch(b.Block().Slot()), slots.ToEpoch(current)) { - return ar, nil + return nil, nil } - kc, err := b.Block().Body().BlobKzgCommitments() + + kzgCommitments, err := b.Block().Body().BlobKzgCommitments() if err != nil { - return ar, err + return nil, err } - if len(kc) > len(ar) { - return ar, errIndexOutOfBounds + + maxBlobCount := params.BeaconConfig().MaxBlobsPerBlock(b.Block().Slot()) + if len(kzgCommitments) > maxBlobCount { + return nil, errIndexOutOfBounds } - copy(ar[:], kc) - return ar, nil + + result := make([][]byte, len(kzgCommitments)) + copy(result, kzgCommitments) + + return result, nil } diff --git a/beacon-chain/das/availability_test.go b/beacon-chain/das/availability_test.go index e59830feb0ce..eca89c929ebf 100644 --- a/beacon-chain/das/availability_test.go +++ b/beacon-chain/das/availability_test.go @@ -8,7 +8,6 @@ import ( errors "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -89,7 +88,7 @@ func Test_commitmentsToCheck(t *testing.T) { require.NoError(t, err) c, err := rb.Block().Body().BlobKzgCommitments() require.NoError(t, err) - require.Equal(t, true, len(c) > fieldparams.MaxBlobsPerBlock) + require.Equal(t, true, len(c) > params.BeaconConfig().MaxBlobsPerBlock(sb.Block().Slot())) return rb }, slot: windowSlots + 1, @@ -105,7 +104,7 @@ func Test_commitmentsToCheck(t *testing.T) { } else { require.NoError(t, err) } - require.Equal(t, len(c.commits), co.count()) + require.Equal(t, len(c.commits), len(co)) for i := 0; i < len(c.commits); i++ { require.Equal(t, true, bytes.Equal(c.commits[i], co[i])) } diff --git a/beacon-chain/das/cache.go b/beacon-chain/das/cache.go index 9702743f944e..9cc332a0a7f1 100644 --- a/beacon-chain/das/cache.go +++ b/beacon-chain/das/cache.go @@ -5,7 +5,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) @@ -60,7 +60,7 @@ func (c *cache) delete(key cacheKey) { // cacheEntry holds a fixed-length cache of BlobSidecars. type cacheEntry struct { - scs [fieldparams.MaxBlobsPerBlock]*blocks.ROBlob + scs []*blocks.ROBlob diskSummary filesystem.BlobStorageSummary } @@ -72,9 +72,13 @@ func (e *cacheEntry) setDiskSummary(sum filesystem.BlobStorageSummary) { // Only the first BlobSidecar of a given Index will be kept in the cache. // stash will return an error if the given blob is already in the cache, or if the Index is out of bounds. func (e *cacheEntry) stash(sc *blocks.ROBlob) error { - if sc.Index >= fieldparams.MaxBlobsPerBlock { + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(sc.Slot()) + if sc.Index >= uint64(maxBlobsPerBlock) { return errors.Wrapf(errIndexOutOfBounds, "index=%d", sc.Index) } + if e.scs == nil { + e.scs = make([]*blocks.ROBlob, maxBlobsPerBlock) + } if e.scs[sc.Index] != nil { return errors.Wrapf(ErrDuplicateSidecar, "root=%#x, index=%d, commitment=%#x", sc.BlockRoot(), sc.Index, sc.KzgCommitment) } @@ -88,12 +92,13 @@ func (e *cacheEntry) stash(sc *blocks.ROBlob) error { // commitments were found in the cache and the sidecar slice return value can be used // to perform a DA check against the cached sidecars. // filter only returns blobs that need to be checked. Blobs already available on disk will be excluded. -func (e *cacheEntry) filter(root [32]byte, kc safeCommitmentArray) ([]blocks.ROBlob, error) { - if e.diskSummary.AllAvailable(kc.count()) { +func (e *cacheEntry) filter(root [32]byte, kc [][]byte, slot primitives.Slot) ([]blocks.ROBlob, error) { + count := len(kc) + if e.diskSummary.AllAvailable(count) { return nil, nil } - scs := make([]blocks.ROBlob, 0, kc.count()) - for i := uint64(0); i < fieldparams.MaxBlobsPerBlock; i++ { + scs := make([]blocks.ROBlob, 0, count) + for i := uint64(0); i < uint64(count); i++ { // We already have this blob, we don't need to write it or validate it. if e.diskSummary.HasIndex(i) { continue @@ -116,16 +121,3 @@ func (e *cacheEntry) filter(root [32]byte, kc safeCommitmentArray) ([]blocks.ROB return scs, nil } - -// safeCommitmentArray is a fixed size array of commitment byte slices. This is helpful for avoiding -// gratuitous bounds checks. -type safeCommitmentArray [fieldparams.MaxBlobsPerBlock][]byte - -func (s safeCommitmentArray) count() int { - for i := range s { - if s[i] == nil { - return i - } - } - return fieldparams.MaxBlobsPerBlock -} diff --git a/beacon-chain/das/cache_test.go b/beacon-chain/das/cache_test.go index cd271fc516ed..b33603e40fd2 100644 --- a/beacon-chain/das/cache_test.go +++ b/beacon-chain/das/cache_test.go @@ -29,10 +29,10 @@ func TestCacheEnsureDelete(t *testing.T) { require.Equal(t, nilEntry, c.entries[k]) } -type filterTestCaseSetupFunc func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) +type filterTestCaseSetupFunc func(t *testing.T) (*cacheEntry, [][]byte, []blocks.ROBlob) func filterTestCaseSetup(slot primitives.Slot, nBlobs int, onDisk []int, numExpected int) filterTestCaseSetupFunc { - return func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) { + return func(t *testing.T) (*cacheEntry, [][]byte, []blocks.ROBlob) { blk, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, nBlobs) commits, err := commitmentsToCheck(blk, blk.Block().Slot()) require.NoError(t, err) @@ -44,7 +44,7 @@ func filterTestCaseSetup(slot primitives.Slot, nBlobs int, onDisk []int, numExpe entry.setDiskSummary(sum) } expected := make([]blocks.ROBlob, 0, nBlobs) - for i := 0; i < commits.count(); i++ { + for i := 0; i < len(commits); i++ { if entry.diskSummary.HasIndex(uint64(i)) { continue } @@ -113,7 +113,7 @@ func TestFilterDiskSummary(t *testing.T) { t.Run(c.name, func(t *testing.T) { entry, commits, expected := c.setup(t) // first (root) argument doesn't matter, it is just for logs - got, err := entry.filter([32]byte{}, commits) + got, err := entry.filter([32]byte{}, commits, 100) require.NoError(t, err) require.Equal(t, len(expected), len(got)) }) @@ -125,12 +125,12 @@ func TestFilter(t *testing.T) { require.NoError(t, err) cases := []struct { name string - setup func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) + setup func(t *testing.T) (*cacheEntry, [][]byte, []blocks.ROBlob) err error }{ { name: "commitments mismatch - extra sidecar", - setup: func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) { + setup: func(t *testing.T) (*cacheEntry, [][]byte, []blocks.ROBlob) { entry, commits, expected := filterTestCaseSetup(denebSlot, 6, []int{0, 1}, 4)(t) commits[5] = nil return entry, commits, expected @@ -139,7 +139,7 @@ func TestFilter(t *testing.T) { }, { name: "sidecar missing", - setup: func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) { + setup: func(t *testing.T) (*cacheEntry, [][]byte, []blocks.ROBlob) { entry, commits, expected := filterTestCaseSetup(denebSlot, 6, []int{0, 1}, 4)(t) entry.scs[5] = nil return entry, commits, expected @@ -148,7 +148,7 @@ func TestFilter(t *testing.T) { }, { name: "commitments mismatch - different bytes", - setup: func(t *testing.T) (*cacheEntry, safeCommitmentArray, []blocks.ROBlob) { + setup: func(t *testing.T) (*cacheEntry, [][]byte, []blocks.ROBlob) { entry, commits, expected := filterTestCaseSetup(denebSlot, 6, []int{0, 1}, 4)(t) entry.scs[5].KzgCommitment = []byte("nope") return entry, commits, expected @@ -160,7 +160,7 @@ func TestFilter(t *testing.T) { t.Run(c.name, func(t *testing.T) { entry, commits, expected := c.setup(t) // first (root) argument doesn't matter, it is just for logs - got, err := entry.filter([32]byte{}, commits) + got, err := entry.filter([32]byte{}, commits, 100) if c.err != nil { require.ErrorIs(t, err, c.err) return diff --git a/beacon-chain/db/filesystem/BUILD.bazel b/beacon-chain/db/filesystem/BUILD.bazel index e4008d70072e..838791e35aff 100644 --- a/beacon-chain/db/filesystem/BUILD.bazel +++ b/beacon-chain/db/filesystem/BUILD.bazel @@ -5,6 +5,10 @@ go_library( srcs = [ "blob.go", "cache.go", + "iteration.go", + "layout.go", + "layout_by_epoch.go", + "layout_flat.go", "log.go", "metrics.go", "mock.go", @@ -13,6 +17,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem", visibility = ["//visibility:public"], deps = [ + "//beacon-chain/db:go_default_library", "//beacon-chain/verification:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", @@ -20,7 +25,6 @@ go_library( "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", "//runtime/logging:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", @@ -37,17 +41,22 @@ go_test( srcs = [ "blob_test.go", "cache_test.go", + "iteration_test.go", + "layout_test.go", + "migration_test.go", "pruner_test.go", ], embed = [":go_default_library"], deps = [ + "//beacon-chain/db:go_default_library", "//beacon-chain/verification:go_default_library", - "//config/fieldparams:go_default_library", + "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", + "//time/slots:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_spf13_afero//:go_default_library", ], diff --git a/beacon-chain/db/filesystem/blob.go b/beacon-chain/db/filesystem/blob.go index f7e518022d30..647561b9df5f 100644 --- a/beacon-chain/db/filesystem/blob.go +++ b/beacon-chain/db/filesystem/blob.go @@ -1,42 +1,31 @@ package filesystem import ( - "context" "fmt" "math" "os" "path" - "strconv" - "strings" "time" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/io/file" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/logging" "github.com/sirupsen/logrus" "github.com/spf13/afero" ) +func directoryPermissions() os.FileMode { + return params.BeaconIoConfig().ReadWriteExecutePermissions +} + var ( - errIndexOutOfBounds = errors.New("blob index in file name >= MaxBlobsPerBlock") - errEmptyBlobWritten = errors.New("zero bytes written to disk when saving blob sidecar") + errIndexOutOfBounds = errors.New("blob index in file name >= MAX_BLOBS_PER_BLOCK") errSidecarEmptySSZData = errors.New("sidecar marshalled to an empty ssz byte slice") errNoBasePath = errors.New("BlobStorage base path not specified in init") - errInvalidRootString = errors.New("Could not parse hex string as a [32]byte") -) - -const ( - sszExt = "ssz" - partExt = "part" - - directoryPermissions = 0700 ) // BlobStorageOption is a functional option for configuring a BlobStorage. @@ -66,6 +55,23 @@ func WithSaveFsync(fsync bool) BlobStorageOption { } } +// WithFs allows the afero.Fs implementation to be customized. Used by tests +// to substitute an in-memory filesystem. +func WithFs(fs afero.Fs) BlobStorageOption { + return func(b *BlobStorage) error { + b.fs = fs + return nil + } +} + +// WithLayout enables the user to specify which layout scheme to use, dictating how blob files are stored on disk. +func WithLayout(name string) BlobStorageOption { + return func(b *BlobStorage) error { + b.layoutName = name + return nil + } +} + // NewBlobStorage creates a new instance of the BlobStorage object. Note that the implementation of BlobStorage may // attempt to hold a file lock to guarantee exclusive control of the blob storage directory, so this should only be // initialized once per beacon node. @@ -76,19 +82,27 @@ func NewBlobStorage(opts ...BlobStorageOption) (*BlobStorage, error) { return nil, errors.Wrap(err, "failed to create blob storage") } } - if b.base == "" { - return nil, errNoBasePath + // Allow tests to set up a different fs using WithFs. + if b.fs == nil { + if b.base == "" { + return nil, errNoBasePath + } + b.base = path.Clean(b.base) + if err := file.MkdirAll(b.base); err != nil { + return nil, errors.Wrapf(err, "failed to create blob storage at %s", b.base) + } + b.fs = afero.NewBasePathFs(afero.NewOsFs(), b.base) } - b.base = path.Clean(b.base) - if err := file.MkdirAll(b.base); err != nil { - return nil, errors.Wrapf(err, "failed to create blob storage at %s", b.base) + b.cache = newBlobStorageCache() + pruner := newBlobPruner(b.retentionEpochs) + if b.layoutName == "" { + b.layoutName = LayoutNameFlat } - b.fs = afero.NewBasePathFs(afero.NewOsFs(), b.base) - pruner, err := newBlobPruner(b.fs, b.retentionEpochs) + layout, err := newLayout(b.layoutName, b.fs, b.cache, pruner) if err != nil { return nil, err } - b.pruner = pruner + b.layout = layout return b, nil } @@ -96,46 +110,103 @@ func NewBlobStorage(opts ...BlobStorageOption) (*BlobStorage, error) { type BlobStorage struct { base string retentionEpochs primitives.Epoch + layoutName string fsync bool fs afero.Fs - pruner *blobPruner + layout fsLayout + cache *blobStorageSummaryCache } // WarmCache runs the prune routine with an expiration of slot of 0, so nothing will be pruned, but the pruner's cache // will be populated at node startup, avoiding a costly cold prune (~4s in syscalls) during syncing. func (bs *BlobStorage) WarmCache() { - if bs.pruner == nil { - return + start := time.Now() + if bs.layoutName == LayoutNameFlat { + log.Info("Blob filesystem cache warm-up started. This may take a few minutes.") + } else { + log.Info("Blob filesystem cache warm-up started.") + } + + if err := warmCache(bs.layout, bs.cache); err != nil { + log.WithError(err).Error("Error encountered while warming up blob filesystem cache.") + } + if err := bs.migrateLayouts(); err != nil { + log.WithError(err).Error("Error encountered while migrating blob storage.") } - go func() { - start := time.Now() - if err := bs.pruner.warmCache(); err != nil { - log.WithError(err).Error("Error encountered while warming up blob pruner cache") + log.WithField("elapsed", time.Since(start)).Info("Blob filesystem cache warm-up complete.") +} + +// If any blob storage directories are found for layouts besides the configured layout, migrate them. +func (bs *BlobStorage) migrateLayouts() error { + for _, name := range LayoutNames { + if name == bs.layoutName { + continue } - log.WithField("elapsed", time.Since(start)).Info("Blob filesystem cache warm-up complete.") - }() + from, err := newLayout(name, bs.fs, bs.cache, nil) + if err != nil { + return err + } + if err := migrateLayout(bs.fs, from, bs.layout, bs.cache); err != nil { + if errors.Is(err, errLayoutNotDetected) { + continue + } + return errors.Wrapf(err, "failed to migrate layout from %s to %s", name, bs.layoutName) + } + } + return nil } -// ErrBlobStorageSummarizerUnavailable is a sentinel error returned when there is no pruner/cache available. -// This should be used by code that optionally uses the summarizer to optimize rpc requests. Being able to -// fallback when there is no summarizer allows client code to avoid test complexity where the summarizer doesn't matter. -var ErrBlobStorageSummarizerUnavailable = errors.New("BlobStorage not initialized with a pruner or cache") - -// WaitForSummarizer blocks until the BlobStorageSummarizer is ready to use. -// BlobStorageSummarizer is not ready immediately on node startup because it needs to sample the blob filesystem to -// determine which blobs are available. -func (bs *BlobStorage) WaitForSummarizer(ctx context.Context) (BlobStorageSummarizer, error) { - if bs == nil || bs.pruner == nil { - return nil, ErrBlobStorageSummarizerUnavailable +func (bs *BlobStorage) writePart(sidecar blocks.VerifiedROBlob) (ppath string, err error) { + ident := identForSidecar(sidecar) + sidecarData, err := sidecar.MarshalSSZ() + if err != nil { + return "", errors.Wrap(err, "failed to serialize sidecar data") + } + if len(sidecarData) == 0 { + return "", errSidecarEmptySSZData + } + + if err := bs.fs.MkdirAll(bs.layout.dir(ident), directoryPermissions()); err != nil { + return "", err + } + ppath = bs.layout.partPath(ident, fmt.Sprintf("%p", sidecarData)) + + // Create a partial file and write the serialized data to it. + partialFile, err := bs.fs.Create(ppath) + if err != nil { + return "", errors.Wrap(err, "failed to create partial file") + } + defer func() { + cerr := partialFile.Close() + // The close error is probably less important than any existing error, so only overwrite nil err. + if cerr != nil && err == nil { + err = cerr + } + }() + + n, err := partialFile.Write(sidecarData) + if err != nil { + return ppath, errors.Wrap(err, "failed to write to partial file") } - return bs.pruner.waitForCache(ctx) + if bs.fsync { + if err := partialFile.Sync(); err != nil { + return ppath, err + } + } + + if n != len(sidecarData) { + return ppath, fmt.Errorf("failed to write the full bytes of sidecarData, wrote only %d of %d bytes", n, len(sidecarData)) + } + + return ppath, nil } // Save saves blobs given a list of sidecars. func (bs *BlobStorage) Save(sidecar blocks.VerifiedROBlob) error { startTime := time.Now() - fname := namerForSidecar(sidecar) - sszPath := fname.path() + + ident := identForSidecar(sidecar) + sszPath := bs.layout.sszPath(ident) exists, err := afero.Exists(bs.fs, sszPath) if err != nil { return err @@ -144,80 +215,39 @@ func (bs *BlobStorage) Save(sidecar blocks.VerifiedROBlob) error { log.WithFields(logging.BlobFields(sidecar.ROBlob)).Debug("Ignoring a duplicate blob sidecar save attempt") return nil } - if bs.pruner != nil { - if err := bs.pruner.notify(sidecar.BlockRoot(), sidecar.Slot(), sidecar.Index); err != nil { - return errors.Wrapf(err, "problem maintaining pruning cache/metrics for sidecar with root=%#x", sidecar.BlockRoot()) - } - } - - // Serialize the ethpb.BlobSidecar to binary data using SSZ. - sidecarData, err := sidecar.MarshalSSZ() - if err != nil { - return errors.Wrap(err, "failed to serialize sidecar data") - } else if len(sidecarData) == 0 { - return errSidecarEmptySSZData - } - - if err := bs.fs.MkdirAll(fname.dir(), directoryPermissions); err != nil { - return err - } - partPath := fname.partPath(fmt.Sprintf("%p", sidecarData)) partialMoved := false + partPath, err := bs.writePart(sidecar) // Ensure the partial file is deleted. defer func() { - if partialMoved { + if partialMoved || partPath == "" { return } // It's expected to error if the save is successful. - err = bs.fs.Remove(partPath) + err := bs.fs.Remove(partPath) if err == nil { log.WithFields(logrus.Fields{ "partPath": partPath, }).Debugf("Removed partial file") } }() - - // Create a partial file and write the serialized data to it. - partialFile, err := bs.fs.Create(partPath) if err != nil { - return errors.Wrap(err, "failed to create partial file") - } - - n, err := partialFile.Write(sidecarData) - if err != nil { - closeErr := partialFile.Close() - if closeErr != nil { - return closeErr - } - return errors.Wrap(err, "failed to write to partial file") - } - if bs.fsync { - if err := partialFile.Sync(); err != nil { - return err - } - } - - if err := partialFile.Close(); err != nil { return err } - if n != len(sidecarData) { - return fmt.Errorf("failed to write the full bytes of sidecarData, wrote only %d of %d bytes", n, len(sidecarData)) - } - - if n == 0 { - return errEmptyBlobWritten - } - // Atomically rename the partial file to its final name. err = bs.fs.Rename(partPath, sszPath) if err != nil { return errors.Wrap(err, "failed to rename partial file to final name") } partialMoved = true + + if err := bs.layout.notify(ident); err != nil { + return errors.Wrapf(err, "problem maintaining pruning cache/metrics for sidecar with root=%#x", sidecar.BlockRoot()) + } blobsWrittenCounter.Inc() blobSaveLatency.Observe(float64(time.Since(startTime).Milliseconds())) + return nil } @@ -226,67 +256,30 @@ func (bs *BlobStorage) Save(sidecar blocks.VerifiedROBlob) error { // value is always a VerifiedROBlob. func (bs *BlobStorage) Get(root [32]byte, idx uint64) (blocks.VerifiedROBlob, error) { startTime := time.Now() - expected := blobNamer{root: root, index: idx} - encoded, err := afero.ReadFile(bs.fs, expected.path()) - var v blocks.VerifiedROBlob + ident, err := bs.layout.ident(root, idx) if err != nil { - return v, err - } - s := ðpb.BlobSidecar{} - if err := s.UnmarshalSSZ(encoded); err != nil { - return v, err - } - ro, err := blocks.NewROBlobWithRoot(s, root) - if err != nil { - return blocks.VerifiedROBlob{}, err + return verification.VerifiedROBlobError(err) } defer func() { blobFetchLatency.Observe(float64(time.Since(startTime).Milliseconds())) }() - return verification.BlobSidecarNoop(ro) + return verification.VerifiedROBlobFromDisk(bs.fs, root, bs.layout.sszPath(ident)) } // Remove removes all blobs for a given root. func (bs *BlobStorage) Remove(root [32]byte) error { - rootDir := blobNamer{root: root}.dir() - return bs.fs.RemoveAll(rootDir) -} - -// Indices generates a bitmap representing which BlobSidecar.Index values are present on disk for a given root. -// This value can be compared to the commitments observed in a block to determine which indices need to be found -// on the network to confirm data availability. -func (bs *BlobStorage) Indices(root [32]byte) ([fieldparams.MaxBlobsPerBlock]bool, error) { - var mask [fieldparams.MaxBlobsPerBlock]bool - rootDir := blobNamer{root: root}.dir() - entries, err := afero.ReadDir(bs.fs, rootDir) + dirIdent, err := bs.layout.dirIdent(root) if err != nil { - if os.IsNotExist(err) { - return mask, nil - } - return mask, err - } - for i := range entries { - if entries[i].IsDir() { - continue - } - name := entries[i].Name() - if !strings.HasSuffix(name, sszExt) { - continue - } - parts := strings.Split(name, ".") - if len(parts) != 2 { - continue - } - u, err := strconv.ParseUint(parts[0], 10, 64) - if err != nil { - return mask, errors.Wrapf(err, "unexpected directory entry breaks listing, %s", parts[0]) - } - if u >= fieldparams.MaxBlobsPerBlock { - return mask, errIndexOutOfBounds - } - mask[u] = true + return err } - return mask, nil + _, err = bs.layout.remove(dirIdent) + return err +} + +// Summary returns the BlobStorageSummary from the layout. +// Internally, this is a cached representation of the directory listing for the given root. +func (bs *BlobStorage) Summary(root [32]byte) BlobStorageSummary { + return bs.layout.summary(root) } // Clear deletes all files on the filesystem. @@ -311,36 +304,3 @@ func (bs *BlobStorage) WithinRetentionPeriod(requested, current primitives.Epoch } return requested+bs.retentionEpochs >= current } - -type blobNamer struct { - root [32]byte - index uint64 -} - -func namerForSidecar(sc blocks.VerifiedROBlob) blobNamer { - return blobNamer{root: sc.BlockRoot(), index: sc.Index} -} - -func (p blobNamer) dir() string { - return rootString(p.root) -} - -func (p blobNamer) partPath(entropy string) string { - return path.Join(p.dir(), fmt.Sprintf("%s-%d.%s", entropy, p.index, partExt)) -} - -func (p blobNamer) path() string { - return path.Join(p.dir(), fmt.Sprintf("%d.%s", p.index, sszExt)) -} - -func rootString(root [32]byte) string { - return fmt.Sprintf("%#x", root) -} - -func stringToRoot(str string) ([32]byte, error) { - slice, err := hexutil.Decode(str) - if err != nil { - return [32]byte{}, errors.Wrapf(errInvalidRootString, "input=%s", str) - } - return bytesutil.ToBytes32(slice), nil -} diff --git a/beacon-chain/db/filesystem/blob_test.go b/beacon-chain/db/filesystem/blob_test.go index cd75c1fbedb4..656b70d71aa1 100644 --- a/beacon-chain/db/filesystem/blob_test.go +++ b/beacon-chain/db/filesystem/blob_test.go @@ -9,26 +9,26 @@ import ( "testing" ssz "github.com/prysmaticlabs/fastssz" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/spf13/afero" ) func TestBlobStorage_SaveBlobData(t *testing.T) { - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 1, fieldparams.MaxBlobsPerBlock) - testSidecars, err := verification.BlobSidecarSliceNoop(sidecars) - require.NoError(t, err) + _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 1, params.BeaconConfig().MaxBlobsPerBlock(1)) + testSidecars := verification.FakeVerifySliceForTest(t, sidecars) t.Run("no error for duplicate", func(t *testing.T) { - fs, bs := NewEphemeralBlobStorageWithFs(t) + fs, bs := NewEphemeralBlobStorageAndFs(t) existingSidecar := testSidecars[0] - blobPath := namerForSidecar(existingSidecar).path() + blobPath := bs.layout.sszPath(identForSidecar(existingSidecar)) // Serialize the existing BlobSidecar to binary data. existingSidecarData, err := ssz.MarshalSSZ(existingSidecar) require.NoError(t, err) @@ -56,10 +56,10 @@ func TestBlobStorage_SaveBlobData(t *testing.T) { require.NoError(t, bs.Save(sc)) actualSc, err := bs.Get(sc.BlockRoot(), sc.Index) require.NoError(t, err) - expectedIdx := [fieldparams.MaxBlobsPerBlock]bool{false, false, true} - actualIdx, err := bs.Indices(actualSc.BlockRoot()) + expectedIdx := blobIndexMask{false, false, true, false, false, false} + actualIdx := bs.Summary(actualSc.BlockRoot()).mask require.NoError(t, err) - require.Equal(t, expectedIdx, actualIdx) + require.DeepEqual(t, expectedIdx, actualIdx) }) t.Run("round trip write then read", func(t *testing.T) { @@ -85,7 +85,7 @@ func TestBlobStorage_SaveBlobData(t *testing.T) { require.NoError(t, bs.Remove(expected.BlockRoot())) _, err = bs.Get(expected.BlockRoot(), expected.Index) - require.ErrorContains(t, "file does not exist", err) + require.Equal(t, true, db.IsNotFound(err)) }) t.Run("clear", func(t *testing.T) { @@ -126,119 +126,38 @@ func TestBlobStorage_SaveBlobData(t *testing.T) { }) } -// pollUntil polls a condition function until it returns true or a timeout is reached. - func TestBlobIndicesBounds(t *testing.T) { - fs, bs := NewEphemeralBlobStorageWithFs(t) + fs := afero.NewMemMapFs() root := [32]byte{} - okIdx := uint64(fieldparams.MaxBlobsPerBlock - 1) - writeFakeSSZ(t, fs, root, okIdx) - indices, err := bs.Indices(root) - require.NoError(t, err) - var expected [fieldparams.MaxBlobsPerBlock]bool + okIdx := uint64(params.BeaconConfig().MaxBlobsPerBlock(0)) - 1 + writeFakeSSZ(t, fs, root, 0, okIdx) + bs := NewWarmedEphemeralBlobStorageUsingFs(t, fs, WithLayout(LayoutNameByEpoch)) + indices := bs.Summary(root).mask + expected := make([]bool, params.BeaconConfig().MaxBlobsPerBlock(0)) expected[okIdx] = true for i := range expected { require.Equal(t, expected[i], indices[i]) } - oobIdx := uint64(fieldparams.MaxBlobsPerBlock) - writeFakeSSZ(t, fs, root, oobIdx) - _, err = bs.Indices(root) - require.ErrorIs(t, err, errIndexOutOfBounds) + oobIdx := uint64(params.BeaconConfig().MaxBlobsPerBlock(0)) + writeFakeSSZ(t, fs, root, 0, oobIdx) + // This now fails at cache warmup time. + require.ErrorIs(t, warmCache(bs.layout, bs.cache), errIndexOutOfBounds) } -func writeFakeSSZ(t *testing.T, fs afero.Fs, root [32]byte, idx uint64) { - namer := blobNamer{root: root, index: idx} - require.NoError(t, fs.MkdirAll(namer.dir(), 0700)) - fh, err := fs.Create(namer.path()) +func writeFakeSSZ(t *testing.T, fs afero.Fs, root [32]byte, slot primitives.Slot, idx uint64) { + epoch := slots.ToEpoch(slot) + namer := newBlobIdent(root, epoch, idx) + layout := periodicEpochLayout{} + require.NoError(t, fs.MkdirAll(layout.dir(namer), 0700)) + fh, err := fs.Create(layout.sszPath(namer)) require.NoError(t, err) _, err = fh.Write([]byte("derp")) require.NoError(t, err) require.NoError(t, fh.Close()) } -func TestBlobStoragePrune(t *testing.T) { - currentSlot := primitives.Slot(200000) - fs, bs := NewEphemeralBlobStorageWithFs(t) - - t.Run("PruneOne", func(t *testing.T) { - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 300, fieldparams.MaxBlobsPerBlock) - testSidecars, err := verification.BlobSidecarSliceNoop(sidecars) - require.NoError(t, err) - - for _, sidecar := range testSidecars { - require.NoError(t, bs.Save(sidecar)) - } - - require.NoError(t, bs.pruner.prune(currentSlot-bs.pruner.windowSize)) - - remainingFolders, err := afero.ReadDir(fs, ".") - require.NoError(t, err) - require.Equal(t, 0, len(remainingFolders)) - }) - t.Run("Prune dangling blob", func(t *testing.T) { - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 299, fieldparams.MaxBlobsPerBlock) - testSidecars, err := verification.BlobSidecarSliceNoop(sidecars) - require.NoError(t, err) - - for _, sidecar := range testSidecars[4:] { - require.NoError(t, bs.Save(sidecar)) - } - - require.NoError(t, bs.pruner.prune(currentSlot-bs.pruner.windowSize)) - - remainingFolders, err := afero.ReadDir(fs, ".") - require.NoError(t, err) - require.Equal(t, 0, len(remainingFolders)) - }) - t.Run("PruneMany", func(t *testing.T) { - blockQty := 10 - slot := primitives.Slot(1) - - for j := 0; j <= blockQty; j++ { - root := bytesutil.ToBytes32(bytesutil.ToBytes(uint64(slot), 32)) - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, root, slot, fieldparams.MaxBlobsPerBlock) - testSidecars, err := verification.BlobSidecarSliceNoop(sidecars) - require.NoError(t, err) - require.NoError(t, bs.Save(testSidecars[0])) - - slot += 10000 - } - - require.NoError(t, bs.pruner.prune(currentSlot-bs.pruner.windowSize)) - - remainingFolders, err := afero.ReadDir(fs, ".") - require.NoError(t, err) - require.Equal(t, 4, len(remainingFolders)) - }) -} - -func BenchmarkPruning(b *testing.B) { - var t *testing.T - _, bs := NewEphemeralBlobStorageWithFs(t) - - blockQty := 10000 - currentSlot := primitives.Slot(150000) - slot := primitives.Slot(0) - - for j := 0; j <= blockQty; j++ { - root := bytesutil.ToBytes32(bytesutil.ToBytes(uint64(slot), 32)) - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, root, slot, fieldparams.MaxBlobsPerBlock) - testSidecars, err := verification.BlobSidecarSliceNoop(sidecars) - require.NoError(t, err) - require.NoError(t, bs.Save(testSidecars[0])) - - slot += 100 - } - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - err := bs.pruner.prune(currentSlot) - require.NoError(b, err) - } -} - func TestNewBlobStorage(t *testing.T) { _, err := NewBlobStorage() require.ErrorIs(t, err, errNoBasePath) @@ -292,3 +211,13 @@ func TestConfig_WithinRetentionPeriod(t *testing.T) { require.Equal(t, true, storage.WithinRetentionPeriod(1, 1)) }) } + +func TestLayoutNames(t *testing.T) { + badLayoutName := "bad" + for _, name := range LayoutNames { + _, err := newLayout(name, nil, nil, nil) + require.NoError(t, err) + } + _, err := newLayout(badLayoutName, nil, nil, nil) + require.ErrorIs(t, err, errInvalidLayoutName) +} diff --git a/beacon-chain/db/filesystem/cache.go b/beacon-chain/db/filesystem/cache.go index 46d1f694c8f9..8ccf0c787dbe 100644 --- a/beacon-chain/db/filesystem/cache.go +++ b/beacon-chain/db/filesystem/cache.go @@ -1,26 +1,27 @@ package filesystem import ( + "fmt" "sync" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) // blobIndexMask is a bitmask representing the set of blob indices that are currently set. -type blobIndexMask [fieldparams.MaxBlobsPerBlock]bool +type blobIndexMask []bool // BlobStorageSummary represents cached information about the BlobSidecars on disk for each root the cache knows about. type BlobStorageSummary struct { - slot primitives.Slot - mask blobIndexMask + epoch primitives.Epoch + mask blobIndexMask } // HasIndex returns true if the BlobSidecar at the given index is available in the filesystem. func (s BlobStorageSummary) HasIndex(idx uint64) bool { - // Protect from panic, but assume callers are sophisticated enough to not need an error telling them they have an invalid idx. - if idx >= fieldparams.MaxBlobsPerBlock { + if idx >= uint64(len(s.mask)) { return false } return s.mask[idx] @@ -28,7 +29,7 @@ func (s BlobStorageSummary) HasIndex(idx uint64) bool { // AllAvailable returns true if we have all blobs for all indices from 0 to count-1. func (s BlobStorageSummary) AllAvailable(count int) bool { - if count > fieldparams.MaxBlobsPerBlock { + if count > len(s.mask) { return false } for i := 0; i < count; i++ { @@ -39,80 +40,122 @@ func (s BlobStorageSummary) AllAvailable(count int) bool { return true } +func (s BlobStorageSummary) MaxBlobsForEpoch() uint64 { + return uint64(params.BeaconConfig().MaxBlobsPerBlockAtEpoch(s.epoch)) +} + +// NewBlobStorageSummary creates a new BlobStorageSummary for a given epoch and mask. +func NewBlobStorageSummary(epoch primitives.Epoch, mask []bool) (BlobStorageSummary, error) { + c := params.BeaconConfig().MaxBlobsPerBlockAtEpoch(epoch) + if len(mask) != c { + return BlobStorageSummary{}, fmt.Errorf("mask length %d does not match expected %d for epoch %d", len(mask), c, epoch) + } + return BlobStorageSummary{ + epoch: epoch, + mask: mask, + }, nil +} + // BlobStorageSummarizer can be used to receive a summary of metadata about blobs on disk for a given root. // The BlobStorageSummary can be used to check which indices (if any) are available for a given block by root. type BlobStorageSummarizer interface { Summary(root [32]byte) BlobStorageSummary } -type blobStorageCache struct { +type blobStorageSummaryCache struct { mu sync.RWMutex nBlobs float64 cache map[[32]byte]BlobStorageSummary } -var _ BlobStorageSummarizer = &blobStorageCache{} +var _ BlobStorageSummarizer = &blobStorageSummaryCache{} -func newBlobStorageCache() *blobStorageCache { - return &blobStorageCache{ - cache: make(map[[32]byte]BlobStorageSummary, params.BeaconConfig().MinEpochsForBlobsSidecarsRequest*fieldparams.SlotsPerEpoch), +func newBlobStorageCache() *blobStorageSummaryCache { + return &blobStorageSummaryCache{ + cache: make(map[[32]byte]BlobStorageSummary), } } // Summary returns the BlobStorageSummary for `root`. The BlobStorageSummary can be used to check for the presence of // BlobSidecars based on Index. -func (s *blobStorageCache) Summary(root [32]byte) BlobStorageSummary { +func (s *blobStorageSummaryCache) Summary(root [32]byte) BlobStorageSummary { s.mu.RLock() defer s.mu.RUnlock() return s.cache[root] } -func (s *blobStorageCache) ensure(key [32]byte, slot primitives.Slot, idx uint64) error { - if idx >= fieldparams.MaxBlobsPerBlock { +func (s *blobStorageSummaryCache) ensure(ident blobIdent) error { + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlockAtEpoch(ident.epoch) + if ident.index >= uint64(maxBlobsPerBlock) { return errIndexOutOfBounds } s.mu.Lock() defer s.mu.Unlock() - v := s.cache[key] - v.slot = slot - if !v.mask[idx] { + v := s.cache[ident.root] + v.epoch = ident.epoch + if v.mask == nil { + v.mask = make(blobIndexMask, maxBlobsPerBlock) + } + if !v.mask[ident.index] { s.updateMetrics(1) } - v.mask[idx] = true - s.cache[key] = v + v.mask[ident.index] = true + s.cache[ident.root] = v return nil } -func (s *blobStorageCache) slot(key [32]byte) (primitives.Slot, bool) { +func (s *blobStorageSummaryCache) get(key [32]byte) (BlobStorageSummary, bool) { s.mu.RLock() defer s.mu.RUnlock() v, ok := s.cache[key] + return v, ok +} + +func (s *blobStorageSummaryCache) identForIdx(key [32]byte, idx uint64) (blobIdent, error) { + v, ok := s.get(key) + if !ok || !v.HasIndex(idx) { + return blobIdent{}, db.ErrNotFound + } + return blobIdent{ + root: key, + index: idx, + epoch: v.epoch, + }, nil +} + +func (s *blobStorageSummaryCache) identForRoot(key [32]byte) (blobIdent, error) { + v, ok := s.get(key) if !ok { - return 0, false + return blobIdent{}, db.ErrNotFound } - return v.slot, ok + return blobIdent{ + root: key, + epoch: v.epoch, + }, nil } -func (s *blobStorageCache) evict(key [32]byte) { - var deleted float64 +func (s *blobStorageSummaryCache) evict(key [32]byte) int { + deleted := 0 s.mu.Lock() + defer s.mu.Unlock() v, ok := s.cache[key] - if ok { - for i := range v.mask { - if v.mask[i] { - deleted += 1 - } + if !ok { + return 0 + } + for i := range v.mask { + if v.mask[i] { + deleted += 1 } } delete(s.cache, key) - s.mu.Unlock() if deleted > 0 { - s.updateMetrics(-deleted) + s.updateMetrics(-float64(deleted)) } + return deleted } -func (s *blobStorageCache) updateMetrics(delta float64) { +func (s *blobStorageSummaryCache) updateMetrics(delta float64) { s.nBlobs += delta blobDiskCount.Set(s.nBlobs) - blobDiskSize.Set(s.nBlobs * bytesPerSidecar) + blobDiskSize.Set(s.nBlobs * fieldparams.BlobSidecarSize) } diff --git a/beacon-chain/db/filesystem/cache_test.go b/beacon-chain/db/filesystem/cache_test.go index 76c8d783a1d4..24bbf5ce4976 100644 --- a/beacon-chain/db/filesystem/cache_test.go +++ b/beacon-chain/db/filesystem/cache_test.go @@ -3,13 +3,17 @@ package filesystem import ( "testing" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/testing/require" ) func TestSlotByRoot_Summary(t *testing.T) { - var noneSet, allSet, firstSet, lastSet, oneSet blobIndexMask + noneSet := make([]bool, params.BeaconConfig().MaxBlobsPerBlock(0)) + allSet := make([]bool, params.BeaconConfig().MaxBlobsPerBlock(0)) + firstSet := make([]bool, params.BeaconConfig().MaxBlobsPerBlock(0)) + lastSet := make([]bool, params.BeaconConfig().MaxBlobsPerBlock(0)) + oneSet := make([]bool, params.BeaconConfig().MaxBlobsPerBlock(0)) firstSet[0] = true lastSet[len(lastSet)-1] = true oneSet[1] = true @@ -19,49 +23,49 @@ func TestSlotByRoot_Summary(t *testing.T) { cases := []struct { name string root [32]byte - expected *blobIndexMask + expected blobIndexMask }{ { name: "not found", }, { name: "none set", - expected: &noneSet, + expected: noneSet, }, { name: "index 1 set", - expected: &oneSet, + expected: oneSet, }, { name: "all set", - expected: &allSet, + expected: allSet, }, { name: "first set", - expected: &firstSet, + expected: firstSet, }, { name: "last set", - expected: &lastSet, + expected: lastSet, }, } sc := newBlobStorageCache() for _, c := range cases { if c.expected != nil { key := bytesutil.ToBytes32([]byte(c.name)) - sc.cache[key] = BlobStorageSummary{slot: 0, mask: *c.expected} + sc.cache[key] = BlobStorageSummary{epoch: 0, mask: c.expected} } } for _, c := range cases { t.Run(c.name, func(t *testing.T) { key := bytesutil.ToBytes32([]byte(c.name)) sum := sc.Summary(key) - for i := range c.expected { + for i, has := range c.expected { ui := uint64(i) if c.expected == nil { require.Equal(t, false, sum.HasIndex(ui)) } else { - require.Equal(t, c.expected[i], sum.HasIndex(ui)) + require.Equal(t, has, sum.HasIndex(ui)) } } }) @@ -121,13 +125,13 @@ func TestAllAvailable(t *testing.T) { }, { name: "out of bound is safe", - count: fieldparams.MaxBlobsPerBlock + 1, + count: params.BeaconConfig().MaxBlobsPerBlock(0) + 1, aa: false, }, { name: "max present", - count: fieldparams.MaxBlobsPerBlock, - idxSet: idxUpTo(fieldparams.MaxBlobsPerBlock), + count: params.BeaconConfig().MaxBlobsPerBlock(0), + idxSet: idxUpTo(params.BeaconConfig().MaxBlobsPerBlock(0)), aa: true, }, { @@ -139,7 +143,7 @@ func TestAllAvailable(t *testing.T) { } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - var mask blobIndexMask + mask := make([]bool, params.BeaconConfig().MaxBlobsPerBlock(0)) for _, idx := range c.idxSet { mask[idx] = true } diff --git a/beacon-chain/db/filesystem/iteration.go b/beacon-chain/db/filesystem/iteration.go new file mode 100644 index 000000000000..bd2e8d2f1b10 --- /dev/null +++ b/beacon-chain/db/filesystem/iteration.go @@ -0,0 +1,237 @@ +package filesystem + +import ( + "fmt" + "io" + "path/filepath" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/sirupsen/logrus" + "github.com/spf13/afero" +) + +var errIdentFailure = errors.New("failed to determine blob metadata, ignoring all sub-paths.") + +type identificationError struct { + err error + path string + ident blobIdent +} + +func (ide *identificationError) Error() string { + return fmt.Sprintf("%s path=%s, err=%s", errIdentFailure.Error(), ide.path, ide.err.Error()) +} + +func (ide *identificationError) Unwrap() error { + return ide.err +} + +func (*identificationError) Is(err error) bool { + return err == errIdentFailure +} + +func (ide *identificationError) LogFields() logrus.Fields { + fields := ide.ident.logFields() + fields["path"] = ide.path + return fields +} + +func newIdentificationError(path string, ident blobIdent, err error) *identificationError { + return &identificationError{path: path, ident: ident, err: err} +} + +func listDir(fs afero.Fs, dir string) ([]string, error) { + top, err := fs.Open(dir) + if err != nil { + return nil, errors.Wrap(err, "failed to open directory descriptor") + } + defer func() { + if err := top.Close(); err != nil { + log.WithError(err).Errorf("Could not close file %s", dir) + } + }() + // re the -1 param: "If n <= 0, Readdirnames returns all the names from the directory in a single slice" + dirs, err := top.Readdirnames(-1) + if err != nil { + return nil, errors.Wrap(err, "failed to read directory listing") + } + return dirs, nil +} + +// identPopulator is a function that sets values in the blobIdent for a given layer of the filesystem layout. +type identPopulator func(blobIdent, string) (blobIdent, error) + +// layoutLayer represents a layer of the nested directory scheme. Each layer is defined by a filter function that +// ensures any entries at that layer of the scheme are named in a valid way, and a populateIdent function that +// parses the directory name into a blobIdent object, used for iterating across the layout in a layout-independent way. +type layoutLayer struct { + populateIdent identPopulator + filter func(string) bool +} + +// identIterator moves through the filesystem in order to yield blobIdents. +// layoutLayers (in the 'layers' field) allows a filesystem layout to control how the +// layout is traversed. A layoutLayer can filter out entries from the directory listing +// via the filter function, and populate fields in the blobIdent via the populateIdent function. +// The blobIdent is populated from an empty value at the root, accumulating values for its fields at each layer. +// The fully populated blobIdent is returned when the iterator reaches the leaf layer. +type identIterator struct { + fs afero.Fs + path string + child *identIterator + ident blobIdent + // layoutLayers are the heart of how the layout defines the nesting of the components of the path. + // Each layer of the layout represents a different layer of the directory layout hierarchy, + // from the relative root at the zero index to the blob files at the end. + layers []layoutLayer + entries []string + offset int + eof bool +} + +// atEOF can be used to peek at the iterator to see if it's already finished. This is useful for the migration code to check +// if there are any entries in the directory indicated by the migration. +func (iter *identIterator) atEOF() bool { + return iter.eof +} + +// next is the only method that a user of the identIterator needs to call. +// identIterator will yield blobIdents in a breadth-first fashion, +// returning an empty blobIdent and io.EOF once all branches have been traversed. +func (iter *identIterator) next() (blobIdent, error) { + if iter.eof { + return blobIdent{}, io.EOF + } + if iter.child != nil { + next, err := iter.child.next() + if err == nil { + return next, nil + } + if !errors.Is(err, io.EOF) { + return blobIdent{}, err + } + } + return iter.advanceChild() +} + +// advanceChild is used to move to the next directory at each layer of the tree, either when +// the nodes are first being initialized at a layer, or when a sub-branch has been exhausted. +func (iter *identIterator) advanceChild() (blobIdent, error) { + defer func() { + iter.offset += 1 + }() + for i := iter.offset; i < len(iter.entries); i++ { + iter.offset = i + nextPath := filepath.Join(iter.path, iter.entries[iter.offset]) + nextLayer := iter.layers[0] + if !nextLayer.filter(nextPath) { + continue + } + ident, err := nextLayer.populateIdent(iter.ident, nextPath) + if err != nil { + return ident, newIdentificationError(nextPath, ident, err) + } + // if we're at the leaf layer , we can return the updated ident. + if len(iter.layers) == 1 { + return ident, nil + } + + entries, err := listDir(iter.fs, nextPath) + if err != nil { + return blobIdent{}, err + } + if len(entries) == 0 { + continue + } + iter.child = &identIterator{ + fs: iter.fs, + path: nextPath, + ident: ident, + layers: iter.layers[1:], + entries: entries, + } + return iter.child.next() + } + + return blobIdent{}, io.EOF +} + +func populateNoop(namer blobIdent, _ string) (blobIdent, error) { + return namer, nil +} + +func populateRoot(namer blobIdent, dir string) (blobIdent, error) { + root, err := rootFromPath(dir) + if err != nil { + return namer, err + } + namer.root = root + return namer, nil +} + +func populateIndex(namer blobIdent, fname string) (blobIdent, error) { + idx, err := idxFromPath(fname) + if err != nil { + return namer, err + } + namer.index = idx + return namer, nil +} + +func rootFromPath(p string) ([32]byte, error) { + subdir := filepath.Base(p) + root, err := stringToRoot(subdir) + if err != nil { + return root, errors.Wrapf(err, "invalid directory, could not parse subdir as root %s", p) + } + return root, nil +} + +func idxFromPath(p string) (uint64, error) { + p = filepath.Base(p) + + if !isSszFile(p) { + return 0, errors.Wrap(errNotBlobSSZ, "does not have .ssz extension") + } + parts := strings.Split(p, ".") + if len(parts) != 2 { + return 0, errors.Wrap(errNotBlobSSZ, "unexpected filename structure (want .ssz)") + } + idx, err := strconv.ParseUint(parts[0], 10, 64) + if err != nil { + return 0, err + } + return idx, nil +} + +func filterNoop(_ string) bool { + return true +} + +func isRootDir(p string) bool { + dir := filepath.Base(p) + return len(dir) == rootStringLen && strings.HasPrefix(dir, "0x") +} + +func isSszFile(s string) bool { + return filepath.Ext(s) == "."+sszExt +} + +func rootToString(root [32]byte) string { + return fmt.Sprintf("%#x", root) +} + +func stringToRoot(str string) ([32]byte, error) { + if len(str) != rootStringLen { + return [32]byte{}, errors.Wrapf(errInvalidRootString, "incorrect len for input=%s", str) + } + slice, err := hexutil.Decode(str) + if err != nil { + return [32]byte{}, errors.Wrapf(errInvalidRootString, "input=%s", str) + } + return bytesutil.ToBytes32(slice), nil +} diff --git a/beacon-chain/db/filesystem/iteration_test.go b/beacon-chain/db/filesystem/iteration_test.go new file mode 100644 index 000000000000..06e21a83860e --- /dev/null +++ b/beacon-chain/db/filesystem/iteration_test.go @@ -0,0 +1,304 @@ +package filesystem + +import ( + "bytes" + "fmt" + "io" + "math" + "os" + "path" + "sort" + "testing" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/spf13/afero" +) + +func TestRootFromDir(t *testing.T) { + cases := []struct { + name string + dir string + err error + root [32]byte + }{ + { + name: "happy path", + dir: "0xffff875e1d985c5ccb214894983f2428edb271f0f87b68ba7010e4a99df3b5cb", + root: [32]byte{255, 255, 135, 94, 29, 152, 92, 92, 203, 33, 72, 148, 152, 63, 36, 40, + 237, 178, 113, 240, 248, 123, 104, 186, 112, 16, 228, 169, 157, 243, 181, 203}, + }, + { + name: "too short", + dir: "0xffff875e1d985c5ccb214894983f2428edb271f0f87b68ba7010e4a99df3b5c", + err: errInvalidRootString, + }, + { + name: "too log", + dir: "0xffff875e1d985c5ccb214894983f2428edb271f0f87b68ba7010e4a99df3b5cbb", + err: errInvalidRootString, + }, + { + name: "missing prefix", + dir: "ffff875e1d985c5ccb214894983f2428edb271f0f87b68ba7010e4a99df3b5cb", + err: errInvalidRootString, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + root, err := stringToRoot(c.dir) + if c.err != nil { + require.ErrorIs(t, err, c.err) + return + } + require.NoError(t, err) + require.Equal(t, c.root, root) + }) + } +} + +func TestSlotFromFile(t *testing.T) { + cases := []struct { + slot primitives.Slot + }{ + {slot: 0}, + {slot: 2}, + {slot: 1123581321}, + {slot: math.MaxUint64}, + } + for _, c := range cases { + t.Run(fmt.Sprintf("slot %d", c.slot), func(t *testing.T) { + fs, bs := NewEphemeralBlobStorageAndFs(t) + _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, c.slot, 1) + sc := verification.FakeVerifyForTest(t, sidecars[0]) + require.NoError(t, bs.Save(sc)) + namer := identForSidecar(sc) + sszPath := bs.layout.sszPath(namer) + slot, err := slotFromFile(sszPath, fs) + require.NoError(t, err) + require.Equal(t, c.slot, slot) + }) + } +} + +type dirFiles struct { + name string + isDir bool + children []dirFiles +} + +func (df dirFiles) reify(t *testing.T, fs afero.Fs, base string) { + fullPath := path.Join(base, df.name) + if df.isDir { + if df.name != "" { + require.NoError(t, fs.Mkdir(fullPath, directoryPermissions())) + } + for _, c := range df.children { + c.reify(t, fs, fullPath) + } + } else { + fp, err := fs.Create(fullPath) + require.NoError(t, err) + _, err = fp.WriteString("derp") + require.NoError(t, err) + } +} + +func (df dirFiles) childNames() []string { + cn := make([]string, len(df.children)) + for i := range df.children { + cn[i] = df.children[i].name + } + return cn +} + +func TestListDir(t *testing.T) { + fs := afero.NewMemMapFs() + rootStrs := []string{ + "0x0023dc5d063c7c1b37016bb54963c6ff4bfe5dfdf6dac29e7ceeb2b8fa81ed7a", + "0xff30526cd634a5af3a09cc9bff67f33a621fc5b975750bb4432f74df077554b4", + "0x23f5f795aaeb78c01fadaf3d06da2e99bd4b3622ae4dfea61b05b7d9adb119c2", + } + + // parent directory + tree := dirFiles{isDir: true} + // break out each subdir for easier assertions + notABlob := dirFiles{name: "notABlob", isDir: true} + childlessBlob := dirFiles{name: rootStrs[0], isDir: true} + blobWithSsz := dirFiles{name: rootStrs[1], isDir: true, + children: []dirFiles{{name: "1.ssz"}, {name: "2.ssz"}}, + } + blobWithSszAndTmp := dirFiles{name: rootStrs[2], isDir: true, + children: []dirFiles{{name: "5.ssz"}, {name: "0.part"}}} + tree.children = append(tree.children, + notABlob, childlessBlob, blobWithSsz, blobWithSszAndTmp) + + topChildren := make([]string, len(tree.children)) + for i := range tree.children { + topChildren[i] = tree.children[i].name + } + + var filter = func(entries []string, filt func(string) bool) []string { + filtered := make([]string, 0, len(entries)) + for i := range entries { + if filt(entries[i]) { + filtered = append(filtered, entries[i]) + } + } + return filtered + } + + tree.reify(t, fs, "") + cases := []struct { + name string + dirPath string + expected []string + filter func(string) bool + err error + }{ + { + name: "non-existent", + dirPath: "derp", + expected: []string{}, + err: os.ErrNotExist, + }, + { + name: "empty", + dirPath: childlessBlob.name, + expected: []string{}, + }, + { + name: "top", + dirPath: ".", + expected: topChildren, + }, + { + name: "custom filter: only notABlob", + dirPath: ".", + expected: []string{notABlob.name}, + filter: func(s string) bool { + return s == notABlob.name + }, + }, + { + name: "root filter", + dirPath: ".", + expected: []string{childlessBlob.name, blobWithSsz.name, blobWithSszAndTmp.name}, + filter: isRootDir, + }, + { + name: "ssz filter", + dirPath: blobWithSsz.name, + expected: blobWithSsz.childNames(), + filter: isSszFile, + }, + { + name: "ssz mixed filter", + dirPath: blobWithSszAndTmp.name, + expected: []string{"5.ssz"}, + filter: isSszFile, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + result, err := listDir(fs, c.dirPath) + if c.filter != nil { + result = filter(result, c.filter) + } + if c.err != nil { + require.ErrorIs(t, err, c.err) + require.Equal(t, 0, len(result)) + } else { + require.NoError(t, err) + sort.Strings(c.expected) + sort.Strings(result) + require.DeepEqual(t, c.expected, result) + } + }) + } +} + +func TestSlotFromBlob(t *testing.T) { + cases := []struct { + slot primitives.Slot + }{ + {slot: 0}, + {slot: 2}, + {slot: 1123581321}, + {slot: math.MaxUint64}, + } + for _, c := range cases { + t.Run(fmt.Sprintf("slot %d", c.slot), func(t *testing.T) { + _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, c.slot, 1) + sc := sidecars[0] + enc, err := sc.MarshalSSZ() + require.NoError(t, err) + slot, err := slotFromBlob(bytes.NewReader(enc)) + require.NoError(t, err) + require.Equal(t, c.slot, slot) + }) + } +} + +func TestIterationComplete(t *testing.T) { + targets := []migrationTestTarget{ + { + ident: ezIdent(t, "0x0125e54c64c925018c9296965a5b622d9f5ab626c10917860dcfb6aa09a0a00b", 1234, 0), + path: "by-epoch/0/1234/0x0125e54c64c925018c9296965a5b622d9f5ab626c10917860dcfb6aa09a0a00b/0.ssz", + }, + { + ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", 5330, 0), + slotOffset: 31, + path: "by-epoch/1/5330/0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86/0.ssz", + }, + { + ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", 5330, 1), + slotOffset: 31, + path: "by-epoch/1/5330/0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86/1.ssz", + }, + { + ident: ezIdent(t, "0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c", 16777216, 0), + slotOffset: 16, + path: "by-epoch/4096/16777216/0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c/0.ssz", + }, + { + ident: ezIdent(t, "0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c", 16777216, 1), + slotOffset: 16, + path: "by-epoch/4096/16777216/0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c/1.ssz", + }, + { + ident: ezIdent(t, "0x42eabe3d2c125410cd226de6f2825fb7575ab896c3f52e43de1fa29e4c809aba", 16777217, 0), + slotOffset: 16, + path: "by-epoch/4096/16777217/0x42eabe3d2c125410cd226de6f2825fb7575ab896c3f52e43de1fa29e4c809aba/0.ssz", + }, + { + ident: ezIdent(t, "0x666cea5034e22bd3b849cb33914cad59afd88ee08e4d5bc0e997411c945fbc1d", 11235, 1), + path: "by-epoch/2/11235/0x666cea5034e22bd3b849cb33914cad59afd88ee08e4d5bc0e997411c945fbc1d/1.ssz", + }, + } + fs := afero.NewMemMapFs() + cache := newBlobStorageCache() + byEpoch, err := newLayout(LayoutNameByEpoch, fs, cache, nil) + require.NoError(t, err) + for _, tar := range targets { + setupTestBlobFile(t, tar.ident, tar.slotOffset, fs, byEpoch) + } + iter, err := byEpoch.iterateIdents(0) + require.NoError(t, err) + nIdents := 0 + for ident, err := iter.next(); err != io.EOF; ident, err = iter.next() { + require.NoError(t, err) + nIdents++ + require.NoError(t, cache.ensure(ident)) + } + require.Equal(t, len(targets), nIdents) + for _, tar := range targets { + entry, ok := cache.get(tar.ident.root) + require.Equal(t, true, ok) + require.Equal(t, tar.ident.epoch, entry.epoch) + require.Equal(t, true, entry.HasIndex(tar.ident.index)) + require.Equal(t, tar.path, byEpoch.sszPath(tar.ident)) + } +} diff --git a/beacon-chain/db/filesystem/layout.go b/beacon-chain/db/filesystem/layout.go new file mode 100644 index 000000000000..9e1abe3ecf8c --- /dev/null +++ b/beacon-chain/db/filesystem/layout.go @@ -0,0 +1,291 @@ +package filesystem + +import ( + "fmt" + "io" + "path/filepath" + "strings" + "time" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/time/slots" + "github.com/sirupsen/logrus" + "github.com/spf13/afero" +) + +const ( + // Full root in directory will be 66 chars, eg: + // >>> len('0x0002fb4db510b8618b04dc82d023793739c26346a8b02eb73482e24b0fec0555') == 66 + rootStringLen = 66 + sszExt = "ssz" + partExt = "part" + periodicEpochBaseDir = "by-epoch" +) + +const ( + LayoutNameFlat = "flat" + LayoutNameByEpoch = "by-epoch" +) + +var LayoutNames = []string{LayoutNameFlat, LayoutNameByEpoch} + +var ( + errMigrationFailure = errors.New("unable to migrate blob directory between old and new layout") + errCacheWarmFailed = errors.New("failed to warm blob filesystem cache") + errPruneFailed = errors.New("failed to prune root") + errInvalidRootString = errors.New("Could not parse hex string as a [32]byte") + errInvalidDirectoryLayout = errors.New("Could not parse blob directory path") + errInvalidLayoutName = errors.New("unknown layout name") + errLayoutNotDetected = errors.New("given layout not observed in the blob filesystem tree") +) + +type blobIdent struct { + root [32]byte + epoch primitives.Epoch + index uint64 +} + +func newBlobIdent(root [32]byte, epoch primitives.Epoch, index uint64) blobIdent { + return blobIdent{root: root, epoch: epoch, index: index} +} + +func identForSidecar(sc blocks.VerifiedROBlob) blobIdent { + return newBlobIdent(sc.BlockRoot(), slots.ToEpoch(sc.Slot()), sc.Index) +} + +func (n blobIdent) sszFname() string { + return fmt.Sprintf("%d.%s", n.index, sszExt) +} + +func (n blobIdent) partFname(entropy string) string { + return fmt.Sprintf("%s-%d.%s", entropy, n.index, partExt) +} + +func (n blobIdent) logFields() logrus.Fields { + return logrus.Fields{ + "root": fmt.Sprintf("%#x", n.root), + "epoch": n.epoch, + "index": n.index, + } +} + +type fsLayout interface { + name() string + dir(n blobIdent) string + sszPath(n blobIdent) string + partPath(n blobIdent, entropy string) string + iterateIdents(before primitives.Epoch) (*identIterator, error) + ident(root [32]byte, idx uint64) (blobIdent, error) + dirIdent(root [32]byte) (blobIdent, error) + summary(root [32]byte) BlobStorageSummary + notify(ident blobIdent) error + pruneBefore(before primitives.Epoch) (*pruneSummary, error) + remove(ident blobIdent) (int, error) + blockParentDirs(ident blobIdent) []string +} + +func newLayout(name string, fs afero.Fs, cache *blobStorageSummaryCache, pruner *blobPruner) (fsLayout, error) { + switch name { + case LayoutNameFlat: + return newFlatLayout(fs, cache, pruner), nil + case LayoutNameByEpoch: + return newPeriodicEpochLayout(fs, cache, pruner), nil + default: + return nil, errors.Wrapf(errInvalidLayoutName, "name=%s", name) + } +} + +func warmCache(l fsLayout, cache *blobStorageSummaryCache) error { + iter, err := l.iterateIdents(0) + if err != nil { + return errors.Wrap(errCacheWarmFailed, err.Error()) + } + for ident, err := iter.next(); !errors.Is(err, io.EOF); ident, err = iter.next() { + if errors.Is(err, errIdentFailure) { + idf := &identificationError{} + if errors.As(err, &idf) { + log.WithFields(idf.LogFields()).WithError(err).Error("Failed to cache blob data for path") + } + continue + } + if err != nil { + return fmt.Errorf("%w: failed to populate blob data cache: %w", errCacheWarmFailed, err) + } + if err := cache.ensure(ident); err != nil { + return fmt.Errorf("%w: failed to write cache entry for %s: %w", errCacheWarmFailed, l.sszPath(ident), err) + } + } + return nil +} + +func migrateLayout(fs afero.Fs, from, to fsLayout, cache *blobStorageSummaryCache) error { + start := time.Now() + iter, err := from.iterateIdents(0) + if err != nil { + return errors.Wrapf(errMigrationFailure, "failed to iterate legacy structure while migrating blobs, err=%s", err.Error()) + } + if iter.atEOF() { + return errLayoutNotDetected + } + log.WithField("fromLayout", from.name()).WithField("toLayout", to.name()).Info("Migrating blob filesystem layout. This one-time operation can take extra time (up to a few minutes for systems with extended blob storage and a cold disk cache).") + lastMoved := "" + parentDirs := make(map[string]bool) // this map should have < 65k keys by design + moved := 0 + dc := newDirCleaner() + for ident, err := iter.next(); !errors.Is(err, io.EOF); ident, err = iter.next() { + if err != nil { + if errors.Is(err, errIdentFailure) { + idf := &identificationError{} + if errors.As(err, &idf) { + log.WithFields(idf.LogFields()).WithError(err).Error("Failed to migrate blob path") + } + continue + } + return errors.Wrapf(errMigrationFailure, "failed to iterate previous layout structure while migrating blobs, err=%s", err.Error()) + } + src := from.dir(ident) + target := to.dir(ident) + if src != lastMoved { + targetParent := filepath.Dir(target) + if targetParent != "" && targetParent != "." && !parentDirs[targetParent] { + if err := fs.MkdirAll(targetParent, directoryPermissions()); err != nil { + return errors.Wrapf(errMigrationFailure, "failed to make enclosing path before moving %s to %s", src, target) + } + parentDirs[targetParent] = true + } + if err := fs.Rename(src, target); err != nil { + return errors.Wrapf(errMigrationFailure, "could not rename %s to %s", src, target) + } + moved += 1 + lastMoved = src + for _, dir := range from.blockParentDirs(ident) { + dc.add(dir) + } + } + if err := cache.ensure(ident); err != nil { + return errors.Wrapf(errMigrationFailure, "could not cache path %s, err=%s", to.sszPath(ident), err.Error()) + } + } + dc.clean(fs) + if moved > 0 { + log.WithField("dirsMoved", moved).WithField("elapsed", time.Since(start)). + Info("Blob filesystem migration complete.") + } + return nil +} + +type dirCleaner struct { + maxDepth int + layers map[int]map[string]struct{} +} + +func newDirCleaner() *dirCleaner { + return &dirCleaner{layers: make(map[int]map[string]struct{})} +} + +func (d *dirCleaner) add(dir string) { + nLayers := len(strings.Split(dir, string(filepath.Separator))) + _, ok := d.layers[nLayers] + if !ok { + d.layers[nLayers] = make(map[string]struct{}) + } + d.layers[nLayers][dir] = struct{}{} + if nLayers > d.maxDepth { + d.maxDepth = nLayers + } +} + +func (d *dirCleaner) clean(fs afero.Fs) { + for i := d.maxDepth; i >= 0; i-- { + d.cleanLayer(fs, i) + } +} + +func (d *dirCleaner) cleanLayer(fs afero.Fs, layer int) { + dirs, ok := d.layers[layer] + if !ok { + return + } + for dir := range dirs { + // Use Remove rather than RemoveAll to make sure we're only removing empty directories + if err := fs.Remove(dir); err != nil { + log.WithField("dir", dir).WithError(err).Error("Failed to remove blob directory, please remove it manually if desired.") + contents, err := listDir(fs, dir) + if err != nil { + log.WithField("dir", dir).WithError(err).Error("Could not list blob directory contents to find reason for removal failure.") + continue + } + for _, c := range contents { + log.WithField("file", c).WithField("dir", dir).Debug("Unexpected file blocking migrated blob directory cleanup.") + } + } + } +} + +type pruneSummary struct { + blobsPruned int + failedRemovals []string +} + +func (s pruneSummary) LogFields() logrus.Fields { + return logrus.Fields{ + "blobsPruned": s.blobsPruned, + "failedRemovals": len(s.failedRemovals), + } +} + +func pruneBefore(before primitives.Epoch, l fsLayout) (map[primitives.Epoch]*pruneSummary, error) { + sums := make(map[primitives.Epoch]*pruneSummary) + iter, err := l.iterateIdents(before) + if err != nil { + return nil, errors.Wrap(err, "failed to iterate blob paths for pruning") + } + + // We will get an ident for each index, but want to prune all indexes for the given root together. + var lastIdent blobIdent + for ident, err := iter.next(); !errors.Is(err, io.EOF); ident, err = iter.next() { + if err != nil { + if errors.Is(err, errIdentFailure) { + idf := &identificationError{} + if errors.As(err, &idf) { + log.WithFields(idf.LogFields()).WithError(err).Error("Failed to prune blob path due to identification errors") + } + continue + } + log.WithError(err).Error("encountered unhandled error during pruning") + return nil, errors.Wrap(errPruneFailed, err.Error()) + } + if ident.epoch >= before { + continue + } + if lastIdent.root != ident.root { + pruneOne(lastIdent, l, sums) + lastIdent = ident + } + } + // handle the final ident + pruneOne(lastIdent, l, sums) + + return sums, nil +} + +func pruneOne(ident blobIdent, l fsLayout, sums map[primitives.Epoch]*pruneSummary) { + // Skip pruning the n-1 ident if we're on the first real ident (lastIdent will be zero value). + if ident.root == params.BeaconConfig().ZeroHash { + return + } + _, ok := sums[ident.epoch] + if !ok { + sums[ident.epoch] = &pruneSummary{} + } + s := sums[ident.epoch] + removed, err := l.remove(ident) + if err != nil { + s.failedRemovals = append(s.failedRemovals, l.dir(ident)) + log.WithField("root", fmt.Sprintf("%#x", ident.root)).Error("Failed to delete blob directory for root") + } + s.blobsPruned += removed +} diff --git a/beacon-chain/db/filesystem/layout_by_epoch.go b/beacon-chain/db/filesystem/layout_by_epoch.go new file mode 100644 index 000000000000..efc4c3a8e370 --- /dev/null +++ b/beacon-chain/db/filesystem/layout_by_epoch.go @@ -0,0 +1,212 @@ +package filesystem + +import ( + "fmt" + "os" + "path" + "path/filepath" + "strconv" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/spf13/afero" +) + +const epochsPerDirectory = 4096 + +type periodicEpochLayout struct { + fs afero.Fs + cache *blobStorageSummaryCache + pruner *blobPruner +} + +var _ fsLayout = &periodicEpochLayout{} + +func newPeriodicEpochLayout(fs afero.Fs, cache *blobStorageSummaryCache, pruner *blobPruner) fsLayout { + l := &periodicEpochLayout{fs: fs, cache: cache, pruner: pruner} + return l +} + +func (l *periodicEpochLayout) name() string { + return LayoutNameByEpoch +} + +func (l *periodicEpochLayout) blockParentDirs(ident blobIdent) []string { + return []string{ + periodicEpochBaseDir, + l.periodDir(ident.epoch), + l.epochDir(ident.epoch), + } +} + +func (l *periodicEpochLayout) notify(ident blobIdent) error { + if err := l.cache.ensure(ident); err != nil { + return err + } + l.pruner.notify(ident.epoch, l) + return nil +} + +// If before == 0, it won't be used as a filter and all idents will be returned. +func (l *periodicEpochLayout) iterateIdents(before primitives.Epoch) (*identIterator, error) { + _, err := l.fs.Stat(periodicEpochBaseDir) + if err != nil { + if os.IsNotExist(err) { + return &identIterator{eof: true}, nil // The directory is non-existent, which is fine; stop iteration. + } + return nil, errors.Wrapf(err, "error reading path %s", periodicEpochBaseDir) + } + // iterate root, which should have directories named by "period" + entries, err := listDir(l.fs, periodicEpochBaseDir) + if err != nil { + return nil, errors.Wrapf(err, "failed to list %s", periodicEpochBaseDir) + } + + return &identIterator{ + fs: l.fs, + path: periodicEpochBaseDir, + // Please see comments on the `layers` field in `identIterator`` if the role of the layers is unclear. + layers: []layoutLayer{ + {populateIdent: populateNoop, filter: isBeforePeriod(before)}, + {populateIdent: populateEpoch, filter: isBeforeEpoch(before)}, + {populateIdent: populateRoot, filter: isRootDir}, // extract root from path + {populateIdent: populateIndex, filter: isSszFile}, // extract index from filename + }, + entries: entries, + }, nil +} + +func (l *periodicEpochLayout) ident(root [32]byte, idx uint64) (blobIdent, error) { + return l.cache.identForIdx(root, idx) +} + +func (l *periodicEpochLayout) dirIdent(root [32]byte) (blobIdent, error) { + return l.cache.identForRoot(root) +} + +func (l *periodicEpochLayout) summary(root [32]byte) BlobStorageSummary { + return l.cache.Summary(root) +} + +func (l *periodicEpochLayout) dir(n blobIdent) string { + return filepath.Join(l.epochDir(n.epoch), rootToString(n.root)) +} + +func (l *periodicEpochLayout) epochDir(epoch primitives.Epoch) string { + return filepath.Join(l.periodDir(epoch), fmt.Sprintf("%d", epoch)) +} + +func (l *periodicEpochLayout) periodDir(epoch primitives.Epoch) string { + return filepath.Join(periodicEpochBaseDir, fmt.Sprintf("%d", periodForEpoch(epoch))) +} + +func (l *periodicEpochLayout) sszPath(n blobIdent) string { + return filepath.Join(l.dir(n), n.sszFname()) +} + +func (l *periodicEpochLayout) partPath(n blobIdent, entropy string) string { + return path.Join(l.dir(n), n.partFname(entropy)) +} + +func (l *periodicEpochLayout) pruneBefore(before primitives.Epoch) (*pruneSummary, error) { + sums, err := pruneBefore(before, l) + if err != nil { + return nil, err + } + // Roll up summaries and clean up per-epoch directories. + rollup := &pruneSummary{} + for epoch, sum := range sums { + rollup.blobsPruned += sum.blobsPruned + rollup.failedRemovals = append(rollup.failedRemovals, sum.failedRemovals...) + rmdir := l.epochDir(epoch) + if len(sum.failedRemovals) == 0 { + if err := l.fs.Remove(rmdir); err != nil { + log.WithField("dir", rmdir).WithError(err).Error("Failed to remove epoch directory while pruning") + } + } else { + log.WithField("dir", rmdir).WithField("numFailed", len(sum.failedRemovals)).WithError(err).Error("Unable to remove epoch directory due to pruning failures") + } + } + + return rollup, nil +} + +func (l *periodicEpochLayout) remove(ident blobIdent) (int, error) { + removed := l.cache.evict(ident.root) + // Skip the syscall if there are no blobs to remove. + if removed == 0 { + return 0, nil + } + if err := l.fs.RemoveAll(l.dir(ident)); err != nil { + return removed, err + } + return removed, nil +} + +func periodForEpoch(epoch primitives.Epoch) primitives.Epoch { + return epoch / params.BeaconConfig().MinEpochsForBlobsSidecarsRequest +} + +// Funcs below this line are iteration support methods that are specific to the epoch layout. + +func isBeforePeriod(before primitives.Epoch) func(string) bool { + if before == 0 { + return filterNoop + } + beforePeriod := periodForEpoch(before) + if before%epochsPerDirectory != 0 { + // Add one because we need to include the period the epoch is in, unless it is the first epoch in the period, + // in which case we can just look at any previous period. + beforePeriod += 1 + } + return func(p string) bool { + period, err := periodFromPath(p) + if err != nil { + return false + } + return primitives.Epoch(period) < beforePeriod + } +} + +func isBeforeEpoch(before primitives.Epoch) func(string) bool { + if before == 0 { + return filterNoop + } + return func(p string) bool { + epoch, err := epochFromPath(p) + if err != nil { + return false + } + return epoch < before + } +} + +func epochFromPath(p string) (primitives.Epoch, error) { + subdir := filepath.Base(p) + epoch, err := strconv.ParseUint(subdir, 10, 64) + if err != nil { + return 0, errors.Wrapf(errInvalidDirectoryLayout, + "failed to decode epoch as uint, err=%s, dir=%s", err.Error(), p) + } + return primitives.Epoch(epoch), nil +} + +func periodFromPath(p string) (uint64, error) { + subdir := filepath.Base(p) + period, err := strconv.ParseUint(subdir, 10, 64) + if err != nil { + return 0, errors.Wrapf(errInvalidDirectoryLayout, + "failed to decode period from path as uint, err=%s, dir=%s", err.Error(), p) + } + return period, nil +} + +func populateEpoch(namer blobIdent, dir string) (blobIdent, error) { + epoch, err := epochFromPath(dir) + if err != nil { + return namer, err + } + namer.epoch = epoch + return namer, nil +} diff --git a/beacon-chain/db/filesystem/layout_flat.go b/beacon-chain/db/filesystem/layout_flat.go new file mode 100644 index 000000000000..37501d3305a7 --- /dev/null +++ b/beacon-chain/db/filesystem/layout_flat.go @@ -0,0 +1,219 @@ +package filesystem + +import ( + "encoding/binary" + "io" + "os" + "path" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/time/slots" + "github.com/spf13/afero" +) + +type flatLayout struct { + fs afero.Fs + cache *blobStorageSummaryCache + pruner *blobPruner +} + +var _ fsLayout = &flatLayout{} + +func newFlatLayout(fs afero.Fs, cache *blobStorageSummaryCache, pruner *blobPruner) fsLayout { + l := &flatLayout{fs: fs, cache: cache, pruner: pruner} + return l +} + +func (l *flatLayout) iterateIdents(before primitives.Epoch) (*identIterator, error) { + if _, err := l.fs.Stat("."); err != nil { + if os.IsNotExist(err) { + return &identIterator{eof: true}, nil // The directory is non-existent, which is fine; stop iteration. + } + return nil, errors.Wrapf(err, "error reading path %s", periodicEpochBaseDir) + } + entries, err := listDir(l.fs, ".") + if err != nil { + return nil, errors.Wrapf(err, "could not list root directory") + } + slotAndIndex := &flatSlotReader{fs: l.fs, cache: l.cache, before: before} + return &identIterator{ + fs: l.fs, + // Please see comments on the `layers` field in `identIterator`` if the role of the layers is unclear. + layers: []layoutLayer{ + {populateIdent: populateRoot, filter: isFlatCachedAndBefore(l.cache, before)}, + {populateIdent: slotAndIndex.populateEpoch, filter: slotAndIndex.isSSZAndBefore}}, + entries: entries, + }, nil +} + +func (*flatLayout) name() string { + return LayoutNameFlat +} + +func (l *flatLayout) blockParentDirs(ident blobIdent) []string { + return []string{} +} + +func (*flatLayout) dir(n blobIdent) string { + return rootToString(n.root) +} + +func (l *flatLayout) sszPath(n blobIdent) string { + return path.Join(l.dir(n), n.sszFname()) +} + +func (l *flatLayout) partPath(n blobIdent, entropy string) string { + return path.Join(l.dir(n), n.partFname(entropy)) +} + +func (l *flatLayout) ident(root [32]byte, idx uint64) (blobIdent, error) { + return l.cache.identForIdx(root, idx) +} + +func (l *flatLayout) dirIdent(root [32]byte) (blobIdent, error) { + return l.cache.identForRoot(root) +} + +func (l *flatLayout) summary(root [32]byte) BlobStorageSummary { + return l.cache.Summary(root) +} + +func (l *flatLayout) remove(ident blobIdent) (int, error) { + removed := l.cache.evict(ident.root) + if err := l.fs.RemoveAll(l.dir(ident)); err != nil { + return removed, err + } + return removed, nil +} + +func (l *flatLayout) notify(ident blobIdent) error { + if err := l.cache.ensure(ident); err != nil { + return err + } + l.pruner.notify(ident.epoch, l) + return nil +} + +func (l *flatLayout) pruneBefore(before primitives.Epoch) (*pruneSummary, error) { + sums, err := pruneBefore(before, l) + if err != nil { + return nil, err + } + + // Roll up summaries and clean up per-epoch directories. + rollup := &pruneSummary{} + for _, sum := range sums { + rollup.blobsPruned += sum.blobsPruned + rollup.failedRemovals = append(rollup.failedRemovals, sum.failedRemovals...) + } + + return rollup, nil +} + +// Below this line are iteration support funcs and types that are specific to the flat layout. + +// Read slot from marshaled BlobSidecar data in the given file. See slotFromBlob for details. +func slotFromFile(name string, fs afero.Fs) (primitives.Slot, error) { + f, err := fs.Open(name) + if err != nil { + return 0, err + } + defer func() { + if err := f.Close(); err != nil { + log.WithError(err).Errorf("Could not close blob file") + } + }() + return slotFromBlob(f) +} + +// slotFromBlob reads the ssz data of a file at the specified offset (8 + 131072 + 48 + 48 = 131176 bytes), +// which is calculated based on the size of the BlobSidecar struct and is based on the size of the fields +// preceding the slot information within SignedBeaconBlockHeader. +func slotFromBlob(at io.ReaderAt) (primitives.Slot, error) { + b := make([]byte, 8) + _, err := at.ReadAt(b, 131176) + if err != nil { + return 0, err + } + rawSlot := binary.LittleEndian.Uint64(b) + return primitives.Slot(rawSlot), nil +} + +type flatSlotReader struct { + before primitives.Epoch + fs afero.Fs + cache *blobStorageSummaryCache +} + +func (l *flatSlotReader) populateEpoch(ident blobIdent, fname string) (blobIdent, error) { + ident, err := populateIndex(ident, fname) + if err != nil { + return ident, err + } + sum, ok := l.cache.get(ident.root) + if ok { + ident.epoch = sum.epoch + // Return early if the index is already known to the cache. + if sum.HasIndex(ident.index) { + return ident, nil + } + } else { + // If the root is not in the cache, we need to read the slot from the file. + slot, err := slotFromFile(fname, l.fs) + if err != nil { + return ident, err + } + ident.epoch = slots.ToEpoch(slot) + } + return ident, l.cache.ensure(ident) +} + +func (l *flatSlotReader) isSSZAndBefore(fname string) bool { + if !isSszFile(fname) { + return false + } + // If 'before' != 0, assuming isSSZAndBefore is used as a filter on the same layer with populateEpoch, this will typically + // call populateEpoch before the iteration code calls it. So we can guarantee that the cache gets populated + // in either case, because if it is filtered out here, we either have a malformed path (root can't be determined) in which case + // the filter code won't call it anyway, or we have a valid path and the cache will be populated before the epoch can be compared. + if l.before == 0 { + return true + } + ident, err := populateRoot(blobIdent{}, path.Dir(fname)) + // Filter out the path if we can't determine its root. + if err != nil { + return false + } + ident, err = l.populateEpoch(ident, fname) + // Filter out the path if we can't determine its epoch or properly cache it. + if err != nil { + return false + } + return ident.epoch < l.before +} + +// isFlatCachedAndBefore returns a filter callback function to exclude roots that are known to be after the given epoch +// based on the cache. It's an opportunistic filter; if the cache is not populated, it will not attempt to populate it. +// isSSZAndBefore on the other hand, is a strict filter that will only return true if the file is an SSZ file and +// the epoch can be determined. +func isFlatCachedAndBefore(cache *blobStorageSummaryCache, before primitives.Epoch) func(string) bool { + if before == 0 { + return isRootDir + } + return func(p string) bool { + if !isRootDir(p) { + return false + } + root, err := rootFromPath(p) + if err != nil { + return false + } + sum, ok := cache.get(root) + // If we don't know the epoch by looking at the root, don't try to filter it. + if !ok { + return true + } + return sum.epoch < before + } +} diff --git a/beacon-chain/db/filesystem/layout_test.go b/beacon-chain/db/filesystem/layout_test.go new file mode 100644 index 000000000000..5b1c61533407 --- /dev/null +++ b/beacon-chain/db/filesystem/layout_test.go @@ -0,0 +1,75 @@ +package filesystem + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +type mockLayout struct { + pruneBeforeFunc func(primitives.Epoch) (*pruneSummary, error) +} + +var _ fsLayout = &mockLayout{} + +func (m *mockLayout) name() string { + return "mock" +} + +func (*mockLayout) dir(_ blobIdent) string { + return "" +} + +func (*mockLayout) blockParentDirs(id blobIdent) []string { + return []string{} +} + +func (*mockLayout) sszPath(_ blobIdent) string { + return "" +} + +func (*mockLayout) partPath(_ blobIdent, _ string) string { + return "" +} + +func (*mockLayout) iterateIdents(_ primitives.Epoch) (*identIterator, error) { + return nil, nil +} + +func (*mockLayout) ident(_ [32]byte, _ uint64) (blobIdent, error) { + return blobIdent{}, nil +} + +func (*mockLayout) dirIdent(_ [32]byte) (blobIdent, error) { + return blobIdent{}, nil +} + +func (*mockLayout) summary(_ [32]byte) BlobStorageSummary { + return BlobStorageSummary{} +} + +func (*mockLayout) notify(blobIdent) error { + return nil +} + +func (m *mockLayout) pruneBefore(before primitives.Epoch) (*pruneSummary, error) { + return m.pruneBeforeFunc(before) +} + +func (*mockLayout) remove(ident blobIdent) (int, error) { + return 0, nil +} + +var _ fsLayout = &mockLayout{} + +func TestCleaner(t *testing.T) { + l := &periodicEpochLayout{} + p := l.periodDir(11235813) + e := l.epochDir(11235813) + dc := newDirCleaner() + dc.add(p) + require.Equal(t, 2, dc.maxDepth) + dc.add(e) + require.Equal(t, 3, dc.maxDepth) +} diff --git a/beacon-chain/db/filesystem/migration_test.go b/beacon-chain/db/filesystem/migration_test.go new file mode 100644 index 000000000000..98ee5c0d1ec5 --- /dev/null +++ b/beacon-chain/db/filesystem/migration_test.go @@ -0,0 +1,180 @@ +package filesystem + +import ( + "os" + "testing" + + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/prysmaticlabs/prysm/v5/time/slots" + "github.com/spf13/afero" +) + +func ezIdent(t *testing.T, rootStr string, epoch primitives.Epoch, index uint64) blobIdent { + r, err := stringToRoot(rootStr) + require.NoError(t, err) + return blobIdent{root: r, epoch: epoch, index: index} +} + +func setupTestBlobFile(t *testing.T, ident blobIdent, offset primitives.Slot, fs afero.Fs, l fsLayout) { + slot, err := slots.EpochStart(ident.epoch) + require.NoError(t, err) + slot += offset + _, sc := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 1) + scb, err := sc[0].MarshalSSZ() + require.NoError(t, err) + dir := l.dir(ident) + require.NoError(t, fs.MkdirAll(dir, directoryPermissions())) + p := l.sszPath(ident) + require.NoError(t, afero.WriteFile(fs, p, scb, 0666)) + _, err = fs.Stat(p) + require.NoError(t, err) +} + +type migrationTestTarget struct { + ident blobIdent + slotOffset primitives.Slot + migrated bool + path string +} + +func testAssertFsMigrated(t *testing.T, fs afero.Fs, ident blobIdent, before, after fsLayout) { + // Assert the pre-migration path is gone. + _, err := fs.Stat(before.sszPath(ident)) + require.ErrorIs(t, err, os.ErrNotExist) + dir := before.dir(ident) + _, err = listDir(fs, dir) + require.ErrorIs(t, err, os.ErrNotExist) + + // Assert the post-migration path present. + _, err = fs.Stat(after.sszPath(ident)) + require.NoError(t, err) +} + +func TestMigrations(t *testing.T) { + cases := []struct { + name string + forwardLayout string + backwardLayout string + targets []migrationTestTarget + }{ + { + name: "all need migration", + backwardLayout: LayoutNameFlat, + forwardLayout: LayoutNameByEpoch, + targets: []migrationTestTarget{ + { + ident: ezIdent(t, "0x0125e54c64c925018c9296965a5b622d9f5ab626c10917860dcfb6aa09a0a00b", 1234, 0), + }, + { + ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", 5330, 0), + slotOffset: 31, + }, + { + ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", 5330, 1), + slotOffset: 31, + }, + { + ident: ezIdent(t, "0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c", 16777216, 0), + slotOffset: 16, + }, + }, + }, + { + name: "mix old and new", + backwardLayout: LayoutNameFlat, + forwardLayout: LayoutNameByEpoch, + targets: []migrationTestTarget{ + { + ident: ezIdent(t, "0x0125e54c64c925018c9296965a5b622d9f5ab626c10917860dcfb6aa09a0a00b", 1234, 0), + }, + { + ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", 5330, 0), + slotOffset: 31, + }, + { + ident: ezIdent(t, "0x0127dba6fd30fdbb47e73e861d5c6e602b38ac3ddc945bb6a2fc4e10761e9a86", 5330, 1), + slotOffset: 31, + }, + { + ident: ezIdent(t, "0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c", 16777216, 0), + slotOffset: 16, + migrated: true, + }, + { + ident: ezIdent(t, "0x0232521756a0b965eab2c2245d7ad85feaeaf5f427cd14d1a7531f9d555b415c", 16777216, 1), + slotOffset: 16, + migrated: true, + }, + { + ident: ezIdent(t, "0x42eabe3d2c125410cd226de6f2825fb7575ab896c3f52e43de1fa29e4c809aba", 16777217, 0), + slotOffset: 16, + migrated: true, + }, + { + ident: ezIdent(t, "0x666cea5034e22bd3b849cb33914cad59afd88ee08e4d5bc0e997411c945fbc1d", 11235, 1), + migrated: true, + }, + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + t.Run("forward", func(t *testing.T) { + testMigration(t, c.forwardLayout, c.backwardLayout, c.targets) + }) + // run the same test in reverse - to cover both directions while making the test table smaller. + t.Run("backward", func(t *testing.T) { + testMigration(t, c.forwardLayout, c.backwardLayout, c.targets) + }) + }) + } +} + +func testMigration(t *testing.T, forwardName, backwardName string, targets []migrationTestTarget) { + fs := afero.NewMemMapFs() + cache := newBlobStorageCache() + forward, err := newLayout(forwardName, fs, cache, nil) + require.NoError(t, err) + backward, err := newLayout(backwardName, fs, cache, nil) + require.NoError(t, err) + for _, tar := range targets { + if tar.migrated { + setupTestBlobFile(t, tar.ident, tar.slotOffset, fs, forward) + } else { + setupTestBlobFile(t, tar.ident, tar.slotOffset, fs, backward) + } + } + require.NoError(t, migrateLayout(fs, backward, forward, cache)) + for _, tar := range targets { + // Make sure the file wound up in the right spot, according to the forward layout + // and that the old file is gone, according to the backward layout. + testAssertFsMigrated(t, fs, tar.ident, backward, forward) + entry, ok := cache.get(tar.ident.root) + // we only expect cache to be populated here by files that needed to be moved. + if !tar.migrated { + require.Equal(t, true, ok) + require.Equal(t, true, entry.HasIndex(tar.ident.index)) + require.Equal(t, tar.ident.epoch, entry.epoch) + } + } + + // Run migration in reverse - testing "undo" + cache = newBlobStorageCache() + forward, err = newLayout(forwardName, fs, cache, nil) + require.NoError(t, err) + backward, err = newLayout(backwardName, fs, cache, nil) + require.NoError(t, err) + // forward and backward are flipped compared to the above + require.NoError(t, migrateLayout(fs, forward, backward, cache)) + for _, tar := range targets { + // just like the above, but forward and backward are flipped + testAssertFsMigrated(t, fs, tar.ident, forward, backward) + entry, ok := cache.get(tar.ident.root) + require.Equal(t, true, ok) + require.Equal(t, true, entry.HasIndex(tar.ident.index)) + require.Equal(t, tar.ident.epoch, entry.epoch) + } +} diff --git a/beacon-chain/db/filesystem/mock.go b/beacon-chain/db/filesystem/mock.go index 2b894eef53a9..c13a540f9b1f 100644 --- a/beacon-chain/db/filesystem/mock.go +++ b/beacon-chain/db/filesystem/mock.go @@ -4,30 +4,41 @@ import ( "testing" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/spf13/afero" ) // NewEphemeralBlobStorage should only be used for tests. // The instance of BlobStorage returned is backed by an in-memory virtual filesystem, // improving test performance and simplifying cleanup. -func NewEphemeralBlobStorage(t testing.TB) *BlobStorage { - fs := afero.NewMemMapFs() - pruner, err := newBlobPruner(fs, params.BeaconConfig().MinEpochsForBlobsSidecarsRequest, withWarmedCache()) - if err != nil { - t.Fatal("test setup issue", err) - } - return &BlobStorage{fs: fs, pruner: pruner} +func NewEphemeralBlobStorage(t testing.TB, opts ...BlobStorageOption) *BlobStorage { + return NewWarmedEphemeralBlobStorageUsingFs(t, afero.NewMemMapFs(), opts...) } -// NewEphemeralBlobStorageWithFs can be used by tests that want access to the virtual filesystem +// NewEphemeralBlobStorageAndFs can be used by tests that want access to the virtual filesystem // in order to interact with it outside the parameters of the BlobStorage api. -func NewEphemeralBlobStorageWithFs(t testing.TB) (afero.Fs, *BlobStorage) { +func NewEphemeralBlobStorageAndFs(t testing.TB, opts ...BlobStorageOption) (afero.Fs, *BlobStorage) { fs := afero.NewMemMapFs() - pruner, err := newBlobPruner(fs, params.BeaconConfig().MinEpochsForBlobsSidecarsRequest, withWarmedCache()) + bs := NewWarmedEphemeralBlobStorageUsingFs(t, fs, opts...) + return fs, bs +} + +func NewEphemeralBlobStorageUsingFs(t testing.TB, fs afero.Fs, opts ...BlobStorageOption) *BlobStorage { + opts = append(opts, + WithBlobRetentionEpochs(params.BeaconConfig().MinEpochsForBlobsSidecarsRequest), + WithFs(fs)) + bs, err := NewBlobStorage(opts...) if err != nil { - t.Fatal("test setup issue", err) + t.Fatalf("error initializing test BlobStorage, err=%s", err.Error()) } - return fs, &BlobStorage{fs: fs, pruner: pruner} + return bs +} + +func NewWarmedEphemeralBlobStorageUsingFs(t testing.TB, fs afero.Fs, opts ...BlobStorageOption) *BlobStorage { + bs := NewEphemeralBlobStorageUsingFs(t, fs, opts...) + bs.WarmCache() + return bs } type BlobMocker struct { @@ -37,17 +48,9 @@ type BlobMocker struct { // CreateFakeIndices creates empty blob sidecar files at the expected path for the given // root and indices to influence the result of Indices(). -func (bm *BlobMocker) CreateFakeIndices(root [32]byte, indices ...uint64) error { +func (bm *BlobMocker) CreateFakeIndices(root [32]byte, slot primitives.Slot, indices ...uint64) error { for i := range indices { - n := blobNamer{root: root, index: indices[i]} - if err := bm.fs.MkdirAll(n.dir(), directoryPermissions); err != nil { - return err - } - f, err := bm.fs.Create(n.path()) - if err != nil { - return err - } - if err := f.Close(); err != nil { + if err := bm.bs.layout.notify(newBlobIdent(root, slots.ToEpoch(slot), indices[i])); err != nil { return err } } @@ -56,9 +59,8 @@ func (bm *BlobMocker) CreateFakeIndices(root [32]byte, indices ...uint64) error // NewEphemeralBlobStorageWithMocker returns a *BlobMocker value in addition to the BlobStorage value. // BlockMocker encapsulates things blob path construction to avoid leaking implementation details. -func NewEphemeralBlobStorageWithMocker(_ testing.TB) (*BlobMocker, *BlobStorage) { - fs := afero.NewMemMapFs() - bs := &BlobStorage{fs: fs} +func NewEphemeralBlobStorageWithMocker(t testing.TB) (*BlobMocker, *BlobStorage) { + fs, bs := NewEphemeralBlobStorageAndFs(t) return &BlobMocker{fs: fs, bs: bs}, bs } @@ -66,7 +68,7 @@ func NewMockBlobStorageSummarizer(t *testing.T, set map[[32]byte][]int) BlobStor c := newBlobStorageCache() for k, v := range set { for i := range v { - if err := c.ensure(k, 0, uint64(v[i])); err != nil { + if err := c.ensure(blobIdent{root: k, epoch: 0, index: uint64(v[i])}); err != nil { t.Fatal(err) } } diff --git a/beacon-chain/db/filesystem/pruner.go b/beacon-chain/db/filesystem/pruner.go index 5ac4ac50d6fa..508f24fa886c 100644 --- a/beacon-chain/db/filesystem/pruner.go +++ b/beacon-chain/db/filesystem/pruner.go @@ -1,320 +1,67 @@ package filesystem import ( - "context" - "encoding/binary" - "io" - "path" - "path/filepath" - "strconv" - "strings" "sync" "sync/atomic" "time" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "github.com/spf13/afero" ) const retentionBuffer primitives.Epoch = 2 -const bytesPerSidecar = 131928 -var ( - errPruningFailures = errors.New("blobs could not be pruned for some roots") - errNotBlobSSZ = errors.New("not a blob ssz file") -) +var errNotBlobSSZ = errors.New("not a blob ssz file") +// blobPruner keeps track of the tail end of the retention period, based only the blobs it has seen via the notify method. +// If the retention period advances in response to notify being called, +// the pruner will invoke the pruneBefore method of the given layout in a new goroutine. +// The details of pruning are left entirely to the layout, with the pruner's only responsibility being to +// schedule just one pruning operation at a time, for each forward movement of the minimum retention epoch. type blobPruner struct { - sync.Mutex - prunedBefore atomic.Uint64 - windowSize primitives.Slot - cache *blobStorageCache - cacheReady chan struct{} - warmed bool - fs afero.Fs + mu sync.Mutex + prunedBefore atomic.Uint64 + retentionPeriod primitives.Epoch } -type prunerOpt func(*blobPruner) error - -func withWarmedCache() prunerOpt { - return func(p *blobPruner) error { - return p.warmCache() - } +func newBlobPruner(retain primitives.Epoch) *blobPruner { + p := &blobPruner{retentionPeriod: retain + retentionBuffer} + return p } -func newBlobPruner(fs afero.Fs, retain primitives.Epoch, opts ...prunerOpt) (*blobPruner, error) { - r, err := slots.EpochStart(retain + retentionBuffer) - if err != nil { - return nil, errors.Wrap(err, "could not set retentionSlots") - } - cw := make(chan struct{}) - p := &blobPruner{fs: fs, windowSize: r, cache: newBlobStorageCache(), cacheReady: cw} - for _, o := range opts { - if err := o(p); err != nil { - return nil, err - } - } - return p, nil -} - -// notify updates the pruner's view of root->blob mappings. This allows the pruner to build a cache -// of root->slot mappings and decide when to evict old blobs based on the age of present blobs. -func (p *blobPruner) notify(root [32]byte, latest primitives.Slot, idx uint64) error { - if err := p.cache.ensure(root, latest, idx); err != nil { - return err - } - pruned := uint64(windowMin(latest, p.windowSize)) - if p.prunedBefore.Swap(pruned) == pruned { - return nil +// notify returns a channel that is closed when the pruning operation is complete. +// This is useful for tests, but at runtime fsLayouts or BlobStorage should not wait for completion. +func (p *blobPruner) notify(latest primitives.Epoch, layout fsLayout) chan struct{} { + done := make(chan struct{}) + floor := periodFloor(latest, p.retentionPeriod) + if primitives.Epoch(p.prunedBefore.Swap(uint64(floor))) >= floor { + // Only trigger pruning if the atomic swap changed the previous value of prunedBefore. + close(done) + return done } go func() { - p.Lock() - defer p.Unlock() - if err := p.prune(primitives.Slot(pruned)); err != nil { - log.WithError(err).Errorf("Failed to prune blobs from slot %d", latest) - } - }() - return nil -} - -func windowMin(latest, offset primitives.Slot) primitives.Slot { - // Safely compute the first slot in the epoch for the latest slot - latest = latest - latest%params.BeaconConfig().SlotsPerEpoch - if latest < offset { - return 0 - } - return latest - offset -} - -func (p *blobPruner) warmCache() error { - p.Lock() - defer func() { - if !p.warmed { - p.warmed = true - close(p.cacheReady) - } - p.Unlock() - }() - if err := p.prune(0); err != nil { - return err - } - return nil -} - -func (p *blobPruner) waitForCache(ctx context.Context) (*blobStorageCache, error) { - select { - case <-p.cacheReady: - return p.cache, nil - case <-ctx.Done(): - return nil, ctx.Err() - } -} - -// Prune prunes blobs in the base directory based on the retention epoch. -// It deletes blobs older than currentEpoch - (retentionEpochs+bufferEpochs). -// This is so that we keep a slight buffer and blobs are deleted after n+2 epochs. -func (p *blobPruner) prune(pruneBefore primitives.Slot) error { - start := time.Now() - totalPruned, totalErr := 0, 0 - // Customize logging/metrics behavior for the initial cache warmup when slot=0. - // We'll never see a prune request for slot 0, unless this is the initial call to warm up the cache. - if pruneBefore == 0 { - defer func() { - log.WithField("duration", time.Since(start).String()).Debug("Warmed up pruner cache") - }() - } else { - defer func() { - log.WithFields(logrus.Fields{ - "upToEpoch": slots.ToEpoch(pruneBefore), - "duration": time.Since(start).String(), - "filesRemoved": totalPruned, - }).Debug("Pruned old blobs") - blobsPrunedCounter.Add(float64(totalPruned)) - }() - } - - entries, err := listDir(p.fs, ".") - if err != nil { - return errors.Wrap(err, "unable to list root blobs directory") - } - dirs := filter(entries, filterRoot) - for _, dir := range dirs { - pruned, err := p.tryPruneDir(dir, pruneBefore) - if err != nil { - totalErr += 1 - log.WithError(err).WithField("directory", dir).Error("Unable to prune directory") - } - totalPruned += pruned - } - - if totalErr > 0 { - return errors.Wrapf(errPruningFailures, "pruning failed for %d root directories", totalErr) - } - return nil -} - -func shouldRetain(slot, pruneBefore primitives.Slot) bool { - return slot >= pruneBefore -} - -func (p *blobPruner) tryPruneDir(dir string, pruneBefore primitives.Slot) (int, error) { - root, err := rootFromDir(dir) - if err != nil { - return 0, errors.Wrapf(err, "invalid directory, could not parse subdir as root %s", dir) - } - slot, slotCached := p.cache.slot(root) - // Return early if the slot is cached and doesn't need pruning. - if slotCached && shouldRetain(slot, pruneBefore) { - return 0, nil - } - - // entries will include things that aren't ssz files, like dangling .part files. We need these to - // completely clean up the directory. - entries, err := listDir(p.fs, dir) - if err != nil { - return 0, errors.Wrapf(err, "failed to list blobs in directory %s", dir) - } - // scFiles filters the dir listing down to the ssz encoded BlobSidecar files. This allows us to peek - // at the first one in the list to figure out the slot. - scFiles := filter(entries, filterSsz) - if len(scFiles) == 0 { - log.WithField("dir", dir).Warn("Pruner ignoring directory with no blob files") - return 0, nil - } - if !slotCached { - slot, err = slotFromFile(path.Join(dir, scFiles[0]), p.fs) + p.mu.Lock() + start := time.Now() + defer p.mu.Unlock() + sum, err := layout.pruneBefore(floor) if err != nil { - return 0, errors.Wrapf(err, "slot could not be read from blob file %s", scFiles[0]) - } - for i := range scFiles { - idx, err := idxFromPath(scFiles[i]) - if err != nil { - return 0, errors.Wrapf(err, "index could not be determined for blob file %s", scFiles[i]) - } - if err := p.cache.ensure(root, slot, idx); err != nil { - return 0, errors.Wrapf(err, "could not update prune cache for blob file %s", scFiles[i]) - } - } - if shouldRetain(slot, pruneBefore) { - return 0, nil - } - } - - removed := 0 - for _, fname := range entries { - fullName := path.Join(dir, fname) - if err := p.fs.Remove(fullName); err != nil { - return removed, errors.Wrapf(err, "unable to remove %s", fullName) - } - // Don't count other files that happen to be in the dir, like dangling .part files. - if filterSsz(fname) { - removed += 1 - } - // Log a warning whenever we clean up a .part file - if filterPart(fullName) { - log.WithField("file", fullName).Warn("Deleting abandoned blob .part file") - } - } - if err := p.fs.Remove(dir); err != nil { - return removed, errors.Wrapf(err, "unable to remove blob directory %s", dir) - } - - p.cache.evict(root) - return len(scFiles), nil -} - -func idxFromPath(fname string) (uint64, error) { - fname = path.Base(fname) - - if filepath.Ext(fname) != dotSszExt { - return 0, errors.Wrap(errNotBlobSSZ, "does not have .ssz extension") - } - parts := strings.Split(fname, ".") - if len(parts) != 2 { - return 0, errors.Wrap(errNotBlobSSZ, "unexpected filename structure (want .ssz)") - } - return strconv.ParseUint(parts[0], 10, 64) -} - -func rootFromDir(dir string) ([32]byte, error) { - subdir := filepath.Base(dir) // end of the path should be the blob directory, named by hex encoding of root - root, err := stringToRoot(subdir) - if err != nil { - return root, errors.Wrapf(err, "invalid directory, could not parse subdir as root %s", dir) - } - return root, nil -} - -// Read slot from marshaled BlobSidecar data in the given file. See slotFromBlob for details. -func slotFromFile(file string, fs afero.Fs) (primitives.Slot, error) { - f, err := fs.Open(file) - if err != nil { - return 0, err - } - defer func() { - if err := f.Close(); err != nil { - log.WithError(err).Errorf("Could not close blob file") - } - }() - return slotFromBlob(f) -} - -// slotFromBlob reads the ssz data of a file at the specified offset (8 + 131072 + 48 + 48 = 131176 bytes), -// which is calculated based on the size of the BlobSidecar struct and is based on the size of the fields -// preceding the slot information within SignedBeaconBlockHeader. -func slotFromBlob(at io.ReaderAt) (primitives.Slot, error) { - b := make([]byte, 8) - _, err := at.ReadAt(b, 131176) - if err != nil { - return 0, err - } - rawSlot := binary.LittleEndian.Uint64(b) - return primitives.Slot(rawSlot), nil -} - -func listDir(fs afero.Fs, dir string) ([]string, error) { - top, err := fs.Open(dir) - if err != nil { - return nil, errors.Wrap(err, "failed to open directory descriptor") - } - defer func() { - if err := top.Close(); err != nil { - log.WithError(err).Errorf("Could not close file %s", dir) + log.WithError(err).WithFields(sum.LogFields()).Warn("Encountered errors during blob pruning.") } + log.WithFields(logrus.Fields{ + "upToEpoch": floor, + "duration": time.Since(start).String(), + "filesRemoved": sum.blobsPruned, + }).Debug("Pruned old blobs") + blobsPrunedCounter.Add(float64(sum.blobsPruned)) + close(done) }() - // re the -1 param: "If n <= 0, Readdirnames returns all the names from the directory in a single slice" - dirs, err := top.Readdirnames(-1) - if err != nil { - return nil, errors.Wrap(err, "failed to read directory listing") - } - return dirs, nil + return done } -func filter(entries []string, filt func(string) bool) []string { - filtered := make([]string, 0, len(entries)) - for i := range entries { - if filt(entries[i]) { - filtered = append(filtered, entries[i]) - } +func periodFloor(latest, period primitives.Epoch) primitives.Epoch { + if latest < period { + return 0 } - return filtered -} - -func filterRoot(s string) bool { - return strings.HasPrefix(s, "0x") -} - -var dotSszExt = "." + sszExt -var dotPartExt = "." + partExt - -func filterSsz(s string) bool { - return filepath.Ext(s) == dotSszExt -} - -func filterPart(s string) bool { - return filepath.Ext(s) == dotPartExt + return latest - period } diff --git a/beacon-chain/db/filesystem/pruner_test.go b/beacon-chain/db/filesystem/pruner_test.go index 3241350dccdc..5a8519bc7578 100644 --- a/beacon-chain/db/filesystem/pruner_test.go +++ b/beacon-chain/db/filesystem/pruner_test.go @@ -1,394 +1,197 @@ package filesystem import ( - "bytes" - "context" - "fmt" - "math" + "encoding/binary" "os" - "path" - "sort" "testing" - "time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/spf13/afero" ) -func TestTryPruneDir_CachedNotExpired(t *testing.T) { - fs := afero.NewMemMapFs() - pr, err := newBlobPruner(fs, 0) - require.NoError(t, err) - slot := pr.windowSize - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, fieldparams.MaxBlobsPerBlock) - sc, err := verification.BlobSidecarNoop(sidecars[0]) - require.NoError(t, err) - rootStr := rootString(sc.BlockRoot()) - // This slot is right on the edge of what would need to be pruned, so by adding it to the cache and - // skipping any other test setup, we can be certain the hot cache path never touches the filesystem. - require.NoError(t, pr.cache.ensure(sc.BlockRoot(), sc.Slot(), 0)) - pruned, err := pr.tryPruneDir(rootStr, pr.windowSize) - require.NoError(t, err) - require.Equal(t, 0, pruned) +type prunerScenario struct { + name string + prunedBefore primitives.Epoch + retentionPeriod primitives.Epoch + latest primitives.Epoch + expected pruneExpectation } -func TestCacheWarmFail(t *testing.T) { - fs := afero.NewMemMapFs() - n := blobNamer{root: bytesutil.ToBytes32([]byte("derp")), index: 0} - bp := n.path() - mkdir := path.Dir(bp) - require.NoError(t, fs.MkdirAll(mkdir, directoryPermissions)) - - // Create an empty blob index in the fs by touching the file at a seemingly valid path. - fi, err := fs.Create(bp) - require.NoError(t, err) - require.NoError(t, fi.Close()) - - // Cache warm should fail due to the unexpected EOF. - pr, err := newBlobPruner(fs, 0) - require.NoError(t, err) - require.ErrorIs(t, pr.warmCache(), errPruningFailures) - - // The cache warm has finished, so calling waitForCache with a super short deadline - // should not block or hit the context deadline. - ctx := context.Background() - ctx, cancel := context.WithDeadline(ctx, time.Now().Add(1*time.Millisecond)) - defer cancel() - c, err := pr.waitForCache(ctx) - // We will get an error and a nil value for the cache if we hit the deadline. - require.NoError(t, err) - require.NotNil(t, c) -} - -func TestTryPruneDir_CachedExpired(t *testing.T) { - t.Run("empty directory", func(t *testing.T) { - fs := afero.NewMemMapFs() - pr, err := newBlobPruner(fs, 0) - require.NoError(t, err) - var slot primitives.Slot = 0 - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 1) - sc, err := verification.BlobSidecarNoop(sidecars[0]) - require.NoError(t, err) - rootStr := rootString(sc.BlockRoot()) - require.NoError(t, fs.Mkdir(rootStr, directoryPermissions)) // make empty directory - require.NoError(t, pr.cache.ensure(sc.BlockRoot(), sc.Slot(), 0)) - pruned, err := pr.tryPruneDir(rootStr, slot+1) - require.NoError(t, err) - require.Equal(t, 0, pruned) - }) - t.Run("blobs to delete", func(t *testing.T) { - fs, bs := NewEphemeralBlobStorageWithFs(t) - var slot primitives.Slot = 0 - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 2) - scs, err := verification.BlobSidecarSliceNoop(sidecars) - require.NoError(t, err) - - require.NoError(t, bs.Save(scs[0])) - require.NoError(t, bs.Save(scs[1])) - - // check that the root->slot is cached - root := scs[0].BlockRoot() - rootStr := rootString(root) - cs, cok := bs.pruner.cache.slot(scs[0].BlockRoot()) - require.Equal(t, true, cok) - require.Equal(t, slot, cs) - - // ensure that we see the saved files in the filesystem - files, err := listDir(fs, rootStr) - require.NoError(t, err) - require.Equal(t, 2, len(files)) - - pruned, err := bs.pruner.tryPruneDir(rootStr, slot+1) - require.NoError(t, err) - require.Equal(t, 2, pruned) - files, err = listDir(fs, rootStr) - require.ErrorIs(t, err, os.ErrNotExist) - require.Equal(t, 0, len(files)) - }) -} - -func TestTryPruneDir_SlotFromFile(t *testing.T) { - t.Run("expired blobs deleted", func(t *testing.T) { - fs, bs := NewEphemeralBlobStorageWithFs(t) - var slot primitives.Slot = 0 - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 2) - scs, err := verification.BlobSidecarSliceNoop(sidecars) - require.NoError(t, err) - - require.NoError(t, bs.Save(scs[0])) - require.NoError(t, bs.Save(scs[1])) - - // check that the root->slot is cached - root := scs[0].BlockRoot() - rootStr := rootString(root) - cs, ok := bs.pruner.cache.slot(root) - require.Equal(t, true, ok) - require.Equal(t, slot, cs) - // evict it from the cache so that we trigger the file read path - bs.pruner.cache.evict(root) - _, ok = bs.pruner.cache.slot(root) - require.Equal(t, false, ok) - - // ensure that we see the saved files in the filesystem - files, err := listDir(fs, rootStr) - require.NoError(t, err) - require.Equal(t, 2, len(files)) - - pruned, err := bs.pruner.tryPruneDir(rootStr, slot+1) - require.NoError(t, err) - require.Equal(t, 2, pruned) - files, err = listDir(fs, rootStr) - require.ErrorIs(t, err, os.ErrNotExist) - require.Equal(t, 0, len(files)) - }) - t.Run("not expired, intact", func(t *testing.T) { - fs, bs := NewEphemeralBlobStorageWithFs(t) - // Set slot equal to the window size, so it should be retained. - slot := bs.pruner.windowSize - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 2) - scs, err := verification.BlobSidecarSliceNoop(sidecars) - require.NoError(t, err) - - require.NoError(t, bs.Save(scs[0])) - require.NoError(t, bs.Save(scs[1])) - - // Evict slot mapping from the cache so that we trigger the file read path. - root := scs[0].BlockRoot() - rootStr := rootString(root) - bs.pruner.cache.evict(root) - _, ok := bs.pruner.cache.slot(root) - require.Equal(t, false, ok) - - // Ensure that we see the saved files in the filesystem. - files, err := listDir(fs, rootStr) - require.NoError(t, err) - require.Equal(t, 2, len(files)) - - // This should use the slotFromFile code (simulating restart). - // Setting pruneBefore == slot, so that the slot will be outside the window (at the boundary). - pruned, err := bs.pruner.tryPruneDir(rootStr, slot) - require.NoError(t, err) - require.Equal(t, 0, pruned) - - // Ensure files are still present. - files, err = listDir(fs, rootStr) - require.NoError(t, err) - require.Equal(t, 2, len(files)) - }) -} - -func TestSlotFromBlob(t *testing.T) { - cases := []struct { - slot primitives.Slot - }{ - {slot: 0}, - {slot: 2}, - {slot: 1123581321}, - {slot: math.MaxUint64}, - } - for _, c := range cases { - t.Run(fmt.Sprintf("slot %d", c.slot), func(t *testing.T) { - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, c.slot, 1) - sc := sidecars[0] - enc, err := sc.MarshalSSZ() - require.NoError(t, err) - slot, err := slotFromBlob(bytes.NewReader(enc)) - require.NoError(t, err) - require.Equal(t, c.slot, slot) - }) - } -} - -func TestSlotFromFile(t *testing.T) { - cases := []struct { - slot primitives.Slot - }{ - {slot: 0}, - {slot: 2}, - {slot: 1123581321}, - {slot: math.MaxUint64}, - } - for _, c := range cases { - t.Run(fmt.Sprintf("slot %d", c.slot), func(t *testing.T) { - fs, bs := NewEphemeralBlobStorageWithFs(t) - _, sidecars := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, c.slot, 1) - sc, err := verification.BlobSidecarNoop(sidecars[0]) - require.NoError(t, err) - require.NoError(t, bs.Save(sc)) - fname := namerForSidecar(sc) - sszPath := fname.path() - slot, err := slotFromFile(sszPath, fs) - require.NoError(t, err) - require.Equal(t, c.slot, slot) - }) - } -} - -type dirFiles struct { - name string - isDir bool - children []dirFiles -} - -func (df dirFiles) reify(t *testing.T, fs afero.Fs, base string) { - fullPath := path.Join(base, df.name) - if df.isDir { - if df.name != "" { - require.NoError(t, fs.Mkdir(fullPath, directoryPermissions)) - } - for _, c := range df.children { - c.reify(t, fs, fullPath) - } - } else { - fp, err := fs.Create(fullPath) - require.NoError(t, err) - _, err = fp.WriteString("derp") - require.NoError(t, err) - } +type pruneExpectation struct { + called bool + arg primitives.Epoch + summary *pruneSummary + err error } -func (df dirFiles) childNames() []string { - cn := make([]string, len(df.children)) - for i := range df.children { - cn[i] = df.children[i].name +func (e *pruneExpectation) record(before primitives.Epoch) (*pruneSummary, error) { + e.called = true + e.arg = before + if e.summary == nil { + e.summary = &pruneSummary{} } - return cn + return e.summary, e.err } -func TestListDir(t *testing.T) { - fs := afero.NewMemMapFs() - - // parent directory - fsLayout := dirFiles{isDir: true} - // break out each subdir for easier assertions - notABlob := dirFiles{name: "notABlob", isDir: true} - childlessBlob := dirFiles{name: "0x0987654321", isDir: true} - blobWithSsz := dirFiles{name: "0x1123581321", isDir: true, - children: []dirFiles{{name: "1.ssz"}, {name: "2.ssz"}}, - } - blobWithSszAndTmp := dirFiles{name: "0x1234567890", isDir: true, - children: []dirFiles{{name: "5.ssz"}, {name: "0.part"}}} - fsLayout.children = append(fsLayout.children, - notABlob, childlessBlob, blobWithSsz, blobWithSszAndTmp) - - topChildren := make([]string, len(fsLayout.children)) - for i := range fsLayout.children { - topChildren[i] = fsLayout.children[i].name - } - - fsLayout.reify(t, fs, "") - cases := []struct { - name string - dirPath string - expected []string - filter func(string) bool - err error - }{ - { - name: "non-existent", - dirPath: "derp", - expected: []string{}, - err: os.ErrNotExist, - }, +func TestPrunerNotify(t *testing.T) { + defaultRetention := params.BeaconConfig().MinEpochsForBlobsSidecarsRequest + cases := []prunerScenario{ { - name: "empty", - dirPath: childlessBlob.name, - expected: []string{}, + name: "last epoch of period", + retentionPeriod: defaultRetention, + prunedBefore: 11235, + latest: defaultRetention + 11235, + expected: pruneExpectation{called: false}, }, { - name: "top", - dirPath: ".", - expected: topChildren, + name: "within period", + retentionPeriod: defaultRetention, + prunedBefore: 11235, + latest: 11235 + defaultRetention - 1, + expected: pruneExpectation{called: false}, }, { - name: "custom filter: only notABlob", - dirPath: ".", - expected: []string{notABlob.name}, - filter: func(s string) bool { - return s == notABlob.name - }, + name: "triggers", + retentionPeriod: defaultRetention, + prunedBefore: 11235, + latest: 11235 + 1 + defaultRetention, + expected: pruneExpectation{called: true, arg: 11235 + 1}, }, { - name: "root filter", - dirPath: ".", - expected: []string{childlessBlob.name, blobWithSsz.name, blobWithSszAndTmp.name}, - filter: filterRoot, + name: "from zero - before first period", + retentionPeriod: defaultRetention, + prunedBefore: 0, + latest: defaultRetention - 1, + expected: pruneExpectation{called: false}, }, { - name: "ssz filter", - dirPath: blobWithSsz.name, - expected: blobWithSsz.childNames(), - filter: filterSsz, + name: "from zero - at boundary", + retentionPeriod: defaultRetention, + prunedBefore: 0, + latest: defaultRetention, + expected: pruneExpectation{called: false}, }, { - name: "ssz mixed filter", - dirPath: blobWithSszAndTmp.name, - expected: []string{"5.ssz"}, - filter: filterSsz, + name: "from zero - triggers", + retentionPeriod: defaultRetention, + prunedBefore: 0, + latest: defaultRetention + 1, + expected: pruneExpectation{called: true, arg: 1}, }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - result, err := listDir(fs, c.dirPath) - if c.filter != nil { - result = filter(result, c.filter) - } - if c.err != nil { - require.ErrorIs(t, err, c.err) - require.Equal(t, 0, len(result)) - } else { - require.NoError(t, err) - sort.Strings(c.expected) - sort.Strings(result) - require.DeepEqual(t, c.expected, result) - } + actual := &pruneExpectation{} + l := &mockLayout{pruneBeforeFunc: actual.record} + pruner := &blobPruner{retentionPeriod: c.retentionPeriod} + pruner.prunedBefore.Store(uint64(c.prunedBefore)) + done := pruner.notify(c.latest, l) + <-done + require.Equal(t, c.expected.called, actual.called) + require.Equal(t, c.expected.arg, actual.arg) }) } } -func TestRootFromDir(t *testing.T) { +func testSetupBlobIdentPaths(t *testing.T, fs afero.Fs, bs *BlobStorage, idents []testIdent) []blobIdent { + created := make([]blobIdent, len(idents)) + for i, id := range idents { + slot, err := slots.EpochStart(id.epoch) + require.NoError(t, err) + slot += id.offset + _, scs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, slot, 1) + sc := verification.FakeVerifyForTest(t, scs[0]) + require.NoError(t, bs.Save(sc)) + ident := identForSidecar(sc) + _, err = fs.Stat(bs.layout.sszPath(ident)) + require.NoError(t, err) + created[i] = ident + } + return created +} + +func testAssertBlobsPruned(t *testing.T, fs afero.Fs, bs *BlobStorage, pruned, remain []blobIdent) { + for _, id := range pruned { + _, err := fs.Stat(bs.layout.sszPath(id)) + require.NotNil(t, err) + require.Equal(t, true, os.IsNotExist(err)) + } + for _, id := range remain { + _, err := fs.Stat(bs.layout.sszPath(id)) + require.NoError(t, err) + } +} + +type testIdent struct { + blobIdent + offset primitives.Slot +} + +func testRoots(n int) [][32]byte { + roots := make([][32]byte, n) + for i := range roots { + binary.LittleEndian.PutUint32(roots[i][:], uint32(1+i)) + } + return roots +} + +func TestLayoutPruneBefore(t *testing.T) { + roots := testRoots(10) cases := []struct { - name string - dir string - err error - root [32]byte + name string + pruned []testIdent + remain []testIdent + pruneBefore primitives.Epoch + err error + sum pruneSummary }{ { - name: "happy path", - dir: "0xffff875e1d985c5ccb214894983f2428edb271f0f87b68ba7010e4a99df3b5cb", - root: [32]byte{255, 255, 135, 94, 29, 152, 92, 92, 203, 33, 72, 148, 152, 63, 36, 40, - 237, 178, 113, 240, 248, 123, 104, 186, 112, 16, 228, 169, 157, 243, 181, 203}, - }, - { - name: "too short", - dir: "0xffff875e1d985c5ccb214894983f2428edb271f0f87b68ba7010e4a99df3b5c", - err: errInvalidRootString, - }, - { - name: "too log", - dir: "0xffff875e1d985c5ccb214894983f2428edb271f0f87b68ba7010e4a99df3b5cbb", - err: errInvalidRootString, + name: "none pruned", + pruneBefore: 1, + pruned: []testIdent{}, + remain: []testIdent{ + {offset: 1, blobIdent: blobIdent{root: roots[0], epoch: 1, index: 0}}, + {offset: 1, blobIdent: blobIdent{root: roots[1], epoch: 1, index: 0}}, + }, }, { - name: "missing prefix", - dir: "ffff875e1d985c5ccb214894983f2428edb271f0f87b68ba7010e4a99df3b5cb", - err: errInvalidRootString, + name: "expected pruned before epoch", + pruneBefore: 3, + pruned: []testIdent{ + {offset: 0, blobIdent: blobIdent{root: roots[0], epoch: 1, index: 0}}, + {offset: 31, blobIdent: blobIdent{root: roots[1], epoch: 1, index: 5}}, + {offset: 0, blobIdent: blobIdent{root: roots[2], epoch: 2, index: 0}}, + {offset: 31, blobIdent: blobIdent{root: roots[3], epoch: 2, index: 3}}, + }, + remain: []testIdent{ + {offset: 0, blobIdent: blobIdent{root: roots[4], epoch: 3, index: 2}}, // boundary + {offset: 31, blobIdent: blobIdent{root: roots[5], epoch: 3, index: 0}}, // boundary + {offset: 0, blobIdent: blobIdent{root: roots[6], epoch: 4, index: 1}}, + {offset: 31, blobIdent: blobIdent{root: roots[7], epoch: 4, index: 5}}, + }, + sum: pruneSummary{blobsPruned: 4}, }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { - root, err := stringToRoot(c.dir) + fs, bs := NewEphemeralBlobStorageAndFs(t, WithLayout(LayoutNameByEpoch)) + pruned := testSetupBlobIdentPaths(t, fs, bs, c.pruned) + remain := testSetupBlobIdentPaths(t, fs, bs, c.remain) + sum, err := bs.layout.pruneBefore(c.pruneBefore) if c.err != nil { require.ErrorIs(t, err, c.err) return } require.NoError(t, err) - require.Equal(t, c.root, root) + testAssertBlobsPruned(t, fs, bs, pruned, remain) + require.Equal(t, c.sum.blobsPruned, sum.blobsPruned) + require.Equal(t, len(c.pruned), sum.blobsPruned) + require.Equal(t, len(c.sum.failedRemovals), len(sum.failedRemovals)) }) } } diff --git a/beacon-chain/db/iface/interface.go b/beacon-chain/db/iface/interface.go index 82e5a019f7d2..81ab5fef8d5b 100644 --- a/beacon-chain/db/iface/interface.go +++ b/beacon-chain/db/iface/interface.go @@ -56,6 +56,10 @@ type ReadOnlyDatabase interface { // Fee recipients operations. FeeRecipientByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (common.Address, error) RegistrationByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (*ethpb.ValidatorRegistrationV1, error) + // light client operations + LightClientUpdates(ctx context.Context, startPeriod, endPeriod uint64) (map[uint64]interfaces.LightClientUpdate, error) + LightClientUpdate(ctx context.Context, period uint64) (interfaces.LightClientUpdate, error) + LightClientBootstrap(ctx context.Context, blockRoot []byte) (interfaces.LightClientBootstrap, error) // origin checkpoint sync support OriginCheckpointBlockRoot(ctx context.Context) ([32]byte, error) @@ -92,8 +96,12 @@ type NoHeadAccessDatabase interface { // Fee recipients operations. SaveFeeRecipientsByValidatorIDs(ctx context.Context, ids []primitives.ValidatorIndex, addrs []common.Address) error SaveRegistrationsByValidatorIDs(ctx context.Context, ids []primitives.ValidatorIndex, regs []*ethpb.ValidatorRegistrationV1) error + // light client operations + SaveLightClientUpdate(ctx context.Context, period uint64, update interfaces.LightClientUpdate) error + SaveLightClientBootstrap(ctx context.Context, blockRoot []byte, bootstrap interfaces.LightClientBootstrap) error CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint primitives.Slot) error + DeleteHistoricalDataBeforeSlot(ctx context.Context, slot primitives.Slot) error } // HeadAccessDatabase defines a struct with access to reading chain head data. diff --git a/beacon-chain/db/kv/BUILD.bazel b/beacon-chain/db/kv/BUILD.bazel index 464a6c82e196..1e57289ca041 100644 --- a/beacon-chain/db/kv/BUILD.bazel +++ b/beacon-chain/db/kv/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "genesis.go", "key.go", "kv.go", + "lightclient.go", "log.go", "migration.go", "migration_archived_index.go", @@ -40,9 +41,11 @@ go_library( "//beacon-chain/state/genesis:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//config/features:go_default_library", + "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", + "//consensus-types/light-client:go_default_library", "//consensus-types/primitives:go_default_library", "//container/slice:go_default_library", "//encoding/bytesutil:go_default_library", @@ -50,6 +53,7 @@ go_library( "//io/file:go_default_library", "//monitoring/progress:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/dbval:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", @@ -67,7 +71,6 @@ go_library( "@com_github_schollz_progressbar_v3//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_etcd_go_bbolt//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) @@ -87,6 +90,7 @@ go_test( "genesis_test.go", "init_test.go", "kv_test.go", + "lightclient_test.go", "migration_archived_index_test.go", "migration_block_slot_index_test.go", "migration_state_validators_test.go", @@ -109,6 +113,7 @@ go_test( "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", + "//consensus-types/light-client:go_default_library", "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/dbval:go_default_library", @@ -119,6 +124,7 @@ go_test( "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", + "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_golang_snappy//:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/db/kv/archived_point.go b/beacon-chain/db/kv/archived_point.go index 64394f5c54c8..64a0aaa35126 100644 --- a/beacon-chain/db/kv/archived_point.go +++ b/beacon-chain/db/kv/archived_point.go @@ -5,8 +5,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // LastArchivedSlot from the db. diff --git a/beacon-chain/db/kv/backfill.go b/beacon-chain/db/kv/backfill.go index ad2497b85814..1f34949a8b48 100644 --- a/beacon-chain/db/kv/backfill.go +++ b/beacon-chain/db/kv/backfill.go @@ -4,9 +4,9 @@ import ( "context" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/proto/dbval" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) diff --git a/beacon-chain/db/kv/backup.go b/beacon-chain/db/kv/backup.go index 60eb7afd18ae..d005f559ea36 100644 --- a/beacon-chain/db/kv/backup.go +++ b/beacon-chain/db/kv/backup.go @@ -8,8 +8,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/io/file" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) const backupsDirectoryName = "backups" diff --git a/beacon-chain/db/kv/blocks.go b/beacon-chain/db/kv/blocks.go index 466afb3f6789..4ce3144fc91b 100644 --- a/beacon-chain/db/kv/blocks.go +++ b/beacon-chain/db/kv/blocks.go @@ -16,17 +16,17 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/container/slice" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) -// used to represent errors for inconsistent slot ranges. +// Used to represent errors for inconsistent slot ranges. var errInvalidSlotRange = errors.New("invalid end slot and start slot provided") -// Block retrieval by root. +// Block retrieval by root. Return nil if block is not found. func (s *Store) Block(ctx context.Context, blockRoot [32]byte) (interfaces.ReadOnlySignedBeaconBlock, error) { ctx, span := trace.StartSpan(ctx, "BeaconDB.Block") defer span.End() @@ -227,10 +227,7 @@ func (s *Store) DeleteBlock(ctx context.Context, root [32]byte) error { return ErrDeleteJustifiedAndFinalized } - if err := tx.Bucket(blocksBucket).Delete(root[:]); err != nil { - return err - } - if err := tx.Bucket(blockParentRootIndicesBucket).Delete(root[:]); err != nil { + if err := s.deleteBlock(tx, root[:]); err != nil { return err } s.blockCache.Del(string(root[:])) @@ -238,6 +235,89 @@ func (s *Store) DeleteBlock(ctx context.Context, root [32]byte) error { }) } +// DeleteHistoricalDataBeforeSlot deletes all blocks and states before the given slot. +// This function deletes data from the following buckets: +// - blocksBucket +// - blockParentRootIndicesBucket +// - finalizedBlockRootsIndexBucket +// - stateBucket +// - stateSummaryBucket +// - blockRootValidatorHashesBucket +// - blockSlotIndicesBucket +// - stateSlotIndicesBucket +func (s *Store) DeleteHistoricalDataBeforeSlot(ctx context.Context, cutoffSlot primitives.Slot) error { + ctx, span := trace.StartSpan(ctx, "BeaconDB.DeleteHistoricalDataBeforeSlot") + defer span.End() + + // Collect slot/root pairs to perform deletions in a separate read only transaction. + var ( + roots [][]byte + slts []primitives.Slot + ) + err := s.db.View(func(tx *bolt.Tx) error { + var err error + roots, slts, err = blockRootsBySlotRange(ctx, tx.Bucket(blockSlotIndicesBucket), primitives.Slot(0), cutoffSlot, nil, nil, nil) + if err != nil { + return errors.Wrap(err, "could not retrieve block roots") + } + return nil + }) + if err != nil { + return errors.Wrap(err, "could not retrieve block roots and slots") + } + + // Perform all deletions in a single transaction for atomicity + return s.db.Update(func(tx *bolt.Tx) error { + for _, root := range roots { + // Delete block + if err = s.deleteBlock(tx, root); err != nil { + return err + } + + // Delete finalized block roots index + if err = tx.Bucket(finalizedBlockRootsIndexBucket).Delete(root); err != nil { + return errors.Wrap(err, "could not delete finalized block root index") + } + + // Delete state + if err = tx.Bucket(stateBucket).Delete(root); err != nil { + return errors.Wrap(err, "could not delete state") + } + + // Delete state summary + if err = tx.Bucket(stateSummaryBucket).Delete(root); err != nil { + return errors.Wrap(err, "could not delete state summary") + } + + // Delete validator entries + if err = s.deleteValidatorHashes(tx, root); err != nil { + return errors.Wrap(err, "could not delete validators") + } + } + + for _, slot := range slts { + // Delete slot indices + if err = tx.Bucket(blockSlotIndicesBucket).Delete(bytesutil.SlotToBytesBigEndian(slot)); err != nil { + return errors.Wrap(err, "could not delete block slot index") + } + if err = tx.Bucket(stateSlotIndicesBucket).Delete(bytesutil.SlotToBytesBigEndian(slot)); err != nil { + return errors.Wrap(err, "could not delete state slot index") + } + } + + // Delete all caches after we have deleted everything from buckets. + // This is done after the buckets are deleted to avoid any issues in case of transaction rollback. + for _, root := range roots { + // Delete block from cache + s.blockCache.Del(string(root)) + // Delete state summary from cache + s.stateSummaryCache.delete([32]byte(root)) + } + + return nil + }) +} + // SaveBlock to the db. func (s *Store) SaveBlock(ctx context.Context, signed interfaces.ReadOnlySignedBeaconBlock) error { ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveBlock") @@ -609,7 +689,7 @@ func blockRootsByFilter(ctx context.Context, tx *bolt.Tx, f *filters.QueryFilter // We retrieve block roots that match a filter criteria of slot ranges, if specified. filtersMap := f.Filters() - rootsBySlotRange, err := blockRootsBySlotRange( + rootsBySlotRange, _, err := blockRootsBySlotRange( ctx, tx.Bucket(blockSlotIndicesBucket), filtersMap[filters.StartSlot], @@ -627,6 +707,7 @@ func blockRootsByFilter(ctx context.Context, tx *bolt.Tx, f *filters.QueryFilter // that list of roots to lookup the block. These block will // meet the filter criteria. indices := lookupValuesForIndices(ctx, indicesByBucket, tx) + keys := rootsBySlotRange if len(indices) > 0 { // If we have found indices that meet the filter criteria, and there are also @@ -653,13 +734,13 @@ func blockRootsBySlotRange( ctx context.Context, bkt *bolt.Bucket, startSlotEncoded, endSlotEncoded, startEpochEncoded, endEpochEncoded, slotStepEncoded interface{}, -) ([][]byte, error) { +) ([][]byte, []primitives.Slot, error) { _, span := trace.StartSpan(ctx, "BeaconDB.blockRootsBySlotRange") defer span.End() // Return nothing when all slot parameters are missing if startSlotEncoded == nil && endSlotEncoded == nil && startEpochEncoded == nil && endEpochEncoded == nil { - return [][]byte{}, nil + return [][]byte{}, nil, nil } var startSlot, endSlot primitives.Slot @@ -680,11 +761,11 @@ func blockRootsBySlotRange( if startEpochOk && endEpochOk { startSlot, err = slots.EpochStart(startEpoch) if err != nil { - return nil, err + return nil, nil, err } endSlot, err = slots.EpochStart(endEpoch) if err != nil { - return nil, err + return nil, nil, err } endSlot = endSlot + params.BeaconConfig().SlotsPerEpoch - 1 } @@ -695,14 +776,15 @@ func blockRootsBySlotRange( return key != nil && bytes.Compare(key, max) <= 0 } if endSlot < startSlot { - return nil, errInvalidSlotRange + return nil, nil, errInvalidSlotRange } rootsRange := endSlot.SubSlot(startSlot).Div(step) roots := make([][]byte, 0, rootsRange) + var slts []primitives.Slot c := bkt.Cursor() for k, v := c.Seek(min); conditional(k, max); k, v = c.Next() { + slot := bytesutil.BytesToSlotBigEndian(k) if step > 1 { - slot := bytesutil.BytesToSlotBigEndian(k) if slot.SubSlot(startSlot).Mod(step) != 0 { continue } @@ -713,8 +795,9 @@ func blockRootsBySlotRange( splitRoots = append(splitRoots, v[i:i+32]) } roots = append(roots, splitRoots...) + slts = append(slts, slot) } - return roots, nil + return roots, slts, nil } // blockRootsBySlot retrieves the block roots by slot @@ -813,9 +896,9 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.ReadOnlySignedBea if err := rawBlock.UnmarshalSSZ(enc[len(denebBlindKey):]); err != nil { return nil, errors.Wrap(err, "could not unmarshal blinded Deneb block") } - case hasElectraKey(enc): + case HasElectraKey(enc): rawBlock = ðpb.SignedBeaconBlockElectra{} - if err := rawBlock.UnmarshalSSZ(enc[len(electraKey):]); err != nil { + if err := rawBlock.UnmarshalSSZ(enc[len(ElectraKey):]); err != nil { return nil, errors.Wrap(err, "could not unmarshal Electra block") } case hasElectraBlindKey(enc): @@ -823,6 +906,16 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.ReadOnlySignedBea if err := rawBlock.UnmarshalSSZ(enc[len(electraBlindKey):]); err != nil { return nil, errors.Wrap(err, "could not unmarshal blinded Electra block") } + case hasFuluKey(enc): + rawBlock = ðpb.SignedBeaconBlockFulu{} + if err := rawBlock.UnmarshalSSZ(enc[len(fuluKey):]); err != nil { + return nil, errors.Wrap(err, "could not unmarshal Fulu block") + } + case hasFuluBlindKey(enc): + rawBlock = ðpb.SignedBlindedBeaconBlockFulu{} + if err := rawBlock.UnmarshalSSZ(enc[len(fuluBlindKey):]); err != nil { + return nil, errors.Wrap(err, "could not unmarshal blinded Fulu block") + } default: // Marshal block bytes to phase 0 beacon block. rawBlock = ðpb.SignedBeaconBlock{} @@ -851,32 +944,79 @@ func encodeBlock(blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { } func keyForBlock(blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) { - switch blk.Version() { - case version.Electra: + v := blk.Version() + + if v >= version.Fulu { + if blk.IsBlinded() { + return fuluBlindKey, nil + } + return fuluKey, nil + } + + if v >= version.Electra { if blk.IsBlinded() { return electraBlindKey, nil } - return electraKey, nil - case version.Deneb: + return ElectraKey, nil + } + + if v >= version.Deneb { if blk.IsBlinded() { return denebBlindKey, nil } return denebKey, nil - case version.Capella: + } + + if v >= version.Capella { if blk.IsBlinded() { return capellaBlindKey, nil } return capellaKey, nil - case version.Bellatrix: + } + + if v >= version.Bellatrix { if blk.IsBlinded() { return bellatrixBlindKey, nil } return bellatrixKey, nil - case version.Altair: + } + + if v >= version.Altair { return altairKey, nil - case version.Phase0: + } + + if v >= version.Phase0 { return nil, nil - default: - return nil, fmt.Errorf("unsupported block version: %v", blk.Version()) } + + return nil, fmt.Errorf("unsupported block version: %v", blk.Version()) +} + +func (s *Store) deleteBlock(tx *bolt.Tx, root []byte) error { + if err := tx.Bucket(blocksBucket).Delete(root); err != nil { + return errors.Wrap(err, "could not delete block") + } + + if err := tx.Bucket(blockParentRootIndicesBucket).Delete(root); err != nil { + return errors.Wrap(err, "could not delete block parent indices") + } + + return nil +} + +func (s *Store) deleteValidatorHashes(tx *bolt.Tx, root []byte) error { + ok, err := s.isStateValidatorMigrationOver() + if err != nil { + return err + } + if !ok { + return nil + } + + // Delete the validator hash index + if err = tx.Bucket(blockRootValidatorHashesBucket).Delete(root); err != nil { + return errors.Wrap(err, "could not delete validator index") + } + + return nil } diff --git a/beacon-chain/db/kv/blocks_test.go b/beacon-chain/db/kv/blocks_test.go index cc6805f1fbba..a964dd08adce 100644 --- a/beacon-chain/db/kv/blocks_test.go +++ b/beacon-chain/db/kv/blocks_test.go @@ -2,12 +2,14 @@ package kv import ( "context" + "fmt" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filters" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" @@ -18,6 +20,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" + bolt "go.etcd.io/bbolt" "google.golang.org/protobuf/proto" ) @@ -353,6 +356,189 @@ func TestStore_DeleteFinalizedBlock(t *testing.T) { require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp)) require.ErrorIs(t, db.DeleteBlock(ctx, root), ErrDeleteJustifiedAndFinalized) } + +func TestStore_HistoricalDataBeforeSlot(t *testing.T) { + slotsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch) + db := setupDB(t) + ctx := context.Background() + + // Save genesis block root + require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisBlockRoot)) + + // Create and save blocks for 4 epochs + blks := makeBlocks(t, 0, slotsPerEpoch*4, genesisBlockRoot) + require.NoError(t, db.SaveBlocks(ctx, blks)) + + // Mark state validator migration as complete + err := db.db.Update(func(tx *bolt.Tx) error { + return tx.Bucket(migrationsBucket).Put(migrationStateValidatorsKey, migrationCompleted) + }) + require.NoError(t, err) + + migrated, err := db.isStateValidatorMigrationOver() + require.NoError(t, err) + require.Equal(t, true, migrated) + + // Create state summaries and states for each block + ss := make([]*ethpb.StateSummary, len(blks)) + states := make([]state.BeaconState, len(blks)) + + for i, blk := range blks { + slot := blk.Block().Slot() + r, err := blk.Block().HashTreeRoot() + require.NoError(t, err) + + // Create and save state summary + ss[i] = ðpb.StateSummary{ + Slot: slot, + Root: r[:], + } + + // Create and save state with validator entries + vals := make([]*ethpb.Validator, 2) + for j := range vals { + vals[j] = ðpb.Validator{ + PublicKey: bytesutil.PadTo([]byte{byte(i*j + 1)}, 48), + WithdrawalCredentials: bytesutil.PadTo([]byte{byte(i*j + 2)}, 32), + } + } + + st, err := util.NewBeaconState(func(state *ethpb.BeaconState) error { + state.Validators = vals + state.Slot = slot + return nil + }) + require.NoError(t, err) + require.NoError(t, db.SaveState(ctx, st, r)) + states[i] = st + + // Verify validator entries are saved to db + valsActual, err := db.validatorEntries(ctx, r) + require.NoError(t, err) + for j, val := range valsActual { + require.DeepEqual(t, vals[j], val) + } + } + require.NoError(t, db.SaveStateSummaries(ctx, ss)) + + // Verify slot indices exist before deletion + err = db.db.View(func(tx *bolt.Tx) error { + blockSlotBkt := tx.Bucket(blockSlotIndicesBucket) + stateSlotBkt := tx.Bucket(stateSlotIndicesBucket) + + for i := uint64(0); i < slotsPerEpoch; i++ { + slot := bytesutil.SlotToBytesBigEndian(primitives.Slot(i + 1)) + assert.NotNil(t, blockSlotBkt.Get(slot), "Expected block slot index to exist") + assert.NotNil(t, stateSlotBkt.Get(slot), "Expected state slot index to exist", i) + } + return nil + }) + require.NoError(t, err) + + // Delete data before slot at epoch 1 + require.NoError(t, db.DeleteHistoricalDataBeforeSlot(ctx, primitives.Slot(slotsPerEpoch))) + + // Verify blocks from epoch 0 are deleted + for i := uint64(0); i < slotsPerEpoch; i++ { + root, err := blks[i].Block().HashTreeRoot() + require.NoError(t, err) + + // Check block is deleted + retrievedBlocks, err := db.BlocksBySlot(ctx, primitives.Slot(i)) + require.NoError(t, err) + assert.Equal(t, 0, len(retrievedBlocks)) + + // Verify block does not exist + assert.Equal(t, false, db.HasBlock(ctx, root)) + + // Verify block parent root does not exist + err = db.db.View(func(tx *bolt.Tx) error { + require.Equal(t, 0, len(tx.Bucket(blockParentRootIndicesBucket).Get(root[:]))) + return nil + }) + require.NoError(t, err) + + // Verify state is deleted + hasState := db.HasState(ctx, root) + assert.Equal(t, false, hasState) + + // Verify state summary is deleted + hasSummary := db.HasStateSummary(ctx, root) + assert.Equal(t, false, hasSummary) + + // Verify validator hashes for block roots are deleted + err = db.db.View(func(tx *bolt.Tx) error { + assert.Equal(t, 0, len(tx.Bucket(blockRootValidatorHashesBucket).Get(root[:]))) + return nil + }) + require.NoError(t, err) + } + + // Verify slot indices are deleted + err = db.db.View(func(tx *bolt.Tx) error { + blockSlotBkt := tx.Bucket(blockSlotIndicesBucket) + stateSlotBkt := tx.Bucket(stateSlotIndicesBucket) + + for i := uint64(0); i < slotsPerEpoch; i++ { + slot := bytesutil.SlotToBytesBigEndian(primitives.Slot(i + 1)) + assert.Equal(t, 0, len(blockSlotBkt.Get(slot)), fmt.Sprintf("Expected block slot index to be deleted, slot: %d", slot)) + assert.Equal(t, 0, len(stateSlotBkt.Get(slot)), fmt.Sprintf("Expected state slot index to be deleted, slot: %d", slot)) + } + return nil + }) + require.NoError(t, err) + + // Verify blocks from epochs 1-3 still exist + for i := slotsPerEpoch; i < slotsPerEpoch*4; i++ { + root, err := blks[i].Block().HashTreeRoot() + require.NoError(t, err) + + // Verify block exists + assert.Equal(t, true, db.HasBlock(ctx, root)) + + // Verify remaining block parent root exists, except last slot since we store parent roots of each block. + if i < slotsPerEpoch*4-1 { + err = db.db.View(func(tx *bolt.Tx) error { + require.NotNil(t, tx.Bucket(blockParentRootIndicesBucket).Get(root[:]), fmt.Sprintf("Expected block parent index to be deleted, slot: %d", i)) + return nil + }) + require.NoError(t, err) + } + + // Verify state exists + hasState := db.HasState(ctx, root) + assert.Equal(t, true, hasState) + + // Verify state summary exists + hasSummary := db.HasStateSummary(ctx, root) + assert.Equal(t, true, hasSummary) + + // Verify slot indices still exist + err = db.db.View(func(tx *bolt.Tx) error { + blockSlotBkt := tx.Bucket(blockSlotIndicesBucket) + stateSlotBkt := tx.Bucket(stateSlotIndicesBucket) + + slot := bytesutil.SlotToBytesBigEndian(primitives.Slot(i + 1)) + assert.NotNil(t, blockSlotBkt.Get(slot), "Expected block slot index to exist") + assert.NotNil(t, stateSlotBkt.Get(slot), "Expected state slot index to exist") + return nil + }) + require.NoError(t, err) + + // Verify validator entries still exist + valsActual, err := db.validatorEntries(ctx, root) + require.NoError(t, err) + assert.NotNil(t, valsActual) + + // Verify remaining validator hashes for block roots exists + err = db.db.View(func(tx *bolt.Tx) error { + assert.NotNil(t, tx.Bucket(blockRootValidatorHashesBucket).Get(root[:])) + return nil + }) + require.NoError(t, err) + } +} + func TestStore_GenesisBlock(t *testing.T) { db := setupDB(t) ctx := context.Background() diff --git a/beacon-chain/db/kv/checkpoint.go b/beacon-chain/db/kv/checkpoint.go index 01579396e77d..30e93d769722 100644 --- a/beacon-chain/db/kv/checkpoint.go +++ b/beacon-chain/db/kv/checkpoint.go @@ -8,9 +8,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) var errMissingStateForCheckpoint = errors.New("missing state summary for checkpoint root") diff --git a/beacon-chain/db/kv/deposit_contract.go b/beacon-chain/db/kv/deposit_contract.go index 3e67b1925b43..e747b149c505 100644 --- a/beacon-chain/db/kv/deposit_contract.go +++ b/beacon-chain/db/kv/deposit_contract.go @@ -5,8 +5,8 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // DepositContractAddress returns contract address is the address of diff --git a/beacon-chain/db/kv/encoding.go b/beacon-chain/db/kv/encoding.go index 8af8efa035d3..8149120fe2cb 100644 --- a/beacon-chain/db/kv/encoding.go +++ b/beacon-chain/db/kv/encoding.go @@ -7,8 +7,8 @@ import ( "github.com/golang/snappy" fastssz "github.com/prysmaticlabs/fastssz" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) diff --git a/beacon-chain/db/kv/execution_chain.go b/beacon-chain/db/kv/execution_chain.go index 2d67f4c4d7f4..a496e0e7cee2 100644 --- a/beacon-chain/db/kv/execution_chain.go +++ b/beacon-chain/db/kv/execution_chain.go @@ -5,9 +5,9 @@ import ( "errors" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" v2 "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) diff --git a/beacon-chain/db/kv/finalized_block_roots.go b/beacon-chain/db/kv/finalized_block_roots.go index 3376abc8ef40..1f39d431320a 100644 --- a/beacon-chain/db/kv/finalized_block_roots.go +++ b/beacon-chain/db/kv/finalized_block_roots.go @@ -10,9 +10,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) var previousFinalizedCheckpointKey = []byte("previous-finalized-checkpoint") diff --git a/beacon-chain/db/kv/key.go b/beacon-chain/db/kv/key.go index 60fa9052d3d6..3ec366e3b61f 100644 --- a/beacon-chain/db/kv/key.go +++ b/beacon-chain/db/kv/key.go @@ -52,11 +52,12 @@ func hasDenebBlindKey(enc []byte) bool { return bytes.Equal(enc[:len(denebBlindKey)], denebBlindKey) } -func hasElectraKey(enc []byte) bool { - if len(electraKey) >= len(enc) { +// HasElectraKey verifies if the encoding is Electra compatible. +func HasElectraKey(enc []byte) bool { + if len(ElectraKey) >= len(enc) { return false } - return bytes.Equal(enc[:len(electraKey)], electraKey) + return bytes.Equal(enc[:len(ElectraKey)], ElectraKey) } func hasElectraBlindKey(enc []byte) bool { @@ -65,3 +66,17 @@ func hasElectraBlindKey(enc []byte) bool { } return bytes.Equal(enc[:len(electraBlindKey)], electraBlindKey) } + +func hasFuluKey(enc []byte) bool { + if len(fuluKey) >= len(enc) { + return false + } + return bytes.Equal(enc[:len(fuluKey)], fuluKey) +} + +func hasFuluBlindKey(enc []byte) bool { + if len(fuluBlindKey) >= len(enc) { + return false + } + return bytes.Equal(enc[:len(fuluBlindKey)], fuluBlindKey) +} diff --git a/beacon-chain/db/kv/kv.go b/beacon-chain/db/kv/kv.go index 90f01a63dffa..684eac07592e 100644 --- a/beacon-chain/db/kv/kv.go +++ b/beacon-chain/db/kv/kv.go @@ -107,6 +107,9 @@ var Buckets = [][]byte{ powchainBucket, stateSummaryBucket, stateValidatorsBucket, + lightClientUpdatesBucket, + lightClientBootstrapBucket, + lightClientSyncCommitteeBucket, // Indices buckets. blockSlotIndicesBucket, stateSlotIndicesBucket, diff --git a/beacon-chain/db/kv/lightclient.go b/beacon-chain/db/kv/lightclient.go new file mode 100644 index 000000000000..ad2b4bb6e654 --- /dev/null +++ b/beacon-chain/db/kv/lightclient.go @@ -0,0 +1,305 @@ +package kv + +import ( + "context" + "encoding/binary" + "fmt" + + "github.com/golang/snappy" + "github.com/pkg/errors" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + bolt "go.etcd.io/bbolt" + "google.golang.org/protobuf/proto" +) + +func (s *Store) SaveLightClientUpdate(ctx context.Context, period uint64, update interfaces.LightClientUpdate) error { + _, span := trace.StartSpan(ctx, "BeaconDB.SaveLightClientUpdate") + defer span.End() + + return s.db.Update(func(tx *bolt.Tx) error { + bkt := tx.Bucket(lightClientUpdatesBucket) + enc, err := encodeLightClientUpdate(update) + if err != nil { + return err + } + return bkt.Put(bytesutil.Uint64ToBytesBigEndian(period), enc) + }) +} + +func (s *Store) SaveLightClientBootstrap(ctx context.Context, blockRoot []byte, bootstrap interfaces.LightClientBootstrap) error { + _, span := trace.StartSpan(ctx, "BeaconDB.SaveLightClientBootstrap") + defer span.End() + + bootstrapCopy, err := light_client.NewWrappedBootstrap(proto.Clone(bootstrap.Proto())) + if err != nil { + return errors.Wrap(err, "could not clone light client bootstrap") + } + syncCommitteeHash, err := bootstrapCopy.CurrentSyncCommittee().HashTreeRoot() + if err != nil { + return errors.Wrap(err, "could not hash current sync committee") + } + + return s.db.Update(func(tx *bolt.Tx) error { + syncCommitteeBucket := tx.Bucket(lightClientSyncCommitteeBucket) + syncCommitteeAlreadyExists := syncCommitteeBucket.Get(syncCommitteeHash[:]) != nil + if !syncCommitteeAlreadyExists { + enc, err := bootstrapCopy.CurrentSyncCommittee().MarshalSSZ() + if err != nil { + return errors.Wrap(err, "could not marshal current sync committee") + } + if err := syncCommitteeBucket.Put(syncCommitteeHash[:], enc); err != nil { + return errors.Wrap(err, "could not save current sync committee") + } + } + + err = bootstrapCopy.SetCurrentSyncCommittee(createEmptySyncCommittee()) + if err != nil { + return errors.Wrap(err, "could not set current sync committee to zero while saving") + } + + bkt := tx.Bucket(lightClientBootstrapBucket) + enc, err := encodeLightClientBootstrap(bootstrapCopy, syncCommitteeHash) + if err != nil { + return err + } + return bkt.Put(blockRoot, enc) + }) +} + +func (s *Store) LightClientBootstrap(ctx context.Context, blockRoot []byte) (interfaces.LightClientBootstrap, error) { + _, span := trace.StartSpan(ctx, "BeaconDB.LightClientBootstrap") + defer span.End() + + var bootstrap interfaces.LightClientBootstrap + var syncCommitteeHash []byte + err := s.db.View(func(tx *bolt.Tx) error { + bkt := tx.Bucket(lightClientBootstrapBucket) + syncCommitteeBucket := tx.Bucket(lightClientSyncCommitteeBucket) + enc := bkt.Get(blockRoot) + if enc == nil { + return nil + } + var err error + bootstrap, syncCommitteeHash, err = decodeLightClientBootstrap(enc) + if err != nil { + return errors.Wrap(err, "could not decode light client bootstrap") + } + var syncCommitteeBytes = syncCommitteeBucket.Get(syncCommitteeHash) + if syncCommitteeBytes == nil { + return errors.New("sync committee not found") + } + syncCommittee := ðpb.SyncCommittee{} + if err := syncCommittee.UnmarshalSSZ(syncCommitteeBytes); err != nil { + return errors.Wrap(err, "could not unmarshal sync committee") + } + err = bootstrap.SetCurrentSyncCommittee(syncCommittee) + if err != nil { + return errors.Wrap(err, "could not set current sync committee while retrieving") + } + return err + }) + return bootstrap, err +} + +func createEmptySyncCommittee() *ethpb.SyncCommittee { + syncCom := make([][]byte, params.BeaconConfig().SyncCommitteeSize) + for i := 0; uint64(i) < params.BeaconConfig().SyncCommitteeSize; i++ { + syncCom[i] = make([]byte, fieldparams.BLSPubkeyLength) + } + + return ðpb.SyncCommittee{ + Pubkeys: syncCom, + AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), + } +} + +func encodeLightClientBootstrap(bootstrap interfaces.LightClientBootstrap, syncCommitteeHash [32]byte) ([]byte, error) { + key, err := keyForLightClientUpdate(bootstrap.Version()) + if err != nil { + return nil, err + } + enc, err := bootstrap.MarshalSSZ() + if err != nil { + return nil, errors.Wrap(err, "could not marshal light client bootstrap") + } + fullEnc := make([]byte, len(key)+32+len(enc)) + copy(fullEnc, key) + copy(fullEnc[len(key):len(key)+32], syncCommitteeHash[:]) + copy(fullEnc[len(key)+32:], enc) + compressedEnc := snappy.Encode(nil, fullEnc) + return compressedEnc, nil +} + +func decodeLightClientBootstrap(enc []byte) (interfaces.LightClientBootstrap, []byte, error) { + var err error + enc, err = snappy.Decode(nil, enc) + if err != nil { + return nil, nil, errors.Wrap(err, "could not snappy decode light client bootstrap") + } + var m proto.Message + var syncCommitteeHash []byte + switch { + case hasAltairKey(enc): + bootstrap := ðpb.LightClientBootstrapAltair{} + if err := bootstrap.UnmarshalSSZ(enc[len(altairKey)+32:]); err != nil { + return nil, nil, errors.Wrap(err, "could not unmarshal Altair light client bootstrap") + } + m = bootstrap + syncCommitteeHash = enc[len(altairKey) : len(altairKey)+32] + case hasCapellaKey(enc): + bootstrap := ðpb.LightClientBootstrapCapella{} + if err := bootstrap.UnmarshalSSZ(enc[len(capellaKey)+32:]); err != nil { + return nil, nil, errors.Wrap(err, "could not unmarshal Capella light client bootstrap") + } + m = bootstrap + syncCommitteeHash = enc[len(capellaKey) : len(capellaKey)+32] + case hasDenebKey(enc): + bootstrap := ðpb.LightClientBootstrapDeneb{} + if err := bootstrap.UnmarshalSSZ(enc[len(denebKey)+32:]); err != nil { + return nil, nil, errors.Wrap(err, "could not unmarshal Deneb light client bootstrap") + } + m = bootstrap + syncCommitteeHash = enc[len(denebKey) : len(denebKey)+32] + case HasElectraKey(enc): + bootstrap := ðpb.LightClientBootstrapElectra{} + if err := bootstrap.UnmarshalSSZ(enc[len(ElectraKey)+32:]); err != nil { + return nil, nil, errors.Wrap(err, "could not unmarshal Electra light client bootstrap") + } + m = bootstrap + syncCommitteeHash = enc[len(ElectraKey) : len(ElectraKey)+32] + default: + return nil, nil, errors.New("decoding of saved light client bootstrap is unsupported") + } + bootstrap, err := light_client.NewWrappedBootstrap(m) + return bootstrap, syncCommitteeHash, err +} + +func (s *Store) LightClientUpdates(ctx context.Context, startPeriod, endPeriod uint64) (map[uint64]interfaces.LightClientUpdate, error) { + _, span := trace.StartSpan(ctx, "BeaconDB.LightClientUpdates") + defer span.End() + + if startPeriod > endPeriod { + return nil, fmt.Errorf("start period %d is greater than end period %d", startPeriod, endPeriod) + } + + updates := make(map[uint64]interfaces.LightClientUpdate) + err := s.db.View(func(tx *bolt.Tx) error { + bkt := tx.Bucket(lightClientUpdatesBucket) + c := bkt.Cursor() + + firstPeriodInDb, _ := c.First() + if firstPeriodInDb == nil { + return nil + } + + for k, v := c.Seek(bytesutil.Uint64ToBytesBigEndian(startPeriod)); k != nil && binary.BigEndian.Uint64(k) <= endPeriod; k, v = c.Next() { + currentPeriod := binary.BigEndian.Uint64(k) + + update, err := decodeLightClientUpdate(v) + if err != nil { + return err + } + updates[currentPeriod] = update + } + + return nil + }) + + if err != nil { + return nil, err + } + return updates, nil +} + +func (s *Store) LightClientUpdate(ctx context.Context, period uint64) (interfaces.LightClientUpdate, error) { + _, span := trace.StartSpan(ctx, "BeaconDB.LightClientUpdate") + defer span.End() + + var update interfaces.LightClientUpdate + err := s.db.View(func(tx *bolt.Tx) error { + bkt := tx.Bucket(lightClientUpdatesBucket) + updateBytes := bkt.Get(bytesutil.Uint64ToBytesBigEndian(period)) + if updateBytes == nil { + return nil + } + var err error + update, err = decodeLightClientUpdate(updateBytes) + return err + }) + return update, err +} + +func encodeLightClientUpdate(update interfaces.LightClientUpdate) ([]byte, error) { + key, err := keyForLightClientUpdate(update.Version()) + if err != nil { + return nil, err + } + enc, err := update.MarshalSSZ() + if err != nil { + return nil, errors.Wrap(err, "could not marshal light client update") + } + fullEnc := make([]byte, len(key)+len(enc)) + copy(fullEnc, key) + copy(fullEnc[len(key):], enc) + return snappy.Encode(nil, fullEnc), nil +} + +func decodeLightClientUpdate(enc []byte) (interfaces.LightClientUpdate, error) { + var err error + enc, err = snappy.Decode(nil, enc) + if err != nil { + return nil, errors.Wrap(err, "could not snappy decode light client update") + } + var m proto.Message + switch { + case hasAltairKey(enc): + update := ðpb.LightClientUpdateAltair{} + if err := update.UnmarshalSSZ(enc[len(altairKey):]); err != nil { + return nil, errors.Wrap(err, "could not unmarshal Altair light client update") + } + m = update + case hasCapellaKey(enc): + update := ðpb.LightClientUpdateCapella{} + if err := update.UnmarshalSSZ(enc[len(capellaKey):]); err != nil { + return nil, errors.Wrap(err, "could not unmarshal Capella light client update") + } + m = update + case hasDenebKey(enc): + update := ðpb.LightClientUpdateDeneb{} + if err := update.UnmarshalSSZ(enc[len(denebKey):]); err != nil { + return nil, errors.Wrap(err, "could not unmarshal Deneb light client update") + } + m = update + case HasElectraKey(enc): + update := ðpb.LightClientUpdateElectra{} + if err := update.UnmarshalSSZ(enc[len(ElectraKey):]); err != nil { + return nil, errors.Wrap(err, "could not unmarshal Electra light client update") + } + m = update + default: + return nil, errors.New("decoding of saved light client update is unsupported") + } + return light_client.NewWrappedUpdate(m) +} + +func keyForLightClientUpdate(v int) ([]byte, error) { + switch v { + case version.Electra: + return ElectraKey, nil + case version.Deneb: + return denebKey, nil + case version.Capella: + return capellaKey, nil + case version.Altair: + return altairKey, nil + default: + return nil, fmt.Errorf("unsupported light client update version %s", version.String(v)) + } +} diff --git a/beacon-chain/db/kv/lightclient_test.go b/beacon-chain/db/kv/lightclient_test.go new file mode 100644 index 000000000000..ad5b879f8dc7 --- /dev/null +++ b/beacon-chain/db/kv/lightclient_test.go @@ -0,0 +1,956 @@ +package kv + +import ( + "context" + "fmt" + "math/rand" + "testing" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/prysmaticlabs/prysm/v5/time/slots" + bolt "go.etcd.io/bbolt" + "google.golang.org/protobuf/proto" +) + +func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { + config := params.BeaconConfig() + var slot primitives.Slot + var header interfaces.LightClientHeader + var st state.BeaconState + var err error + + sampleRoot := make([]byte, 32) + for i := 0; i < 32; i++ { + sampleRoot[i] = byte(i) + } + + sampleExecutionBranch := make([][]byte, fieldparams.ExecutionBranchDepth) + for i := 0; i < 4; i++ { + sampleExecutionBranch[i] = make([]byte, 32) + for j := 0; j < 32; j++ { + sampleExecutionBranch[i][j] = byte(i + j) + } + } + + switch v { + case version.Altair: + slot = primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + }) + require.NoError(t, err) + st, err = util.NewBeaconState() + require.NoError(t, err) + case version.Capella: + slot = primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + Execution: &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: sampleExecutionBranch, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateCapella() + require.NoError(t, err) + case version.Deneb: + slot = primitives.Slot(config.DenebForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: sampleExecutionBranch, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateDeneb() + require.NoError(t, err) + case version.Electra: + slot = primitives.Slot(config.ElectraForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: sampleExecutionBranch, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateElectra() + require.NoError(t, err) + case version.Fulu: + slot = primitives.Slot(config.FuluForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: sampleExecutionBranch, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateFulu() + require.NoError(t, err) + default: + return nil, fmt.Errorf("unsupported version %s", version.String(v)) + } + + update, err := createDefaultLightClientUpdate(slot, st) + require.NoError(t, err) + update.SetSignatureSlot(slot - 1) + syncCommitteeBits := make([]byte, 64) + syncCommitteeSignature := make([]byte, 96) + update.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: syncCommitteeBits, + SyncCommitteeSignature: syncCommitteeSignature, + }) + + require.NoError(t, update.SetAttestedHeader(header)) + require.NoError(t, update.SetFinalizedHeader(header)) + + return update, nil +} + +func TestStore_LightClientUpdate_CanSaveRetrieve(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + cfg.AltairForkEpoch = 0 + cfg.CapellaForkEpoch = 1 + cfg.DenebForkEpoch = 2 + cfg.ElectraForkEpoch = 3 + cfg.FuluForkEpoch = 3 + params.OverrideBeaconConfig(cfg) + + db := setupDB(t) + ctx := context.Background() + + t.Run("Altair", func(t *testing.T) { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + period := uint64(1) + + err = db.SaveLightClientUpdate(ctx, period, update) + require.NoError(t, err) + + retrievedUpdate, err := db.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") + }) + t.Run("Capella", func(t *testing.T) { + update, err := createUpdate(t, version.Capella) + require.NoError(t, err) + period := uint64(1) + err = db.SaveLightClientUpdate(ctx, period, update) + require.NoError(t, err) + + retrievedUpdate, err := db.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") + }) + t.Run("Deneb", func(t *testing.T) { + update, err := createUpdate(t, version.Deneb) + require.NoError(t, err) + period := uint64(1) + err = db.SaveLightClientUpdate(ctx, period, update) + require.NoError(t, err) + + retrievedUpdate, err := db.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") + }) + t.Run("Electra", func(t *testing.T) { + update, err := createUpdate(t, version.Electra) + require.NoError(t, err) + period := uint64(1) + err = db.SaveLightClientUpdate(ctx, period, update) + require.NoError(t, err) + + retrievedUpdate, err := db.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") + }) + t.Run("Fulu", func(t *testing.T) { + update, err := createUpdate(t, version.Fulu) + require.NoError(t, err) + period := uint64(1) + err = db.SaveLightClientUpdate(ctx, period, update) + require.NoError(t, err) + + retrievedUpdate, err := db.LightClientUpdate(ctx, period) + require.NoError(t, err) + require.DeepEqual(t, update, retrievedUpdate, "retrieved update does not match saved update") + }) +} + +func TestStore_LightClientUpdates_canRetrieveRange(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + updates := make([]interfaces.LightClientUpdate, 0, 3) + for i := 1; i <= 3; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for i, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(i+1), update) + require.NoError(t, err) + } + + // Retrieve the updates + retrievedUpdatesMap, err := db.LightClientUpdates(ctx, 1, 3) + require.NoError(t, err) + require.Equal(t, len(updates), len(retrievedUpdatesMap), "retrieved updates do not match saved updates") + for i, update := range updates { + require.DeepEqual(t, update, retrievedUpdatesMap[uint64(i+1)], "retrieved update does not match saved update") + } + +} + +func TestStore_LightClientUpdate_EndPeriodSmallerThanStartPeriod(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + updates := make([]interfaces.LightClientUpdate, 0, 3) + for i := 1; i <= 3; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for i, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(i+1), update) + require.NoError(t, err) + } + + // Retrieve the updates + retrievedUpdates, err := db.LightClientUpdates(ctx, 3, 1) + require.NotNil(t, err) + require.Equal(t, err.Error(), "start period 3 is greater than end period 1") + require.IsNil(t, retrievedUpdates) + +} + +func TestStore_LightClientUpdate_EndPeriodEqualToStartPeriod(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + updates := make([]interfaces.LightClientUpdate, 0, 3) + for i := 1; i <= 3; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for i, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(i+1), update) + require.NoError(t, err) + } + + // Retrieve the updates + retrievedUpdates, err := db.LightClientUpdates(ctx, 2, 2) + require.NoError(t, err) + require.Equal(t, 1, len(retrievedUpdates)) + require.DeepEqual(t, updates[1], retrievedUpdates[2], "retrieved update does not match saved update") +} + +func TestStore_LightClientUpdate_StartPeriodBeforeFirstUpdate(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + updates := make([]interfaces.LightClientUpdate, 0, 3) + for i := 1; i <= 3; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for i, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(i+1), update) + require.NoError(t, err) + } + + // Retrieve the updates + retrievedUpdates, err := db.LightClientUpdates(ctx, 0, 4) + require.NoError(t, err) + require.Equal(t, 3, len(retrievedUpdates)) + for i, update := range updates { + require.DeepEqual(t, update, retrievedUpdates[uint64(i+1)], "retrieved update does not match saved update") + } +} + +func TestStore_LightClientUpdate_EndPeriodAfterLastUpdate(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + updates := make([]interfaces.LightClientUpdate, 0, 3) + for i := 1; i <= 3; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for i, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(i+1), update) + require.NoError(t, err) + } + + // Retrieve the updates + retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 6) + require.NoError(t, err) + require.Equal(t, 3, len(retrievedUpdates)) + for i, update := range updates { + require.DeepEqual(t, update, retrievedUpdates[uint64(i+1)], "retrieved update does not match saved update") + } +} + +func TestStore_LightClientUpdate_PartialUpdates(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + updates := make([]interfaces.LightClientUpdate, 0, 3) + for i := 1; i <= 3; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for i, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(i+1), update) + require.NoError(t, err) + } + + // Retrieve the updates + retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 2) + require.NoError(t, err) + require.Equal(t, 2, len(retrievedUpdates)) + for i, update := range updates[:2] { + require.DeepEqual(t, update, retrievedUpdates[uint64(i+1)], "retrieved update does not match saved update") + } +} + +func TestStore_LightClientUpdate_MissingPeriods_SimpleData(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + updates := make([]interfaces.LightClientUpdate, 0, 4) + for i := 1; i <= 4; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for i, update := range updates { + if i == 1 || i == 2 { + continue + } + err := db.SaveLightClientUpdate(ctx, uint64(i+1), update) + require.NoError(t, err) + } + + // Retrieve the updates + retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 4) + require.NoError(t, err) + require.Equal(t, 2, len(retrievedUpdates)) + require.DeepEqual(t, updates[0], retrievedUpdates[uint64(1)], "retrieved update does not match saved update") + require.DeepEqual(t, updates[3], retrievedUpdates[uint64(4)], "retrieved update does not match saved update") + + // Retrieve the updates from the middle + retrievedUpdates, err = db.LightClientUpdates(ctx, 2, 4) + require.NoError(t, err) + require.Equal(t, 1, len(retrievedUpdates)) + require.DeepEqual(t, updates[3], retrievedUpdates[4], "retrieved update does not match saved update") + + // Retrieve the updates from after the missing period + retrievedUpdates, err = db.LightClientUpdates(ctx, 4, 4) + require.NoError(t, err) + require.Equal(t, 1, len(retrievedUpdates)) + require.DeepEqual(t, updates[3], retrievedUpdates[4], "retrieved update does not match saved update") + + //retrieve the updates from before the missing period to after the missing period + retrievedUpdates, err = db.LightClientUpdates(ctx, 0, 6) + require.NoError(t, err) + require.Equal(t, 2, len(retrievedUpdates)) + require.DeepEqual(t, updates[0], retrievedUpdates[uint64(1)], "retrieved update does not match saved update") + require.DeepEqual(t, updates[3], retrievedUpdates[uint64(4)], "retrieved update does not match saved update") +} + +func TestStore_LightClientUpdate_EmptyDB(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + + // Retrieve the updates + retrievedUpdates, err := db.LightClientUpdates(ctx, 1, 3) + require.IsNil(t, err) + require.Equal(t, 0, len(retrievedUpdates)) +} + +func TestStore_LightClientUpdate_RetrieveMissingPeriodDistributed(t *testing.T) { + db := setupDB(t) + ctx := context.Background() + updates := make([]interfaces.LightClientUpdate, 0, 5) + for i := 1; i <= 5; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for i, update := range updates { + if i == 1 || i == 3 { + continue + } + err := db.SaveLightClientUpdate(ctx, uint64(i+1), update) + require.NoError(t, err) + } + + // Retrieve the updates + retrievedUpdates, err := db.LightClientUpdates(ctx, 0, 7) + require.NoError(t, err) + require.Equal(t, 3, len(retrievedUpdates)) + require.DeepEqual(t, updates[0], retrievedUpdates[uint64(1)], "retrieved update does not match saved update") + require.DeepEqual(t, updates[2], retrievedUpdates[uint64(3)], "retrieved update does not match saved update") + require.DeepEqual(t, updates[4], retrievedUpdates[uint64(5)], "retrieved update does not match saved update") +} + +func createDefaultLightClientUpdate(currentSlot primitives.Slot, attestedState state.BeaconState) (interfaces.LightClientUpdate, error) { + currentEpoch := slots.ToEpoch(currentSlot) + + syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize + pubKeys := make([][]byte, syncCommitteeSize) + for i := uint64(0); i < syncCommitteeSize; i++ { + pubKeys[i] = make([]byte, fieldparams.BLSPubkeyLength) + } + nextSyncCommittee := &pb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), + } + + var nextSyncCommitteeBranch [][]byte + if attestedState.Version() >= version.Electra { + nextSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepthElectra) + } else { + nextSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepth) + } + for i := 0; i < len(nextSyncCommitteeBranch); i++ { + nextSyncCommitteeBranch[i] = make([]byte, fieldparams.RootLength) + } + + executionBranch := make([][]byte, fieldparams.ExecutionBranchDepth) + for i := 0; i < fieldparams.ExecutionBranchDepth; i++ { + executionBranch[i] = make([]byte, 32) + } + + var finalityBranch [][]byte + if attestedState.Version() >= version.Electra { + finalityBranch = make([][]byte, fieldparams.FinalityBranchDepthElectra) + } else { + finalityBranch = make([][]byte, fieldparams.FinalityBranchDepth) + } + for i := 0; i < len(finalityBranch); i++ { + finalityBranch[i] = make([]byte, 32) + } + + var m proto.Message + if currentEpoch < params.BeaconConfig().CapellaForkEpoch { + m = &pb.LightClientUpdateAltair{ + AttestedHeader: &pb.LightClientHeaderAltair{}, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + } + } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { + m = &pb.LightClientUpdateCapella{ + AttestedHeader: &pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderCapella{}, + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + } + } else if currentEpoch < params.BeaconConfig().ElectraForkEpoch { + m = &pb.LightClientUpdateDeneb{ + AttestedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + } + } else { + if attestedState.Version() >= version.Electra { + m = &pb.LightClientUpdateElectra{ + AttestedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + } + } else { + m = &pb.LightClientUpdateDeneb{ + AttestedHeader: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{}, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{}, + ExecutionBranch: executionBranch, + }, + NextSyncCommittee: nextSyncCommittee, + NextSyncCommitteeBranch: nextSyncCommitteeBranch, + FinalityBranch: finalityBranch, + } + } + } + + return light_client.NewWrappedUpdate(m) +} + +func TestStore_LightClientBootstrap_CanSaveRetrieve(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + cfg.AltairForkEpoch = 0 + cfg.CapellaForkEpoch = 1 + cfg.DenebForkEpoch = 2 + cfg.ElectraForkEpoch = 3 + cfg.EpochsPerSyncCommitteePeriod = 1 + params.OverrideBeaconConfig(cfg) + + db := setupDB(t) + ctx := context.Background() + + t.Run("Nil", func(t *testing.T) { + retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("NilBlockRoot")) + require.NoError(t, err) + require.IsNil(t, retrievedBootstrap) + }) + + t.Run("Altair", func(t *testing.T) { + bootstrap, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))) + require.NoError(t, err) + + err = bootstrap.SetCurrentSyncCommittee(createRandomSyncCommittee()) + require.NoError(t, err) + + err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair"), bootstrap) + require.NoError(t, err) + + retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair")) + require.NoError(t, err) + require.DeepEqual(t, bootstrap.Header(), retrievedBootstrap.Header(), "retrieved bootstrap header does not match saved bootstrap header") + require.DeepEqual(t, bootstrap.CurrentSyncCommittee(), retrievedBootstrap.CurrentSyncCommittee(), "retrieved bootstrap sync committee does not match saved bootstrap sync committee") + savedBranch, err := bootstrap.CurrentSyncCommitteeBranch() + require.NoError(t, err) + retrievedBranch, err := retrievedBootstrap.CurrentSyncCommitteeBranch() + require.NoError(t, err) + require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap sync committee branch does not match saved bootstrap sync committee branch") + }) + + t.Run("Capella", func(t *testing.T) { + bootstrap, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().CapellaForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))) + require.NoError(t, err) + + err = bootstrap.SetCurrentSyncCommittee(createRandomSyncCommittee()) + require.NoError(t, err) + + err = db.SaveLightClientBootstrap(ctx, []byte("blockRootCapella"), bootstrap) + require.NoError(t, err) + + retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootCapella")) + require.NoError(t, err) + require.DeepEqual(t, bootstrap.Header(), retrievedBootstrap.Header(), "retrieved bootstrap header does not match saved bootstrap header") + require.DeepEqual(t, bootstrap.CurrentSyncCommittee(), retrievedBootstrap.CurrentSyncCommittee(), "retrieved bootstrap sync committee does not match saved bootstrap sync committee") + savedBranch, err := bootstrap.CurrentSyncCommitteeBranch() + require.NoError(t, err) + retrievedBranch, err := retrievedBootstrap.CurrentSyncCommitteeBranch() + require.NoError(t, err) + require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap sync committee branch does not match saved bootstrap sync committee branch") + }) + + t.Run("Deneb", func(t *testing.T) { + bootstrap, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().DenebForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))) + require.NoError(t, err) + + err = bootstrap.SetCurrentSyncCommittee(createRandomSyncCommittee()) + require.NoError(t, err) + + err = db.SaveLightClientBootstrap(ctx, []byte("blockRootDeneb"), bootstrap) + require.NoError(t, err) + + retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootDeneb")) + require.NoError(t, err) + require.DeepEqual(t, bootstrap.Header(), retrievedBootstrap.Header(), "retrieved bootstrap header does not match saved bootstrap header") + require.DeepEqual(t, bootstrap.CurrentSyncCommittee(), retrievedBootstrap.CurrentSyncCommittee(), "retrieved bootstrap sync committee does not match saved bootstrap sync committee") + savedBranch, err := bootstrap.CurrentSyncCommitteeBranch() + require.NoError(t, err) + retrievedBranch, err := retrievedBootstrap.CurrentSyncCommitteeBranch() + require.NoError(t, err) + require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap sync committee branch does not match saved bootstrap sync committee branch") + }) + + t.Run("Electra", func(t *testing.T) { + bootstrap, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().ElectraForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))) + require.NoError(t, err) + + err = bootstrap.SetCurrentSyncCommittee(createRandomSyncCommittee()) + require.NoError(t, err) + + err = db.SaveLightClientBootstrap(ctx, []byte("blockRootElectra"), bootstrap) + require.NoError(t, err) + + retrievedBootstrap, err := db.LightClientBootstrap(ctx, []byte("blockRootElectra")) + require.NoError(t, err) + require.DeepEqual(t, bootstrap.Header(), retrievedBootstrap.Header(), "retrieved bootstrap header does not match saved bootstrap header") + require.DeepEqual(t, bootstrap.CurrentSyncCommittee(), retrievedBootstrap.CurrentSyncCommittee(), "retrieved bootstrap sync committee does not match saved bootstrap sync committee") + savedBranch, err := bootstrap.CurrentSyncCommitteeBranchElectra() + require.NoError(t, err) + retrievedBranch, err := retrievedBootstrap.CurrentSyncCommitteeBranchElectra() + require.NoError(t, err) + require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap sync committee branch does not match saved bootstrap sync committee branch") + }) +} + +func TestStore_LightClientBootstrap_MultipleBootstrapsWithSameSyncCommittee(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + cfg.AltairForkEpoch = 0 + cfg.CapellaForkEpoch = 1 + cfg.DenebForkEpoch = 2 + cfg.ElectraForkEpoch = 3 + cfg.EpochsPerSyncCommitteePeriod = 1 + params.OverrideBeaconConfig(cfg) + + db := setupDB(t) + ctx := context.Background() + + bootstrap1, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))) + require.NoError(t, err) + bootstrap2, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))) + require.NoError(t, err) + + randomSyncCommittee := createRandomSyncCommittee() + + err = bootstrap1.SetCurrentSyncCommittee(randomSyncCommittee) + require.NoError(t, err) + err = bootstrap2.SetCurrentSyncCommittee(randomSyncCommittee) + require.NoError(t, err) + + err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair1"), bootstrap1) + require.NoError(t, err) + err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair2"), bootstrap2) + require.NoError(t, err) + + retrievedBootstrap1, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair1")) + require.NoError(t, err) + retrievedBootstrap2, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair2")) + require.NoError(t, err) + + require.DeepEqual(t, bootstrap1.Header(), retrievedBootstrap1.Header(), "retrieved bootstrap1 header does not match saved bootstrap1 header") + require.DeepEqual(t, randomSyncCommittee, retrievedBootstrap1.CurrentSyncCommittee(), "retrieved bootstrap1 sync committee does not match saved bootstrap1 sync committee") + savedBranch, err := bootstrap1.CurrentSyncCommitteeBranch() + require.NoError(t, err) + retrievedBranch, err := retrievedBootstrap1.CurrentSyncCommitteeBranch() + require.NoError(t, err) + require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap1 sync committee branch does not match saved bootstrap1 sync committee branch") + + require.DeepEqual(t, bootstrap2.Header(), retrievedBootstrap2.Header(), "retrieved bootstrap1 header does not match saved bootstrap1 header") + require.DeepEqual(t, randomSyncCommittee, retrievedBootstrap2.CurrentSyncCommittee(), "retrieved bootstrap1 sync committee does not match saved bootstrap1 sync committee") + savedBranch2, err := bootstrap2.CurrentSyncCommitteeBranch() + require.NoError(t, err) + retrievedBranch2, err := retrievedBootstrap2.CurrentSyncCommitteeBranch() + require.NoError(t, err) + require.DeepEqual(t, savedBranch2, retrievedBranch2, "retrieved bootstrap1 sync committee branch does not match saved bootstrap1 sync committee branch") + + // Ensure that the sync committee is only stored once + err = db.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket(lightClientSyncCommitteeBucket) + require.NotNil(t, bucket) + count := bucket.Stats().KeyN + require.Equal(t, 1, count) + return nil + }) + require.NoError(t, err) +} + +func TestStore_LightClientBootstrap_MultipleBootstrapsWithDifferentSyncCommittees(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + cfg.AltairForkEpoch = 0 + cfg.CapellaForkEpoch = 1 + cfg.DenebForkEpoch = 2 + cfg.ElectraForkEpoch = 3 + cfg.EpochsPerSyncCommitteePeriod = 1 + params.OverrideBeaconConfig(cfg) + + db := setupDB(t) + ctx := context.Background() + + bootstrap1, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))) + require.NoError(t, err) + bootstrap2, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))) + require.NoError(t, err) + + err = bootstrap1.SetCurrentSyncCommittee(createRandomSyncCommittee()) + require.NoError(t, err) + err = bootstrap2.SetCurrentSyncCommittee(createRandomSyncCommittee()) + require.NoError(t, err) + + err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair1"), bootstrap1) + require.NoError(t, err) + err = db.SaveLightClientBootstrap(ctx, []byte("blockRootAltair2"), bootstrap2) + require.NoError(t, err) + + retrievedBootstrap1, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair1")) + require.NoError(t, err) + retrievedBootstrap2, err := db.LightClientBootstrap(ctx, []byte("blockRootAltair2")) + require.NoError(t, err) + + require.DeepEqual(t, bootstrap1.Header(), retrievedBootstrap1.Header(), "retrieved bootstrap1 header does not match saved bootstrap1 header") + require.DeepEqual(t, bootstrap1.CurrentSyncCommittee(), retrievedBootstrap1.CurrentSyncCommittee(), "retrieved bootstrap1 sync committee does not match saved bootstrap1 sync committee") + savedBranch, err := bootstrap1.CurrentSyncCommitteeBranch() + require.NoError(t, err) + retrievedBranch, err := retrievedBootstrap1.CurrentSyncCommitteeBranch() + require.NoError(t, err) + require.DeepEqual(t, savedBranch, retrievedBranch, "retrieved bootstrap1 sync committee branch does not match saved bootstrap1 sync committee branch") + + require.DeepEqual(t, bootstrap2.Header(), retrievedBootstrap2.Header(), "retrieved bootstrap1 header does not match saved bootstrap1 header") + require.DeepEqual(t, bootstrap2.CurrentSyncCommittee(), retrievedBootstrap2.CurrentSyncCommittee(), "retrieved bootstrap1 sync committee does not match saved bootstrap1 sync committee") + savedBranch2, err := bootstrap2.CurrentSyncCommitteeBranch() + require.NoError(t, err) + retrievedBranch2, err := retrievedBootstrap2.CurrentSyncCommitteeBranch() + require.NoError(t, err) + require.DeepEqual(t, savedBranch2, retrievedBranch2, "retrieved bootstrap1 sync committee branch does not match saved bootstrap1 sync committee branch") + + // Ensure that the sync committee is stored twice + err = db.db.View(func(tx *bolt.Tx) error { + bucket := tx.Bucket(lightClientSyncCommitteeBucket) + require.NotNil(t, bucket) + count := bucket.Stats().KeyN + require.Equal(t, 2, count) + return nil + }) + require.NoError(t, err) +} + +func createDefaultLightClientBootstrap(currentSlot primitives.Slot) (interfaces.LightClientBootstrap, error) { + currentEpoch := slots.ToEpoch(currentSlot) + syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize + pubKeys := make([][]byte, syncCommitteeSize) + for i := uint64(0); i < syncCommitteeSize; i++ { + pubKeys[i] = make([]byte, fieldparams.BLSPubkeyLength) + } + currentSyncCommittee := &pb.SyncCommittee{ + Pubkeys: pubKeys, + AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), + } + + var currentSyncCommitteeBranch [][]byte + if currentEpoch >= params.BeaconConfig().ElectraForkEpoch { + currentSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepthElectra) + } else { + currentSyncCommitteeBranch = make([][]byte, fieldparams.SyncCommitteeBranchDepth) + } + for i := 0; i < len(currentSyncCommitteeBranch); i++ { + currentSyncCommitteeBranch[i] = make([]byte, fieldparams.RootLength) + } + + executionBranch := make([][]byte, fieldparams.ExecutionBranchDepth) + for i := 0; i < fieldparams.ExecutionBranchDepth; i++ { + executionBranch[i] = make([]byte, 32) + } + + // TODO: can this be based on the current epoch? + var m proto.Message + if currentEpoch < params.BeaconConfig().CapellaForkEpoch { + m = &pb.LightClientBootstrapAltair{ + Header: &pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else if currentEpoch < params.BeaconConfig().DenebForkEpoch { + m = &pb.LightClientBootstrapCapella{ + Header: &pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else if currentEpoch < params.BeaconConfig().ElectraForkEpoch { + m = &pb.LightClientBootstrapDeneb{ + Header: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, + }, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } else { + m = &pb.LightClientBootstrapElectra{ + Header: &pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: 0, + GasUsed: 0, + }, + ExecutionBranch: executionBranch, + }, + CurrentSyncCommittee: currentSyncCommittee, + CurrentSyncCommitteeBranch: currentSyncCommitteeBranch, + } + } + + return light_client.NewWrappedBootstrap(m) +} + +func createRandomSyncCommittee() *pb.SyncCommittee { + // random number between 2 and 128 + base := rand.Int()%127 + 2 + + syncCom := make([][]byte, params.BeaconConfig().SyncCommitteeSize) + for i := 0; uint64(i) < params.BeaconConfig().SyncCommitteeSize; i++ { + if i%base == 0 { + syncCom[i] = make([]byte, fieldparams.BLSPubkeyLength) + syncCom[i][0] = 1 + continue + } + syncCom[i] = make([]byte, fieldparams.BLSPubkeyLength) + } + + return &pb.SyncCommittee{ + Pubkeys: syncCom, + AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), + } +} diff --git a/beacon-chain/db/kv/schema.go b/beacon-chain/db/kv/schema.go index 108849e9f652..77264be47c49 100644 --- a/beacon-chain/db/kv/schema.go +++ b/beacon-chain/db/kv/schema.go @@ -17,6 +17,11 @@ var ( feeRecipientBucket = []byte("fee-recipient") registrationBucket = []byte("registration") + // Light Client Updates Bucket + lightClientUpdatesBucket = []byte("light-client-updates") + lightClientBootstrapBucket = []byte("light-client-bootstrap") + lightClientSyncCommitteeBucket = []byte("light-client-sync-committee") + // Deprecated: This bucket was migrated in PR 6461. Do not use, except for migrations. slotsHasObjectBucket = []byte("slots-has-objects") // Deprecated: This bucket was migrated in PR 6461. Do not use, except for migrations. @@ -48,8 +53,10 @@ var ( saveBlindedBeaconBlocksKey = []byte("save-blinded-beacon-blocks") denebKey = []byte("deneb") denebBlindKey = []byte("blind-deneb") - electraKey = []byte("electra") + ElectraKey = []byte("electra") electraBlindKey = []byte("blind-electra") + fuluKey = []byte("fulu") + fuluBlindKey = []byte("blind-fulu") // block root included in the beacon state used by weak subjectivity initial sync originCheckpointBlockRootKey = []byte("origin-checkpoint-block-root") diff --git a/beacon-chain/db/kv/state.go b/beacon-chain/db/kv/state.go index 05ae8b978ecf..0efd7bf8166a 100644 --- a/beacon-chain/db/kv/state.go +++ b/beacon-chain/db/kv/state.go @@ -16,11 +16,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // State returns the saved state using block's signing root, @@ -74,7 +75,7 @@ func (s *Store) GenesisState(ctx context.Context) (state.BeaconState, error) { tracing.AnnotateError(span, err) return nil, err } - span.AddAttributes(trace.BoolAttribute("cache_hit", cached != nil)) + span.SetAttributes(trace.BoolAttribute("cache_hit", cached != nil)) if cached != nil { return cached, nil } @@ -356,7 +357,7 @@ func (s *Store) processElectra(ctx context.Context, pbState *ethpb.BeaconStateEl if err != nil { return err } - encodedState := snappy.Encode(nil, append(electraKey, rawObj...)) + encodedState := snappy.Encode(nil, append(ElectraKey, rawObj...)) if err := bucket.Put(rootHash, encodedState); err != nil { return err } @@ -516,9 +517,22 @@ func (s *Store) unmarshalState(_ context.Context, enc []byte, validatorEntries [ } switch { - case hasElectraKey(enc): + case hasFuluKey(enc): protoState := ðpb.BeaconStateElectra{} - if err := protoState.UnmarshalSSZ(enc[len(electraKey):]); err != nil { + if err := protoState.UnmarshalSSZ(enc[len(fuluKey):]); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal encoding for Fulu") + } + ok, err := s.isStateValidatorMigrationOver() + if err != nil { + return nil, err + } + if ok { + protoState.Validators = validatorEntries + } + return statenative.InitializeFromProtoUnsafeFulu(protoState) + case HasElectraKey(enc): + protoState := ðpb.BeaconStateElectra{} + if err := protoState.UnmarshalSSZ(enc[len(ElectraKey):]); err != nil { return nil, errors.Wrap(err, "failed to unmarshal encoding for Electra") } ok, err := s.isStateValidatorMigrationOver() @@ -603,14 +617,14 @@ func (s *Store) unmarshalState(_ context.Context, enc []byte, validatorEntries [ // marshal versioned state from struct type down to bytes. func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, error) { - switch st.ToProtoUnsafe().(type) { - case *ethpb.BeaconState: + switch st.Version() { + case version.Phase0: rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconState) if !ok { return nil, errors.New("non valid inner state") } return encode(ctx, rState) - case *ethpb.BeaconStateAltair: + case version.Altair: rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateAltair) if !ok { return nil, errors.New("non valid inner state") @@ -623,7 +637,7 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er return nil, err } return snappy.Encode(nil, append(altairKey, rawObj...)), nil - case *ethpb.BeaconStateBellatrix: + case version.Bellatrix: rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateBellatrix) if !ok { return nil, errors.New("non valid inner state") @@ -636,7 +650,7 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er return nil, err } return snappy.Encode(nil, append(bellatrixKey, rawObj...)), nil - case *ethpb.BeaconStateCapella: + case version.Capella: rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateCapella) if !ok { return nil, errors.New("non valid inner state") @@ -649,7 +663,7 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er return nil, err } return snappy.Encode(nil, append(capellaKey, rawObj...)), nil - case *ethpb.BeaconStateDeneb: + case version.Deneb: rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateDeneb) if !ok { return nil, errors.New("non valid inner state") @@ -662,7 +676,20 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er return nil, err } return snappy.Encode(nil, append(denebKey, rawObj...)), nil - case *ethpb.BeaconStateElectra: + case version.Electra: + rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateElectra) + if !ok { + return nil, errors.New("non valid inner state") + } + if rState == nil { + return nil, errors.New("nil state") + } + rawObj, err := rState.MarshalSSZ() + if err != nil { + return nil, err + } + return snappy.Encode(nil, append(ElectraKey, rawObj...)), nil + case version.Fulu: rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateElectra) if !ok { return nil, errors.New("non valid inner state") @@ -674,7 +701,7 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er if err != nil { return nil, err } - return snappy.Encode(nil, append(electraKey, rawObj...)), nil + return snappy.Encode(nil, append(fuluKey, rawObj...)), nil default: return nil, errors.New("invalid inner state") } @@ -698,7 +725,7 @@ func (s *Store) validatorEntries(ctx context.Context, blockRoot [32]byte) ([]*et idxBkt := tx.Bucket(blockRootValidatorHashesBucket) valKey := idxBkt.Get(blockRoot[:]) if len(valKey) == 0 { - return errors.Errorf("invalid compressed validator keys length") + return errors.Errorf("validator keys not found for given block root: %x", blockRoot) } // decompress the keys and check if they are of proper length. diff --git a/beacon-chain/db/kv/state_summary.go b/beacon-chain/db/kv/state_summary.go index d99dde29753f..187129a556cd 100644 --- a/beacon-chain/db/kv/state_summary.go +++ b/beacon-chain/db/kv/state_summary.go @@ -4,9 +4,9 @@ import ( "context" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // SaveStateSummary saves a state summary object to the DB. diff --git a/beacon-chain/db/kv/state_test.go b/beacon-chain/db/kv/state_test.go index f6f63593f8be..6f2c279b152c 100644 --- a/beacon-chain/db/kv/state_test.go +++ b/beacon-chain/db/kv/state_test.go @@ -2,8 +2,10 @@ package kv import ( "context" + "crypto/rand" "encoding/binary" - "math/rand" + mathRand "math/rand" + "strconv" "testing" "time" @@ -137,21 +139,18 @@ func TestState_CanSaveRetrieve(t *testing.T) { st, err := util.NewBeaconStateElectra() require.NoError(t, err) require.NoError(t, st.SetSlot(100)) - p, err := blocks.WrappedExecutionPayloadHeaderElectra(&enginev1.ExecutionPayloadHeaderElectra{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, 32), - ReceiptsRoot: make([]byte, 32), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, 32), - ExtraData: []byte("foo"), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, 32), - WithdrawalsRoot: make([]byte, 32), - DepositRequestsRoot: make([]byte, 32), - WithdrawalRequestsRoot: make([]byte, 32), - ConsolidationRequestsRoot: make([]byte, 32), + p, err := blocks.WrappedExecutionPayloadHeaderDeneb(&enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: []byte("foo"), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, 32), + WithdrawalsRoot: make([]byte, 32), }) require.NoError(t, err) require.NoError(t, st.SetLatestExecutionPayloadHeader(p)) @@ -881,16 +880,16 @@ func validators(limit int) []*ethpb.Validator { var vals []*ethpb.Validator for i := 0; i < limit; i++ { pubKey := make([]byte, params.BeaconConfig().BLSPubkeyLength) - binary.LittleEndian.PutUint64(pubKey, rand.Uint64()) + binary.LittleEndian.PutUint64(pubKey, mathRand.Uint64()) val := ðpb.Validator{ PublicKey: pubKey, - WithdrawalCredentials: bytesutil.ToBytes(rand.Uint64(), 32), - EffectiveBalance: rand.Uint64(), + WithdrawalCredentials: bytesutil.ToBytes(mathRand.Uint64(), 32), + EffectiveBalance: mathRand.Uint64(), Slashed: i%2 != 0, - ActivationEligibilityEpoch: primitives.Epoch(rand.Uint64()), - ActivationEpoch: primitives.Epoch(rand.Uint64()), - ExitEpoch: primitives.Epoch(rand.Uint64()), - WithdrawableEpoch: primitives.Epoch(rand.Uint64()), + ActivationEligibilityEpoch: primitives.Epoch(mathRand.Uint64()), + ActivationEpoch: primitives.Epoch(mathRand.Uint64()), + ExitEpoch: primitives.Epoch(mathRand.Uint64()), + WithdrawableEpoch: primitives.Epoch(mathRand.Uint64()), } vals = append(vals, val) } @@ -916,8 +915,8 @@ func checkStateSaveTime(b *testing.B, saveCount int) { allValidators := append(initialSetOfValidators, validatosToAddInTest...) // shuffle validators. - rand.Seed(time.Now().UnixNano()) - rand.Shuffle(len(allValidators), func(i, j int) { allValidators[i], allValidators[j] = allValidators[j], allValidators[i] }) + mathRand.New(mathRand.NewSource(time.Now().UnixNano())) + mathRand.Shuffle(len(allValidators), func(i, j int) { allValidators[i], allValidators[j] = allValidators[j], allValidators[i] }) require.NoError(b, st.SetValidators(allValidators)) require.NoError(b, db.SaveState(context.Background(), st, bytesutil.ToBytes32(key))) @@ -962,8 +961,8 @@ func checkStateReadTime(b *testing.B, saveCount int) { allValidators := append(initialSetOfValidators, validatosToAddInTest...) // shuffle validators. - rand.Seed(time.Now().UnixNano()) - rand.Shuffle(len(allValidators), func(i, j int) { allValidators[i], allValidators[j] = allValidators[j], allValidators[i] }) + mathRand.New(mathRand.NewSource(time.Now().UnixNano())) + mathRand.Shuffle(len(allValidators), func(i, j int) { allValidators[i], allValidators[j] = allValidators[j], allValidators[i] }) require.NoError(b, st.SetValidators(allValidators)) require.NoError(b, db.SaveState(context.Background(), st, bytesutil.ToBytes32(key))) diff --git a/beacon-chain/db/kv/utils.go b/beacon-chain/db/kv/utils.go index 1a292c7122c3..522b3860cd5c 100644 --- a/beacon-chain/db/kv/utils.go +++ b/beacon-chain/db/kv/utils.go @@ -6,8 +6,8 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // lookupValuesForIndices takes in a list of indices and looks up diff --git a/beacon-chain/db/kv/validated_checkpoint.go b/beacon-chain/db/kv/validated_checkpoint.go index 4223097e0953..3317cd1a3a4d 100644 --- a/beacon-chain/db/kv/validated_checkpoint.go +++ b/beacon-chain/db/kv/validated_checkpoint.go @@ -3,9 +3,9 @@ package kv import ( "context" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // LastValidatedCheckpoint returns the latest fully validated checkpoint in beacon chain. diff --git a/beacon-chain/db/pruner/BUILD.bazel b/beacon-chain/db/pruner/BUILD.bazel new file mode 100644 index 000000000000..d6a73162bb79 --- /dev/null +++ b/beacon-chain/db/pruner/BUILD.bazel @@ -0,0 +1,38 @@ +load("@prysm//tools/go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["pruner.go"], + importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/pruner", + visibility = [ + "//beacon-chain:__subpackages__", + ], + deps = [ + "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/db:go_default_library", + "//beacon-chain/db/iface:go_default_library", + "//config/params:go_default_library", + "//consensus-types/primitives:go_default_library", + "//time/slots:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = ["pruner_test.go"], + embed = [":go_default_library"], + deps = [ + "//beacon-chain/db/testing:go_default_library", + "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/primitives:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "//time/slots/testing:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_sirupsen_logrus//hooks/test:go_default_library", + ], +) diff --git a/beacon-chain/db/pruner/pruner.go b/beacon-chain/db/pruner/pruner.go new file mode 100644 index 000000000000..5bdb1015714b --- /dev/null +++ b/beacon-chain/db/pruner/pruner.go @@ -0,0 +1,174 @@ +package pruner + +import ( + "context" + "time" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/iface" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/time/slots" + "github.com/sirupsen/logrus" +) + +var log = logrus.WithField("prefix", "db-pruner") + +type ServiceOption func(*Service) + +// WithRetentionPeriod allows the user to specify a different data retention period than the spec default. +// The retention period is specified in epochs, and must be >= MIN_EPOCHS_FOR_BLOCK_REQUESTS. +func WithRetentionPeriod(retentionEpochs primitives.Epoch) ServiceOption { + return func(s *Service) { + defaultRetentionEpochs := helpers.MinEpochsForBlockRequests() + 1 + if retentionEpochs < defaultRetentionEpochs { + log.WithField("userEpochs", retentionEpochs). + WithField("minRequired", defaultRetentionEpochs). + Warn("Retention period too low, using minimum required value") + } + + s.ps = pruneStartSlotFunc(retentionEpochs) + } +} + +func WithSlotTicker(slotTicker slots.Ticker) ServiceOption { + return func(s *Service) { + s.slotTicker = slotTicker + } +} + +// Service defines a service that prunes beacon chain DB based on MIN_EPOCHS_FOR_BLOCK_REQUESTS. +type Service struct { + ctx context.Context + db db.Database + ps func(current primitives.Slot) primitives.Slot + prunedUpto primitives.Slot + done chan struct{} + slotTicker slots.Ticker + backfillWaiter func() error + initSyncWaiter func() error +} + +func New(ctx context.Context, db iface.Database, genesisTime uint64, initSyncWaiter, backfillWaiter func() error, opts ...ServiceOption) (*Service, error) { + p := &Service{ + ctx: ctx, + db: db, + ps: pruneStartSlotFunc(helpers.MinEpochsForBlockRequests() + 1), // Default retention epochs is MIN_EPOCHS_FOR_BLOCK_REQUESTS + 1 from the current slot. + done: make(chan struct{}), + slotTicker: slots.NewSlotTicker(slots.StartTime(genesisTime, 0), params.BeaconConfig().SecondsPerSlot), + initSyncWaiter: initSyncWaiter, + backfillWaiter: backfillWaiter, + } + + for _, o := range opts { + o(p) + } + + return p, nil +} + +func (p *Service) Start() { + log.Info("Starting Beacon DB pruner service") + p.run() +} + +func (p *Service) Stop() error { + log.Info("Stopping Beacon DB pruner service") + close(p.done) + return nil +} + +func (p *Service) Status() error { + return nil +} + +func (p *Service) run() { + if p.initSyncWaiter != nil { + log.Info("Waiting for initial sync service to complete before starting pruner") + if err := p.initSyncWaiter(); err != nil { + log.WithError(err).Error("Failed to start database pruner, error waiting for initial sync completion") + return + } + } + if p.backfillWaiter != nil { + log.Info("Waiting for backfill service to complete before starting pruner") + if err := p.backfillWaiter(); err != nil { + log.WithError(err).Error("Failed to start database pruner, error waiting for backfill completion") + return + } + } + + defer p.slotTicker.Done() + + for { + select { + case <-p.ctx.Done(): + log.Debug("Stopping Beacon DB pruner service", "prunedUpto", p.prunedUpto) + return + case <-p.done: + log.Debug("Stopping Beacon DB pruner service", "prunedUpto", p.prunedUpto) + return + case slot := <-p.slotTicker.C(): + // Prune at the middle of every epoch since we do a lot of things around epoch boundaries. + if slots.SinceEpochStarts(slot) != (params.BeaconConfig().SlotsPerEpoch / 2) { + continue + } + + if err := p.prune(slot); err != nil { + log.WithError(err).Error("Failed to prune database") + } + } + } +} + +// prune deletes historical chain data beyond the pruneSlot. +func (p *Service) prune(slot primitives.Slot) error { + // Prune everything up to this slot (inclusive). + pruneUpto := p.ps(slot) + + // Can't prune beyond genesis. + if pruneUpto == 0 { + return nil + } + + // Skip if already pruned up to this slot. + if pruneUpto <= p.prunedUpto { + return nil + } + + log.WithFields(logrus.Fields{ + "pruneUpto": pruneUpto, + }).Debug("Pruning chain data") + + tt := time.Now() + if err := p.db.DeleteHistoricalDataBeforeSlot(p.ctx, pruneUpto); err != nil { + return errors.Wrapf(err, "could not delete upto slot %d", pruneUpto) + } + + log.WithFields(logrus.Fields{ + "prunedUpto": pruneUpto, + "duration": time.Since(tt), + "currentSlot": slot, + }).Debug("Successfully pruned chain data") + + // Update pruning checkpoint. + p.prunedUpto = pruneUpto + + return nil +} + +// pruneStartSlotFunc returns the function to determine the start slot to start pruning. +func pruneStartSlotFunc(retentionEpochs primitives.Epoch) func(primitives.Slot) primitives.Slot { + return func(current primitives.Slot) primitives.Slot { + if retentionEpochs > slots.MaxSafeEpoch() { + retentionEpochs = slots.MaxSafeEpoch() + } + offset := slots.UnsafeEpochStart(retentionEpochs) + if offset >= current { + return 0 + } + return current - offset + } +} diff --git a/beacon-chain/db/pruner/pruner_test.go b/beacon-chain/db/pruner/pruner_test.go new file mode 100644 index 000000000000..542ac0c71024 --- /dev/null +++ b/beacon-chain/db/pruner/pruner_test.go @@ -0,0 +1,135 @@ +package pruner + +import ( + "context" + "testing" + "time" + + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + + "github.com/prysmaticlabs/prysm/v5/testing/util" + slottest "github.com/prysmaticlabs/prysm/v5/time/slots/testing" + "github.com/sirupsen/logrus" + + dbtest "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/testing/require" + logTest "github.com/sirupsen/logrus/hooks/test" +) + +func TestPruner_PruningConditions(t *testing.T) { + tests := []struct { + name string + synced bool + backfillCompleted bool + expectedLog string + }{ + { + name: "Not synced", + synced: false, + backfillCompleted: true, + expectedLog: "Waiting for initial sync service to complete before starting pruner", + }, + { + name: "Backfill incomplete", + synced: true, + backfillCompleted: false, + expectedLog: "Waiting for backfill service to complete before starting pruner", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + logrus.SetLevel(logrus.DebugLevel) + hook := logTest.NewGlobal() + ctx, cancel := context.WithCancel(context.Background()) + beaconDB := dbtest.SetupDB(t) + + slotTicker := &slottest.MockTicker{Channel: make(chan primitives.Slot)} + + waitChan := make(chan struct{}) + waiter := func() error { + close(waitChan) + return nil + } + + var initSyncWaiter, backfillWaiter func() error + if !tt.synced { + initSyncWaiter = waiter + } + if !tt.backfillCompleted { + backfillWaiter = waiter + } + p, err := New(ctx, beaconDB, uint64(time.Now().Unix()), initSyncWaiter, backfillWaiter, WithSlotTicker(slotTicker)) + require.NoError(t, err) + + go p.Start() + <-waitChan + cancel() + + if tt.expectedLog != "" { + require.LogsContain(t, hook, tt.expectedLog) + } + + require.NoError(t, p.Stop()) + }) + } +} + +func TestPruner_PruneSuccess(t *testing.T) { + ctx := context.Background() + beaconDB := dbtest.SetupDB(t) + + // Create and save some blocks at different slots + var blks []*eth.SignedBeaconBlock + for slot := primitives.Slot(1); slot <= 32; slot++ { + blk := util.NewBeaconBlock() + blk.Block.Slot = slot + wsb, err := blocks.NewSignedBeaconBlock(blk) + require.NoError(t, err) + require.NoError(t, beaconDB.SaveBlock(ctx, wsb)) + blks = append(blks, blk) + } + + // Create pruner with retention of 2 epochs (64 slots) + retentionEpochs := primitives.Epoch(2) + slotTicker := &slottest.MockTicker{Channel: make(chan primitives.Slot)} + + p, err := New( + ctx, + beaconDB, + uint64(time.Now().Unix()), + nil, + nil, + WithSlotTicker(slotTicker), + ) + require.NoError(t, err) + + p.ps = func(current primitives.Slot) primitives.Slot { + return current - primitives.Slot(retentionEpochs)*params.BeaconConfig().SlotsPerEpoch + } + + // Start pruner and trigger at middle of 3rd epoch (slot 80) + go p.Start() + currentSlot := primitives.Slot(80) // Middle of 3rd epoch + slotTicker.Channel <- currentSlot + // Send the same slot again to ensure the pruning operation completes + slotTicker.Channel <- currentSlot + + for slot := primitives.Slot(1); slot <= 32; slot++ { + root, err := blks[slot-1].Block.HashTreeRoot() + require.NoError(t, err) + present := beaconDB.HasBlock(ctx, root) + if slot <= 16 { // These should be pruned + require.NoError(t, err) + require.Equal(t, false, present, "Expected present at slot %d to be pruned", slot) + } else { // These should remain + require.NoError(t, err) + require.Equal(t, true, present, "Expected present at slot %d to exist", slot) + } + } + + require.NoError(t, p.Stop()) +} diff --git a/beacon-chain/db/slasherkv/BUILD.bazel b/beacon-chain/db/slasherkv/BUILD.bazel index 5cfdd142b48b..6615999499e7 100644 --- a/beacon-chain/db/slasherkv/BUILD.bazel +++ b/beacon-chain/db/slasherkv/BUILD.bazel @@ -15,12 +15,15 @@ go_library( visibility = ["//beacon-chain:__subpackages__"], deps = [ "//beacon-chain/db/iface:go_default_library", + "//beacon-chain/db/kv:go_default_library", "//beacon-chain/slasher/types:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_golang_snappy//:go_default_library", "@com_github_pkg_errors//:go_default_library", @@ -29,7 +32,6 @@ go_library( "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_etcd_go_bbolt//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", ], ) @@ -50,6 +52,7 @@ go_test( "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/require:go_default_library", "//time/slots:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", diff --git a/beacon-chain/db/slasherkv/pruning_test.go b/beacon-chain/db/slasherkv/pruning_test.go index 131fdcbd664b..b8d272accc72 100644 --- a/beacon-chain/db/slasherkv/pruning_test.go +++ b/beacon-chain/db/slasherkv/pruning_test.go @@ -8,6 +8,7 @@ import ( slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/time/slots" logTest "github.com/sirupsen/logrus/hooks/test" @@ -177,8 +178,8 @@ func TestStore_PruneAttestations_OK(t *testing.T) { if i > 0 { source = target - 1 } - att1 := createAttestationWrapper(source, target, []uint64{attester1}, []byte{0}) - att2 := createAttestationWrapper(source, target, []uint64{attester2}, []byte{1}) + att1 := createAttestationWrapper(version.Phase0, source, target, []uint64{attester1}, []byte{0}) + att2 := createAttestationWrapper(version.Phase0, source, target, []uint64{attester2}, []byte{1}) attestations = append(attestations, att1, att2) } } diff --git a/beacon-chain/db/slasherkv/slasher.go b/beacon-chain/db/slasherkv/slasher.go index 2d52da30ee0e..81a56e926406 100644 --- a/beacon-chain/db/slasherkv/slasher.go +++ b/beacon-chain/db/slasherkv/slasher.go @@ -11,12 +11,14 @@ import ( "github.com/golang/snappy" "github.com/pkg/errors" ssz "github.com/prysmaticlabs/fastssz" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/kv" slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" "golang.org/x/sync/errgroup" ) @@ -688,10 +690,15 @@ func decodeSlasherChunk(enc []byte) ([]uint16, error) { // Encode attestation record to bytes. // The output encoded attestation record consists in the signing root concatenated with the compressed attestation record. func encodeAttestationRecord(att *slashertypes.IndexedAttestationWrapper) ([]byte, error) { - if att == nil || att.IndexedAttestation == nil { + if att == nil || att.IndexedAttestation == nil || att.IndexedAttestation.IsNil() { return []byte{}, errors.New("nil proposal record") } + var versionKey []byte + if att.IndexedAttestation.Version() >= version.Electra { + versionKey = kv.ElectraKey + } + // Encode attestation. encodedAtt, err := att.IndexedAttestation.MarshalSSZ() if err != nil { @@ -701,7 +708,14 @@ func encodeAttestationRecord(att *slashertypes.IndexedAttestationWrapper) ([]byt // Compress attestation. compressedAtt := snappy.Encode(nil, encodedAtt) - return append(att.DataRoot[:], compressedAtt...), nil + enc := make([]byte, len(versionKey)+len(att.DataRoot)+len(compressedAtt)) + if len(versionKey) > 0 { + copy(enc, versionKey) + } + copy(enc[len(versionKey):len(versionKey)+len(att.DataRoot)], att.DataRoot[:]) + copy(enc[len(versionKey)+len(att.DataRoot):], compressedAtt) + + return enc, nil } // Decode attestation record from bytes. @@ -711,6 +725,11 @@ func decodeAttestationRecord(encoded []byte) (*slashertypes.IndexedAttestationWr return nil, fmt.Errorf("wrong length for encoded attestation record, want minimum %d, got %d", rootSize, len(encoded)) } + postElectra := kv.HasElectraKey(encoded) + if postElectra { + encoded = encoded[len(kv.ElectraKey):] + } + // Decompress attestation. decodedAttBytes, err := snappy.Decode(nil, encoded[rootSize:]) if err != nil { @@ -718,8 +737,14 @@ func decodeAttestationRecord(encoded []byte) (*slashertypes.IndexedAttestationWr } // Decode attestation. - decodedAtt := ðpb.IndexedAttestation{} - if err := decodedAtt.UnmarshalSSZ(decodedAttBytes); err != nil { + var decodedAtt ethpb.IndexedAtt + if postElectra { + decodedAtt = ðpb.IndexedAttestationElectra{} + } else { + decodedAtt = ðpb.IndexedAttestation{} + } + + if err = decodedAtt.UnmarshalSSZ(decodedAttBytes); err != nil { return nil, err } diff --git a/beacon-chain/db/slasherkv/slasher_test.go b/beacon-chain/db/slasherkv/slasher_test.go index 292e109042c2..c2bac212deb1 100644 --- a/beacon-chain/db/slasherkv/slasher_test.go +++ b/beacon-chain/db/slasherkv/slasher_test.go @@ -14,20 +14,16 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" ) func TestStore_AttestationRecordForValidator_SaveRetrieve(t *testing.T) { const attestationsCount = 11_000 - - // Create context. ctx := context.Background() - - // Create database. beaconDB := setupDB(t) - - // Define the validator index. - validatorIndex := primitives.ValidatorIndex(1) + phase0ValidatorIndex := primitives.ValidatorIndex(1) + electraValidatorIndex := primitives.ValidatorIndex(2) // Defines attestations to save and retrieve. attWrappers := make([]*slashertypes.IndexedAttestationWrapper, attestationsCount) @@ -36,33 +32,71 @@ func TestStore_AttestationRecordForValidator_SaveRetrieve(t *testing.T) { binary.LittleEndian.PutUint64(dataRoot[:], uint64(i)) attWrapper := createAttestationWrapper( + version.Phase0, primitives.Epoch(i), primitives.Epoch(i+1), - []uint64{uint64(validatorIndex)}, + []uint64{uint64(phase0ValidatorIndex)}, dataRoot[:], ) attWrappers[i] = attWrapper } + attWrappersElectra := make([]*slashertypes.IndexedAttestationWrapper, attestationsCount) + for i := 0; i < attestationsCount; i++ { + var dataRoot [32]byte + binary.LittleEndian.PutUint64(dataRoot[:], uint64(i)) - // Check on a sample of validators that no attestation records are available. - for i := 0; i < attestationsCount; i += 100 { - attRecord, err := beaconDB.AttestationRecordForValidator(ctx, validatorIndex, primitives.Epoch(i+1)) - require.NoError(t, err) - require.Equal(t, true, attRecord == nil) + attWrapper := createAttestationWrapper( + version.Electra, + primitives.Epoch(i), + primitives.Epoch(i+1), + []uint64{uint64(electraValidatorIndex)}, + dataRoot[:], + ) + + attWrappersElectra[i] = attWrapper } - // Save the attestation records to the database. - err := beaconDB.SaveAttestationRecordsForValidators(ctx, attWrappers) - require.NoError(t, err) + type testCase struct { + name string + atts []*slashertypes.IndexedAttestationWrapper + vi primitives.ValidatorIndex + } + testCases := []testCase{ + { + name: "phase0", + atts: attWrappers, + vi: phase0ValidatorIndex, + }, + { + name: "electra", + atts: attWrappersElectra, + vi: electraValidatorIndex, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Check on a sample of validators that no attestation records are available. + for i := 0; i < attestationsCount; i += 100 { + attRecord, err := beaconDB.AttestationRecordForValidator(ctx, tc.vi, primitives.Epoch(i+1)) + require.NoError(t, err) + require.Equal(t, true, attRecord == nil) + } + + // Save the attestation records to the database. + err := beaconDB.SaveAttestationRecordsForValidators(ctx, tc.atts) + require.NoError(t, err) - // Check on a sample of validators that attestation records are available. - for i := 0; i < attestationsCount; i += 100 { - expected := attWrappers[i] - actual, err := beaconDB.AttestationRecordForValidator(ctx, validatorIndex, primitives.Epoch(i+1)) - require.NoError(t, err) + // Check on a sample of validators that attestation records are available. + for i := 0; i < attestationsCount; i += 100 { + expected := attWrappers[i] + actual, err := beaconDB.AttestationRecordForValidator(ctx, tc.vi, primitives.Epoch(i+1)) + require.NoError(t, err) - require.DeepEqual(t, expected.IndexedAttestation.GetData().Source.Epoch, actual.IndexedAttestation.GetData().Source.Epoch) + require.DeepEqual(t, expected.IndexedAttestation.GetData().Source.Epoch, actual.IndexedAttestation.GetData().Source.Epoch) + } + }) } } @@ -108,55 +142,60 @@ func TestStore_LastEpochWrittenForValidators(t *testing.T) { func TestStore_CheckAttesterDoubleVotes(t *testing.T) { ctx := context.Background() - beaconDB := setupDB(t) - err := beaconDB.SaveAttestationRecordsForValidators(ctx, []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{1}), - createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{3}), - }) - require.NoError(t, err) - slashableAtts := []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{2}), // Different signing root. - createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{4}), // Different signing root. - } + for _, ver := range []int{version.Phase0, version.Electra} { + t.Run(version.String(ver), func(t *testing.T) { + beaconDB := setupDB(t) + err := beaconDB.SaveAttestationRecordsForValidators(ctx, []*slashertypes.IndexedAttestationWrapper{ + createAttestationWrapper(version.Phase0, 2, 3, []uint64{0, 1}, []byte{1}), + createAttestationWrapper(version.Phase0, 3, 4, []uint64{2, 3}, []byte{3}), + }) + require.NoError(t, err) - wanted := []*slashertypes.AttesterDoubleVote{ - { - ValidatorIndex: 0, - Target: 3, - Wrapper_1: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{1}), - Wrapper_2: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{2}), - }, - { - ValidatorIndex: 1, - Target: 3, - Wrapper_1: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{1}), - Wrapper_2: createAttestationWrapper(2, 3, []uint64{0, 1}, []byte{2}), - }, - { - ValidatorIndex: 2, - Target: 4, - Wrapper_1: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{3}), - Wrapper_2: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{4}), - }, - { - ValidatorIndex: 3, - Target: 4, - Wrapper_1: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{3}), - Wrapper_2: createAttestationWrapper(3, 4, []uint64{2, 3}, []byte{4}), - }, - } - doubleVotes, err := beaconDB.CheckAttesterDoubleVotes(ctx, slashableAtts) - require.NoError(t, err) - sort.SliceStable(doubleVotes, func(i, j int) bool { - return uint64(doubleVotes[i].ValidatorIndex) < uint64(doubleVotes[j].ValidatorIndex) - }) - require.Equal(t, len(wanted), len(doubleVotes)) - for i, double := range doubleVotes { - require.DeepEqual(t, wanted[i].ValidatorIndex, double.ValidatorIndex) - require.DeepEqual(t, wanted[i].Target, double.Target) - require.DeepEqual(t, wanted[i].Wrapper_1, double.Wrapper_1) - require.DeepEqual(t, wanted[i].Wrapper_2, double.Wrapper_2) + slashableAtts := []*slashertypes.IndexedAttestationWrapper{ + createAttestationWrapper(version.Phase0, 2, 3, []uint64{0, 1}, []byte{2}), // Different signing root. + createAttestationWrapper(version.Phase0, 3, 4, []uint64{2, 3}, []byte{4}), // Different signing root. + } + + wanted := []*slashertypes.AttesterDoubleVote{ + { + ValidatorIndex: 0, + Target: 3, + Wrapper_1: createAttestationWrapper(version.Phase0, 2, 3, []uint64{0, 1}, []byte{1}), + Wrapper_2: createAttestationWrapper(version.Phase0, 2, 3, []uint64{0, 1}, []byte{2}), + }, + { + ValidatorIndex: 1, + Target: 3, + Wrapper_1: createAttestationWrapper(version.Phase0, 2, 3, []uint64{0, 1}, []byte{1}), + Wrapper_2: createAttestationWrapper(version.Phase0, 2, 3, []uint64{0, 1}, []byte{2}), + }, + { + ValidatorIndex: 2, + Target: 4, + Wrapper_1: createAttestationWrapper(version.Phase0, 3, 4, []uint64{2, 3}, []byte{3}), + Wrapper_2: createAttestationWrapper(version.Phase0, 3, 4, []uint64{2, 3}, []byte{4}), + }, + { + ValidatorIndex: 3, + Target: 4, + Wrapper_1: createAttestationWrapper(version.Phase0, 3, 4, []uint64{2, 3}, []byte{3}), + Wrapper_2: createAttestationWrapper(version.Phase0, 3, 4, []uint64{2, 3}, []byte{4}), + }, + } + doubleVotes, err := beaconDB.CheckAttesterDoubleVotes(ctx, slashableAtts) + require.NoError(t, err) + sort.SliceStable(doubleVotes, func(i, j int) bool { + return uint64(doubleVotes[i].ValidatorIndex) < uint64(doubleVotes[j].ValidatorIndex) + }) + require.Equal(t, len(wanted), len(doubleVotes)) + for i, double := range doubleVotes { + require.DeepEqual(t, wanted[i].ValidatorIndex, double.ValidatorIndex) + require.DeepEqual(t, wanted[i].Target, double.Target) + require.DeepEqual(t, wanted[i].Wrapper_1, double.Wrapper_1) + require.DeepEqual(t, wanted[i].Wrapper_2, double.Wrapper_2) + } + }) } } @@ -376,12 +415,20 @@ func Test_encodeDecodeAttestationRecord(t *testing.T) { wantErr bool }{ { - name: "empty standard encode/decode", - attWrapper: createAttestationWrapper(0, 0, nil /* indices */, nil /* signingRoot */), + name: "phase0 empty standard encode/decode", + attWrapper: createAttestationWrapper(version.Phase0, 0, 0, nil /* indices */, nil /* signingRoot */), }, { - name: "standard encode/decode", - attWrapper: createAttestationWrapper(15, 6, []uint64{2, 4}, []byte("1") /* signingRoot */), + name: "phase0 standard encode/decode", + attWrapper: createAttestationWrapper(version.Phase0, 15, 6, []uint64{2, 4}, []byte("1") /* signingRoot */), + }, + { + name: "electra empty standard encode/decode", + attWrapper: createAttestationWrapper(version.Electra, 0, 0, nil /* indices */, nil /* signingRoot */), + }, + { + name: "electra standard encode/decode", + attWrapper: createAttestationWrapper(version.Electra, 15, 6, []uint64{2, 4}, []byte("1") /* signingRoot */), }, { name: "failing encode/decode", @@ -433,7 +480,7 @@ func TestStore_HighestAttestations(t *testing.T) { { name: "should get highest att if single att in db", attestationsInDB: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapper(0, 3, []uint64{1}, []byte{1}), + createAttestationWrapper(version.Phase0, 0, 3, []uint64{1}, []byte{1}), }, indices: []primitives.ValidatorIndex{1}, expected: []*ethpb.HighestAttestation{ @@ -447,10 +494,10 @@ func TestStore_HighestAttestations(t *testing.T) { { name: "should get highest att for multiple with diff histories", attestationsInDB: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapper(0, 3, []uint64{2}, []byte{1}), - createAttestationWrapper(1, 4, []uint64{3}, []byte{2}), - createAttestationWrapper(2, 3, []uint64{4}, []byte{3}), - createAttestationWrapper(5, 6, []uint64{5}, []byte{4}), + createAttestationWrapper(version.Phase0, 0, 3, []uint64{2}, []byte{1}), + createAttestationWrapper(version.Phase0, 1, 4, []uint64{3}, []byte{2}), + createAttestationWrapper(version.Phase0, 2, 3, []uint64{4}, []byte{3}), + createAttestationWrapper(version.Phase0, 5, 6, []uint64{5}, []byte{4}), }, indices: []primitives.ValidatorIndex{2, 3, 4, 5}, expected: []*ethpb.HighestAttestation{ @@ -479,10 +526,10 @@ func TestStore_HighestAttestations(t *testing.T) { { name: "should get correct highest att for multiple shared atts with diff histories", attestationsInDB: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapper(1, 4, []uint64{2, 3}, []byte{1}), - createAttestationWrapper(2, 5, []uint64{3, 5}, []byte{2}), - createAttestationWrapper(4, 5, []uint64{1, 2}, []byte{3}), - createAttestationWrapper(6, 7, []uint64{5}, []byte{4}), + createAttestationWrapper(version.Phase0, 1, 4, []uint64{2, 3}, []byte{1}), + createAttestationWrapper(version.Phase0, 2, 5, []uint64{3, 5}, []byte{2}), + createAttestationWrapper(version.Phase0, 4, 5, []uint64{1, 2}, []byte{3}), + createAttestationWrapper(version.Phase0, 6, 7, []uint64{5}, []byte{4}), }, indices: []primitives.ValidatorIndex{2, 3, 4, 5}, expected: []*ethpb.HighestAttestation{ @@ -533,7 +580,7 @@ func BenchmarkHighestAttestations(b *testing.B) { } atts := make([]*slashertypes.IndexedAttestationWrapper, count) for i := 0; i < count; i++ { - atts[i] = createAttestationWrapper(primitives.Epoch(i), primitives.Epoch(i+2), indicesPerAtt[i], []byte{}) + atts[i] = createAttestationWrapper(version.Phase0, primitives.Epoch(i), primitives.Epoch(i+2), indicesPerAtt[i], []byte{}) } ctx := context.Background() @@ -570,7 +617,7 @@ func BenchmarkStore_CheckDoubleBlockProposals(b *testing.B) { } atts := make([]*slashertypes.IndexedAttestationWrapper, count) for i := 0; i < count; i++ { - atts[i] = createAttestationWrapper(primitives.Epoch(i), primitives.Epoch(i+2), indicesPerAtt[i], []byte{}) + atts[i] = createAttestationWrapper(version.Phase0, primitives.Epoch(i), primitives.Epoch(i+2), indicesPerAtt[i], []byte{}) } ctx := context.Background() @@ -609,7 +656,7 @@ func createProposalWrapper(t *testing.T, slot primitives.Slot, proposerIndex pri } } -func createAttestationWrapper(source, target primitives.Epoch, indices []uint64, dataRootBytes []byte) *slashertypes.IndexedAttestationWrapper { +func createAttestationWrapper(ver int, source, target primitives.Epoch, indices []uint64, dataRootBytes []byte) *slashertypes.IndexedAttestationWrapper { dataRoot := bytesutil.ToBytes32(dataRootBytes) if dataRootBytes == nil { dataRoot = params.BeaconConfig().ZeroHash @@ -627,6 +674,16 @@ func createAttestationWrapper(source, target primitives.Epoch, indices []uint64, }, } + if ver >= version.Electra { + return &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: data, + Signature: params.BeaconConfig().EmptySignature[:], + }, + DataRoot: dataRoot, + } + } return &slashertypes.IndexedAttestationWrapper{ IndexedAttestation: ðpb.IndexedAttestation{ AttestingIndices: indices, diff --git a/beacon-chain/db/slasherkv/slasherkv_test.go b/beacon-chain/db/slasherkv/slasherkv_test.go index 000a279d97a9..30d8e253f5b8 100644 --- a/beacon-chain/db/slasherkv/slasherkv_test.go +++ b/beacon-chain/db/slasherkv/slasherkv_test.go @@ -2,6 +2,7 @@ package slasherkv import ( "io" + "os" "testing" "github.com/sirupsen/logrus" @@ -10,5 +11,5 @@ import ( func TestMain(m *testing.M) { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(io.Discard) - m.Run() + os.Exit(m.Run()) } diff --git a/beacon-chain/deterministic-genesis/BUILD.bazel b/beacon-chain/deterministic-genesis/BUILD.bazel deleted file mode 100644 index 32267dc50f34..000000000000 --- a/beacon-chain/deterministic-genesis/BUILD.bazel +++ /dev/null @@ -1,24 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "log.go", - "service.go", - ], - importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/deterministic-genesis", - visibility = ["//beacon-chain:__subpackages__"], - deps = [ - "//beacon-chain/cache:go_default_library", - "//beacon-chain/db:go_default_library", - "//beacon-chain/execution:go_default_library", - "//beacon-chain/state:go_default_library", - "//beacon-chain/state/state-native:go_default_library", - "//consensus-types/primitives:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "//runtime:go_default_library", - "//runtime/interop:go_default_library", - "//time/slots:go_default_library", - "@com_github_sirupsen_logrus//:go_default_library", - ], -) diff --git a/beacon-chain/deterministic-genesis/log.go b/beacon-chain/deterministic-genesis/log.go deleted file mode 100644 index a9a259fe87bc..000000000000 --- a/beacon-chain/deterministic-genesis/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package interopcoldstart - -import ( - "github.com/sirupsen/logrus" -) - -var log = logrus.WithField("prefix", "deterministic-genesis") diff --git a/beacon-chain/deterministic-genesis/service.go b/beacon-chain/deterministic-genesis/service.go deleted file mode 100644 index 163acfcd4488..000000000000 --- a/beacon-chain/deterministic-genesis/service.go +++ /dev/null @@ -1,206 +0,0 @@ -// Package interopcoldstart allows for spinning up a deterministic-genesis -// local chain without the need for eth1 deposits useful for -// local client development and interoperability testing. -package interopcoldstart - -import ( - "context" - "math/big" - "os" - "time" - - "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/runtime" - "github.com/prysmaticlabs/prysm/v5/runtime/interop" - "github.com/prysmaticlabs/prysm/v5/time/slots" -) - -var _ runtime.Service = (*Service)(nil) -var _ cache.FinalizedFetcher = (*Service)(nil) -var _ execution.ChainStartFetcher = (*Service)(nil) - -// Service spins up an client interoperability service that handles responsibilities such -// as kickstarting a genesis state for the beacon node from cli flags or a genesis.ssz file. -type Service struct { - cfg *Config - ctx context.Context - cancel context.CancelFunc - chainStartDeposits []*ethpb.Deposit -} - -// All of these methods are stubs as they are not used by a node running with deterministic-genesis. - -func (s *Service) AllDepositContainers(ctx context.Context) []*ethpb.DepositContainer { - log.Errorf("AllDepositContainers should not be called") - return nil -} - -func (s *Service) InsertPendingDeposit(ctx context.Context, d *ethpb.Deposit, blockNum uint64, index int64, depositRoot [32]byte) { - log.Errorf("InsertPendingDeposit should not be called") -} - -func (s *Service) PendingDeposits(ctx context.Context, untilBlk *big.Int) []*ethpb.Deposit { - log.Errorf("PendingDeposits should not be called") - return nil -} - -func (s *Service) PendingContainers(ctx context.Context, untilBlk *big.Int) []*ethpb.DepositContainer { - log.Errorf("PendingContainers should not be called") - return nil -} - -func (s *Service) PrunePendingDeposits(ctx context.Context, merkleTreeIndex int64) { - log.Errorf("PrunePendingDeposits should not be called") -} - -func (s *Service) PruneProofs(ctx context.Context, untilDepositIndex int64) error { - log.Errorf("PruneProofs should not be called") - return nil -} - -// Config options for the interop service. -type Config struct { - GenesisTime uint64 - NumValidators uint64 - BeaconDB db.HeadAccessDatabase - DepositCache cache.DepositCache - GenesisPath string -} - -// NewService is an interoperability testing service to inject a deterministically generated genesis state -// into the beacon chain database and running services at start up. This service should not be used in production -// as it does not have any value other than ease of use for testing purposes. -func NewService(ctx context.Context, cfg *Config) *Service { - ctx, cancel := context.WithCancel(ctx) - - return &Service{ - cfg: cfg, - ctx: ctx, - cancel: cancel, - } -} - -// Start initializes the genesis state from configured flags. -func (s *Service) Start() { - log.Warn("Saving generated genesis state in database for interop testing") - - if s.cfg.GenesisPath != "" { - data, err := os.ReadFile(s.cfg.GenesisPath) - if err != nil { - log.WithError(err).Fatal("Could not read pre-loaded state") - } - genesisState := ðpb.BeaconState{} - if err := genesisState.UnmarshalSSZ(data); err != nil { - log.WithError(err).Fatal("Could not unmarshal pre-loaded state") - } - genesisTrie, err := state_native.InitializeFromProtoPhase0(genesisState) - if err != nil { - log.WithError(err).Fatal("Could not get state trie") - } - if err := s.saveGenesisState(s.ctx, genesisTrie); err != nil { - log.WithError(err).Fatal("Could not save interop genesis state") - } - return - } - - // Save genesis state in db - genesisState, _, err := interop.GenerateGenesisState(s.ctx, s.cfg.GenesisTime, s.cfg.NumValidators) - if err != nil { - log.WithError(err).Fatal("Could not generate interop genesis state") - } - genesisTrie, err := state_native.InitializeFromProtoPhase0(genesisState) - if err != nil { - log.WithError(err).Fatal("Could not get state trie") - } - if s.cfg.GenesisTime == 0 { - // Generated genesis time; fetch it - s.cfg.GenesisTime = genesisTrie.GenesisTime() - } - gRoot, err := genesisTrie.HashTreeRoot(s.ctx) - if err != nil { - log.WithError(err).Fatal("Could not hash tree root genesis state") - } - go slots.CountdownToGenesis(s.ctx, time.Unix(int64(s.cfg.GenesisTime), 0), s.cfg.NumValidators, gRoot) - - if err := s.saveGenesisState(s.ctx, genesisTrie); err != nil { - log.WithError(err).Fatal("Could not save interop genesis state") - } -} - -// Stop does nothing. -func (_ *Service) Stop() error { - return nil -} - -// Status always returns nil. -func (_ *Service) Status() error { - return nil -} - -// AllDeposits mocks out the deposit cache functionality for interop. -func (_ *Service) AllDeposits(_ context.Context, _ *big.Int) []*ethpb.Deposit { - return []*ethpb.Deposit{} -} - -// ChainStartEth1Data mocks out the powchain functionality for interop. -func (_ *Service) ChainStartEth1Data() *ethpb.Eth1Data { - return ðpb.Eth1Data{} -} - -// PreGenesisState returns an empty beacon state. -func (_ *Service) PreGenesisState() state.BeaconState { - s, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{}) - if err != nil { - panic("could not initialize state") - } - return s -} - -// ClearPreGenesisData -- -func (_ *Service) ClearPreGenesisData() { - // no-op -} - -// DepositByPubkey mocks out the deposit cache functionality for interop. -func (_ *Service) DepositByPubkey(_ context.Context, _ []byte) (*ethpb.Deposit, *big.Int) { - return ðpb.Deposit{}, nil -} - -// DepositsNumberAndRootAtHeight mocks out the deposit cache functionality for interop. -func (_ *Service) DepositsNumberAndRootAtHeight(_ context.Context, _ *big.Int) (uint64, [32]byte) { - return 0, [32]byte{} -} - -// FinalizedDeposits mocks out the deposit cache functionality for interop. -func (_ *Service) FinalizedDeposits(ctx context.Context) (cache.FinalizedDeposits, error) { - return nil, nil -} - -// NonFinalizedDeposits mocks out the deposit cache functionality for interop. -func (_ *Service) NonFinalizedDeposits(_ context.Context, _ int64, _ *big.Int) []*ethpb.Deposit { - return []*ethpb.Deposit{} -} - -func (s *Service) saveGenesisState(ctx context.Context, genesisState state.BeaconState) error { - if err := s.cfg.BeaconDB.SaveGenesisData(ctx, genesisState); err != nil { - return err - } - - s.chainStartDeposits = make([]*ethpb.Deposit, genesisState.NumValidators()) - - for i := primitives.ValidatorIndex(0); uint64(i) < uint64(genesisState.NumValidators()); i++ { - pk := genesisState.PubkeyAtIndex(i) - s.chainStartDeposits[i] = ðpb.Deposit{ - Data: ðpb.Deposit_Data{ - PublicKey: pk[:], - }, - } - } - return nil -} diff --git a/beacon-chain/execution/BUILD.bazel b/beacon-chain/execution/BUILD.bazel index 15b1bb55a2b2..42daa7ba6984 100644 --- a/beacon-chain/execution/BUILD.bazel +++ b/beacon-chain/execution/BUILD.bazel @@ -37,6 +37,7 @@ go_library( "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/verification:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", @@ -50,6 +51,7 @@ go_library( "//io/logs:go_default_library", "//monitoring/clientstats:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network:go_default_library", "//network/authorization:go_default_library", "//proto/engine/v1:go_default_library", @@ -70,7 +72,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_k8s_client_go//tools/cache:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) @@ -102,11 +103,15 @@ go_test( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/signing:go_default_library", "//beacon-chain/db:go_default_library", + "//beacon-chain/db/filesystem:go_default_library", "//beacon-chain/db/testing:go_default_library", "//beacon-chain/execution/testing:go_default_library", "//beacon-chain/execution/types:go_default_library", + "//beacon-chain/forkchoice:go_default_library", "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", + "//beacon-chain/startup:go_default_library", "//beacon-chain/state/stategen:go_default_library", + "//beacon-chain/verification:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", @@ -127,11 +132,11 @@ go_test( "//testing/util:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//:go_default_library", - "@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library", "@com_github_ethereum_go_ethereum//beacon/engine:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", + "@com_github_ethereum_go_ethereum//ethclient/simulated:go_default_library", "@com_github_ethereum_go_ethereum//rpc:go_default_library", "@com_github_holiman_uint256//:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/execution/block_cache.go b/beacon-chain/execution/block_cache.go index cdeb10186eed..4866ee75d1f1 100644 --- a/beacon-chain/execution/block_cache.go +++ b/beacon-chain/execution/block_cache.go @@ -164,6 +164,6 @@ func trim(queue *cache.FIFO, maxSize uint64) { } // popProcessNoopFunc is a no-op function that never returns an error. -func popProcessNoopFunc(_ interface{}) error { +func popProcessNoopFunc(_ interface{}, _ bool) error { return nil } diff --git a/beacon-chain/execution/block_reader.go b/beacon-chain/execution/block_reader.go index 6918a6e9e978..e3deacd422f0 100644 --- a/beacon-chain/execution/block_reader.go +++ b/beacon-chain/execution/block_reader.go @@ -10,7 +10,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/types" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) // searchThreshold to apply for when searching for blocks of a particular time. If the buffer @@ -31,10 +31,10 @@ func (s *Service) BlockExists(ctx context.Context, hash common.Hash) (bool, *big if err != nil { return false, nil, err } - span.AddAttributes(trace.BoolAttribute("blockCacheHit", true)) + span.SetAttributes(trace.BoolAttribute("blockCacheHit", true)) return true, hdrInfo.Number, nil } - span.AddAttributes(trace.BoolAttribute("blockCacheHit", false)) + span.SetAttributes(trace.BoolAttribute("blockCacheHit", false)) header, err := s.HeaderByHash(ctx, hash) if err != nil { return false, big.NewInt(0), errors.Wrap(err, "could not query block with given hash") @@ -56,10 +56,10 @@ func (s *Service) BlockHashByHeight(ctx context.Context, height *big.Int) (commo if err != nil { return [32]byte{}, err } - span.AddAttributes(trace.BoolAttribute("headerCacheHit", true)) + span.SetAttributes(trace.BoolAttribute("headerCacheHit", true)) return hInfo.Hash, nil } - span.AddAttributes(trace.BoolAttribute("headerCacheHit", false)) + span.SetAttributes(trace.BoolAttribute("headerCacheHit", false)) if s.rpcClient == nil { err := errors.New("nil rpc client") diff --git a/beacon-chain/execution/block_reader_test.go b/beacon-chain/execution/block_reader_test.go index 6dbda1d2118f..10d10b81590a 100644 --- a/beacon-chain/execution/block_reader_test.go +++ b/beacon-chain/execution/block_reader_test.go @@ -12,6 +12,7 @@ import ( dbutil "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" mockExecution "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/types" + "github.com/prysmaticlabs/prysm/v5/config/params" contracts "github.com/prysmaticlabs/prysm/v5/contracts/deposit" "github.com/prysmaticlabs/prysm/v5/contracts/deposit/mock" "github.com/prysmaticlabs/prysm/v5/testing/assert" @@ -44,7 +45,7 @@ func TestLatestMainchainInfo_OK(t *testing.T) { web3Service = setDefaultMocks(web3Service) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) testAcc.Backend.Commit() @@ -141,7 +142,7 @@ func TestBlockExists_ValidHash(t *testing.T) { web3Service = setDefaultMocks(web3Service) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} testAcc.Backend.Commit() - block, err := testAcc.Backend.BlockByNumber(context.Background(), big.NewInt(0)) + block, err := testAcc.Backend.Client().BlockByNumber(context.Background(), big.NewInt(0)) assert.NoError(t, err) exists, height, err := web3Service.BlockExists(context.Background(), block.Hash()) @@ -201,8 +202,10 @@ func TestBlockExists_UsesCachedBlockInfo(t *testing.T) { } func TestService_BlockNumberByTimestamp(t *testing.T) { + ctx := context.Background() beaconDB := dbutil.SetupDB(t) testAcc, err := mock.Setup() + require.NoError(t, err, "Unable to set up simulated backend") server, endpoint, err := mockExecution.SetupRPCServer() require.NoError(t, err) @@ -216,16 +219,22 @@ func TestService_BlockNumberByTimestamp(t *testing.T) { require.NoError(t, err) web3Service = setDefaultMocks(web3Service) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} - + // simulated backend sets eth1 block + params.SetupTestConfigCleanup(t) + conf := params.BeaconConfig().Copy() + conf.SecondsPerETH1Block = 1 + params.OverrideBeaconConfig(conf) + initialHead, err := testAcc.Backend.Client().HeaderByNumber(ctx, nil) + require.NoError(t, err) for i := 0; i < 200; i++ { testAcc.Backend.Commit() } - ctx := context.Background() - hd, err := testAcc.Backend.HeaderByNumber(ctx, nil) + + hd, err := testAcc.Backend.Client().HeaderByNumber(ctx, nil) require.NoError(t, err) web3Service.latestEth1Data.BlockTime = hd.Time web3Service.latestEth1Data.BlockHeight = hd.Number.Uint64() - blk, err := web3Service.BlockByTimestamp(ctx, 1000 /* time */) + blk, err := web3Service.BlockByTimestamp(ctx, initialHead.Time+100 /* time */) require.NoError(t, err) if blk.Number.Cmp(big.NewInt(0)) == 0 { t.Error("Returned a block with zero number, expected to be non zero") @@ -253,7 +262,7 @@ func TestService_BlockNumberByTimestampLessTargetTime(t *testing.T) { testAcc.Backend.Commit() } ctx := context.Background() - hd, err := testAcc.Backend.HeaderByNumber(ctx, nil) + hd, err := testAcc.Backend.Client().HeaderByNumber(ctx, nil) require.NoError(t, err) web3Service.latestEth1Data.BlockTime = hd.Time // Use extremely small deadline to illustrate that context deadlines are respected. @@ -291,7 +300,7 @@ func TestService_BlockNumberByTimestampMoreTargetTime(t *testing.T) { testAcc.Backend.Commit() } ctx := context.Background() - hd, err := testAcc.Backend.HeaderByNumber(ctx, nil) + hd, err := testAcc.Backend.Client().HeaderByNumber(ctx, nil) require.NoError(t, err) web3Service.latestEth1Data.BlockTime = hd.Time // Use extremely small deadline to illustrate that context deadlines are respected. diff --git a/beacon-chain/execution/engine_client.go b/beacon-chain/execution/engine_client.go index 7875fa6c2d77..87f539d3f576 100644 --- a/beacon-chain/execution/engine_client.go +++ b/beacon-chain/execution/engine_client.go @@ -14,6 +14,7 @@ import ( "github.com/holiman/uint256" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/types" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" @@ -21,11 +22,12 @@ import ( payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" pb "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) @@ -34,18 +36,18 @@ var ( NewPayloadMethod, NewPayloadMethodV2, NewPayloadMethodV3, - NewPayloadMethodV4, ForkchoiceUpdatedMethod, ForkchoiceUpdatedMethodV2, ForkchoiceUpdatedMethodV3, GetPayloadMethod, GetPayloadMethodV2, GetPayloadMethodV3, - GetPayloadMethodV4, GetPayloadBodiesByHashV1, GetPayloadBodiesByRangeV1, - GetPayloadBodiesByHashV2, - GetPayloadBodiesByRangeV2, + } + electraEngineEndpoints = []string{ + NewPayloadMethodV4, + GetPayloadMethodV4, } ) @@ -77,14 +79,12 @@ const ( BlockByNumberMethod = "eth_getBlockByNumber" // GetPayloadBodiesByHashV1 is the engine_getPayloadBodiesByHashX JSON-RPC method for pre-Electra payloads. GetPayloadBodiesByHashV1 = "engine_getPayloadBodiesByHashV1" - // GetPayloadBodiesByHashV2 is the engine_getPayloadBodiesByHashX JSON-RPC method introduced by Electra. - GetPayloadBodiesByHashV2 = "engine_getPayloadBodiesByHashV2" // GetPayloadBodiesByRangeV1 is the engine_getPayloadBodiesByRangeX JSON-RPC method for pre-Electra payloads. GetPayloadBodiesByRangeV1 = "engine_getPayloadBodiesByRangeV1" - // GetPayloadBodiesByRangeV2 is the engine_getPayloadBodiesByRangeX JSON-RPC method introduced by Electra. - GetPayloadBodiesByRangeV2 = "engine_getPayloadBodiesByRangeV2" // ExchangeCapabilities request string for JSON-RPC. ExchangeCapabilities = "engine_exchangeCapabilities" + // GetBlobsV1 request string for JSON-RPC. + GetBlobsV1 = "engine_getBlobsV1" // Defines the seconds before timing out engine endpoints with non-block execution semantics. defaultEngineTimeout = time.Second ) @@ -99,22 +99,21 @@ type ForkchoiceUpdatedResponse struct { ValidationError string `json:"validationError"` } -// PayloadReconstructor defines a service that can reconstruct a full beacon -// block with an execution payload from a signed beacon block and a connection -// to an execution client's engine API. -type PayloadReconstructor interface { +// Reconstructor defines a service responsible for reconstructing full beacon chain objects by utilizing the execution API and making requests through the execution client. +type Reconstructor interface { ReconstructFullBlock( ctx context.Context, blindedBlock interfaces.ReadOnlySignedBeaconBlock, ) (interfaces.SignedBeaconBlock, error) ReconstructFullBellatrixBlockBatch( ctx context.Context, blindedBlocks []interfaces.ReadOnlySignedBeaconBlock, ) ([]interfaces.SignedBeaconBlock, error) + ReconstructBlobSidecars(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock, blockRoot [32]byte, hi func(uint64) bool) ([]blocks.VerifiedROBlob, error) } // EngineCaller defines a client that can interact with an Ethereum // execution node's engine service via JSON-RPC. type EngineCaller interface { - NewPayload(ctx context.Context, payload interfaces.ExecutionData, versionedHashes []common.Hash, parentBlockRoot *common.Hash) ([]byte, error) + NewPayload(ctx context.Context, payload interfaces.ExecutionData, versionedHashes []common.Hash, parentBlockRoot *common.Hash, executionRequests *pb.ExecutionRequests) ([]byte, error) ForkchoiceUpdated( ctx context.Context, state *pb.ForkchoiceState, attrs payloadattribute.Attributer, ) (*pb.PayloadIDBytes, []byte, error) @@ -125,8 +124,8 @@ type EngineCaller interface { var ErrEmptyBlockHash = errors.New("Block hash is empty 0x0000...") -// NewPayload calls the engine_newPayloadVX method via JSON-RPC. -func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionData, versionedHashes []common.Hash, parentBlockRoot *common.Hash) ([]byte, error) { +// NewPayload request calls the engine_newPayloadVX method via JSON-RPC. +func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionData, versionedHashes []common.Hash, parentBlockRoot *common.Hash, executionRequests *pb.ExecutionRequests) ([]byte, error) { ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.NewPayload") defer span.End() start := time.Now() @@ -139,42 +138,32 @@ func (s *Service) NewPayload(ctx context.Context, payload interfaces.ExecutionDa defer cancel() result := &pb.PayloadStatus{} - switch payload.Proto().(type) { + switch payloadPb := payload.Proto().(type) { case *pb.ExecutionPayload: - payloadPb, ok := payload.Proto().(*pb.ExecutionPayload) - if !ok { - return nil, errors.New("execution data must be a Bellatrix or Capella execution payload") - } err := s.rpcClient.CallContext(ctx, result, NewPayloadMethod, payloadPb) if err != nil { return nil, handleRPCError(err) } case *pb.ExecutionPayloadCapella: - payloadPb, ok := payload.Proto().(*pb.ExecutionPayloadCapella) - if !ok { - return nil, errors.New("execution data must be a Capella execution payload") - } err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV2, payloadPb) if err != nil { return nil, handleRPCError(err) } case *pb.ExecutionPayloadDeneb: - payloadPb, ok := payload.Proto().(*pb.ExecutionPayloadDeneb) - if !ok { - return nil, errors.New("execution data must be a Deneb execution payload") - } - err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV3, payloadPb, versionedHashes, parentBlockRoot) - if err != nil { - return nil, handleRPCError(err) - } - case *pb.ExecutionPayloadElectra: - payloadPb, ok := payload.Proto().(*pb.ExecutionPayloadElectra) - if !ok { - return nil, errors.New("execution data must be a Electra execution payload") - } - err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV4, payloadPb, versionedHashes, parentBlockRoot) - if err != nil { - return nil, handleRPCError(err) + if executionRequests == nil { + err := s.rpcClient.CallContext(ctx, result, NewPayloadMethodV3, payloadPb, versionedHashes, parentBlockRoot) + if err != nil { + return nil, handleRPCError(err) + } + } else { + flattenedRequests, err := pb.EncodeExecutionRequests(executionRequests) + if err != nil { + return nil, errors.Wrap(err, "failed to encode execution requests") + } + err = s.rpcClient.CallContext(ctx, result, NewPayloadMethodV4, payloadPb, versionedHashes, parentBlockRoot, flattenedRequests) + if err != nil { + return nil, handleRPCError(err) + } } default: return nil, errors.New("unknown execution data type") @@ -234,7 +223,7 @@ func (s *Service) ForkchoiceUpdated( if err != nil { return nil, nil, handleRPCError(err) } - case version.Deneb, version.Electra: + case version.Deneb, version.Electra, version.Fulu: a, err := attrs.PbV3() if err != nil { return nil, nil, err @@ -269,7 +258,7 @@ func (s *Service) ForkchoiceUpdated( func getPayloadMethodAndMessage(slot primitives.Slot) (string, proto.Message) { pe := slots.ToEpoch(slot) if pe >= params.BeaconConfig().ElectraForkEpoch { - return GetPayloadMethodV4, &pb.ExecutionPayloadElectraWithValueAndBlobsBundle{} + return GetPayloadMethodV4, &pb.ExecutionBundleElectra{} } if pe >= params.BeaconConfig().DenebForkEpoch { return GetPayloadMethodV3, &pb.ExecutionPayloadDenebWithValueAndBlobsBundle{} @@ -309,13 +298,20 @@ func (s *Service) ExchangeCapabilities(ctx context.Context) ([]string, error) { ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.ExchangeCapabilities") defer span.End() - result := &pb.ExchangeCapabilities{} + // Only check for electra related engine methods if it has been activated. + if params.ElectraEnabled() { + supportedEngineEndpoints = append(supportedEngineEndpoints, electraEngineEndpoints...) + } + var result []string err := s.rpcClient.CallContext(ctx, &result, ExchangeCapabilities, supportedEngineEndpoints) + if err != nil { + return nil, handleRPCError(err) + } var unsupported []string for _, s1 := range supportedEngineEndpoints { supported := false - for _, s2 := range result.SupportedMethods { + for _, s2 := range result { if s1 == s2 { supported = true break @@ -328,7 +324,7 @@ func (s *Service) ExchangeCapabilities(ctx context.Context) ([]string, error) { if len(unsupported) != 0 { log.Warnf("Please update client, detected the following unsupported engine methods: %s", unsupported) } - return result.SupportedMethods, handleRPCError(err) + return result, handleRPCError(err) } // GetTerminalBlockHash returns the valid terminal block hash based on total difficulty. @@ -495,6 +491,20 @@ func (s *Service) HeaderByNumber(ctx context.Context, number *big.Int) (*types.H return hdr, err } +// GetBlobs returns the blob and proof from the execution engine for the given versioned hashes. +func (s *Service) GetBlobs(ctx context.Context, versionedHashes []common.Hash) ([]*pb.BlobAndProof, error) { + ctx, span := trace.StartSpan(ctx, "powchain.engine-api-client.GetBlobs") + defer span.End() + // If the execution engine does not support `GetBlobsV1`, return early to prevent encountering an error later. + if !s.capabilityCache.has(GetBlobsV1) { + return nil, nil + } + + result := make([]*pb.BlobAndProof, len(versionedHashes)) + err := s.rpcClient.CallContext(ctx, &result, GetBlobsV1, versionedHashes) + return result, handleRPCError(err) +} + // ReconstructFullBlock takes in a blinded beacon block and reconstructs // a beacon block with a full execution payload via the engine API. func (s *Service) ReconstructFullBlock( @@ -523,50 +533,96 @@ func (s *Service) ReconstructFullBellatrixBlockBatch( return unb, nil } +// ReconstructBlobSidecars reconstructs the verified blob sidecars for a given beacon block. +// It retrieves the KZG commitments from the block body, fetches the associated blobs and proofs, +// and constructs the corresponding verified read-only blob sidecars. +// +// The 'hasIndex' argument is a function returns true if the given uint64 blob index already exists on disc. +// Only the blobs that do not already exist (where hasIndex(i) is false) +// will be fetched from the execution engine using the KZG commitments from block body. +func (s *Service) ReconstructBlobSidecars(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock, blockRoot [32]byte, hasIndex func(uint64) bool) ([]blocks.VerifiedROBlob, error) { + blockBody := block.Block().Body() + kzgCommitments, err := blockBody.BlobKzgCommitments() + if err != nil { + return nil, errors.Wrap(err, "could not get blob KZG commitments") + } + + // Collect KZG hashes for non-existing blobs + var kzgHashes []common.Hash + var kzgIndexes []int + for i, commitment := range kzgCommitments { + if !hasIndex(uint64(i)) { + kzgHashes = append(kzgHashes, primitives.ConvertKzgCommitmentToVersionedHash(commitment)) + kzgIndexes = append(kzgIndexes, i) + } + } + if len(kzgHashes) == 0 { + return nil, nil + } + + // Fetch blobs from EL + blobs, err := s.GetBlobs(ctx, kzgHashes) + if err != nil { + return nil, errors.Wrap(err, "could not get blobs") + } + if len(blobs) == 0 { + return nil, nil + } + + header, err := block.Header() + if err != nil { + return nil, errors.Wrap(err, "could not get header") + } + + // Reconstruct verified blob sidecars + var verifiedBlobs []blocks.VerifiedROBlob + for i := 0; i < len(kzgHashes); i++ { + if blobs[i] == nil { + continue + } + blob := blobs[i] + blobIndex := kzgIndexes[i] + proof, err := blocks.MerkleProofKZGCommitment(blockBody, blobIndex) + if err != nil { + log.WithError(err).WithField("index", blobIndex).Error("failed to get Merkle proof for KZG commitment") + continue + } + sidecar := ðpb.BlobSidecar{ + Index: uint64(blobIndex), + Blob: blob.Blob, + KzgCommitment: kzgCommitments[blobIndex], + KzgProof: blob.KzgProof, + SignedBlockHeader: header, + CommitmentInclusionProof: proof, + } + + roBlob, err := blocks.NewROBlobWithRoot(sidecar, blockRoot) + if err != nil { + log.WithError(err).WithField("index", blobIndex).Error("failed to create RO blob with root") + continue + } + + v := s.blobVerifier(roBlob, verification.ELMemPoolRequirements) + verifiedBlob, err := v.VerifiedROBlob() + if err != nil { + log.WithError(err).WithField("index", blobIndex).Error("failed to verify RO blob") + continue + } + + verifiedBlobs = append(verifiedBlobs, verifiedBlob) + } + + return verifiedBlobs, nil +} + func fullPayloadFromPayloadBody( header interfaces.ExecutionData, body *pb.ExecutionPayloadBody, bVersion int, ) (interfaces.ExecutionData, error) { - if header.IsNil() || body == nil { + if header == nil || header.IsNil() || body == nil { return nil, errors.New("execution block and header cannot be nil") } - switch bVersion { - case version.Bellatrix: - return blocks.WrappedExecutionPayload(&pb.ExecutionPayload{ - ParentHash: header.ParentHash(), - FeeRecipient: header.FeeRecipient(), - StateRoot: header.StateRoot(), - ReceiptsRoot: header.ReceiptsRoot(), - LogsBloom: header.LogsBloom(), - PrevRandao: header.PrevRandao(), - BlockNumber: header.BlockNumber(), - GasLimit: header.GasLimit(), - GasUsed: header.GasUsed(), - Timestamp: header.Timestamp(), - ExtraData: header.ExtraData(), - BaseFeePerGas: header.BaseFeePerGas(), - BlockHash: header.BlockHash(), - Transactions: pb.RecastHexutilByteSlice(body.Transactions), - }) - case version.Capella: - return blocks.WrappedExecutionPayloadCapella(&pb.ExecutionPayloadCapella{ - ParentHash: header.ParentHash(), - FeeRecipient: header.FeeRecipient(), - StateRoot: header.StateRoot(), - ReceiptsRoot: header.ReceiptsRoot(), - LogsBloom: header.LogsBloom(), - PrevRandao: header.PrevRandao(), - BlockNumber: header.BlockNumber(), - GasLimit: header.GasLimit(), - GasUsed: header.GasUsed(), - Timestamp: header.Timestamp(), - ExtraData: header.ExtraData(), - BaseFeePerGas: header.BaseFeePerGas(), - BlockHash: header.BlockHash(), - Transactions: pb.RecastHexutilByteSlice(body.Transactions), - Withdrawals: body.Withdrawals, - }) // We can't get the block value and don't care about the block value for this instance - case version.Deneb: + if bVersion >= version.Deneb { ebg, err := header.ExcessBlobGas() if err != nil { return nil, errors.Wrap(err, "unable to extract ExcessBlobGas attribute from execution payload header") @@ -595,53 +651,48 @@ func fullPayloadFromPayloadBody( ExcessBlobGas: ebg, BlobGasUsed: bgu, }) // We can't get the block value and don't care about the block value for this instance - case version.Electra: - ebg, err := header.ExcessBlobGas() - if err != nil { - return nil, errors.Wrap(err, "unable to extract ExcessBlobGas attribute from execution payload header") - } - bgu, err := header.BlobGasUsed() - if err != nil { - return nil, errors.Wrap(err, "unable to extract BlobGasUsed attribute from execution payload header") - } - wr, err := pb.JsonWithdrawalRequestsToProto(body.WithdrawalRequests) - if err != nil { - return nil, err - } - dr, err := pb.JsonDepositRequestsToProto(body.DepositRequests) - if err != nil { - return nil, err - } - cr, err := pb.JsonConsolidationRequestsToProto(body.ConsolidationRequests) - if err != nil { - return nil, err - } - return blocks.WrappedExecutionPayloadElectra( - &pb.ExecutionPayloadElectra{ - ParentHash: header.ParentHash(), - FeeRecipient: header.FeeRecipient(), - StateRoot: header.StateRoot(), - ReceiptsRoot: header.ReceiptsRoot(), - LogsBloom: header.LogsBloom(), - PrevRandao: header.PrevRandao(), - BlockNumber: header.BlockNumber(), - GasLimit: header.GasLimit(), - GasUsed: header.GasUsed(), - Timestamp: header.Timestamp(), - ExtraData: header.ExtraData(), - BaseFeePerGas: header.BaseFeePerGas(), - BlockHash: header.BlockHash(), - Transactions: pb.RecastHexutilByteSlice(body.Transactions), - Withdrawals: body.Withdrawals, - ExcessBlobGas: ebg, - BlobGasUsed: bgu, - DepositRequests: dr, - WithdrawalRequests: wr, - ConsolidationRequests: cr, - }) // We can't get the block value and don't care about the block value for this instance - default: - return nil, fmt.Errorf("unknown execution block version for payload %d", bVersion) } + + if bVersion >= version.Capella { + return blocks.WrappedExecutionPayloadCapella(&pb.ExecutionPayloadCapella{ + ParentHash: header.ParentHash(), + FeeRecipient: header.FeeRecipient(), + StateRoot: header.StateRoot(), + ReceiptsRoot: header.ReceiptsRoot(), + LogsBloom: header.LogsBloom(), + PrevRandao: header.PrevRandao(), + BlockNumber: header.BlockNumber(), + GasLimit: header.GasLimit(), + GasUsed: header.GasUsed(), + Timestamp: header.Timestamp(), + ExtraData: header.ExtraData(), + BaseFeePerGas: header.BaseFeePerGas(), + BlockHash: header.BlockHash(), + Transactions: pb.RecastHexutilByteSlice(body.Transactions), + Withdrawals: body.Withdrawals, + }) // We can't get the block value and don't care about the block value for this instance + } + + if bVersion >= version.Bellatrix { + return blocks.WrappedExecutionPayload(&pb.ExecutionPayload{ + ParentHash: header.ParentHash(), + FeeRecipient: header.FeeRecipient(), + StateRoot: header.StateRoot(), + ReceiptsRoot: header.ReceiptsRoot(), + LogsBloom: header.LogsBloom(), + PrevRandao: header.PrevRandao(), + BlockNumber: header.BlockNumber(), + GasLimit: header.GasLimit(), + GasUsed: header.GasUsed(), + Timestamp: header.Timestamp(), + ExtraData: header.ExtraData(), + BaseFeePerGas: header.BaseFeePerGas(), + BlockHash: header.BlockHash(), + Transactions: pb.RecastHexutilByteSlice(body.Transactions), + }) + } + + return nil, fmt.Errorf("unknown execution block version for payload %s", version.String(bVersion)) } // Handles errors received from the RPC server according to the specification. @@ -732,10 +783,9 @@ func tDStringToUint256(td string) (*uint256.Int, error) { return i, nil } -func buildEmptyExecutionPayload(v int) (proto.Message, error) { - switch v { - case version.Bellatrix: - return &pb.ExecutionPayload{ +func EmptyExecutionPayload(v int) (proto.Message, error) { + if v >= version.Deneb { + return &pb.ExecutionPayloadDeneb{ ParentHash: make([]byte, fieldparams.RootLength), FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), StateRoot: make([]byte, fieldparams.RootLength), @@ -746,8 +796,11 @@ func buildEmptyExecutionPayload(v int) (proto.Message, error) { BaseFeePerGas: make([]byte, fieldparams.RootLength), BlockHash: make([]byte, fieldparams.RootLength), Transactions: make([][]byte, 0), + Withdrawals: make([]*pb.Withdrawal, 0), }, nil - case version.Capella: + } + + if v >= version.Capella { return &pb.ExecutionPayloadCapella{ ParentHash: make([]byte, fieldparams.RootLength), FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), @@ -761,8 +814,10 @@ func buildEmptyExecutionPayload(v int) (proto.Message, error) { Transactions: make([][]byte, 0), Withdrawals: make([]*pb.Withdrawal, 0), }, nil - case version.Deneb: - return &pb.ExecutionPayloadDeneb{ + } + + if v >= version.Bellatrix { + return &pb.ExecutionPayload{ ParentHash: make([]byte, fieldparams.RootLength), FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), StateRoot: make([]byte, fieldparams.RootLength), @@ -773,27 +828,60 @@ func buildEmptyExecutionPayload(v int) (proto.Message, error) { BaseFeePerGas: make([]byte, fieldparams.RootLength), BlockHash: make([]byte, fieldparams.RootLength), Transactions: make([][]byte, 0), - Withdrawals: make([]*pb.Withdrawal, 0), }, nil - case version.Electra: - return &pb.ExecutionPayloadElectra{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - Transactions: make([][]byte, 0), - Withdrawals: make([]*pb.Withdrawal, 0), - WithdrawalRequests: make([]*pb.WithdrawalRequest, 0), - DepositRequests: make([]*pb.DepositRequest, 0), + } + + return nil, errors.Wrapf(ErrUnsupportedVersion, "version=%s", version.String(v)) +} + +func EmptyExecutionPayloadHeader(v int) (proto.Message, error) { + if v >= version.Deneb { + return &pb.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, nil + } + + if v >= version.Capella { + return &pb.ExecutionPayloadHeaderCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), }, nil - default: - return nil, errors.Wrapf(ErrUnsupportedVersion, "version=%s", version.String(v)) } + + if v >= version.Bellatrix { + return &pb.ExecutionPayloadHeader{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, nil + } + + return nil, errors.Wrapf(ErrUnsupportedVersion, "version=%s", version.String(v)) } func toBlockNumArg(number *big.Int) string { diff --git a/beacon-chain/execution/engine_client_test.go b/beacon-chain/execution/engine_client_test.go index 2e3e29b1defb..903c99bb22da 100644 --- a/beacon-chain/execution/engine_client_test.go +++ b/beacon-chain/execution/engine_client_test.go @@ -2,6 +2,7 @@ package execution import ( "context" + "crypto/rand" "encoding/json" "fmt" "io" @@ -19,7 +20,9 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/holiman/uint256" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" mocks "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" @@ -37,9 +40,9 @@ import ( ) var ( - _ = PayloadReconstructor(&Service{}) + _ = Reconstructor(&Service{}) _ = EngineCaller(&Service{}) - _ = PayloadReconstructor(&Service{}) + _ = Reconstructor(&Service{}) _ = EngineCaller(&mocks.EngineClient{}) ) @@ -123,7 +126,7 @@ func TestClient_IPC(t *testing.T) { require.Equal(t, true, ok) wrappedPayload, err := blocks.WrappedExecutionPayload(req) require.NoError(t, err) - latestValidHash, err := srv.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + latestValidHash, err := srv.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.NoError(t, err) require.DeepEqual(t, bytesutil.ToBytes32(want.LatestValidHash), bytesutil.ToBytes32(latestValidHash)) }) @@ -134,7 +137,7 @@ func TestClient_IPC(t *testing.T) { require.Equal(t, true, ok) wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(req) require.NoError(t, err) - latestValidHash, err := srv.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + latestValidHash, err := srv.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.NoError(t, err) require.DeepEqual(t, bytesutil.ToBytes32(want.LatestValidHash), bytesutil.ToBytes32(latestValidHash)) }) @@ -163,7 +166,7 @@ func TestClient_HTTP(t *testing.T) { cfg := params.BeaconConfig().Copy() cfg.CapellaForkEpoch = 1 cfg.DenebForkEpoch = 2 - cfg.ElectraForkEpoch = 2 + cfg.ElectraForkEpoch = 3 params.OverrideBeaconConfig(cfg) t.Run(GetPayloadMethod, func(t *testing.T) { @@ -322,7 +325,7 @@ func TestClient_HTTP(t *testing.T) { }) t.Run(GetPayloadMethodV4, func(t *testing.T) { payloadId := [8]byte{1} - want, ok := fix["ExecutionPayloadElectraWithValue"].(*pb.GetPayloadV4ResponseJson) + want, ok := fix["ExecutionBundleElectra"].(*pb.GetPayloadV4ResponseJson) require.Equal(t, true, ok) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -358,7 +361,7 @@ func TestClient_HTTP(t *testing.T) { client.rpcClient = rpcClient // We call the RPC method via HTTP and expect a proper result. - resp, err := client.GetPayload(ctx, payloadId, 2*params.BeaconConfig().SlotsPerEpoch) + resp, err := client.GetPayload(ctx, payloadId, 3*params.BeaconConfig().SlotsPerEpoch) require.NoError(t, err) require.Equal(t, true, resp.OverrideBuilder) g, err := resp.ExecutionData.ExcessBlobGas() @@ -374,18 +377,35 @@ func TestClient_HTTP(t *testing.T) { require.DeepEqual(t, proofs, resp.BlobsBundle.Proofs) blobs := [][]byte{bytesutil.PadTo([]byte("a"), fieldparams.BlobLength), bytesutil.PadTo([]byte("b"), fieldparams.BlobLength)} require.DeepEqual(t, blobs, resp.BlobsBundle.Blobs) - ede, ok := resp.ExecutionData.(interfaces.ExecutionDataElectra) - require.Equal(t, true, ok) - require.NotNil(t, ede.WithdrawalRequests()) - wrequestsNotOverMax := len(ede.WithdrawalRequests()) <= int(params.BeaconConfig().MaxWithdrawalRequestsPerPayload) - require.Equal(t, true, wrequestsNotOverMax) - require.NotNil(t, ede.DepositRequests()) - drequestsNotOverMax := len(ede.DepositRequests()) <= int(params.BeaconConfig().MaxDepositRequestsPerPayload) - require.Equal(t, true, drequestsNotOverMax) - require.NotNil(t, ede.ConsolidationRequests()) - consolidationsNotOverMax := len(ede.ConsolidationRequests()) <= int(params.BeaconConfig().MaxConsolidationsRequestsPerPayload) - require.Equal(t, true, consolidationsNotOverMax) + requests := &pb.ExecutionRequests{ + Deposits: []*pb.DepositRequest{ + { + Pubkey: bytesutil.PadTo([]byte{byte('a')}, fieldparams.BLSPubkeyLength), + WithdrawalCredentials: bytesutil.PadTo([]byte{byte('b')}, fieldparams.RootLength), + Amount: params.BeaconConfig().MinActivationBalance, + Signature: bytesutil.PadTo([]byte{byte('c')}, fieldparams.BLSSignatureLength), + Index: 0, + }, + }, + Withdrawals: []*pb.WithdrawalRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('d')}, common.AddressLength), + ValidatorPubkey: bytesutil.PadTo([]byte{byte('e')}, fieldparams.BLSPubkeyLength), + Amount: params.BeaconConfig().MinActivationBalance, + }, + }, + Consolidations: []*pb.ConsolidationRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('f')}, common.AddressLength), + SourcePubkey: bytesutil.PadTo([]byte{byte('g')}, fieldparams.BLSPubkeyLength), + TargetPubkey: bytesutil.PadTo([]byte{byte('h')}, fieldparams.BLSPubkeyLength), + }, + }, + } + + require.DeepEqual(t, requests, resp.ExecutionRequests) }) + t.Run(ForkchoiceUpdatedMethod+" VALID status", func(t *testing.T) { forkChoiceState := &pb.ForkchoiceState{ HeadBlockHash: []byte("head"), @@ -536,7 +556,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayload(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.NoError(t, err) require.DeepEqual(t, want.LatestValidHash, resp) }) @@ -550,7 +570,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.NoError(t, err) require.DeepEqual(t, want.LatestValidHash, resp) }) @@ -564,21 +584,46 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}, nil) require.NoError(t, err) require.DeepEqual(t, want.LatestValidHash, resp) }) t.Run(NewPayloadMethodV4+" VALID status", func(t *testing.T) { - execPayload, ok := fix["ExecutionPayloadElectra"].(*pb.ExecutionPayloadElectra) + execPayload, ok := fix["ExecutionPayloadDeneb"].(*pb.ExecutionPayloadDeneb) require.Equal(t, true, ok) want, ok := fix["ValidPayloadStatus"].(*pb.PayloadStatus) require.Equal(t, true, ok) - client := newPayloadV4Setup(t, want, execPayload) // We call the RPC method via HTTP and expect a proper result. - wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload) + wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}) + requests := &pb.ExecutionRequests{ + Deposits: []*pb.DepositRequest{ + { + Pubkey: bytesutil.PadTo([]byte{byte('a')}, fieldparams.BLSPubkeyLength), + WithdrawalCredentials: bytesutil.PadTo([]byte{byte('b')}, fieldparams.RootLength), + Amount: params.BeaconConfig().MinActivationBalance, + Signature: bytesutil.PadTo([]byte{byte('c')}, fieldparams.BLSSignatureLength), + Index: 0, + }, + }, + Withdrawals: []*pb.WithdrawalRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('d')}, common.AddressLength), + ValidatorPubkey: bytesutil.PadTo([]byte{byte('e')}, fieldparams.BLSPubkeyLength), + Amount: params.BeaconConfig().MinActivationBalance, + }, + }, + Consolidations: []*pb.ConsolidationRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('f')}, common.AddressLength), + SourcePubkey: bytesutil.PadTo([]byte{byte('g')}, fieldparams.BLSPubkeyLength), + TargetPubkey: bytesutil.PadTo([]byte{byte('h')}, fieldparams.BLSPubkeyLength), + }, + }, + } + client := newPayloadV4Setup(t, want, execPayload, requests) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}, requests) require.NoError(t, err) require.DeepEqual(t, want.LatestValidHash, resp) }) @@ -592,7 +637,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayload(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) @@ -606,7 +651,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) @@ -620,21 +665,46 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}, nil) require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) t.Run(NewPayloadMethodV4+" SYNCING status", func(t *testing.T) { - execPayload, ok := fix["ExecutionPayloadElectra"].(*pb.ExecutionPayloadElectra) + execPayload, ok := fix["ExecutionPayloadDeneb"].(*pb.ExecutionPayloadDeneb) require.Equal(t, true, ok) want, ok := fix["SyncingStatus"].(*pb.PayloadStatus) require.Equal(t, true, ok) - client := newPayloadV4Setup(t, want, execPayload) // We call the RPC method via HTTP and expect a proper result. - wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload) + wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}) + requests := &pb.ExecutionRequests{ + Deposits: []*pb.DepositRequest{ + { + Pubkey: bytesutil.PadTo([]byte{byte('a')}, fieldparams.BLSPubkeyLength), + WithdrawalCredentials: bytesutil.PadTo([]byte{byte('b')}, fieldparams.RootLength), + Amount: params.BeaconConfig().MinActivationBalance, + Signature: bytesutil.PadTo([]byte{byte('c')}, fieldparams.BLSSignatureLength), + Index: 0, + }, + }, + Withdrawals: []*pb.WithdrawalRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('d')}, common.AddressLength), + ValidatorPubkey: bytesutil.PadTo([]byte{byte('e')}, fieldparams.BLSPubkeyLength), + Amount: params.BeaconConfig().MinActivationBalance, + }, + }, + Consolidations: []*pb.ConsolidationRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('f')}, common.AddressLength), + SourcePubkey: bytesutil.PadTo([]byte{byte('g')}, fieldparams.BLSPubkeyLength), + TargetPubkey: bytesutil.PadTo([]byte{byte('h')}, fieldparams.BLSPubkeyLength), + }, + }, + } + client := newPayloadV4Setup(t, want, execPayload, requests) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}, requests) require.ErrorIs(t, ErrAcceptedSyncingPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) @@ -648,7 +718,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayload(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) @@ -662,7 +732,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) @@ -676,21 +746,45 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}, nil) require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) t.Run(NewPayloadMethodV4+" INVALID_BLOCK_HASH status", func(t *testing.T) { - execPayload, ok := fix["ExecutionPayloadElectra"].(*pb.ExecutionPayloadElectra) + execPayload, ok := fix["ExecutionPayloadDeneb"].(*pb.ExecutionPayloadDeneb) require.Equal(t, true, ok) want, ok := fix["InvalidBlockHashStatus"].(*pb.PayloadStatus) require.Equal(t, true, ok) - client := newPayloadV4Setup(t, want, execPayload) - // We call the RPC method via HTTP and expect a proper result. - wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload) + wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}) + requests := &pb.ExecutionRequests{ + Deposits: []*pb.DepositRequest{ + { + Pubkey: bytesutil.PadTo([]byte{byte('a')}, fieldparams.BLSPubkeyLength), + WithdrawalCredentials: bytesutil.PadTo([]byte{byte('b')}, fieldparams.RootLength), + Amount: params.BeaconConfig().MinActivationBalance, + Signature: bytesutil.PadTo([]byte{byte('c')}, fieldparams.BLSSignatureLength), + Index: 0, + }, + }, + Withdrawals: []*pb.WithdrawalRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('d')}, common.AddressLength), + ValidatorPubkey: bytesutil.PadTo([]byte{byte('e')}, fieldparams.BLSPubkeyLength), + Amount: params.BeaconConfig().MinActivationBalance, + }, + }, + Consolidations: []*pb.ConsolidationRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('f')}, common.AddressLength), + SourcePubkey: bytesutil.PadTo([]byte{byte('g')}, fieldparams.BLSPubkeyLength), + TargetPubkey: bytesutil.PadTo([]byte{byte('h')}, fieldparams.BLSPubkeyLength), + }, + }, + } + client := newPayloadV4Setup(t, want, execPayload, requests) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}, requests) require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) @@ -704,7 +798,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayload(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.ErrorIs(t, ErrInvalidPayloadStatus, err) require.DeepEqual(t, want.LatestValidHash, resp) }) @@ -718,7 +812,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayloadCapella(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.ErrorIs(t, ErrInvalidPayloadStatus, err) require.DeepEqual(t, want.LatestValidHash, resp) }) @@ -732,21 +826,46 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}, nil) require.ErrorIs(t, ErrInvalidPayloadStatus, err) require.DeepEqual(t, want.LatestValidHash, resp) }) t.Run(NewPayloadMethodV4+" INVALID status", func(t *testing.T) { - execPayload, ok := fix["ExecutionPayloadElectra"].(*pb.ExecutionPayloadElectra) + execPayload, ok := fix["ExecutionPayloadDeneb"].(*pb.ExecutionPayloadDeneb) require.Equal(t, true, ok) want, ok := fix["InvalidStatus"].(*pb.PayloadStatus) require.Equal(t, true, ok) - client := newPayloadV4Setup(t, want, execPayload) // We call the RPC method via HTTP and expect a proper result. - wrappedPayload, err := blocks.WrappedExecutionPayloadElectra(execPayload) + wrappedPayload, err := blocks.WrappedExecutionPayloadDeneb(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}) + requests := &pb.ExecutionRequests{ + Deposits: []*pb.DepositRequest{ + { + Pubkey: bytesutil.PadTo([]byte{byte('a')}, fieldparams.BLSPubkeyLength), + WithdrawalCredentials: bytesutil.PadTo([]byte{byte('b')}, fieldparams.RootLength), + Amount: params.BeaconConfig().MinActivationBalance, + Signature: bytesutil.PadTo([]byte{byte('c')}, fieldparams.BLSSignatureLength), + Index: 0, + }, + }, + Withdrawals: []*pb.WithdrawalRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('d')}, common.AddressLength), + ValidatorPubkey: bytesutil.PadTo([]byte{byte('e')}, fieldparams.BLSPubkeyLength), + Amount: params.BeaconConfig().MinActivationBalance, + }, + }, + Consolidations: []*pb.ConsolidationRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('f')}, common.AddressLength), + SourcePubkey: bytesutil.PadTo([]byte{byte('g')}, fieldparams.BLSPubkeyLength), + TargetPubkey: bytesutil.PadTo([]byte{byte('h')}, fieldparams.BLSPubkeyLength), + }, + }, + } + client := newPayloadV4Setup(t, want, execPayload, requests) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{'a'}, requests) require.ErrorIs(t, ErrInvalidPayloadStatus, err) require.DeepEqual(t, want.LatestValidHash, resp) }) @@ -760,7 +879,7 @@ func TestClient_HTTP(t *testing.T) { // We call the RPC method via HTTP and expect a proper result. wrappedPayload, err := blocks.WrappedExecutionPayload(execPayload) require.NoError(t, err) - resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}) + resp, err := client.NewPayload(ctx, wrappedPayload, []common.Hash{}, &common.Hash{}, nil) require.ErrorIs(t, ErrUnknownPayloadStatus, err) require.DeepEqual(t, []uint8(nil), resp) }) @@ -1417,10 +1536,9 @@ func fixtures() map[string]interface{} { "ExecutionPayload": s.ExecutionPayload, "ExecutionPayloadCapella": s.ExecutionPayloadCapella, "ExecutionPayloadDeneb": s.ExecutionPayloadDeneb, - "ExecutionPayloadElectra": s.ExecutionPayloadElectra, "ExecutionPayloadCapellaWithValue": s.ExecutionPayloadWithValueCapella, "ExecutionPayloadDenebWithValue": s.ExecutionPayloadWithValueDeneb, - "ExecutionPayloadElectraWithValue": s.ExecutionPayloadWithValueElectra, + "ExecutionBundleElectra": s.ExecutionBundleElectra, "ValidPayloadStatus": s.ValidPayloadStatus, "InvalidBlockHashStatus": s.InvalidBlockHashStatus, "AcceptedStatus": s.AcceptedStatus, @@ -1558,40 +1676,6 @@ func fixturesStruct() *payloadFixtures { TargetPubkey: &tPubkey, } } - dr, err := pb.JsonDepositRequestsToProto(depositRequests) - if err != nil { - panic(err) - } - wr, err := pb.JsonWithdrawalRequestsToProto(withdrawalRequests) - if err != nil { - panic(err) - } - cr, err := pb.JsonConsolidationRequestsToProto(consolidationRequests) - if err != nil { - panic(err) - } - executionPayloadFixtureElectra := &pb.ExecutionPayloadElectra{ - ParentHash: foo[:], - FeeRecipient: bar, - StateRoot: foo[:], - ReceiptsRoot: foo[:], - LogsBloom: baz, - PrevRandao: foo[:], - BlockNumber: 1, - GasLimit: 1, - GasUsed: 1, - Timestamp: 1, - ExtraData: foo[:], - BaseFeePerGas: bytesutil.PadTo(baseFeePerGas.Bytes(), fieldparams.RootLength), - BlockHash: foo[:], - Transactions: [][]byte{foo[:]}, - Withdrawals: []*pb.Withdrawal{}, - BlobGasUsed: 2, - ExcessBlobGas: 3, - DepositRequests: dr, - WithdrawalRequests: wr, - ConsolidationRequests: cr, - } hexUint := hexutil.Uint64(1) executionPayloadWithValueFixtureCapella := &pb.GetPayloadV2ResponseJson{ ExecutionPayload: &pb.ExecutionPayloadCapellaJSON{ @@ -1641,28 +1725,44 @@ func fixturesStruct() *payloadFixtures { Blobs: []hexutil.Bytes{{'a'}, {'b'}}, }, } - executionPayloadWithValueFixtureElectra := &pb.GetPayloadV4ResponseJson{ + + depositRequestBytes, err := hexutil.Decode("0x610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "620000000000000000000000000000000000000000000000000000000000000000" + + "4059730700000063000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + if err != nil { + panic("failed to decode deposit request") + } + withdrawalRequestBytes, err := hexutil.Decode("0x6400000000000000000000000000000000000000" + + "6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040597307000000") + if err != nil { + panic("failed to decode withdrawal request") + } + consolidationRequestBytes, err := hexutil.Decode("0x6600000000000000000000000000000000000000" + + "670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + if err != nil { + panic("failed to decode consolidation request") + } + executionBundleFixtureElectra := &pb.GetPayloadV4ResponseJson{ ShouldOverrideBuilder: true, - ExecutionPayload: &pb.ExecutionPayloadElectraJSON{ - ParentHash: &common.Hash{'a'}, - FeeRecipient: &common.Address{'b'}, - StateRoot: &common.Hash{'c'}, - ReceiptsRoot: &common.Hash{'d'}, - LogsBloom: &hexutil.Bytes{'e'}, - PrevRandao: &common.Hash{'f'}, - BaseFeePerGas: "0x123", - BlockHash: &common.Hash{'g'}, - Transactions: []hexutil.Bytes{{'h'}}, - Withdrawals: []*pb.Withdrawal{}, - BlockNumber: &hexUint, - GasLimit: &hexUint, - GasUsed: &hexUint, - Timestamp: &hexUint, - BlobGasUsed: &bgu, - ExcessBlobGas: &ebg, - DepositRequests: depositRequests, - WithdrawalRequests: withdrawalRequests, - ConsolidationRequests: consolidationRequests, + ExecutionPayload: &pb.ExecutionPayloadDenebJSON{ + ParentHash: &common.Hash{'a'}, + FeeRecipient: &common.Address{'b'}, + StateRoot: &common.Hash{'c'}, + ReceiptsRoot: &common.Hash{'d'}, + LogsBloom: &hexutil.Bytes{'e'}, + PrevRandao: &common.Hash{'f'}, + BaseFeePerGas: "0x123", + BlockHash: &common.Hash{'g'}, + Transactions: []hexutil.Bytes{{'h'}}, + Withdrawals: []*pb.Withdrawal{}, + BlockNumber: &hexUint, + GasLimit: &hexUint, + GasUsed: &hexUint, + Timestamp: &hexUint, + BlobGasUsed: &bgu, + ExcessBlobGas: &ebg, }, BlockValue: "0x11fffffffff", BlobsBundle: &pb.BlobBundleJSON{ @@ -1670,6 +1770,9 @@ func fixturesStruct() *payloadFixtures { Proofs: []hexutil.Bytes{[]byte("proof1"), []byte("proof2")}, Blobs: []hexutil.Bytes{{'a'}, {'b'}}, }, + ExecutionRequests: []hexutil.Bytes{append([]byte{pb.DepositRequestType}, depositRequestBytes...), + append([]byte{pb.WithdrawalRequestType}, withdrawalRequestBytes...), + append([]byte{pb.ConsolidationRequestType}, consolidationRequestBytes...)}, } parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength) sha3Uncles := bytesutil.PadTo([]byte("sha3Uncles"), fieldparams.RootLength) @@ -1762,10 +1865,9 @@ func fixturesStruct() *payloadFixtures { ExecutionPayloadCapella: executionPayloadFixtureCapella, ExecutionPayloadDeneb: executionPayloadFixtureDeneb, EmptyExecutionPayloadDeneb: emptyExecutionPayloadDeneb, - ExecutionPayloadElectra: executionPayloadFixtureElectra, ExecutionPayloadWithValueCapella: executionPayloadWithValueFixtureCapella, ExecutionPayloadWithValueDeneb: executionPayloadWithValueFixtureDeneb, - ExecutionPayloadWithValueElectra: executionPayloadWithValueFixtureElectra, + ExecutionBundleElectra: executionBundleFixtureElectra, ValidPayloadStatus: validStatus, InvalidBlockHashStatus: inValidBlockHashStatus, AcceptedStatus: acceptedStatus, @@ -1787,10 +1889,9 @@ type payloadFixtures struct { ExecutionPayloadCapella *pb.ExecutionPayloadCapella EmptyExecutionPayloadDeneb *pb.ExecutionPayloadDeneb ExecutionPayloadDeneb *pb.ExecutionPayloadDeneb - ExecutionPayloadElectra *pb.ExecutionPayloadElectra ExecutionPayloadWithValueCapella *pb.GetPayloadV2ResponseJson ExecutionPayloadWithValueDeneb *pb.GetPayloadV3ResponseJson - ExecutionPayloadWithValueElectra *pb.GetPayloadV4ResponseJson + ExecutionBundleElectra *pb.GetPayloadV4ResponseJson ValidPayloadStatus *pb.PayloadStatus InvalidBlockHashStatus *pb.PayloadStatus AcceptedStatus *pb.PayloadStatus @@ -2149,7 +2250,7 @@ func newPayloadV3Setup(t *testing.T, status *pb.PayloadStatus, payload *pb.Execu return service } -func newPayloadV4Setup(t *testing.T, status *pb.PayloadStatus, payload *pb.ExecutionPayloadElectra) *Service { +func newPayloadV4Setup(t *testing.T, status *pb.PayloadStatus, payload *pb.ExecutionPayloadDeneb, requests *pb.ExecutionRequests) *Service { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") defer func() { @@ -2158,14 +2259,28 @@ func newPayloadV4Setup(t *testing.T, status *pb.PayloadStatus, payload *pb.Execu enc, err := io.ReadAll(r.Body) require.NoError(t, err) jsonRequestString := string(enc) + require.Equal(t, true, strings.Contains( + jsonRequestString, string("engine_newPayloadV4"), + )) - reqArg, err := json.Marshal(payload) + reqPayload, err := json.Marshal(payload) require.NoError(t, err) // We expect the JSON string RPC request contains the right arguments. require.Equal(t, true, strings.Contains( - jsonRequestString, string(reqArg), + jsonRequestString, string(reqPayload), + )) + + reqRequests, err := pb.EncodeExecutionRequests(requests) + require.NoError(t, err) + + jsonRequests, err := json.Marshal(reqRequests) + require.NoError(t, err) + + require.Equal(t, true, strings.Contains( + jsonRequestString, string(jsonRequests), )) + resp := map[string]interface{}{ "jsonrpc": "2.0", "id": 1, @@ -2222,11 +2337,10 @@ func Test_ExchangeCapabilities(t *testing.T) { defer func() { require.NoError(t, r.Body.Close()) }() - exchangeCapabilities := &pb.ExchangeCapabilities{} resp := map[string]interface{}{ "jsonrpc": "2.0", "id": 1, - "result": exchangeCapabilities, + "result": []string{}, } err := json.NewEncoder(w).Encode(resp) require.NoError(t, err) @@ -2255,14 +2369,11 @@ func Test_ExchangeCapabilities(t *testing.T) { defer func() { require.NoError(t, r.Body.Close()) }() - exchangeCapabilities := &pb.ExchangeCapabilities{ - SupportedMethods: []string{"A", "B", "C"}, - } resp := map[string]interface{}{ "jsonrpc": "2.0", "id": 1, - "result": exchangeCapabilities, + "result": []string{"A", "B", "C"}, } err := json.NewEncoder(w).Encode(resp) require.NoError(t, err) @@ -2284,3 +2395,139 @@ func Test_ExchangeCapabilities(t *testing.T) { } }) } + +func mockSummary(t *testing.T, exists []bool) func(uint64) bool { + hi, err := filesystem.NewBlobStorageSummary(params.BeaconConfig().DenebForkEpoch, exists) + require.NoError(t, err) + return hi.HasIndex +} + +func TestReconstructBlobSidecars(t *testing.T) { + client := &Service{capabilityCache: &capabilityCache{}} + b := util.NewBeaconBlockDeneb() + kzgCommitments := createRandomKzgCommitments(t, 6) + + b.Block.Body.BlobKzgCommitments = kzgCommitments + r, err := b.Block.HashTreeRoot() + require.NoError(t, err) + sb, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + + ctx := context.Background() + t.Run("all seen", func(t *testing.T) { + hi := mockSummary(t, []bool{true, true, true, true, true, true}) + verifiedBlobs, err := client.ReconstructBlobSidecars(ctx, sb, r, hi) + require.NoError(t, err) + require.Equal(t, 0, len(verifiedBlobs)) + }) + + t.Run("get-blobs end point is not supported", func(t *testing.T) { + hi := mockSummary(t, []bool{true, true, true, true, true, false}) + verifiedBlobs, err := client.ReconstructBlobSidecars(ctx, sb, r, hi) + require.NoError(t, err) + require.Equal(t, 0, len(verifiedBlobs)) + }) + + client.capabilityCache = &capabilityCache{capabilities: map[string]interface{}{GetBlobsV1: nil}} + + t.Run("recovered 6 missing blobs", func(t *testing.T) { + srv := createBlobServer(t, 6) + defer srv.Close() + + rpcClient, client := setupRpcClient(t, srv.URL, client) + defer rpcClient.Close() + + hi := mockSummary(t, make([]bool, 6)) + verifiedBlobs, err := client.ReconstructBlobSidecars(ctx, sb, r, hi) + require.NoError(t, err) + require.Equal(t, 6, len(verifiedBlobs)) + }) + + t.Run("recovered 3 missing blobs", func(t *testing.T) { + srv := createBlobServer(t, 3) + defer srv.Close() + + rpcClient, client := setupRpcClient(t, srv.URL, client) + defer rpcClient.Close() + + hi := mockSummary(t, []bool{true, false, true, false, true, false}) + verifiedBlobs, err := client.ReconstructBlobSidecars(ctx, sb, r, hi) + require.NoError(t, err) + require.Equal(t, 3, len(verifiedBlobs)) + }) + + t.Run("recovered 3 missing blobs with mutated blob mask", func(t *testing.T) { + exists := []bool{true, false, true, false, true, false} + hi := mockSummary(t, exists) + + srv := createBlobServer(t, 3, func() { + // Mutate blob mask + exists[1] = true + exists[3] = true + }) + defer srv.Close() + + rpcClient, client := setupRpcClient(t, srv.URL, client) + defer rpcClient.Close() + + verifiedBlobs, err := client.ReconstructBlobSidecars(ctx, sb, r, hi) + require.NoError(t, err) + require.Equal(t, 3, len(verifiedBlobs)) + }) +} + +func createRandomKzgCommitments(t *testing.T, num int) [][]byte { + kzgCommitments := make([][]byte, num) + for i := range kzgCommitments { + kzgCommitments[i] = make([]byte, 48) + _, err := rand.Read(kzgCommitments[i]) + require.NoError(t, err) + } + return kzgCommitments +} + +func createBlobServer(t *testing.T, numBlobs int, callbackFuncs ...func()) *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + defer func() { + require.NoError(t, r.Body.Close()) + }() + // Execute callback functions for each request. + for _, f := range callbackFuncs { + f() + } + + blobs := make([]pb.BlobAndProofJson, numBlobs) + for i := range blobs { + blobs[i] = pb.BlobAndProofJson{Blob: []byte(fmt.Sprintf("blob%d", i+1)), KzgProof: []byte(fmt.Sprintf("proof%d", i+1))} + } + + respJSON := map[string]interface{}{ + "jsonrpc": "2.0", + "id": 1, + "result": blobs, + } + require.NoError(t, json.NewEncoder(w).Encode(respJSON)) + })) +} + +func setupRpcClient(t *testing.T, url string, client *Service) (*rpc.Client, *Service) { + rpcClient, err := rpc.DialHTTP(url) + require.NoError(t, err) + + client.rpcClient = rpcClient + client.capabilityCache = &capabilityCache{capabilities: map[string]interface{}{GetBlobsV1: nil}} + client.blobVerifier = testNewBlobVerifier() + + return rpcClient, client +} + +func testNewBlobVerifier() verification.NewBlobVerifier { + return func(b blocks.ROBlob, reqs []verification.Requirement) verification.BlobVerifier { + return &verification.MockBlobVerifier{ + CbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { + return blocks.VerifiedROBlob{}, nil + }, + } + } +} diff --git a/beacon-chain/execution/execution_chain_test.go b/beacon-chain/execution/execution_chain_test.go index 0eeb166caefa..e6bcb1c6ba89 100644 --- a/beacon-chain/execution/execution_chain_test.go +++ b/beacon-chain/execution/execution_chain_test.go @@ -2,6 +2,7 @@ package execution import ( "io" + "os" "testing" "github.com/sirupsen/logrus" @@ -11,5 +12,5 @@ func TestMain(m *testing.M) { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(io.Discard) - m.Run() + os.Exit(m.Run()) } diff --git a/beacon-chain/execution/log_processing_test.go b/beacon-chain/execution/log_processing_test.go index 4120ca136f8e..c7f46239d71b 100644 --- a/beacon-chain/execution/log_processing_test.go +++ b/beacon-chain/execution/log_processing_test.go @@ -47,7 +47,7 @@ func TestProcessDepositLog_OK(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) testAcc.Backend.Commit() @@ -72,7 +72,7 @@ func TestProcessDepositLog_OK(t *testing.T) { }, } - logs, err := testAcc.Backend.FilterLogs(web3Service.ctx, query) + logs, err := testAcc.Backend.Client().FilterLogs(web3Service.ctx, query) require.NoError(t, err, "Unable to retrieve logs") if len(logs) == 0 { @@ -116,7 +116,7 @@ func TestProcessDepositLog_InsertsPendingDeposit(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) testAcc.Backend.Commit() @@ -144,7 +144,7 @@ func TestProcessDepositLog_InsertsPendingDeposit(t *testing.T) { }, } - logs, err := testAcc.Backend.FilterLogs(web3Service.ctx, query) + logs, err := testAcc.Backend.Client().FilterLogs(web3Service.ctx, query) require.NoError(t, err, "Unable to retrieve logs") web3Service.chainStartData.Chainstarted = true @@ -176,7 +176,7 @@ func TestUnpackDepositLogData_OK(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) testAcc.Backend.Commit() @@ -199,7 +199,7 @@ func TestUnpackDepositLogData_OK(t *testing.T) { }, } - logz, err := testAcc.Backend.FilterLogs(web3Service.ctx, query) + logz, err := testAcc.Backend.Client().FilterLogs(web3Service.ctx, query) require.NoError(t, err, "Unable to retrieve logs") loggedPubkey, withCreds, _, loggedSig, index, err := contracts.UnpackDepositLogData(logz[0].Data) @@ -232,7 +232,7 @@ func TestProcessETH2GenesisLog_8DuplicatePubkeys(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) params.SetupTestConfigCleanup(t) @@ -269,7 +269,7 @@ func TestProcessETH2GenesisLog_8DuplicatePubkeys(t *testing.T) { }, } - logs, err := testAcc.Backend.FilterLogs(web3Service.ctx, query) + logs, err := testAcc.Backend.Client().FilterLogs(web3Service.ctx, query) require.NoError(t, err, "Unable to retrieve logs") for i := range logs { @@ -307,7 +307,7 @@ func TestProcessETH2GenesisLog(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} require.NoError(t, err) params.SetupTestConfigCleanup(t) @@ -342,7 +342,7 @@ func TestProcessETH2GenesisLog(t *testing.T) { }, } - logs, err := testAcc.Backend.FilterLogs(web3Service.ctx, query) + logs, err := testAcc.Backend.Client().FilterLogs(web3Service.ctx, query) require.NoError(t, err, "Unable to retrieve logs") require.Equal(t, depositsReqForChainStart, len(logs)) @@ -400,16 +400,18 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} - web3Service.httpLogger = testAcc.Backend + web3Service.httpLogger = testAcc.Backend.Client() web3Service.latestEth1Data.LastRequestedBlock = 0 - web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64() - web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time + block, err := testAcc.Backend.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) + web3Service.latestEth1Data.BlockHeight = block.NumberU64() + web3Service.latestEth1Data.BlockTime = block.Time() bConfig := params.MinimalSpecConfig().Copy() bConfig.MinGenesisTime = 0 - bConfig.SecondsPerETH1Block = 10 + bConfig.SecondsPerETH1Block = 1 params.OverrideBeaconConfig(bConfig) nConfig := params.BeaconNetworkConfig() nConfig.ContractDeploymentBlock = 0 @@ -444,8 +446,10 @@ func TestProcessETH2GenesisLog_CorrectNumOfDeposits(t *testing.T) { for i := uint64(0); i < params.BeaconConfig().Eth1FollowDistance; i++ { testAcc.Backend.Commit() } - web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64() - web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time + b, err := testAcc.Backend.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) + web3Service.latestEth1Data.BlockHeight = b.NumberU64() + web3Service.latestEth1Data.BlockTime = b.Time() // Set up our subscriber now to listen for the chain started event. stateChannel := make(chan *feed.Event, 1) @@ -497,13 +501,15 @@ func TestProcessETH2GenesisLog_LargePeriodOfNoLogs(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} - web3Service.httpLogger = testAcc.Backend + web3Service.httpLogger = testAcc.Backend.Client() web3Service.latestEth1Data.LastRequestedBlock = 0 - web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64() - web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time + b, err := testAcc.Backend.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) + web3Service.latestEth1Data.BlockHeight = b.NumberU64() + web3Service.latestEth1Data.BlockTime = b.Time() bConfig := params.MinimalSpecConfig().Copy() bConfig.SecondsPerETH1Block = 10 params.OverrideBeaconConfig(bConfig) @@ -540,14 +546,19 @@ func TestProcessETH2GenesisLog_LargePeriodOfNoLogs(t *testing.T) { for i := uint64(0); i < 1500; i++ { testAcc.Backend.Commit() } - wantedGenesisTime := testAcc.Backend.Blockchain().CurrentBlock().Time + genesisBlock, err := testAcc.Backend.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) + + wantedGenesisTime := genesisBlock.Time() // Forward the chain to account for the follow distance for i := uint64(0); i < params.BeaconConfig().Eth1FollowDistance; i++ { testAcc.Backend.Commit() } - web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64() - web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time + currBlock, err := testAcc.Backend.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) + web3Service.latestEth1Data.BlockHeight = currBlock.NumberU64() + web3Service.latestEth1Data.BlockTime = currBlock.Time() // Set the genesis time 500 blocks ahead of the last // deposit log. @@ -608,7 +619,7 @@ func newPowchainService(t *testing.T, eth1Backend *mock.TestAccount, beaconDB db ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(eth1Backend.ContractAddr, eth1Backend.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(eth1Backend.ContractAddr, eth1Backend.Backend.Client()) require.NoError(t, err) web3Service.rpcClient = &mockExecution.RPCClient{Backend: eth1Backend.Backend} diff --git a/beacon-chain/execution/mock_test.go b/beacon-chain/execution/mock_test.go index a77c83ecc446..16f61f870855 100644 --- a/beacon-chain/execution/mock_test.go +++ b/beacon-chain/execution/mock_test.go @@ -3,7 +3,6 @@ package execution import ( "context" "encoding/json" - "math" "net/http" "net/http/httptest" "testing" @@ -84,11 +83,15 @@ func (s *mockEngine) callCount(method string) int { } func mockParseUintList(t *testing.T, data json.RawMessage) []uint64 { - var list []uint64 + var list []string if err := json.Unmarshal(data, &list); err != nil { t.Fatalf("failed to parse uint list: %v", err) } - return list + uints := make([]uint64, len(list)) + for i, u := range list { + uints[i] = hexutil.MustDecodeUint64(u) + } + return uints } func mockParseHexByteList(t *testing.T, data json.RawMessage) []hexutil.Bytes { @@ -117,7 +120,7 @@ func TestParseRequest(t *testing.T) { ctx := context.Background() cases := []struct { method string - uintArgs []uint64 + hexArgs []string // uint64 as hex byteArgs []hexutil.Bytes }{ { @@ -128,33 +131,24 @@ func TestParseRequest(t *testing.T) { }, }, { - method: GetPayloadBodiesByHashV2, - byteArgs: []hexutil.Bytes{ - strToHexBytes(t, "0x656d707479000000000000000000000000000000000000000000000000000000"), - strToHexBytes(t, "0x66756c6c00000000000000000000000000000000000000000000000000000000"), - }, - }, - { - method: GetPayloadBodiesByRangeV1, - uintArgs: []uint64{0, 1}, - }, - { - method: GetPayloadBodiesByRangeV2, - uintArgs: []uint64{math.MaxUint64, 1}, + method: GetPayloadBodiesByRangeV1, + hexArgs: []string{hexutil.EncodeUint64(0), hexutil.EncodeUint64(1)}, }, } for _, c := range cases { t.Run(c.method, func(t *testing.T) { cli, srv := newMockEngine(t) - srv.register(c.method, func(msg *jsonrpcMessage, w http.ResponseWriter, r *http.Request) { + srv.register(c.method, func(msg *jsonrpcMessage, w http.ResponseWriter, _ *http.Request) { require.Equal(t, c.method, msg.Method) nr := uint64(len(c.byteArgs)) if len(c.byteArgs) > 0 { require.DeepEqual(t, c.byteArgs, mockParseHexByteList(t, msg.Params)) } - if len(c.uintArgs) > 0 { + if len(c.hexArgs) > 0 { rang := mockParseUintList(t, msg.Params) - require.DeepEqual(t, c.uintArgs, rang) + for i, r := range rang { + require.Equal(t, c.hexArgs[i], hexutil.EncodeUint64(r)) + } nr = rang[1] } mockWriteResult(t, w, msg, make([]*pb.ExecutionPayloadBody, nr)) @@ -165,18 +159,18 @@ func TestParseRequest(t *testing.T) { if len(c.byteArgs) > 0 { args = []interface{}{c.byteArgs} } - if len(c.uintArgs) > 0 { - args = make([]interface{}, len(c.uintArgs)) - for i := range c.uintArgs { - args[i] = c.uintArgs[i] + if len(c.hexArgs) > 0 { + args = make([]interface{}, len(c.hexArgs)) + for i := range c.hexArgs { + args[i] = c.hexArgs[i] } } require.NoError(t, cli.CallContext(ctx, &result, c.method, args...)) if len(c.byteArgs) > 0 { require.Equal(t, len(c.byteArgs), len(result)) } - if len(c.uintArgs) > 0 { - require.Equal(t, int(c.uintArgs[1]), len(result)) + if len(c.hexArgs) > 0 { + require.Equal(t, int(hexutil.MustDecodeUint64(c.hexArgs[1])), len(result)) } }) } @@ -185,9 +179,7 @@ func TestParseRequest(t *testing.T) { func TestCallCount(t *testing.T) { methods := []string{ GetPayloadBodiesByHashV1, - GetPayloadBodiesByHashV2, GetPayloadBodiesByRangeV1, - GetPayloadBodiesByRangeV2, } cases := []struct { method string @@ -195,15 +187,13 @@ func TestCallCount(t *testing.T) { }{ {method: GetPayloadBodiesByHashV1, count: 1}, {method: GetPayloadBodiesByHashV1, count: 2}, - {method: GetPayloadBodiesByHashV2, count: 1}, {method: GetPayloadBodiesByRangeV1, count: 1}, {method: GetPayloadBodiesByRangeV1, count: 2}, - {method: GetPayloadBodiesByRangeV2, count: 1}, } for _, c := range cases { t.Run(c.method, func(t *testing.T) { cli, srv := newMockEngine(t) - srv.register(c.method, func(msg *jsonrpcMessage, w http.ResponseWriter, r *http.Request) { + srv.register(c.method, func(msg *jsonrpcMessage, w http.ResponseWriter, _ *http.Request) { mockWriteResult(t, w, msg, nil) }) for i := 0; i < c.count; i++ { diff --git a/beacon-chain/execution/options.go b/beacon-chain/execution/options.go index edc616bcc533..028b7f0c1c38 100644 --- a/beacon-chain/execution/options.go +++ b/beacon-chain/execution/options.go @@ -7,6 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" "github.com/prysmaticlabs/prysm/v5/network" "github.com/prysmaticlabs/prysm/v5/network/authorization" ) @@ -115,3 +116,11 @@ func WithJwtId(jwtId string) Option { return nil } } + +// WithVerifierWaiter gives the sync package direct access to the verifier waiter. +func WithVerifierWaiter(v *verification.InitializerWaiter) Option { + return func(s *Service) error { + s.verifierWaiter = v + return nil + } +} diff --git a/beacon-chain/execution/payload_body.go b/beacon-chain/execution/payload_body.go index 71e8f7473978..4021bb2339f2 100644 --- a/beacon-chain/execution/payload_body.go +++ b/beacon-chain/execution/payload_body.go @@ -5,13 +5,13 @@ import ( "sort" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" pb "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" - "github.com/prysmaticlabs/prysm/v5/runtime/version" "google.golang.org/protobuf/proto" ) @@ -66,7 +66,7 @@ func (r *blindedBlockReconstructor) addToBatch(b interfaces.ReadOnlySignedBeacon if err != nil { return err } - if header.IsNil() { + if header == nil || header.IsNil() { return errors.New("execution payload header in blinded block was nil") } r.orderedBlocks = append(r.orderedBlocks, &blockWithHeader{block: b, header: header}) @@ -86,10 +86,7 @@ func (r *blindedBlockReconstructor) addToBatch(b interfaces.ReadOnlySignedBeacon return nil } -func payloadBodyMethodForBlock(b interface{ Version() int }) string { - if b.Version() > version.Deneb { - return GetPayloadBodiesByHashV2 - } +func payloadBodyMethodForBlock(_ interface{ Version() int }) string { return GetPayloadBodiesByHashV1 } @@ -160,7 +157,7 @@ func computeRanges(hbns []hashBlockNumber) []byRangeReq { func (r *blindedBlockReconstructor) requestBodiesByRange(ctx context.Context, client RPCClient, method string, req byRangeReq) error { result := make([]*pb.ExecutionPayloadBody, 0) - if err := client.CallContext(ctx, &result, method, req.start, req.count); err != nil { + if err := client.CallContext(ctx, &result, method, hexutil.EncodeUint64(req.start), hexutil.EncodeUint64(req.count)); err != nil { return err } if uint64(len(result)) != req.count { @@ -208,7 +205,7 @@ func (r *blindedBlockReconstructor) requestBodiesByHash(ctx context.Context, cli func (r *blindedBlockReconstructor) payloadForHeader(header interfaces.ExecutionData, v int) (proto.Message, error) { bodyKey := bytesutil.ToBytes32(header.BlockHash()) if bodyKey == params.BeaconConfig().ZeroHash { - payload, err := buildEmptyExecutionPayload(v) + payload, err := EmptyExecutionPayload(v) if err != nil { return nil, errors.Wrapf(err, "failed to reconstruct payload for body hash %#x", bodyKey) } @@ -242,9 +239,6 @@ func (r *blindedBlockReconstructor) unblinded() ([]interfaces.SignedBeaconBlock, return unblinded, nil } -func rangeMethodForHashMethod(method string) string { - if method == GetPayloadBodiesByHashV2 { - return GetPayloadBodiesByRangeV2 - } +func rangeMethodForHashMethod(_ string) string { return GetPayloadBodiesByRangeV1 } diff --git a/beacon-chain/execution/payload_body_test.go b/beacon-chain/execution/payload_body_test.go index ab447502c054..0585f05c4ac7 100644 --- a/beacon-chain/execution/payload_body_test.go +++ b/beacon-chain/execution/payload_body_test.go @@ -17,41 +17,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/time/slots" ) -type versioner struct { - version int -} - -func (v versioner) Version() int { - return v.version -} - -func TestPayloadBodyMethodForBlock(t *testing.T) { - cases := []struct { - versions []int - want string - }{ - { - versions: []int{version.Phase0, version.Altair, version.Bellatrix, version.Capella, version.Deneb}, - want: GetPayloadBodiesByHashV1, - }, - { - versions: []int{version.Electra}, - want: GetPayloadBodiesByHashV2, - }, - } - for _, c := range cases { - for _, v := range c.versions { - t.Run(version.String(v), func(t *testing.T) { - v := versioner{version: v} - require.Equal(t, c.want, payloadBodyMethodForBlock(v)) - }) - } - } - t.Run("post-electra", func(t *testing.T) { - require.Equal(t, GetPayloadBodiesByHashV2, payloadBodyMethodForBlock(versioner{version: version.Electra + 1})) - }) -} - func payloadToBody(t *testing.T, ed interfaces.ExecutionData) *pb.ExecutionPayloadBody { body := &pb.ExecutionPayloadBody{} txs, err := ed.Transactions() @@ -64,12 +29,6 @@ func payloadToBody(t *testing.T, ed interfaces.ExecutionData) *pb.ExecutionPaylo for i := range txs { body.Transactions = append(body.Transactions, txs[i]) } - eed, isElectra := ed.(interfaces.ExecutionDataElectra) - if isElectra { - body.DepositRequests = pb.ProtoDepositRequestsToJson(eed.DepositRequests()) - body.WithdrawalRequests = pb.ProtoWithdrawalRequestsToJson(eed.WithdrawalRequests()) - body.ConsolidationRequests = pb.ProtoConsolidationRequestsToJson(eed.ConsolidationRequests()) - } return body } @@ -78,6 +37,7 @@ type blindedBlockFixtures struct { emptyDenebBlock *fullAndBlinded afterSkipDeneb *fullAndBlinded electra *fullAndBlinded + fulu *fullAndBlinded } type fullAndBlinded struct { @@ -110,6 +70,12 @@ func electraSlot(t *testing.T) primitives.Slot { return s } +func fuluSlot(t *testing.T) primitives.Slot { + s, err := slots.EpochStart(params.BeaconConfig().FuluForkEpoch) + require.NoError(t, err) + return s +} + func testBlindedBlockFixtures(t *testing.T) *blindedBlockFixtures { pfx := fixturesStruct() fx := &blindedBlockFixtures{} @@ -132,16 +98,23 @@ func testBlindedBlockFixtures(t *testing.T) *blindedBlockFixtures { afterSkipBlock, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, denebSlot(t)+3, 0, util.WithPayloadSetter(afterSkip)) fx.afterSkipDeneb = blindedBlockWithHeader(t, afterSkipBlock) - electra := fixturesStruct().ExecutionPayloadElectra + electra := fixturesStruct().ExecutionPayloadDeneb electra.BlockHash = bytesutil.PadTo([]byte("electra"), 32) electra.BlockNumber = 5 electraBlock, _ := util.GenerateTestElectraBlockWithSidecar(t, [32]byte{}, electraSlot(t), 0, util.WithElectraPayload(electra)) fx.electra = blindedBlockWithHeader(t, electraBlock) + + fulu := fixturesStruct().ExecutionPayloadDeneb + fulu.BlockHash = bytesutil.PadTo([]byte("fulu"), 32) + fulu.BlockNumber = 6 + fuluBlock, _ := util.GenerateTestElectraBlockWithSidecar(t, [32]byte{}, fuluSlot(t), 0, util.WithElectraPayload(fulu)) + fx.fulu = blindedBlockWithHeader(t, fuluBlock) + return fx } func TestPayloadBodiesViaUnblinder(t *testing.T) { - defer util.HackElectraMaxuint(t)() + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() fx := testBlindedBlockFixtures(t) t.Run("mix of non-empty and empty", func(t *testing.T) { cli, srv := newMockEngine(t) @@ -164,6 +137,7 @@ func TestPayloadBodiesViaUnblinder(t *testing.T) { payload, err := bbr.payloadForHeader(fx.denebBlock.blinded.header, fx.denebBlock.blinded.block.Version()) require.NoError(t, err) + require.Equal(t, version.Deneb, fx.denebBlock.blinded.block.Version()) unblindFull, err := blocks.BuildSignedBeaconBlockFromExecutionPayload(fx.denebBlock.blinded.block, payload) require.NoError(t, err) testAssertReconstructedEquivalent(t, fx.denebBlock.full, unblindFull) @@ -177,7 +151,7 @@ func TestPayloadBodiesViaUnblinder(t *testing.T) { } func TestFixtureEquivalence(t *testing.T) { - defer util.HackElectraMaxuint(t)() + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() fx := testBlindedBlockFixtures(t) t.Run("full and blinded block equivalence", func(t *testing.T) { testAssertReconstructedEquivalent(t, fx.denebBlock.blinded.block, fx.denebBlock.full) @@ -280,7 +254,7 @@ func TestComputeRanges(t *testing.T) { } func TestReconstructBlindedBlockBatchFallbackToRange(t *testing.T) { - defer util.HackElectraMaxuint(t)() + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() ctx := context.Background() t.Run("fallback fails", func(t *testing.T) { cli, srv := newMockEngine(t) @@ -352,22 +326,6 @@ func TestReconstructBlindedBlockBatchFallbackToRange(t *testing.T) { } mockWriteResult(t, w, msg, executionPayloadBodies) }) - // separate methods for the electra block - srv.register(GetPayloadBodiesByHashV2, func(msg *jsonrpcMessage, w http.ResponseWriter, r *http.Request) { - executionPayloadBodies := []*pb.ExecutionPayloadBody{nil} - mockWriteResult(t, w, msg, executionPayloadBodies) - }) - srv.register(GetPayloadBodiesByRangeV2, func(msg *jsonrpcMessage, w http.ResponseWriter, r *http.Request) { - p := mockParseUintList(t, msg.Params) - require.Equal(t, 2, len(p)) - start, count := p[0], p[1] - require.Equal(t, fx.electra.blinded.header.BlockNumber(), start) - require.Equal(t, uint64(1), count) - executionPayloadBodies := []*pb.ExecutionPayloadBody{ - payloadToBody(t, fx.electra.blinded.header), - } - mockWriteResult(t, w, msg, executionPayloadBodies) - }) blind := []interfaces.ReadOnlySignedBeaconBlock{ fx.denebBlock.blinded.block, fx.emptyDenebBlock.blinded.block, @@ -381,23 +339,19 @@ func TestReconstructBlindedBlockBatchFallbackToRange(t *testing.T) { }) } -func TestReconstructBlindedBlockBatchDenebAndElectra(t *testing.T) { - defer util.HackElectraMaxuint(t)() - t.Run("deneb and electra", func(t *testing.T) { +func TestReconstructBlindedBlockBatchDenebAndBeyond(t *testing.T) { + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() + t.Run("deneb and beyond", func(t *testing.T) { cli, srv := newMockEngine(t) fx := testBlindedBlockFixtures(t) - // The reconstructed should make separate calls for the deneb (v1) and electra (v2) blocks. srv.register(GetPayloadBodiesByHashV1, func(msg *jsonrpcMessage, w http.ResponseWriter, r *http.Request) { - executionPayloadBodies := []*pb.ExecutionPayloadBody{payloadToBody(t, fx.denebBlock.blinded.header)} - mockWriteResult(t, w, msg, executionPayloadBodies) - }) - srv.register(GetPayloadBodiesByHashV2, func(msg *jsonrpcMessage, w http.ResponseWriter, r *http.Request) { - executionPayloadBodies := []*pb.ExecutionPayloadBody{payloadToBody(t, fx.electra.blinded.header)} + executionPayloadBodies := []*pb.ExecutionPayloadBody{payloadToBody(t, fx.denebBlock.blinded.header), payloadToBody(t, fx.electra.blinded.header), payloadToBody(t, fx.fulu.blinded.header)} mockWriteResult(t, w, msg, executionPayloadBodies) }) blinded := []interfaces.ReadOnlySignedBeaconBlock{ fx.denebBlock.blinded.block, fx.electra.blinded.block, + fx.fulu.blinded.block, } unblinded, err := reconstructBlindedBlockBatch(context.Background(), cli, blinded) require.NoError(t, err) diff --git a/beacon-chain/execution/rpc_connection.go b/beacon-chain/execution/rpc_connection.go index 04e63ab2a0ba..4730cf3d6a07 100644 --- a/beacon-chain/execution/rpc_connection.go +++ b/beacon-chain/execution/rpc_connection.go @@ -78,6 +78,13 @@ func (s *Service) pollConnectionStatus(ctx context.Context) { currClient.Close() } log.WithField("endpoint", logs.MaskCredentialsLogging(s.cfg.currHttpEndpoint.Url)).Info("Connected to new endpoint") + + c, err := s.ExchangeCapabilities(ctx) + if err != nil { + errorLogger(err, "Could not exchange capabilities with execution client") + } + s.capabilityCache.save(c) + return case <-s.ctx.Done(): log.Debug("Received cancelled context,closing existing powchain service") diff --git a/beacon-chain/execution/service.go b/beacon-chain/execution/service.go index d71b0b949407..41dbfdb5dcd2 100644 --- a/beacon-chain/execution/service.go +++ b/beacon-chain/execution/service.go @@ -29,7 +29,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/container/trie" contracts "github.com/prysmaticlabs/prysm/v5/contracts/deposit" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" @@ -155,6 +157,9 @@ type Service struct { lastReceivedMerkleIndex int64 // Keeps track of the last received index to prevent log spam. runError error preGenesisState state.BeaconState + verifierWaiter *verification.InitializerWaiter + blobVerifier verification.NewBlobVerifier + capabilityCache *capabilityCache } // NewService sets up a new instance with an ethclient when given a web3 endpoint as a string in the config. @@ -192,6 +197,7 @@ func NewService(ctx context.Context, opts ...Option) (*Service, error) { lastReceivedMerkleIndex: -1, preGenesisState: genState, eth1HeadTicker: time.NewTicker(time.Duration(params.BeaconConfig().SecondsPerETH1Block) * time.Second), + capabilityCache: &capabilityCache{}, } for _, opt := range opts { @@ -229,6 +235,13 @@ func (s *Service) Start() { } } + v, err := s.verifierWaiter.WaitForInitializer(s.ctx) + if err != nil { + log.WithError(err).Error("Could not get verification initializer") + return + } + s.blobVerifier = newBlobVerifierFromInitializer(v) + s.isRunning = true // Poll the execution client connection and fallback if errors occur. @@ -886,3 +899,39 @@ func (s *Service) migrateOldDepositTree(eth1DataInDB *ethpb.ETH1ChainData) error func (s *Service) removeStartupState() { s.cfg.finalizedStateAtStartup = nil } + +func newBlobVerifierFromInitializer(ini *verification.Initializer) verification.NewBlobVerifier { + return func(b blocks.ROBlob, reqs []verification.Requirement) verification.BlobVerifier { + return ini.NewBlobVerifier(b, reqs) + } +} + +type capabilityCache struct { + capabilities map[string]interface{} + capabilitiesLock sync.RWMutex +} + +func (c *capabilityCache) save(cs []string) { + c.capabilitiesLock.Lock() + defer c.capabilitiesLock.Unlock() + + if c.capabilities == nil { + c.capabilities = make(map[string]interface{}) + } + + for _, capability := range cs { + c.capabilities[capability] = struct{}{} + } +} + +func (c *capabilityCache) has(capability string) bool { + c.capabilitiesLock.RLock() + defer c.capabilitiesLock.RUnlock() + + if c.capabilities == nil { + return false + } + + _, ok := c.capabilities[capability] + return ok +} diff --git a/beacon-chain/execution/service_test.go b/beacon-chain/execution/service_test.go index 32e8bc56dfa4..901b82c143c1 100644 --- a/beacon-chain/execution/service_test.go +++ b/beacon-chain/execution/service_test.go @@ -8,10 +8,10 @@ import ( "time" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" gethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient/simulated" "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/async/event" @@ -19,8 +19,11 @@ import ( dbutil "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" mockExecution "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/types" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice" doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/container/trie" contracts "github.com/prysmaticlabs/prysm/v5/contracts/deposit" @@ -41,7 +44,7 @@ var _ POWBlockFetcher = (*Service)(nil) var _ Chain = (*Service)(nil) type goodLogger struct { - backend *backends.SimulatedBackend + backend *simulated.Backend } func (_ *goodLogger) Close() {} @@ -50,7 +53,7 @@ func (g *goodLogger) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQ if g.backend == nil { return new(event.Feed).Subscribe(ch), nil } - return g.backend.SubscribeFilterLogs(ctx, q, ch) + return g.backend.Client().SubscribeFilterLogs(ctx, q, ch) } func (g *goodLogger) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]gethTypes.Log, error) { @@ -66,14 +69,14 @@ func (g *goodLogger) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([] } return logs, nil } - return g.backend.FilterLogs(ctx, q) + return g.backend.Client().FilterLogs(ctx, q) } type goodNotifier struct { MockStateFeed *event.Feed } -func (g *goodNotifier) StateFeed() *event.Feed { +func (g *goodNotifier) StateFeed() event.SubscriberSender { if g.MockStateFeed == nil { g.MockStateFeed = new(event.Feed) } @@ -92,15 +95,21 @@ func TestStart_OK(t *testing.T) { t.Cleanup(func() { server.Stop() }) + c := startup.NewClockSynchronizer() + require.NoError(t, c.SetClock(startup.NewClock(time.Unix(0, 0), [32]byte{}))) + waiter := verification.NewInitializerWaiter( + c, forkchoice.NewROForkChoice(nil), nil) + web3Service, err := NewService(context.Background(), WithHttpEndpoint(endpoint), WithDepositContractAddress(testAcc.ContractAddr), WithDatabase(beaconDB), + WithVerifierWaiter(waiter), ) require.NoError(t, err, "unable to setup execution service") web3Service = setDefaultMocks(web3Service) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) testAcc.Backend.Commit() @@ -147,7 +156,7 @@ func TestStop_OK(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) testAcc.Backend.Commit() @@ -177,10 +186,12 @@ func TestService_Eth1Synced(t *testing.T) { ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") web3Service = setDefaultMocks(web3Service) - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) - currTime := testAcc.Backend.Blockchain().CurrentHeader().Time + header, err := testAcc.Backend.Client().HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + currTime := header.Time now := time.Now() assert.NoError(t, testAcc.Backend.AdjustTime(now.Sub(time.Unix(int64(currTime), 0)))) testAcc.Backend.Commit() @@ -203,22 +214,29 @@ func TestFollowBlock_OK(t *testing.T) { require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") // simulated backend sets eth1 block - // time as 10 seconds params.SetupTestConfigCleanup(t) conf := params.BeaconConfig().Copy() - conf.SecondsPerETH1Block = 10 + conf.SecondsPerETH1Block = 1 params.OverrideBeaconConfig(conf) web3Service = setDefaultMocks(web3Service) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} - baseHeight := testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64() + block, err := testAcc.Backend.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) + baseHeight := block.NumberU64() // process follow_distance blocks + var lastHash common.Hash for i := 0; i < int(params.BeaconConfig().Eth1FollowDistance); i++ { - testAcc.Backend.Commit() + lastHash = testAcc.Backend.Commit() } + lb, err := testAcc.Backend.Client().BlockByHash(context.Background(), lastHash) + require.NoError(t, err) + log.Println(lb.NumberU64()) // set current height - web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64() - web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time + block, err = testAcc.Backend.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) + web3Service.latestEth1Data.BlockHeight = block.NumberU64() + web3Service.latestEth1Data.BlockTime = block.Time() h, err := web3Service.followedBlockHeight(context.Background()) require.NoError(t, err) @@ -229,9 +247,12 @@ func TestFollowBlock_OK(t *testing.T) { for i := uint64(0); i < numToForward; i++ { testAcc.Backend.Commit() } + + newBlock, err := testAcc.Backend.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) // set current height - web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentBlock().Number.Uint64() - web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentBlock().Time + web3Service.latestEth1Data.BlockHeight = newBlock.NumberU64() + web3Service.latestEth1Data.BlockTime = newBlock.Time() h, err = web3Service.followedBlockHeight(context.Background()) require.NoError(t, err) @@ -316,11 +337,11 @@ func TestLogTillGenesis_OK(t *testing.T) { WithDatabase(beaconDB), ) require.NoError(t, err, "unable to setup web3 ETH1.0 chain service") - web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend) + web3Service.depositContractCaller, err = contracts.NewDepositContractCaller(testAcc.ContractAddr, testAcc.Backend.Client()) require.NoError(t, err) web3Service.rpcClient = &mockExecution.RPCClient{Backend: testAcc.Backend} - web3Service.httpLogger = testAcc.Backend + web3Service.httpLogger = testAcc.Backend.Client() for i := 0; i < 30; i++ { testAcc.Backend.Commit() } @@ -476,15 +497,18 @@ func TestNewService_EarliestVotingBlock(t *testing.T) { for i := 0; i < numToForward; i++ { testAcc.Backend.Commit() } - currTime := testAcc.Backend.Blockchain().CurrentHeader().Time + currHeader, err := testAcc.Backend.Client().HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + currTime := currHeader.Time now := time.Now() err = testAcc.Backend.AdjustTime(now.Sub(time.Unix(int64(currTime), 0))) require.NoError(t, err) testAcc.Backend.Commit() - - currTime = testAcc.Backend.Blockchain().CurrentHeader().Time - web3Service.latestEth1Data.BlockHeight = testAcc.Backend.Blockchain().CurrentHeader().Number.Uint64() - web3Service.latestEth1Data.BlockTime = testAcc.Backend.Blockchain().CurrentHeader().Time + currHeader, err = testAcc.Backend.Client().HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + currTime = currHeader.Time + web3Service.latestEth1Data.BlockHeight = currHeader.Number.Uint64() + web3Service.latestEth1Data.BlockTime = currHeader.Time web3Service.chainStartData.GenesisTime = currTime // With a current slot of zero, only request follow_blocks behind. diff --git a/beacon-chain/execution/testdata/fuzz/FuzzForkChoiceResponse/c966e94eace691f7 b/beacon-chain/execution/testdata/fuzz/FuzzForkChoiceResponse/c966e94eace691f7 new file mode 100644 index 000000000000..df592562c83b --- /dev/null +++ b/beacon-chain/execution/testdata/fuzz/FuzzForkChoiceResponse/c966e94eace691f7 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("{\"pAYloAdStAtus\":{\"000000\":\"0000000000000000000000\",\"witness\":0}}") diff --git a/beacon-chain/execution/testing/BUILD.bazel b/beacon-chain/execution/testing/BUILD.bazel index ba5b27f98f6a..e9b1ef77e238 100644 --- a/beacon-chain/execution/testing/BUILD.bazel +++ b/beacon-chain/execution/testing/BUILD.bazel @@ -25,10 +25,10 @@ go_library( "//encoding/bytesutil:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", + "@com_github_ethereum_go_ethereum//ethclient/simulated:go_default_library", "@com_github_ethereum_go_ethereum//rpc:go_default_library", "@com_github_holiman_uint256//:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/execution/testing/mock_engine_client.go b/beacon-chain/execution/testing/mock_engine_client.go index 5fd5c41bd25c..efc6057f3d49 100644 --- a/beacon-chain/execution/testing/mock_engine_client.go +++ b/beacon-chain/execution/testing/mock_engine_client.go @@ -36,10 +36,12 @@ type EngineClient struct { OverrideValidHash [32]byte GetPayloadResponse *blocks.GetPayloadResponse ErrGetPayload error + BlobSidecars []blocks.VerifiedROBlob + ErrorBlobSidecars error } // NewPayload -- -func (e *EngineClient) NewPayload(_ context.Context, _ interfaces.ExecutionData, _ []common.Hash, _ *common.Hash) ([]byte, error) { +func (e *EngineClient) NewPayload(_ context.Context, _ interfaces.ExecutionData, _ []common.Hash, _ *common.Hash, _ *pb.ExecutionRequests) ([]byte, error) { return e.NewPayloadResp, e.ErrNewPayload } @@ -54,7 +56,7 @@ func (e *EngineClient) ForkchoiceUpdated( } // GetPayload -- -func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte, s primitives.Slot) (*blocks.GetPayloadResponse, error) { +func (e *EngineClient) GetPayload(_ context.Context, _ [8]byte, _ primitives.Slot) (*blocks.GetPayloadResponse, error) { return e.GetPayloadResponse, e.ErrGetPayload } @@ -106,6 +108,11 @@ func (e *EngineClient) ReconstructFullBellatrixBlockBatch( return fullBlocks, nil } +// ReconstructBlobSidecars is a mock implementation of the ReconstructBlobSidecars method. +func (e *EngineClient) ReconstructBlobSidecars(context.Context, interfaces.ReadOnlySignedBeaconBlock, [32]byte, func(uint64) bool) ([]blocks.VerifiedROBlob, error) { + return e.BlobSidecars, e.ErrorBlobSidecars +} + // GetTerminalBlockHash -- func (e *EngineClient) GetTerminalBlockHash(ctx context.Context, transitionTime uint64) ([]byte, bool, error) { ttd := new(big.Int) diff --git a/beacon-chain/execution/testing/mock_execution_chain.go b/beacon-chain/execution/testing/mock_execution_chain.go index 95b8718d2668..287738e18909 100644 --- a/beacon-chain/execution/testing/mock_execution_chain.go +++ b/beacon-chain/execution/testing/mock_execution_chain.go @@ -9,10 +9,10 @@ import ( "net/http/httptest" "time" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" gethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient/simulated" "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/async/event" @@ -141,7 +141,7 @@ func (m *Chain) ETH1ConnectionErrors() []error { // RPCClient defines the mock rpc client. type RPCClient struct { - Backend *backends.SimulatedBackend + Backend *simulated.Backend BlockNumMap map[uint64]*types.HeaderInfo } @@ -195,7 +195,7 @@ func (r *RPCClient) CallContext(ctx context.Context, obj interface{}, methodName return err } } - h, err := r.Backend.HeaderByNumber(ctx, num) + h, err := r.Backend.Client().HeaderByNumber(ctx, num) if err != nil { return err } @@ -213,7 +213,7 @@ func (r *RPCClient) CallContext(ctx context.Context, obj interface{}, methodName if !ok { return errors.Errorf("wrong argument type provided: %T", args[0]) } - h, err := r.Backend.HeaderByHash(ctx, val) + h, err := r.Backend.Client().HeaderByHash(ctx, val) if err != nil { return err } @@ -241,7 +241,7 @@ func (r *RPCClient) BatchCall(b []rpc.BatchElem) error { if err != nil { return err } - h, err := r.Backend.HeaderByNumber(context.Background(), num) + h, err := r.Backend.Client().HeaderByNumber(context.Background(), num) if err != nil { return err } diff --git a/beacon-chain/forkchoice/BUILD.bazel b/beacon-chain/forkchoice/BUILD.bazel index 8dc67d81a000..7b922444c9f8 100644 --- a/beacon-chain/forkchoice/BUILD.bazel +++ b/beacon-chain/forkchoice/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//beacon-chain/forkchoice/types:go_default_library", "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", + "//consensus-types/blocks:go_default_library", "//consensus-types/forkchoice:go_default_library", "//consensus-types/primitives:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel b/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel index 85e199d2abce..1bf47ea02a47 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel +++ b/beacon-chain/forkchoice/doubly-linked-tree/BUILD.bazel @@ -23,16 +23,17 @@ go_library( "//testing/spectest:__subpackages__", ], deps = [ - "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/epoch/precompute:go_default_library", "//beacon-chain/forkchoice:go_default_library", "//beacon-chain/forkchoice/types:go_default_library", "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", "//consensus-types/forkchoice:go_default_library", "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", @@ -40,7 +41,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/forkchoice/doubly-linked-tree/errors.go b/beacon-chain/forkchoice/doubly-linked-tree/errors.go index 2a2795e6bc8e..4286765daa75 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/errors.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/errors.go @@ -11,4 +11,3 @@ var errInvalidOptimisticStatus = errors.New("invalid optimistic status") var errInvalidNilCheckpoint = errors.New("invalid nil checkpoint") var errInvalidUnrealizedJustifiedEpoch = errors.New("invalid unrealized justified epoch") var errInvalidUnrealizedFinalizedEpoch = errors.New("invalid unrealized finalized epoch") -var errNilBlockHeader = errors.New("invalid nil block header") diff --git a/beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go b/beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go index 807e0d80f9b3..47ed987475fa 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go @@ -6,20 +6,19 @@ import ( "time" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice" forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" + consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" forkchoice2 "github.com/prysmaticlabs/prysm/v5/consensus-types/forkchoice" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // New initializes a new fork choice store. @@ -105,26 +104,10 @@ func (f *ForkChoice) ProcessAttestation(ctx context.Context, validatorIndices [] } // InsertNode processes a new block by inserting it to the fork choice store. -func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, root [32]byte) error { +func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, roblock consensus_blocks.ROBlock) error { ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.InsertNode") defer span.End() - slot := state.Slot() - bh := state.LatestBlockHeader() - if bh == nil { - return errNilBlockHeader - } - parentRoot := bytesutil.ToBytes32(bh.ParentRoot) - var payloadHash [32]byte - if state.Version() >= version.Bellatrix { - ph, err := state.LatestExecutionPayloadHeader() - if err != nil { - return err - } - if ph != nil { - copy(payloadHash[:], ph.BlockHash()) - } - } jc := state.CurrentJustifiedCheckpoint() if jc == nil { return errInvalidNilCheckpoint @@ -135,13 +118,20 @@ func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, ro return errInvalidNilCheckpoint } finalizedEpoch := fc.Epoch - node, err := f.store.insert(ctx, slot, root, parentRoot, payloadHash, justifiedEpoch, finalizedEpoch) + node, err := f.store.insert(ctx, roblock, justifiedEpoch, finalizedEpoch) if err != nil { return err } jc, fc = f.store.pullTips(state, node, jc, fc) - return f.updateCheckpoints(ctx, jc, fc) + if err := f.updateCheckpoints(ctx, jc, fc); err != nil { + _, remErr := f.store.removeNode(ctx, node) + if remErr != nil { + log.WithError(remErr).Error("could not remove node") + } + return errors.Wrap(err, "could not update checkpoints") + } + return nil } // updateCheckpoints update the checkpoints when inserting a new node. @@ -483,15 +473,8 @@ func (f *ForkChoice) InsertChain(ctx context.Context, chain []*forkchoicetypes.B return nil } for i := len(chain) - 1; i > 0; i-- { - b := chain[i].Block - r := chain[i-1].Block.ParentRoot() - parentRoot := b.ParentRoot() - payloadHash, err := blocks.GetBlockPayloadHash(b) - if err != nil { - return err - } if _, err := f.store.insert(ctx, - b.Slot(), r, parentRoot, payloadHash, + chain[i].Block, chain[i].JustifiedCheckpoint.Epoch, chain[i].FinalizedCheckpoint.Epoch); err != nil { return err } diff --git a/beacon-chain/forkchoice/doubly-linked-tree/forkchoice_test.go b/beacon-chain/forkchoice/doubly-linked-tree/forkchoice_test.go index 54c6c53edad9..4a62115a66c9 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/forkchoice_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/forkchoice_test.go @@ -3,6 +3,7 @@ package doublylinkedtree import ( "context" "encoding/binary" + "errors" "testing" "time" @@ -31,7 +32,7 @@ func prepareForkchoiceState( payloadHash [32]byte, justifiedEpoch primitives.Epoch, finalizedEpoch primitives.Epoch, -) (state.BeaconState, [32]byte, error) { +) (state.BeaconState, blocks.ROBlock, error) { blockHeader := ðpb.BeaconBlockHeader{ ParentRoot: parentRoot[:], } @@ -58,21 +59,40 @@ func prepareForkchoiceState( } st, err := state_native.InitializeFromProtoBellatrix(base) - return st, blockRoot, err + if err != nil { + return nil, blocks.ROBlock{}, err + } + blk := ðpb.SignedBeaconBlockBellatrix{ + Block: ðpb.BeaconBlockBellatrix{ + Slot: slot, + ParentRoot: parentRoot[:], + Body: ðpb.BeaconBlockBodyBellatrix{ + ExecutionPayload: &enginev1.ExecutionPayload{ + BlockHash: payloadHash[:], + }, + }, + }, + } + signed, err := blocks.NewSignedBeaconBlock(blk) + if err != nil { + return nil, blocks.ROBlock{}, err + } + roblock, err := blocks.NewROBlockWithRoot(signed, blockRoot) + return st, roblock, err } func TestForkChoice_UpdateBalancesPositiveChange(t *testing.T) { f := setup(0, 0) ctx := context.Background() - st, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) + st, roblock, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) f.votes = []Vote{ {indexToHash(1), indexToHash(1), 0}, @@ -93,15 +113,15 @@ func TestForkChoice_UpdateBalancesPositiveChange(t *testing.T) { func TestForkChoice_UpdateBalancesNegativeChange(t *testing.T) { f := setup(0, 0) ctx := context.Background() - st, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) + st, roblock, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) s := f.store s.nodeByRoot[indexToHash(1)].balance = 100 s.nodeByRoot[indexToHash(2)].balance = 100 @@ -124,15 +144,15 @@ func TestForkChoice_UpdateBalancesNegativeChange(t *testing.T) { func TestForkChoice_UpdateBalancesUnderflow(t *testing.T) { f := setup(0, 0) ctx := context.Background() - st, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) + st, roblock, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) s := f.store s.nodeByRoot[indexToHash(1)].balance = 100 s.nodeByRoot[indexToHash(2)].balance = 100 @@ -155,24 +175,24 @@ func TestForkChoice_UpdateBalancesUnderflow(t *testing.T) { func TestForkChoice_IsCanonical(t *testing.T) { f := setup(1, 1) ctx := context.Background() - st, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 4, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 4, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 5, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 5, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 6, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 6, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) require.Equal(t, true, f.IsCanonical(params.BeaconConfig().ZeroHash)) require.Equal(t, false, f.IsCanonical(indexToHash(1))) @@ -186,24 +206,24 @@ func TestForkChoice_IsCanonical(t *testing.T) { func TestForkChoice_IsCanonicalReorg(t *testing.T) { f := setup(1, 1) ctx := context.Background() - st, blkRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'1'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 1, [32]byte{'1'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 2, [32]byte{'2'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 2, [32]byte{'2'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'3'}, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 3, [32]byte{'3'}, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 4, [32]byte{'4'}, [32]byte{'2'}, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 4, [32]byte{'4'}, [32]byte{'2'}, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 5, [32]byte{'5'}, [32]byte{'4'}, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 5, [32]byte{'5'}, [32]byte{'4'}, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 6, [32]byte{'6'}, [32]byte{'5'}, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 6, [32]byte{'6'}, [32]byte{'5'}, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) f.store.nodeByRoot[[32]byte{'3'}].balance = 10 require.NoError(t, f.store.treeRootNode.applyWeightChanges(ctx)) @@ -232,15 +252,15 @@ func TestForkChoice_IsCanonicalReorg(t *testing.T) { func TestForkChoice_AncestorRoot(t *testing.T) { f := setup(1, 1) ctx := context.Background() - st, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 5, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 5, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) f.store.treeRootNode = f.store.nodeByRoot[indexToHash(1)] f.store.treeRootNode.parent = nil @@ -264,12 +284,12 @@ func TestForkChoice_AncestorRoot(t *testing.T) { func TestForkChoice_AncestorEqualSlot(t *testing.T) { f := setup(1, 1) ctx := context.Background() - st, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'1'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 100, [32]byte{'1'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 101, [32]byte{'3'}, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 101, [32]byte{'3'}, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) r, err := f.AncestorRoot(ctx, [32]byte{'3'}, 100) require.NoError(t, err) @@ -279,12 +299,12 @@ func TestForkChoice_AncestorEqualSlot(t *testing.T) { func TestForkChoice_AncestorLowerSlot(t *testing.T) { f := setup(1, 1) ctx := context.Background() - st, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'1'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 100, [32]byte{'1'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 200, [32]byte{'3'}, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 200, [32]byte{'3'}, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) r, err := f.AncestorRoot(ctx, [32]byte{'3'}, 150) require.NoError(t, err) @@ -295,20 +315,20 @@ func TestForkChoice_RemoveEquivocating(t *testing.T) { ctx := context.Background() f := setup(1, 1) // Insert a block it will be head - st, blkRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) head, err := f.Head(ctx) require.NoError(t, err) require.Equal(t, [32]byte{'a'}, head) // Insert two extra blocks - st, blkRoot, err = prepareForkchoiceState(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1) + st, roblock, err = prepareForkchoiceState(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) head, err = f.Head(ctx) require.NoError(t, err) require.Equal(t, [32]byte{'c'}, head) @@ -377,36 +397,36 @@ func TestStore_CommonAncestor(t *testing.T) { // \-- c -- f // \-- g // \ -- h -- i -- j - st, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 0, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 1, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 1, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 2, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 2, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'d'}, [32]byte{'b'}, [32]byte{}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 3, [32]byte{'d'}, [32]byte{'b'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 4, [32]byte{'e'}, [32]byte{'d'}, [32]byte{}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 4, [32]byte{'e'}, [32]byte{'d'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 5, [32]byte{'f'}, [32]byte{'c'}, [32]byte{}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 5, [32]byte{'f'}, [32]byte{'c'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 6, [32]byte{'g'}, [32]byte{'c'}, [32]byte{}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 6, [32]byte{'g'}, [32]byte{'c'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 7, [32]byte{'h'}, [32]byte{'c'}, [32]byte{}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 7, [32]byte{'h'}, [32]byte{'c'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 8, [32]byte{'i'}, [32]byte{'h'}, [32]byte{}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 8, [32]byte{'i'}, [32]byte{'h'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 9, [32]byte{'j'}, [32]byte{'i'}, [32]byte{}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 9, [32]byte{'j'}, [32]byte{'i'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) tests := []struct { name string @@ -497,18 +517,18 @@ func TestStore_CommonAncestor(t *testing.T) { // a -- b -- c -- d f = setup(0, 0) - st, blkRoot, err = prepareForkchoiceState(ctx, 0, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) + st, roblock, err = prepareForkchoiceState(ctx, 0, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 1, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 1, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 2, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 2, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'C'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'d'}, [32]byte{'c'}, [32]byte{}, 1, 1) + require.NoError(t, f.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 3, [32]byte{'d'}, [32]byte{'c'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) tests = []struct { name string r1 [32]byte @@ -589,7 +609,9 @@ func TestStore_InsertChain(t *testing.T) { require.NoError(t, err) wsb, err := blocks.NewSignedBeaconBlock(blk) require.NoError(t, err) - blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), + roblock, err := blocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: roblock, JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]}, FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]}, }) @@ -598,14 +620,16 @@ func TestStore_InsertChain(t *testing.T) { blk.Block.Slot = primitives.Slot(i) copiedRoot := root blk.Block.ParentRoot = copiedRoot[:] + root, err = blk.Block.HashTreeRoot() + require.NoError(t, err) wsb, err = blocks.NewSignedBeaconBlock(blk) require.NoError(t, err) - blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), + roblock, err := blocks.NewROBlockWithRoot(wsb, root) + require.NoError(t, err) + blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: roblock, JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]}, FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]}, }) - root, err = blk.Block.HashTreeRoot() - require.NoError(t, err) } args := make([]*forkchoicetypes.BlockAndCheckpoints, 10) for i := 0; i < len(blks); i++ { @@ -669,26 +693,26 @@ func TestForkChoice_UpdateCheckpoints(t *testing.T) { fcs.store.finalizedCheckpoint = tt.finalized fcs.store.genesisTime = uint64(time.Now().Unix()) - uint64(tt.currentSlot)*params.BeaconConfig().SecondsPerSlot - st, blkRoot, err := prepareForkchoiceState(ctx, 32, [32]byte{'f'}, + st, roblock, err := prepareForkchoiceState(ctx, 32, [32]byte{'f'}, [32]byte{}, [32]byte{}, tt.finalized.Epoch, tt.finalized.Epoch) require.NoError(t, err) - require.NoError(t, fcs.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 64, [32]byte{'j'}, + require.NoError(t, fcs.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 64, [32]byte{'j'}, [32]byte{'f'}, [32]byte{}, tt.justified.Epoch, tt.finalized.Epoch) require.NoError(t, err) - require.NoError(t, fcs.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 96, [32]byte{'b'}, + require.NoError(t, fcs.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 96, [32]byte{'b'}, [32]byte{'j'}, [32]byte{}, tt.newJustified.Epoch, tt.newFinalized.Epoch) require.NoError(t, err) - require.NoError(t, fcs.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 96, [32]byte{'c'}, + require.NoError(t, fcs.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 96, [32]byte{'c'}, [32]byte{'f'}, [32]byte{}, tt.newJustified.Epoch, tt.newFinalized.Epoch) require.NoError(t, err) - require.NoError(t, fcs.InsertNode(ctx, st, blkRoot)) - st, blkRoot, err = prepareForkchoiceState(ctx, 65, [32]byte{'h'}, + require.NoError(t, fcs.InsertNode(ctx, st, roblock)) + st, roblock, err = prepareForkchoiceState(ctx, 65, [32]byte{'h'}, [32]byte{'f'}, [32]byte{}, tt.newFinalized.Epoch, tt.newFinalized.Epoch) require.NoError(t, err) - require.NoError(t, fcs.InsertNode(ctx, st, blkRoot)) + require.NoError(t, fcs.InsertNode(ctx, st, roblock)) // restart justifications cause insertion messed it up fcs.store.justifiedCheckpoint = tt.justified fcs.store.finalizedCheckpoint = tt.finalized @@ -714,9 +738,9 @@ func TestWeight(t *testing.T) { f := setup(0, 0) root := [32]byte{'a'} - st, blkRoot, err := prepareForkchoiceState(ctx, 0, root, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 0, root, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) n, ok := f.store.nodeByRoot[root] require.Equal(t, true, ok) @@ -746,9 +770,9 @@ func TestForkChoice_UnrealizedJustifiedPayloadBlockHash(t *testing.T) { ctx := context.Background() f := setup(0, 0) - st, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) + st, roblock, err := prepareForkchoiceState(ctx, 0, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, blkRoot)) + require.NoError(t, f.InsertNode(ctx, st, roblock)) f.store.unrealizedJustifiedCheckpoint.Root = [32]byte{'a'} got := f.UnrealizedJustifiedPayloadBlockHash() @@ -759,90 +783,90 @@ func TestForkChoiceIsViableForCheckpoint(t *testing.T) { f := setup(0, 0) ctx := context.Background() - st, root, err := prepareForkchoiceState(ctx, 0, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0) + st, blk, err := prepareForkchoiceState(ctx, 0, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0) require.NoError(t, err) // No Node - viable, err := f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: root}) + viable, err := f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk.Root()}) require.NoError(t, err) require.Equal(t, false, viable) // No Children - require.NoError(t, f.InsertNode(ctx, st, root)) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: root, Epoch: 0}) + require.NoError(t, f.InsertNode(ctx, st, blk)) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk.Root(), Epoch: 0}) require.NoError(t, err) require.Equal(t, true, viable) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: root, Epoch: 1}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk.Root(), Epoch: 1}) require.NoError(t, err) require.Equal(t, true, viable) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: root, Epoch: 2}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk.Root(), Epoch: 2}) require.NoError(t, err) require.Equal(t, true, viable) - st, bRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'b'}, root, [32]byte{'B'}, 0, 0) + st, blk2, err := prepareForkchoiceState(ctx, 1, [32]byte{'b'}, blk.Root(), [32]byte{'B'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, bRoot)) + require.NoError(t, f.InsertNode(ctx, st, blk2)) // Epoch start - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: root}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk.Root()}) require.NoError(t, err) require.Equal(t, true, viable) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: root, Epoch: 1}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk.Root(), Epoch: 1}) require.NoError(t, err) require.Equal(t, false, viable) // No Children but impossible checkpoint - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: bRoot}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk2.Root()}) require.NoError(t, err) require.Equal(t, false, viable) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: bRoot, Epoch: 1}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk2.Root(), Epoch: 1}) require.NoError(t, err) require.Equal(t, true, viable) - st, cRoot, err := prepareForkchoiceState(ctx, 2, [32]byte{'c'}, bRoot, [32]byte{'C'}, 0, 0) + st, blk3, err := prepareForkchoiceState(ctx, 2, [32]byte{'c'}, blk2.Root(), [32]byte{'C'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, cRoot)) + require.NoError(t, f.InsertNode(ctx, st, blk3)) // Children in same epoch - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: bRoot}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk2.Root()}) require.NoError(t, err) require.Equal(t, false, viable) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: bRoot, Epoch: 1}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk2.Root(), Epoch: 1}) require.NoError(t, err) require.Equal(t, false, viable) - st, dRoot, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch, [32]byte{'d'}, bRoot, [32]byte{'D'}, 0, 0) + st, blk4, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch, [32]byte{'d'}, blk2.Root(), [32]byte{'D'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, dRoot)) + require.NoError(t, f.InsertNode(ctx, st, blk4)) // Children in next epoch but boundary - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: bRoot}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk2.Root()}) require.NoError(t, err) require.Equal(t, false, viable) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: bRoot, Epoch: 1}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk2.Root(), Epoch: 1}) require.NoError(t, err) require.Equal(t, false, viable) // Boundary block - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: dRoot, Epoch: 1}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk4.Root(), Epoch: 1}) require.NoError(t, err) require.Equal(t, true, viable) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: dRoot, Epoch: 0}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk4.Root(), Epoch: 0}) require.NoError(t, err) require.Equal(t, false, viable) // Children in next epoch - st, eRoot, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'e'}, bRoot, [32]byte{'E'}, 0, 0) + st, blk5, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'e'}, blk2.Root(), [32]byte{'E'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, eRoot)) + require.NoError(t, f.InsertNode(ctx, st, blk5)) - viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: bRoot, Epoch: 1}) + viable, err = f.IsViableForCheckpoint(&forkchoicetypes.Checkpoint{Root: blk2.Root(), Epoch: 1}) require.NoError(t, err) require.Equal(t, true, viable) } @@ -850,14 +874,14 @@ func TestForkChoiceIsViableForCheckpoint(t *testing.T) { func TestForkChoiceSlot(t *testing.T) { f := setup(0, 0) ctx := context.Background() - st, root, err := prepareForkchoiceState(ctx, 3, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0) + st, blk, err := prepareForkchoiceState(ctx, 3, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0) require.NoError(t, err) // No Node - _, err = f.Slot(root) + _, err = f.Slot(blk.Root()) require.ErrorIs(t, ErrNilNode, err) - require.NoError(t, f.InsertNode(ctx, st, root)) - slot, err := f.Slot(root) + require.NoError(t, f.InsertNode(ctx, st, blk)) + slot, err := f.Slot(blk.Root()) require.NoError(t, err) require.Equal(t, primitives.Slot(3), slot) } @@ -866,16 +890,16 @@ func TestForkchoiceParentRoot(t *testing.T) { f := setup(0, 0) ctx := context.Background() root1 := [32]byte{'a'} - st, root, err := prepareForkchoiceState(ctx, 3, root1, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0) + st, blk, err := prepareForkchoiceState(ctx, 3, root1, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, root)) + require.NoError(t, f.InsertNode(ctx, st, blk)) root2 := [32]byte{'b'} - st, root, err = prepareForkchoiceState(ctx, 3, root2, root1, [32]byte{'A'}, 0, 0) + st, blk, err = prepareForkchoiceState(ctx, 3, root2, root1, [32]byte{'A'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, root)) + require.NoError(t, f.InsertNode(ctx, st, blk)) - root, err = f.ParentRoot(root2) + root, err := f.ParentRoot(root2) require.NoError(t, err) require.Equal(t, root1, root) @@ -887,3 +911,16 @@ func TestForkchoiceParentRoot(t *testing.T) { require.NoError(t, err) require.Equal(t, zeroHash, root) } + +func TestForkChoice_CleanupInserting(t *testing.T) { + f := setup(0, 0) + ctx := context.Background() + st, roblock, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 2, 2) + f.SetBalancesByRooter(func(_ context.Context, _ [32]byte) ([]uint64, error) { + return f.justifiedBalances, errors.New("mock err") + }) + + require.NoError(t, err) + require.NotNil(t, f.InsertNode(ctx, st, roblock)) + require.Equal(t, false, f.HasNode(roblock.Root())) +} diff --git a/beacon-chain/forkchoice/doubly-linked-tree/node_test.go b/beacon-chain/forkchoice/doubly-linked-tree/node_test.go index 66bd0e6079e8..f6b40b1c98c9 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/node_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/node_test.go @@ -14,15 +14,15 @@ import ( func TestNode_ApplyWeightChanges_PositiveChange(t *testing.T) { f := setup(0, 0) ctx := context.Background() - state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) + state, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) // The updated balances of each node is 100 s := f.store @@ -41,15 +41,15 @@ func TestNode_ApplyWeightChanges_PositiveChange(t *testing.T) { func TestNode_ApplyWeightChanges_NegativeChange(t *testing.T) { f := setup(0, 0) ctx := context.Background() - state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) + state, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) // The updated balances of each node is 100 s := f.store @@ -72,9 +72,9 @@ func TestNode_UpdateBestDescendant_NonViableChild(t *testing.T) { f := setup(1, 1) ctx := context.Background() // Input child is not viable. - state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 2, 3) + state, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 2, 3) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) // Verify parent's best child and best descendant are `none`. s := f.store @@ -87,9 +87,9 @@ func TestNode_UpdateBestDescendant_ViableChild(t *testing.T) { f := setup(1, 1) ctx := context.Background() // Input child is the best descendant - state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + state, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) s := f.store assert.Equal(t, 1, len(s.treeRootNode.children)) @@ -100,12 +100,12 @@ func TestNode_UpdateBestDescendant_HigherWeightChild(t *testing.T) { f := setup(1, 1) ctx := context.Background() // Input child is the best descendant - state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + state, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) s := f.store s.nodeByRoot[indexToHash(1)].weight = 100 @@ -120,12 +120,12 @@ func TestNode_UpdateBestDescendant_LowerWeightChild(t *testing.T) { f := setup(1, 1) ctx := context.Background() // Input child is the best descendant - state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + state, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) s := f.store s.nodeByRoot[indexToHash(1)].weight = 200 @@ -159,21 +159,21 @@ func TestNode_ViableForHead(t *testing.T) { func TestNode_LeadsToViableHead(t *testing.T) { f := setup(4, 3) ctx := context.Background() - state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + state, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 4, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 4, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - state, blkRoot, err = prepareForkchoiceState(ctx, 5, indexToHash(5), indexToHash(3), params.BeaconConfig().ZeroHash, 4, 3) + require.NoError(t, f.InsertNode(ctx, state, blk)) + state, blk, err = prepareForkchoiceState(ctx, 5, indexToHash(5), indexToHash(3), params.BeaconConfig().ZeroHash, 4, 3) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) require.Equal(t, true, f.store.treeRootNode.leadsToViableHead(4, 5)) require.Equal(t, true, f.store.nodeByRoot[indexToHash(5)].leadsToViableHead(4, 5)) @@ -192,28 +192,28 @@ func TestNode_SetFullyValidated(t *testing.T) { // \ // -- 5 (true) // - state, blkRoot, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + state, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - storeNodes[1] = f.store.nodeByRoot[blkRoot] + require.NoError(t, f.InsertNode(ctx, state, blk)) + storeNodes[1] = f.store.nodeByRoot[blk.Root()] require.NoError(t, f.SetOptimisticToValid(ctx, params.BeaconConfig().ZeroHash)) - state, blkRoot, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) + state, blk, err = prepareForkchoiceState(ctx, 2, indexToHash(2), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - storeNodes[2] = f.store.nodeByRoot[blkRoot] + require.NoError(t, f.InsertNode(ctx, state, blk)) + storeNodes[2] = f.store.nodeByRoot[blk.Root()] require.NoError(t, f.SetOptimisticToValid(ctx, indexToHash(1))) - state, blkRoot, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1) + state, blk, err = prepareForkchoiceState(ctx, 3, indexToHash(3), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - storeNodes[3] = f.store.nodeByRoot[blkRoot] - state, blkRoot, err = prepareForkchoiceState(ctx, 4, indexToHash(4), indexToHash(3), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, state, blk)) + storeNodes[3] = f.store.nodeByRoot[blk.Root()] + state, blk, err = prepareForkchoiceState(ctx, 4, indexToHash(4), indexToHash(3), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - storeNodes[4] = f.store.nodeByRoot[blkRoot] - state, blkRoot, err = prepareForkchoiceState(ctx, 5, indexToHash(5), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) + require.NoError(t, f.InsertNode(ctx, state, blk)) + storeNodes[4] = f.store.nodeByRoot[blk.Root()] + state, blk, err = prepareForkchoiceState(ctx, 5, indexToHash(5), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - storeNodes[5] = f.store.nodeByRoot[blkRoot] + require.NoError(t, f.InsertNode(ctx, state, blk)) + storeNodes[5] = f.store.nodeByRoot[blk.Root()] opt, err := f.IsOptimistic(indexToHash(5)) require.NoError(t, err) @@ -266,9 +266,9 @@ func TestNode_TimeStampsChecks(t *testing.T) { driftGenesisTime(f, 1, 1) root := [32]byte{'a'} f.justifiedBalances = []uint64{10} - state, blkRoot, err := prepareForkchoiceState(ctx, 1, root, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0) + state, blk, err := prepareForkchoiceState(ctx, 1, root, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) headRoot, err := f.Head(ctx) require.NoError(t, err) require.Equal(t, root, headRoot) @@ -283,9 +283,9 @@ func TestNode_TimeStampsChecks(t *testing.T) { // late block driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+1) root = [32]byte{'b'} - state, blkRoot, err = prepareForkchoiceState(ctx, 2, root, [32]byte{'a'}, [32]byte{'B'}, 0, 0) + state, blk, err = prepareForkchoiceState(ctx, 2, root, [32]byte{'a'}, [32]byte{'B'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) headRoot, err = f.Head(ctx) require.NoError(t, err) require.Equal(t, root, headRoot) @@ -299,9 +299,9 @@ func TestNode_TimeStampsChecks(t *testing.T) { // very late block driftGenesisTime(f, 3, ProcessAttestationsThreshold+1) root = [32]byte{'c'} - state, blkRoot, err = prepareForkchoiceState(ctx, 3, root, [32]byte{'b'}, [32]byte{'C'}, 0, 0) + state, blk, err = prepareForkchoiceState(ctx, 3, root, [32]byte{'b'}, [32]byte{'C'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) headRoot, err = f.Head(ctx) require.NoError(t, err) require.Equal(t, root, headRoot) @@ -314,9 +314,9 @@ func TestNode_TimeStampsChecks(t *testing.T) { // block from the future root = [32]byte{'d'} - state, blkRoot, err = prepareForkchoiceState(ctx, 5, root, [32]byte{'c'}, [32]byte{'D'}, 1, 1) + state, blk, err = prepareForkchoiceState(ctx, 5, root, [32]byte{'c'}, [32]byte{'D'}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) + require.NoError(t, f.InsertNode(ctx, state, blk)) headRoot, err = f.Head(ctx) require.NoError(t, err) require.Equal(t, root, headRoot) diff --git a/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost.go b/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost.go index 0ebbd83de857..fc56102ff380 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost.go @@ -1,8 +1,6 @@ package doublylinkedtree import ( - "fmt" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" ) @@ -15,7 +13,7 @@ func (f *ForkChoice) applyProposerBoostScore() error { if s.previousProposerBoostRoot != params.BeaconConfig().ZeroHash { previousNode, ok := s.nodeByRoot[s.previousProposerBoostRoot] if !ok || previousNode == nil { - log.WithError(errInvalidProposerBoostRoot).Errorf(fmt.Sprintf("invalid prev root %#x", s.previousProposerBoostRoot)) + log.WithError(errInvalidProposerBoostRoot).Errorf("invalid prev root %#x", s.previousProposerBoostRoot) } else { previousNode.balance -= s.previousProposerBoostScore } @@ -24,7 +22,7 @@ func (f *ForkChoice) applyProposerBoostScore() error { if s.proposerBoostRoot != params.BeaconConfig().ZeroHash { currentNode, ok := s.nodeByRoot[s.proposerBoostRoot] if !ok || currentNode == nil { - log.WithError(errInvalidProposerBoostRoot).Errorf(fmt.Sprintf("invalid current root %#x", s.proposerBoostRoot)) + log.WithError(errInvalidProposerBoostRoot).Errorf("invalid current root %#x", s.proposerBoostRoot) } else { proposerScore = (s.committeeWeight * params.BeaconConfig().ProposerScoreBoost) / 100 currentNode.balance += proposerScore diff --git a/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost_test.go b/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost_test.go index 28b1be753596..a4f79edbf3a1 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/proposer_boost_test.go @@ -484,23 +484,23 @@ func TestForkChoice_missingProposerBoostRoots(t *testing.T) { } f.justifiedBalances = balances driftGenesisTime(f, 1, 0) - st, root, err := prepareForkchoiceState(ctx, 1, [32]byte{'r'}, [32]byte{}, [32]byte{}, 1, 1) + st, blk, err := prepareForkchoiceState(ctx, 1, [32]byte{'r'}, [32]byte{}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, root)) + require.NoError(t, f.InsertNode(ctx, st, blk)) f.store.previousProposerBoostRoot = [32]byte{'p'} headRoot, err := f.Head(ctx) require.NoError(t, err) - require.Equal(t, root, headRoot) + require.Equal(t, blk.Root(), headRoot) require.Equal(t, [32]byte{'r'}, f.store.proposerBoostRoot) f.store.proposerBoostRoot = [32]byte{'p'} driftGenesisTime(f, 3, 0) - st, root, err = prepareForkchoiceState(ctx, 2, [32]byte{'a'}, [32]byte{'r'}, [32]byte{}, 1, 1) + st, blk, err = prepareForkchoiceState(ctx, 2, [32]byte{'a'}, [32]byte{'r'}, [32]byte{}, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, root)) + require.NoError(t, f.InsertNode(ctx, st, blk)) headRoot, err = f.Head(ctx) require.NoError(t, err) - require.Equal(t, root, headRoot) + require.Equal(t, blk.Root(), headRoot) require.Equal(t, [32]byte{'p'}, f.store.proposerBoostRoot) } diff --git a/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks.go b/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks.go index 8bc717802fae..ed223482a3e8 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks.go @@ -53,7 +53,7 @@ func (f *ForkChoice) ShouldOverrideFCU() (override bool) { // Only reorg blocks that arrive late early, err := head.arrivedEarly(f.store.genesisTime) if err != nil { - log.WithError(err).Error("could not check if block arrived early") + log.WithError(err).Error("Could not check if block arrived early") return } if early { @@ -78,7 +78,7 @@ func (f *ForkChoice) ShouldOverrideFCU() (override bool) { // } // Only orphan a block if the head LMD vote is weak - if head.weight*100 > f.store.committeeWeight*params.BeaconConfig().ReorgWeightThreshold { + if head.weight*100 > f.store.committeeWeight*params.BeaconConfig().ReorgHeadWeightThreshold { return } @@ -143,7 +143,7 @@ func (f *ForkChoice) GetProposerHead() [32]byte { } // Only orphan a block if the head LMD vote is weak - if head.weight*100 > f.store.committeeWeight*params.BeaconConfig().ReorgWeightThreshold { + if head.weight*100 > f.store.committeeWeight*params.BeaconConfig().ReorgHeadWeightThreshold { return head.root } diff --git a/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks_test.go b/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks_test.go index dd6694aed7cb..990a8105a445 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/reorg_late_blocks_test.go @@ -19,23 +19,23 @@ func TestForkChoice_ShouldOverrideFCU(t *testing.T) { f.store.committeeWeight /= uint64(params.BeaconConfig().SlotsPerEpoch) ctx := context.Background() driftGenesisTime(f, 1, 0) - st, root, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, [32]byte{}, [32]byte{'A'}, 0, 0) + st, blk, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, [32]byte{}, [32]byte{'A'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, root)) + require.NoError(t, f.InsertNode(ctx, st, blk)) attesters := make([]uint64, f.numActiveValidators-64) for i := range attesters { attesters[i] = uint64(i + 64) } - f.ProcessAttestation(ctx, attesters, root, 0) + f.ProcessAttestation(ctx, attesters, blk.Root(), 0) orphanLateBlockFirstThreshold := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot driftGenesisTime(f, 2, orphanLateBlockFirstThreshold+1) - st, root, err = prepareForkchoiceState(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 0, 0) + st, blk, err = prepareForkchoiceState(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, root)) + require.NoError(t, f.InsertNode(ctx, st, blk)) headRoot, err := f.Head(ctx) require.NoError(t, err) - require.Equal(t, root, headRoot) + require.Equal(t, blk.Root(), headRoot) t.Run("head is weak", func(t *testing.T) { require.Equal(t, true, f.ShouldOverrideFCU()) @@ -117,23 +117,23 @@ func TestForkChoice_GetProposerHead(t *testing.T) { ctx := context.Background() driftGenesisTime(f, 1, 0) parentRoot := [32]byte{'a'} - st, root, err := prepareForkchoiceState(ctx, 1, parentRoot, [32]byte{}, [32]byte{'A'}, 0, 0) + st, blk, err := prepareForkchoiceState(ctx, 1, parentRoot, [32]byte{}, [32]byte{'A'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, root)) + require.NoError(t, f.InsertNode(ctx, st, blk)) attesters := make([]uint64, f.numActiveValidators-64) for i := range attesters { attesters[i] = uint64(i + 64) } - f.ProcessAttestation(ctx, attesters, root, 0) + f.ProcessAttestation(ctx, attesters, blk.Root(), 0) driftGenesisTime(f, 3, 1) childRoot := [32]byte{'b'} - st, root, err = prepareForkchoiceState(ctx, 2, childRoot, [32]byte{'a'}, [32]byte{'B'}, 0, 0) + st, blk, err = prepareForkchoiceState(ctx, 2, childRoot, [32]byte{'a'}, [32]byte{'B'}, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, st, root)) + require.NoError(t, f.InsertNode(ctx, st, blk)) headRoot, err := f.Head(ctx) require.NoError(t, err) - require.Equal(t, root, headRoot) + require.Equal(t, blk.Root(), headRoot) orphanLateBlockFirstThreshold := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot f.store.headNode.timestamp -= params.BeaconConfig().SecondsPerSlot - orphanLateBlockFirstThreshold t.Run("head is weak", func(t *testing.T) { diff --git a/beacon-chain/forkchoice/doubly-linked-tree/store.go b/beacon-chain/forkchoice/doubly-linked-tree/store.go index 23b58a05811b..68b99a1584dc 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/store.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/store.go @@ -8,9 +8,11 @@ import ( "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" + consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // head starts from justified root and then follows the best descendant links @@ -63,12 +65,24 @@ func (s *Store) head(ctx context.Context) ([32]byte, error) { // insert registers a new block node to the fork choice store's node list. // It then updates the new node's parent with the best child and descendant node. func (s *Store) insert(ctx context.Context, - slot primitives.Slot, - root, parentRoot, payloadHash [fieldparams.RootLength]byte, + roblock consensus_blocks.ROBlock, justifiedEpoch, finalizedEpoch primitives.Epoch) (*Node, error) { ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.insert") defer span.End() + root := roblock.Root() + block := roblock.Block() + slot := block.Slot() + parentRoot := block.ParentRoot() + var payloadHash [32]byte + if block.Version() >= version.Bellatrix { + execution, err := block.Body().Execution() + if err != nil { + return nil, err + } + copy(payloadHash[:], execution.BlockHash()) + } + // Return if the block has been inserted into Store before. if n, ok := s.nodeByRoot[root]; ok { return n, nil @@ -107,7 +121,9 @@ func (s *Store) insert(ctx context.Context, s.headNode = n s.highestReceivedNode = n } else { - return n, errInvalidParentRoot + delete(s.nodeByRoot, root) + delete(s.nodeByPayload, payloadHash) + return nil, errInvalidParentRoot } } else { parent.children = append(parent.children, n) @@ -128,7 +144,11 @@ func (s *Store) insert(ctx context.Context, jEpoch := s.justifiedCheckpoint.Epoch fEpoch := s.finalizedCheckpoint.Epoch if err := s.treeRootNode.updateBestDescendant(ctx, jEpoch, fEpoch, slots.ToEpoch(currentSlot)); err != nil { - return n, err + _, remErr := s.removeNode(ctx, n) + if remErr != nil { + log.WithError(remErr).Error("could not remove node") + } + return nil, errors.Wrap(err, "could not update best descendants") } } // Update metrics. diff --git a/beacon-chain/forkchoice/doubly-linked-tree/store_test.go b/beacon-chain/forkchoice/doubly-linked-tree/store_test.go index ba621b56ca6d..383d377ad67e 100644 --- a/beacon-chain/forkchoice/doubly-linked-tree/store_test.go +++ b/beacon-chain/forkchoice/doubly-linked-tree/store_test.go @@ -26,9 +26,9 @@ func TestStore_FinalizedEpoch(t *testing.T) { func TestStore_NodeCount(t *testing.T) { f := setup(0, 0) - state, blkRoot, err := prepareForkchoiceState(context.Background(), 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) + state, blk, err := prepareForkchoiceState(context.Background(), 1, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.NoError(t, f.InsertNode(context.Background(), state, blkRoot)) + require.NoError(t, f.InsertNode(context.Background(), state, blk)) require.Equal(t, 2, f.NodeCount()) } @@ -133,7 +133,10 @@ func TestStore_Insert(t *testing.T) { fc := &forkchoicetypes.Checkpoint{Epoch: 0} s := &Store{nodeByRoot: nodeByRoot, treeRootNode: treeRootNode, nodeByPayload: nodeByPayload, justifiedCheckpoint: jc, finalizedCheckpoint: fc, highestReceivedNode: &Node{}} payloadHash := [32]byte{'a'} - _, err := s.insert(context.Background(), 100, indexToHash(100), indexToHash(0), payloadHash, 1, 1) + ctx := context.Background() + _, blk, err := prepareForkchoiceState(ctx, 100, indexToHash(100), indexToHash(0), payloadHash, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) assert.Equal(t, 2, len(s.nodeByRoot), "Did not insert block") assert.Equal(t, (*Node)(nil), treeRootNode.parent, "Incorrect parent") @@ -327,7 +330,10 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // Make sure it doesn't underflow s.genesisTime = uint64(time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix()) - _, err := s.insert(context.Background(), 1, [32]byte{'a'}, b, b, 1, 1) + ctx := context.Background() + _, blk, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) count, err := f.ReceivedBlocksLastEpoch() require.NoError(t, err) @@ -337,7 +343,9 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // 64 // Received block last epoch is 1 - _, err = s.insert(context.Background(), 64, [32]byte{'A'}, b, b, 1, 1) + _, blk, err = prepareForkchoiceState(ctx, 64, [32]byte{'A'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) s.genesisTime = uint64(time.Now().Add(time.Duration((-64*int64(params.BeaconConfig().SecondsPerSlot))-1) * time.Second).Unix()) count, err = f.ReceivedBlocksLastEpoch() @@ -348,7 +356,9 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // 64 65 // Received block last epoch is 2 - _, err = s.insert(context.Background(), 65, [32]byte{'B'}, b, b, 1, 1) + _, blk, err = prepareForkchoiceState(ctx, 65, [32]byte{'B'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) s.genesisTime = uint64(time.Now().Add(time.Duration(-66*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix()) count, err = f.ReceivedBlocksLastEpoch() @@ -359,7 +369,9 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // 64 65 66 // Received block last epoch is 3 - _, err = s.insert(context.Background(), 66, [32]byte{'C'}, b, b, 1, 1) + _, blk, err = prepareForkchoiceState(ctx, 66, [32]byte{'C'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) s.genesisTime = uint64(time.Now().Add(time.Duration(-66*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix()) count, err = f.ReceivedBlocksLastEpoch() @@ -370,7 +382,9 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // 64 65 66 // 98 // Received block last epoch is 1 - _, err = s.insert(context.Background(), 98, [32]byte{'D'}, b, b, 1, 1) + _, blk, err = prepareForkchoiceState(ctx, 98, [32]byte{'D'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) s.genesisTime = uint64(time.Now().Add(time.Duration(-98*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix()) count, err = f.ReceivedBlocksLastEpoch() @@ -382,7 +396,9 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // 98 // 132 // Received block last epoch is 1 - _, err = s.insert(context.Background(), 132, [32]byte{'E'}, b, b, 1, 1) + _, blk, err = prepareForkchoiceState(ctx, 132, [32]byte{'E'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) s.genesisTime = uint64(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix()) count, err = f.ReceivedBlocksLastEpoch() @@ -395,7 +411,9 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // 132 // 99 // Received block last epoch is still 1. 99 is outside the window - _, err = s.insert(context.Background(), 99, [32]byte{'F'}, b, b, 1, 1) + _, blk, err = prepareForkchoiceState(ctx, 99, [32]byte{'F'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) s.genesisTime = uint64(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix()) count, err = f.ReceivedBlocksLastEpoch() @@ -408,7 +426,9 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // 132 // 99 100 // Received block last epoch is still 1. 100 is at the same position as 132 - _, err = s.insert(context.Background(), 100, [32]byte{'G'}, b, b, 1, 1) + _, blk, err = prepareForkchoiceState(ctx, 100, [32]byte{'G'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) s.genesisTime = uint64(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix()) count, err = f.ReceivedBlocksLastEpoch() @@ -421,7 +441,9 @@ func TestForkChoice_ReceivedBlocksLastEpoch(t *testing.T) { // 132 // 99 100 101 // Received block last epoch is 2. 101 is within the window - _, err = s.insert(context.Background(), 101, [32]byte{'H'}, b, b, 1, 1) + _, blk, err = prepareForkchoiceState(ctx, 101, [32]byte{'H'}, b, b, 1, 1) + require.NoError(t, err) + _, err = s.insert(ctx, blk, 1, 1) require.NoError(t, err) s.genesisTime = uint64(time.Now().Add(time.Duration(-132*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second).Unix()) count, err = f.ReceivedBlocksLastEpoch() @@ -443,85 +465,94 @@ func TestStore_TargetRootForEpoch(t *testing.T) { ctx := context.Background() f := setup(1, 1) - state, blkRoot, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch, [32]byte{'a'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) + state, blk, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch, [32]byte{'a'}, params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, blkRoot)) - target, err := f.TargetRootForEpoch(blkRoot, 1) + require.NoError(t, f.InsertNode(ctx, state, blk)) + target, err := f.TargetRootForEpoch(blk.Root(), 1) require.NoError(t, err) - require.Equal(t, target, blkRoot) + require.Equal(t, target, blk.Root()) - state, root1, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'b'}, blkRoot, params.BeaconConfig().ZeroHash, 1, 1) + state, blk1, err := prepareForkchoiceState(ctx, params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'b'}, blk.Root(), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, root1)) - target, err = f.TargetRootForEpoch(root1, 1) + require.NoError(t, f.InsertNode(ctx, state, blk1)) + target, err = f.TargetRootForEpoch(blk1.Root(), 1) require.NoError(t, err) - require.Equal(t, target, blkRoot) + require.Equal(t, target, blk.Root()) // Insert a block for the next epoch (missed slot 0) - state, root2, err := prepareForkchoiceState(ctx, 2*params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'c'}, root1, params.BeaconConfig().ZeroHash, 1, 1) + state, blk2, err := prepareForkchoiceState(ctx, 2*params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'c'}, blk1.Root(), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, root2)) - target, err = f.TargetRootForEpoch(root2, 2) + require.NoError(t, f.InsertNode(ctx, state, blk2)) + target, err = f.TargetRootForEpoch(blk2.Root(), 2) require.NoError(t, err) - require.Equal(t, target, root1) + require.Equal(t, target, blk1.Root()) - state, root3, err := prepareForkchoiceState(ctx, 2*params.BeaconConfig().SlotsPerEpoch+2, [32]byte{'d'}, root2, params.BeaconConfig().ZeroHash, 1, 1) + state, blk3, err := prepareForkchoiceState(ctx, 2*params.BeaconConfig().SlotsPerEpoch+2, [32]byte{'d'}, blk2.Root(), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, root3)) - target, err = f.TargetRootForEpoch(root2, 2) + require.NoError(t, f.InsertNode(ctx, state, blk3)) + target, err = f.TargetRootForEpoch(blk2.Root(), 2) require.NoError(t, err) - require.Equal(t, target, root1) + require.Equal(t, target, blk1.Root()) // Prune finalization s := f.store - s.finalizedCheckpoint.Root = root1 + s.finalizedCheckpoint.Root = blk1.Root() require.NoError(t, s.prune(ctx)) - target, err = f.TargetRootForEpoch(root1, 1) + target, err = f.TargetRootForEpoch(blk1.Root(), 1) require.NoError(t, err) require.Equal(t, [32]byte{}, target) // Insert a block for next epoch (slot 0 present) - state, root4, err := prepareForkchoiceState(ctx, 3*params.BeaconConfig().SlotsPerEpoch, [32]byte{'e'}, root1, params.BeaconConfig().ZeroHash, 1, 1) + state, blk4, err := prepareForkchoiceState(ctx, 3*params.BeaconConfig().SlotsPerEpoch, [32]byte{'e'}, blk1.Root(), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, root4)) - target, err = f.TargetRootForEpoch(root4, 3) + require.NoError(t, f.InsertNode(ctx, state, blk4)) + target, err = f.TargetRootForEpoch(blk4.Root(), 3) require.NoError(t, err) - require.Equal(t, target, root4) + require.Equal(t, target, blk4.Root()) - state, root5, err := prepareForkchoiceState(ctx, 3*params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'f'}, root4, params.BeaconConfig().ZeroHash, 1, 1) + state, blk5, err := prepareForkchoiceState(ctx, 3*params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'f'}, blk4.Root(), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, root5)) - target, err = f.TargetRootForEpoch(root5, 3) + require.NoError(t, f.InsertNode(ctx, state, blk5)) + target, err = f.TargetRootForEpoch(blk5.Root(), 3) require.NoError(t, err) - require.Equal(t, target, root4) + require.Equal(t, target, blk4.Root()) // Target root where the target epoch is same or ahead of the block slot - target, err = f.TargetRootForEpoch(root5, 4) + target, err = f.TargetRootForEpoch(blk5.Root(), 4) require.NoError(t, err) - require.Equal(t, target, root5) + require.Equal(t, target, blk5.Root()) // Target root where the target epoch is two epochs ago - target, err = f.TargetRootForEpoch(root5, 2) + target, err = f.TargetRootForEpoch(blk5.Root(), 2) require.NoError(t, err) - require.Equal(t, root1, target) // the parent of root4 in epoch 3 is root 1 in epoch 1 + require.Equal(t, blk1.Root(), target) // the parent of root4 in epoch 3 is root 1 in epoch 1 // Target root where the target is two epochs ago, slot 0 was missed - state, root6, err := prepareForkchoiceState(ctx, 4*params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'g'}, root5, params.BeaconConfig().ZeroHash, 1, 1) + state, blk6, err := prepareForkchoiceState(ctx, 4*params.BeaconConfig().SlotsPerEpoch+1, [32]byte{'g'}, blk5.Root(), params.BeaconConfig().ZeroHash, 1, 1) require.NoError(t, err) - require.NoError(t, f.InsertNode(ctx, state, root6)) - target, err = f.TargetRootForEpoch(root6, 4) + require.NoError(t, f.InsertNode(ctx, state, blk6)) + target, err = f.TargetRootForEpoch(blk6.Root(), 4) require.NoError(t, err) - require.Equal(t, target, root5) - target, err = f.TargetRootForEpoch(root6, 2) + require.Equal(t, target, blk5.Root()) + target, err = f.TargetRootForEpoch(blk6.Root(), 2) require.NoError(t, err) - require.Equal(t, target, root1) + require.Equal(t, target, blk1.Root()) // Prune finalization - s.finalizedCheckpoint.Root = root4 + s.finalizedCheckpoint.Root = blk4.Root() require.NoError(t, s.prune(ctx)) - target, err = f.TargetRootForEpoch(root4, 3) + target, err = f.TargetRootForEpoch(blk4.Root(), 3) + require.NoError(t, err) + require.Equal(t, blk4.Root(), target) +} + +func TestStore_CleanupInserting(t *testing.T) { + f := setup(0, 0) + ctx := context.Background() + st, blk, err := prepareForkchoiceState(ctx, 1, indexToHash(1), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0) require.NoError(t, err) - require.Equal(t, root4, target) + require.NotNil(t, f.InsertNode(ctx, st, blk)) + require.Equal(t, false, f.HasNode(blk.Root())) } diff --git a/beacon-chain/forkchoice/interfaces.go b/beacon-chain/forkchoice/interfaces.go index 9db82c6920a4..08a84d5ea425 100644 --- a/beacon-chain/forkchoice/interfaces.go +++ b/beacon-chain/forkchoice/interfaces.go @@ -6,6 +6,7 @@ import ( forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" forkchoice2 "github.com/prysmaticlabs/prysm/v5/consensus-types/forkchoice" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) @@ -41,7 +42,7 @@ type HeadRetriever interface { // BlockProcessor processes the block that's used for accounting fork choice. type BlockProcessor interface { - InsertNode(context.Context, state.BeaconState, [32]byte) error + InsertNode(context.Context, state.BeaconState, consensus_blocks.ROBlock) error InsertChain(context.Context, []*forkchoicetypes.BlockAndCheckpoints) error } diff --git a/beacon-chain/forkchoice/types/BUILD.bazel b/beacon-chain/forkchoice/types/BUILD.bazel index b85cf2eed684..c6c258b94ed1 100644 --- a/beacon-chain/forkchoice/types/BUILD.bazel +++ b/beacon-chain/forkchoice/types/BUILD.bazel @@ -7,7 +7,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//config/fieldparams:go_default_library", - "//consensus-types/interfaces:go_default_library", + "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", "//proto/prysm/v1alpha1:go_default_library", ], diff --git a/beacon-chain/forkchoice/types/types.go b/beacon-chain/forkchoice/types/types.go index 214b64b6959d..fb9bfbae3489 100644 --- a/beacon-chain/forkchoice/types/types.go +++ b/beacon-chain/forkchoice/types/types.go @@ -2,7 +2,7 @@ package types import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) @@ -17,7 +17,7 @@ type Checkpoint struct { // BlockAndCheckpoints to call the InsertOptimisticChain function type BlockAndCheckpoints struct { - Block interfaces.ReadOnlyBeaconBlock + Block consensus_blocks.ROBlock JustifiedCheckpoint *ethpb.Checkpoint FinalizedCheckpoint *ethpb.Checkpoint } diff --git a/beacon-chain/gateway/BUILD.bazel b/beacon-chain/gateway/BUILD.bazel deleted file mode 100644 index 60df0caac826..000000000000 --- a/beacon-chain/gateway/BUILD.bazel +++ /dev/null @@ -1,27 +0,0 @@ -load("@prysm//tools/go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["helpers.go"], - importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/gateway", - visibility = ["//beacon-chain:__subpackages__"], - deps = [ - "//api:go_default_library", - "//api/gateway:go_default_library", - "//cmd/beacon-chain/flags:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", - "@org_golang_google_protobuf//encoding/protojson:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["helpers_test.go"], - embed = [":go_default_library"], - deps = [ - "//api/gateway:go_default_library", - "//testing/assert:go_default_library", - "//testing/require:go_default_library", - ], -) diff --git a/beacon-chain/gateway/helpers.go b/beacon-chain/gateway/helpers.go deleted file mode 100644 index fb74f2a8e6eb..000000000000 --- a/beacon-chain/gateway/helpers.go +++ /dev/null @@ -1,78 +0,0 @@ -package gateway - -import ( - gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/prysmaticlabs/prysm/v5/api" - "github.com/prysmaticlabs/prysm/v5/api/gateway" - "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" - ethpbalpha "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "google.golang.org/protobuf/encoding/protojson" -) - -// MuxConfig contains configuration that should be used when registering the beacon node in the gateway. -type MuxConfig struct { - EthPbMux *gateway.PbMux - V1AlphaPbMux *gateway.PbMux -} - -// DefaultConfig returns a fully configured MuxConfig with standard gateway behavior. -func DefaultConfig(enableDebugRPCEndpoints bool, httpModules string) MuxConfig { - var v1AlphaPbHandler, ethPbHandler *gateway.PbMux - if flags.EnableHTTPPrysmAPI(httpModules) { - v1AlphaRegistrations := []gateway.PbHandlerRegistration{ - ethpbalpha.RegisterNodeHandler, - ethpbalpha.RegisterBeaconChainHandler, - ethpbalpha.RegisterBeaconNodeValidatorHandler, - ethpbalpha.RegisterHealthHandler, - } - if enableDebugRPCEndpoints { - v1AlphaRegistrations = append(v1AlphaRegistrations, ethpbalpha.RegisterDebugHandler) - } - v1AlphaMux := gwruntime.NewServeMux( - gwruntime.WithMarshalerOption(gwruntime.MIMEWildcard, &gwruntime.HTTPBodyMarshaler{ - Marshaler: &gwruntime.JSONPb{ - MarshalOptions: protojson.MarshalOptions{ - EmitUnpopulated: true, - }, - UnmarshalOptions: protojson.UnmarshalOptions{ - DiscardUnknown: true, - }, - }, - }), - gwruntime.WithMarshalerOption( - api.EventStreamMediaType, &gwruntime.EventSourceJSONPb{}, - ), - ) - v1AlphaPbHandler = &gateway.PbMux{ - Registrations: v1AlphaRegistrations, - Patterns: []string{"/eth/v1alpha1/", "/eth/v1alpha2/"}, - Mux: v1AlphaMux, - } - } - if flags.EnableHTTPEthAPI(httpModules) { - ethRegistrations := []gateway.PbHandlerRegistration{} - ethMux := gwruntime.NewServeMux( - gwruntime.WithMarshalerOption(gwruntime.MIMEWildcard, &gwruntime.HTTPBodyMarshaler{ - Marshaler: &gwruntime.JSONPb{ - MarshalOptions: protojson.MarshalOptions{ - UseProtoNames: true, - EmitUnpopulated: true, - }, - UnmarshalOptions: protojson.UnmarshalOptions{ - DiscardUnknown: true, - }, - }, - }), - ) - ethPbHandler = &gateway.PbMux{ - Registrations: ethRegistrations, - Patterns: []string{"/internal/eth/v1/", "/internal/eth/v2/"}, - Mux: ethMux, - } - } - - return MuxConfig{ - EthPbMux: ethPbHandler, - V1AlphaPbMux: v1AlphaPbHandler, - } -} diff --git a/beacon-chain/gateway/helpers_test.go b/beacon-chain/gateway/helpers_test.go deleted file mode 100644 index e5d076790047..000000000000 --- a/beacon-chain/gateway/helpers_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package gateway - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/v5/api/gateway" - "github.com/prysmaticlabs/prysm/v5/testing/assert" - "github.com/prysmaticlabs/prysm/v5/testing/require" -) - -func TestDefaultConfig(t *testing.T) { - t.Run("Without Prysm API", func(t *testing.T) { - cfg := DefaultConfig(true, "eth") - assert.NotNil(t, cfg.EthPbMux.Mux) - require.Equal(t, 2, len(cfg.EthPbMux.Patterns)) - assert.Equal(t, "/internal/eth/v1/", cfg.EthPbMux.Patterns[0]) - assert.Equal(t, 0, len(cfg.EthPbMux.Registrations)) - assert.Equal(t, (*gateway.PbMux)(nil), cfg.V1AlphaPbMux) - }) - t.Run("Without Eth API", func(t *testing.T) { - cfg := DefaultConfig(true, "prysm") - assert.Equal(t, (*gateway.PbMux)(nil), cfg.EthPbMux) - assert.NotNil(t, cfg.V1AlphaPbMux.Mux) - require.Equal(t, 2, len(cfg.V1AlphaPbMux.Patterns)) - assert.Equal(t, "/eth/v1alpha1/", cfg.V1AlphaPbMux.Patterns[0]) - assert.Equal(t, "/eth/v1alpha2/", cfg.V1AlphaPbMux.Patterns[1]) - assert.Equal(t, 5, len(cfg.V1AlphaPbMux.Registrations)) - }) -} diff --git a/beacon-chain/monitor/process_attestation.go b/beacon-chain/monitor/process_attestation.go index 7191aebdd19d..3bc6a5cd2e8a 100644 --- a/beacon-chain/monitor/process_attestation.go +++ b/beacon-chain/monitor/process_attestation.go @@ -34,11 +34,17 @@ func (s *Service) canUpdateAttestedValidator(idx primitives.ValidatorIndex, slot // attestingIndices returns the indices of validators that participated in the given aggregated attestation. func attestingIndices(ctx context.Context, state state.BeaconState, att ethpb.Att) ([]uint64, error) { - committee, err := helpers.BeaconCommitteeFromState(ctx, state, att.GetData().Slot, att.GetData().CommitteeIndex) - if err != nil { - return nil, err + committeeBits := att.CommitteeBitsVal().BitIndices() + committees := make([][]primitives.ValidatorIndex, len(committeeBits)) + var err error + for i, ci := range committeeBits { + committees[i], err = helpers.BeaconCommitteeFromState(ctx, state, att.GetData().Slot, primitives.CommitteeIndex(ci)) + if err != nil { + return nil, err + } } - return attestation.AttestingIndices(att, committee) + + return attestation.AttestingIndices(att, committees...) } // logMessageTimelyFlagsForIndex returns the log message with performance info for the attestation (head, source, target) @@ -160,6 +166,23 @@ func (s *Service) processIncludedAttestation(ctx context.Context, state state.Be } } +// processSingleAttestation logs when the beacon node observes a single attestation from tracked validator. +func (s *Service) processSingleAttestation(att ethpb.Att) { + s.RLock() + defer s.RUnlock() + + single, ok := att.(*ethpb.SingleAttestation) + if !ok { + log.Errorf("Wrong attestation type (expected %T, got %T)", ðpb.SingleAttestation{}, att) + return + } + + if s.canUpdateAttestedValidator(single.AttesterIndex, single.GetData().Slot) { + logFields := logMessageTimelyFlagsForIndex(single.AttesterIndex, att.GetData()) + log.WithFields(logFields).Info("Processed unaggregated attestation") + } +} + // processUnaggregatedAttestation logs when the beacon node observes an unaggregated attestation from tracked validator. func (s *Service) processUnaggregatedAttestation(ctx context.Context, att ethpb.Att) { s.RLock() @@ -185,42 +208,42 @@ func (s *Service) processUnaggregatedAttestation(ctx context.Context, att ethpb. } // processUnaggregatedAttestation logs when the beacon node observes an aggregated attestation from tracked validator. -func (s *Service) processAggregatedAttestation(ctx context.Context, att *ethpb.AggregateAttestationAndProof) { +func (s *Service) processAggregatedAttestation(ctx context.Context, att ethpb.AggregateAttAndProof) { s.Lock() defer s.Unlock() - if s.trackedIndex(att.AggregatorIndex) { + if s.trackedIndex(att.GetAggregatorIndex()) { log.WithFields(logrus.Fields{ - "aggregatorIndex": att.AggregatorIndex, - "slot": att.Aggregate.Data.Slot, + "aggregatorIndex": att.GetAggregatorIndex(), + "slot": att.AggregateVal().GetData().Slot, "beaconBlockRoot": fmt.Sprintf("%#x", bytesutil.Trunc( - att.Aggregate.Data.BeaconBlockRoot)), + att.AggregateVal().GetData().BeaconBlockRoot)), "sourceRoot": fmt.Sprintf("%#x", bytesutil.Trunc( - att.Aggregate.Data.Source.Root)), + att.AggregateVal().GetData().Source.Root)), "targetRoot": fmt.Sprintf("%#x", bytesutil.Trunc( - att.Aggregate.Data.Target.Root)), + att.AggregateVal().GetData().Target.Root)), }).Info("Processed attestation aggregation") - aggregatedPerf := s.aggregatedPerformance[att.AggregatorIndex] + aggregatedPerf := s.aggregatedPerformance[att.GetAggregatorIndex()] aggregatedPerf.totalAggregations++ - s.aggregatedPerformance[att.AggregatorIndex] = aggregatedPerf - aggregationCounter.WithLabelValues(fmt.Sprintf("%d", att.AggregatorIndex)).Inc() + s.aggregatedPerformance[att.GetAggregatorIndex()] = aggregatedPerf + aggregationCounter.WithLabelValues(fmt.Sprintf("%d", att.GetAggregatorIndex())).Inc() } var root [32]byte - copy(root[:], att.Aggregate.Data.BeaconBlockRoot) + copy(root[:], att.AggregateVal().GetData().BeaconBlockRoot) st := s.config.StateGen.StateByRootIfCachedNoCopy(root) if st == nil { log.WithField("beaconBlockRoot", fmt.Sprintf("%#x", bytesutil.Trunc(root[:]))).Debug( "Skipping aggregated attestation due to state not found in cache") return } - attestingIndices, err := attestingIndices(ctx, st, att.Aggregate) + attestingIndices, err := attestingIndices(ctx, st, att.AggregateVal()) if err != nil { log.WithError(err).Error("Could not get attesting indices") return } for _, idx := range attestingIndices { - if s.canUpdateAttestedValidator(primitives.ValidatorIndex(idx), att.Aggregate.Data.Slot) { - logFields := logMessageTimelyFlagsForIndex(primitives.ValidatorIndex(idx), att.Aggregate.Data) + if s.canUpdateAttestedValidator(primitives.ValidatorIndex(idx), att.AggregateVal().GetData().Slot) { + logFields := logMessageTimelyFlagsForIndex(primitives.ValidatorIndex(idx), att.AggregateVal().GetData()) log.WithFields(logFields).Info("Processed aggregated attestation") } } diff --git a/beacon-chain/monitor/service.go b/beacon-chain/monitor/service.go index 21f96641acba..e8ceb69ecec9 100644 --- a/beacon-chain/monitor/service.go +++ b/beacon-chain/monitor/service.go @@ -236,6 +236,13 @@ func (s *Service) monitorRoutine(stateChannel chan *feed.Event, stateSub event.S } else { s.processAggregatedAttestation(s.ctx, data.Attestation) } + case operation.SingleAttReceived: + data, ok := e.Data.(*operation.SingleAttReceivedData) + if !ok { + log.Error("Event feed data is not of type *operation.SingleAttReceivedData") + } else { + s.processSingleAttestation(data.Attestation) + } case operation.ExitReceived: data, ok := e.Data.(*operation.ExitReceivedData) if !ok { diff --git a/beacon-chain/node/BUILD.bazel b/beacon-chain/node/BUILD.bazel index 883a6078fd38..d09e1df4dcd0 100644 --- a/beacon-chain/node/BUILD.bazel +++ b/beacon-chain/node/BUILD.bazel @@ -15,7 +15,7 @@ go_library( "//cmd/beacon-chain:__subpackages__", ], deps = [ - "//api/gateway:go_default_library", + "//api/server/httprest:go_default_library", "//api/server/middleware:go_default_library", "//async/event:go_default_library", "//beacon-chain/blockchain:go_default_library", @@ -25,12 +25,11 @@ go_library( "//beacon-chain/db:go_default_library", "//beacon-chain/db/filesystem:go_default_library", "//beacon-chain/db/kv:go_default_library", + "//beacon-chain/db/pruner:go_default_library", "//beacon-chain/db/slasherkv:go_default_library", - "//beacon-chain/deterministic-genesis:go_default_library", "//beacon-chain/execution:go_default_library", "//beacon-chain/forkchoice:go_default_library", "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", - "//beacon-chain/gateway:go_default_library", "//beacon-chain/monitor:go_default_library", "//beacon-chain/node/registration:go_default_library", "//beacon-chain/operations/attestations:go_default_library", @@ -66,7 +65,6 @@ go_library( "//runtime/prereqs:go_default_library", "//runtime/version:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", @@ -83,6 +81,7 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//api/server/middleware:go_default_library", "//beacon-chain/blockchain:go_default_library", "//beacon-chain/builder:go_default_library", "//beacon-chain/core/feed/state:go_default_library", @@ -93,12 +92,9 @@ go_test( "//cmd:go_default_library", "//cmd/beacon-chain/flags:go_default_library", "//config/features:go_default_library", - "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", "//runtime:go_default_library", - "//runtime/interop:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", diff --git a/beacon-chain/node/config.go b/beacon-chain/node/config.go index 19f7d74d700a..42216a05ff04 100644 --- a/beacon-chain/node/config.go +++ b/beacon-chain/node/config.go @@ -8,12 +8,13 @@ import ( "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - tracing2 "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" "github.com/urfave/cli/v2" ) func configureTracing(cliCtx *cli.Context) error { - return tracing2.Setup( + return tracing.Setup( + cliCtx.Context, "beacon-chain", // service name cliCtx.String(cmd.TracingProcessNameFlag.Name), cliCtx.String(cmd.TracingEndpointFlag.Name), @@ -132,7 +133,7 @@ func configureEth1Config(cliCtx *cli.Context) error { } func configureNetwork(cliCtx *cli.Context) { - if len(cliCtx.StringSlice(cmd.BootstrapNode.Name)) > 0 { + if cliCtx.IsSet(cmd.BootstrapNode.Name) { c := params.BeaconNetworkConfig() c.BootstrapNodes = cliCtx.StringSlice(cmd.BootstrapNode.Name) params.OverrideBeaconNetworkConfig(c) @@ -144,23 +145,6 @@ func configureNetwork(cliCtx *cli.Context) { } } -func configureInteropConfig(cliCtx *cli.Context) error { - // an explicit chain config was specified, don't mess with it - if cliCtx.IsSet(cmd.ChainConfigFileFlag.Name) { - return nil - } - genTimeIsSet := cliCtx.IsSet(flags.InteropGenesisTimeFlag.Name) - numValsIsSet := cliCtx.IsSet(flags.InteropNumValidatorsFlag.Name) - votesIsSet := cliCtx.IsSet(flags.InteropMockEth1DataVotesFlag.Name) - - if genTimeIsSet || numValsIsSet || votesIsSet { - if err := params.SetActive(params.InteropConfig().Copy()); err != nil { - return err - } - } - return nil -} - func configureExecutionSetting(cliCtx *cli.Context) error { if cliCtx.IsSet(flags.TerminalTotalDifficultyOverride.Name) { c := params.BeaconConfig() @@ -182,7 +166,7 @@ func configureExecutionSetting(cliCtx *cli.Context) error { } if !cliCtx.IsSet(flags.SuggestedFeeRecipient.Name) { - log.Warnf("In order to receive transaction fees from proposing blocks, " + + log.Warn("In order to receive transaction fees from proposing blocks, " + "you must provide flag --" + flags.SuggestedFeeRecipient.Name + " with a valid ethereum address when starting your beacon node. " + "Please see our documentation for more information on this requirement (https://docs.prylabs.network/docs/execution-node/fee-recipient).") return nil diff --git a/beacon-chain/node/config_test.go b/beacon-chain/node/config_test.go index f2c08f380b51..f545f156d01b 100644 --- a/beacon-chain/node/config_test.go +++ b/beacon-chain/node/config_test.go @@ -169,62 +169,25 @@ func TestConfigureNetwork_ConfigFile(t *testing.T) { require.NoError(t, os.Remove("flags_test.yaml")) } -func TestConfigureInterop(t *testing.T) { - params.SetupTestConfigCleanup(t) - - tests := []struct { - name string - flagSetter func() *cli.Context - configName string - }{ - { - "nothing set", - func() *cli.Context { - app := cli.App{} - set := flag.NewFlagSet("test", 0) - return cli.NewContext(&app, set, nil) - }, - "mainnet", - }, - { - "mock votes set", - func() *cli.Context { - app := cli.App{} - set := flag.NewFlagSet("test", 0) - set.Bool(flags.InteropMockEth1DataVotesFlag.Name, false, "") - assert.NoError(t, set.Set(flags.InteropMockEth1DataVotesFlag.Name, "true")) - return cli.NewContext(&app, set, nil) - }, - "interop", - }, - { - "validators set", - func() *cli.Context { - app := cli.App{} - set := flag.NewFlagSet("test", 0) - set.Uint64(flags.InteropNumValidatorsFlag.Name, 0, "") - assert.NoError(t, set.Set(flags.InteropNumValidatorsFlag.Name, "20")) - return cli.NewContext(&app, set, nil) - }, - "interop", - }, - { - "genesis time set", - func() *cli.Context { - app := cli.App{} - set := flag.NewFlagSet("test", 0) - set.Uint64(flags.InteropGenesisTimeFlag.Name, 0, "") - assert.NoError(t, set.Set(flags.InteropGenesisTimeFlag.Name, "200")) - return cli.NewContext(&app, set, nil) - }, - "interop", +func TestAliasFlag(t *testing.T) { + // Create a new app with the flag + app := &cli.App{ + Flags: []cli.Flag{flags.HTTPServerHost}, + Action: func(c *cli.Context) error { + // Test if the alias works and sets the flag correctly + if c.IsSet("grpc-gateway-host") && c.IsSet("http-host") { + return nil + } + return cli.Exit("Alias or flag not set", 1) }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require.NoError(t, configureInteropConfig(tt.flagSetter())) - assert.DeepEqual(t, tt.configName, params.BeaconConfig().ConfigName) - }) - } + // Simulate command line arguments that include the alias + args := []string{"app", "--grpc-gateway-host", "config.yml"} + + // Run the app with the simulated arguments + err := app.Run(args) + + // Check if the alias set the flag correctly + assert.NoError(t, err) } diff --git a/beacon-chain/node/node.go b/beacon-chain/node/node.go index d3f3af2ecfbd..89ee2e7ef8c6 100644 --- a/beacon-chain/node/node.go +++ b/beacon-chain/node/node.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "net" + "net/http" "os" "os/signal" "path/filepath" @@ -17,9 +18,8 @@ import ( "syscall" "github.com/ethereum/go-ethereum/common" - "github.com/gorilla/mux" "github.com/pkg/errors" - apigateway "github.com/prysmaticlabs/prysm/v5/api/gateway" + "github.com/prysmaticlabs/prysm/v5/api/server/httprest" "github.com/prysmaticlabs/prysm/v5/api/server/middleware" "github.com/prysmaticlabs/prysm/v5/async/event" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" @@ -29,12 +29,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/kv" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/pruner" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/slasherkv" - interopcoldstart "github.com/prysmaticlabs/prysm/v5/beacon-chain/deterministic-genesis" "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution" "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice" doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/gateway" "github.com/prysmaticlabs/prysm/v5/beacon-chain/monitor" "github.com/prysmaticlabs/prysm/v5/beacon-chain/node/registration" "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations" @@ -95,6 +94,7 @@ type BeaconNode struct { stop chan struct{} // Channel to wait for termination notifications. db db.Database slasherDB db.SlasherDatabase + attestationCache *cache.AttestationCache attestationPool attestations.Pool exitPool voluntaryexits.PoolManager slashingsPool slashings.PoolManager @@ -146,6 +146,7 @@ func New(cliCtx *cli.Context, cancel context.CancelFunc, opts ...Option) (*Beaco stateFeed: new(event.Feed), blockFeed: new(event.Feed), opFeed: new(event.Feed), + attestationCache: cache.NewAttestationCache(), attestationPool: attestations.NewPool(), exitPool: voluntaryexits.NewPool(), slashingsPool: slashings.NewPool(), @@ -193,20 +194,13 @@ func New(cliCtx *cli.Context, cancel context.CancelFunc, opts ...Option) (*Beaco beacon.verifyInitWaiter = verification.NewInitializerWaiter( beacon.clockWaiter, forkchoice.NewROForkChoice(beacon.forkChoicer), beacon.stateGen) - pa := peers.NewAssigner(beacon.fetchP2P().Peers(), beacon.forkChoicer) - beacon.BackfillOpts = append( beacon.BackfillOpts, backfill.WithVerifierWaiter(beacon.verifyInitWaiter), backfill.WithInitSyncWaiter(initSyncWaiter(ctx, beacon.initialSyncComplete)), ) - bf, err := backfill.NewService(ctx, bfs, beacon.BlobStorage, beacon.clockWaiter, beacon.fetchP2P(), pa, beacon.BackfillOpts...) - if err != nil { - return nil, errors.Wrap(err, "error initializing backfill service") - } - - if err := registerServices(cliCtx, beacon, synchronizer, bf, bfs); err != nil { + if err := registerServices(cliCtx, beacon, synchronizer, bfs); err != nil { return nil, errors.Wrap(err, "could not register services") } @@ -269,10 +263,6 @@ func configureBeacon(cliCtx *cli.Context) error { configureNetwork(cliCtx) - if err := configureInteropConfig(cliCtx); err != nil { - return errors.Wrap(err, "could not configure interop config") - } - if err := configureExecutionSetting(cliCtx); err != nil { return errors.Wrap(err, "could not configure execution setting") } @@ -293,11 +283,6 @@ func startBaseServices(cliCtx *cli.Context, beacon *BeaconNode, depositAddress s return nil, errors.Wrap(err, "could not start slashing DB") } - log.Debugln("Registering P2P Service") - if err := beacon.registerP2P(cliCtx); err != nil { - return nil, errors.Wrap(err, "could not register P2P service") - } - bfs, err := backfill.NewUpdater(ctx, beacon.db) if err != nil { return nil, errors.Wrap(err, "could not create backfill updater") @@ -316,9 +301,15 @@ func startBaseServices(cliCtx *cli.Context, beacon *BeaconNode, depositAddress s return bfs, nil } -func registerServices(cliCtx *cli.Context, beacon *BeaconNode, synchronizer *startup.ClockSynchronizer, bf *backfill.Service, bfs *backfill.Store) error { - if err := beacon.services.RegisterService(bf); err != nil { - return errors.Wrap(err, "could not register backfill service") +func registerServices(cliCtx *cli.Context, beacon *BeaconNode, synchronizer *startup.ClockSynchronizer, bfs *backfill.Store) error { + log.Debugln("Registering P2P Service") + if err := beacon.registerP2P(cliCtx); err != nil { + return errors.Wrap(err, "could not register P2P service") + } + + log.Debugln("Registering Backfill Service") + if err := beacon.RegisterBackfillService(cliCtx, bfs); err != nil { + return errors.Wrap(err, "could not register Back Fill service") } log.Debugln("Registering POW Chain Service") @@ -331,11 +322,6 @@ func registerServices(cliCtx *cli.Context, beacon *BeaconNode, synchronizer *sta return errors.Wrap(err, "could not register attestation pool service") } - log.Debugln("Registering Deterministic Genesis Service") - if err := beacon.registerDeterministicGenesisService(); err != nil { - return errors.Wrap(err, "could not register deterministic genesis service") - } - log.Debugln("Registering Blockchain Service") if err := beacon.registerBlockchainService(beacon.forkChoicer, synchronizer, beacon.initialSyncComplete); err != nil { return errors.Wrap(err, "could not register blockchain service") @@ -351,6 +337,11 @@ func registerServices(cliCtx *cli.Context, beacon *BeaconNode, synchronizer *sta return errors.Wrap(err, "could not register sync service") } + log.Debugln("Registering Slashing Pool Service") + if err := beacon.registerSlashingPoolService(); err != nil { + return errors.Wrap(err, "could not register slashing pool service") + } + log.Debugln("Registering Slasher Service") if err := beacon.registerSlasherService(); err != nil { return errors.Wrap(err, "could not register slasher service") @@ -362,14 +353,14 @@ func registerServices(cliCtx *cli.Context, beacon *BeaconNode, synchronizer *sta } log.Debugln("Registering RPC Service") - router := newRouter(cliCtx) + router := http.NewServeMux() if err := beacon.registerRPCService(router); err != nil { return errors.Wrap(err, "could not register RPC service") } - log.Debugln("Registering GRPC Gateway Service") - if err := beacon.registerGRPCGateway(router); err != nil { - return errors.Wrap(err, "could not register GRPC gateway service") + log.Debugln("Registering HTTP Service") + if err := beacon.registerHTTPService(router); err != nil { + return errors.Wrap(err, "could not register HTTP service") } log.Debugln("Registering Validator Monitoring Service") @@ -384,6 +375,13 @@ func registerServices(cliCtx *cli.Context, beacon *BeaconNode, synchronizer *sta } } + if cliCtx.Bool(flags.BeaconDBPruning.Name) { + log.Debugln("Registering Pruner Service") + if err := beacon.registerPrunerService(cliCtx); err != nil { + return errors.Wrap(err, "could not register pruner service") + } + } + return nil } @@ -398,21 +396,8 @@ func initSyncWaiter(ctx context.Context, complete chan struct{}) func() error { } } -func newRouter(cliCtx *cli.Context) *mux.Router { - var allowedOrigins []string - if cliCtx.IsSet(flags.GPRCGatewayCorsDomain.Name) { - allowedOrigins = strings.Split(cliCtx.String(flags.GPRCGatewayCorsDomain.Name), ",") - } else { - allowedOrigins = strings.Split(flags.GPRCGatewayCorsDomain.Value, ",") - } - r := mux.NewRouter() - r.Use(middleware.NormalizeQueryValuesHandler) - r.Use(middleware.CorsHandler(allowedOrigins)) - return r -} - // StateFeed implements statefeed.Notifier. -func (b *BeaconNode) StateFeed() *event.Feed { +func (b *BeaconNode) StateFeed() event.SubscriberSender { return b.stateFeed } @@ -422,7 +407,7 @@ func (b *BeaconNode) BlockFeed() *event.Feed { } // OperationFeed implements opfeed.Notifier. -func (b *BeaconNode) OperationFeed() *event.Feed { +func (b *BeaconNode) OperationFeed() event.SubscriberSender { return b.opFeed } @@ -587,6 +572,7 @@ func (b *BeaconNode) startDB(cliCtx *cli.Context, depositAddress string) error { } if b.CheckpointInitializer != nil { + log.Info("Checkpoint sync - Downloading origin state and block") if err := b.CheckpointInitializer.Initialize(b.ctx, d); err != nil { return err } @@ -733,6 +719,7 @@ func (b *BeaconNode) fetchBuilderService() *builder.Service { func (b *BeaconNode) registerAttestationPool() error { s, err := attestations.NewService(b.ctx, &attestations.Config{ + Cache: b.attestationCache, Pool: b.attestationPool, InitialSyncComplete: b.initialSyncComplete, }) @@ -742,6 +729,16 @@ func (b *BeaconNode) registerAttestationPool() error { return b.services.RegisterService(s) } +func (b *BeaconNode) registerSlashingPoolService() error { + var chainService *blockchain.Service + if err := b.services.FetchService(&chainService); err != nil { + return err + } + + s := slashings.NewPoolService(b.ctx, b.slashingsPool, slashings.WithElectraTimer(b.clockWaiter, chainService.CurrentSlot)) + return b.services.RegisterService(s) +} + func (b *BeaconNode) registerBlockchainService(fc forkchoice.ForkChoicer, gs *startup.ClockSynchronizer, syncComplete chan struct{}) error { var web3Service *execution.Service if err := b.services.FetchService(&web3Service); err != nil { @@ -761,6 +758,7 @@ func (b *BeaconNode) registerBlockchainService(fc forkchoice.ForkChoicer, gs *st blockchain.WithDepositCache(b.depositCache), blockchain.WithChainStartFetcher(web3Service), blockchain.WithExecutionEngineCaller(web3Service), + blockchain.WithAttestationCache(b.attestationCache), blockchain.WithAttestationPool(b.attestationPool), blockchain.WithExitPool(b.exitPool), blockchain.WithSlashingPool(b.slashingsPool), @@ -810,6 +808,7 @@ func (b *BeaconNode) registerPOWChainService() error { execution.WithBeaconNodeStatsUpdater(bs), execution.WithFinalizedStateAtStartup(b.finalizedStateAtStartUp), execution.WithJwtId(b.cliCtx.String(flags.JwtId.Name)), + execution.WithVerifierWaiter(b.verifyInitWaiter), ) web3Service, err := execution.NewService(b.ctx, opts...) if err != nil { @@ -844,6 +843,7 @@ func (b *BeaconNode) registerSyncService(initialSyncComplete chan struct{}, bFil regularsync.WithBlockNotifier(b), regularsync.WithAttestationNotifier(b), regularsync.WithOperationNotifier(b), + regularsync.WithAttestationCache(b.attestationCache), regularsync.WithAttestationPool(b.attestationPool), regularsync.WithExitPool(b.exitPool), regularsync.WithSlashingPool(b.slashingsPool), @@ -852,7 +852,7 @@ func (b *BeaconNode) registerSyncService(initialSyncComplete chan struct{}, bFil regularsync.WithStateGen(b.stateGen), regularsync.WithSlasherAttestationsFeed(b.slasherAttestationsFeed), regularsync.WithSlasherBlockHeadersFeed(b.slasherBlockHeadersFeed), - regularsync.WithPayloadReconstructor(web3Service), + regularsync.WithReconstructor(web3Service), regularsync.WithClockWaiter(b.clockWaiter), regularsync.WithInitialSyncComplete(initialSyncComplete), regularsync.WithStateNotifier(b), @@ -917,7 +917,7 @@ func (b *BeaconNode) registerSlasherService() error { return b.services.RegisterService(slasherSrv) } -func (b *BeaconNode) registerRPCService(router *mux.Router) error { +func (b *BeaconNode) registerRPCService(router *http.ServeMux) error { var chainService *blockchain.Service if err := b.services.FetchService(&chainService); err != nil { return err @@ -940,20 +940,8 @@ func (b *BeaconNode) registerRPCService(router *mux.Router) error { } } - genesisValidators := b.cliCtx.Uint64(flags.InteropNumValidatorsFlag.Name) - var depositFetcher cache.DepositFetcher - var chainStartFetcher execution.ChainStartFetcher - if genesisValidators > 0 { - var interopService *interopcoldstart.Service - if err := b.services.FetchService(&interopService); err != nil { - return err - } - depositFetcher = interopService - chainStartFetcher = interopService - } else { - depositFetcher = b.depositCache - chainStartFetcher = web3Service - } + depositFetcher := b.depositCache + chainStartFetcher := web3Service host := b.cliCtx.String(flags.RPCHost.Name) port := b.cliCtx.String(flags.RPCPort.Name) @@ -967,55 +955,56 @@ func (b *BeaconNode) registerRPCService(router *mux.Router) error { p2pService := b.fetchP2P() rpcService := rpc.NewService(b.ctx, &rpc.Config{ - ExecutionEngineCaller: web3Service, - ExecutionPayloadReconstructor: web3Service, - Host: host, - Port: port, - BeaconMonitoringHost: beaconMonitoringHost, - BeaconMonitoringPort: beaconMonitoringPort, - CertFlag: cert, - KeyFlag: key, - BeaconDB: b.db, - Broadcaster: p2pService, - PeersFetcher: p2pService, - PeerManager: p2pService, - MetadataProvider: p2pService, - ChainInfoFetcher: chainService, - HeadFetcher: chainService, - CanonicalFetcher: chainService, - ForkFetcher: chainService, - ForkchoiceFetcher: chainService, - FinalizationFetcher: chainService, - BlockReceiver: chainService, - BlobReceiver: chainService, - AttestationReceiver: chainService, - GenesisTimeFetcher: chainService, - GenesisFetcher: chainService, - OptimisticModeFetcher: chainService, - AttestationsPool: b.attestationPool, - ExitPool: b.exitPool, - SlashingsPool: b.slashingsPool, - BLSChangesPool: b.blsToExecPool, - SyncCommitteeObjectPool: b.syncCommitteePool, - ExecutionChainService: web3Service, - ExecutionChainInfoFetcher: web3Service, - ChainStartFetcher: chainStartFetcher, - MockEth1Votes: mockEth1DataVotes, - SyncService: syncService, - DepositFetcher: depositFetcher, - PendingDepositFetcher: b.depositCache, - BlockNotifier: b, - StateNotifier: b, - OperationNotifier: b, - StateGen: b.stateGen, - EnableDebugRPCEndpoints: enableDebugRPCEndpoints, - MaxMsgSize: maxMsgSize, - BlockBuilder: b.fetchBuilderService(), - Router: router, - ClockWaiter: b.clockWaiter, - BlobStorage: b.BlobStorage, - TrackedValidatorsCache: b.trackedValidatorsCache, - PayloadIDCache: b.payloadIDCache, + ExecutionEngineCaller: web3Service, + ExecutionReconstructor: web3Service, + Host: host, + Port: port, + BeaconMonitoringHost: beaconMonitoringHost, + BeaconMonitoringPort: beaconMonitoringPort, + CertFlag: cert, + KeyFlag: key, + BeaconDB: b.db, + Broadcaster: p2pService, + PeersFetcher: p2pService, + PeerManager: p2pService, + MetadataProvider: p2pService, + ChainInfoFetcher: chainService, + HeadFetcher: chainService, + CanonicalFetcher: chainService, + ForkFetcher: chainService, + ForkchoiceFetcher: chainService, + FinalizationFetcher: chainService, + BlockReceiver: chainService, + BlobReceiver: chainService, + AttestationReceiver: chainService, + GenesisTimeFetcher: chainService, + GenesisFetcher: chainService, + OptimisticModeFetcher: chainService, + AttestationCache: b.attestationCache, + AttestationsPool: b.attestationPool, + ExitPool: b.exitPool, + SlashingsPool: b.slashingsPool, + BLSChangesPool: b.blsToExecPool, + SyncCommitteeObjectPool: b.syncCommitteePool, + ExecutionChainService: web3Service, + ExecutionChainInfoFetcher: web3Service, + ChainStartFetcher: chainStartFetcher, + MockEth1Votes: mockEth1DataVotes, + SyncService: syncService, + DepositFetcher: depositFetcher, + PendingDepositFetcher: b.depositCache, + BlockNotifier: b, + StateNotifier: b, + OperationNotifier: b, + StateGen: b.stateGen, + EnableDebugRPCEndpoints: enableDebugRPCEndpoints, + MaxMsgSize: maxMsgSize, + BlockBuilder: b.fetchBuilderService(), + Router: router, + ClockWaiter: b.clockWaiter, + BlobStorage: b.BlobStorage, + TrackedValidatorsCache: b.trackedValidatorsCache, + PayloadIDCache: b.payloadIDCache, }) return b.services.RegisterService(rpcService) @@ -1044,75 +1033,37 @@ func (b *BeaconNode) registerPrometheusService(_ *cli.Context) error { return b.services.RegisterService(service) } -func (b *BeaconNode) registerGRPCGateway(router *mux.Router) error { - if b.cliCtx.Bool(flags.DisableGRPCGateway.Name) { - return nil +func (b *BeaconNode) registerHTTPService(router *http.ServeMux) error { + host := b.cliCtx.String(flags.HTTPServerHost.Name) + port := b.cliCtx.Int(flags.HTTPServerPort.Name) + address := net.JoinHostPort(host, strconv.Itoa(port)) + var allowedOrigins []string + if b.cliCtx.IsSet(flags.HTTPServerCorsDomain.Name) { + allowedOrigins = strings.Split(b.cliCtx.String(flags.HTTPServerCorsDomain.Name), ",") + } else { + allowedOrigins = strings.Split(flags.HTTPServerCorsDomain.Value, ",") } - gatewayHost := b.cliCtx.String(flags.GRPCGatewayHost.Name) - gatewayPort := b.cliCtx.Int(flags.GRPCGatewayPort.Name) - rpcHost := b.cliCtx.String(flags.RPCHost.Name) - rpcPort := b.cliCtx.Int(flags.RPCPort.Name) - enableDebugRPCEndpoints := !b.cliCtx.Bool(flags.DisableDebugRPCEndpoints.Name) - selfAddress := net.JoinHostPort(rpcHost, strconv.Itoa(rpcPort)) - gatewayAddress := net.JoinHostPort(gatewayHost, strconv.Itoa(gatewayPort)) - allowedOrigins := strings.Split(b.cliCtx.String(flags.GPRCGatewayCorsDomain.Name), ",") - selfCert := b.cliCtx.String(flags.CertFlag.Name) - maxCallSize := b.cliCtx.Uint64(cmd.GrpcMaxCallRecvMsgSizeFlag.Name) - httpModules := b.cliCtx.String(flags.HTTPModules.Name) - timeout := b.cliCtx.Int(cmd.ApiTimeoutFlag.Name) - - gatewayConfig := gateway.DefaultConfig(enableDebugRPCEndpoints, httpModules) - muxs := make([]*apigateway.PbMux, 0) - if gatewayConfig.V1AlphaPbMux != nil { - muxs = append(muxs, gatewayConfig.V1AlphaPbMux) - } - if gatewayConfig.EthPbMux != nil { - muxs = append(muxs, gatewayConfig.EthPbMux) - } - - opts := []apigateway.Option{ - apigateway.WithRouter(router), - apigateway.WithGatewayAddr(gatewayAddress), - apigateway.WithRemoteAddr(selfAddress), - apigateway.WithPbHandlers(muxs), - apigateway.WithRemoteCert(selfCert), - apigateway.WithMaxCallRecvMsgSize(maxCallSize), - apigateway.WithAllowedOrigins(allowedOrigins), - apigateway.WithTimeout(uint64(timeout)), - } - g, err := apigateway.New(b.ctx, opts...) + + middlewares := []middleware.Middleware{ + middleware.NormalizeQueryValuesHandler, + middleware.CorsHandler(allowedOrigins), + } + + opts := []httprest.Option{ + httprest.WithRouter(router), + httprest.WithHTTPAddr(address), + httprest.WithMiddlewares(middlewares), + } + if b.cliCtx.IsSet(cmd.ApiTimeoutFlag.Name) { + opts = append(opts, httprest.WithTimeout(b.cliCtx.Duration(cmd.ApiTimeoutFlag.Name))) + } + g, err := httprest.New(b.ctx, opts...) if err != nil { return err } return b.services.RegisterService(g) } -func (b *BeaconNode) registerDeterministicGenesisService() error { - genesisTime := b.cliCtx.Uint64(flags.InteropGenesisTimeFlag.Name) - genesisValidators := b.cliCtx.Uint64(flags.InteropNumValidatorsFlag.Name) - - if genesisValidators > 0 { - svc := interopcoldstart.NewService(b.ctx, &interopcoldstart.Config{ - GenesisTime: genesisTime, - NumValidators: genesisValidators, - BeaconDB: b.db, - DepositCache: b.depositCache, - }) - svc.Start() - - // Register genesis state as start-up state when interop mode. - // The start-up state gets reused across services. - st, err := b.db.GenesisState(b.ctx) - if err != nil { - return err - } - b.finalizedStateAtStartUp = st - - return b.services.RegisterService(svc) - } - return nil -} - func (b *BeaconNode) registerValidatorMonitorService(initialSyncComplete chan struct{}) error { cliSlice := b.cliCtx.IntSlice(cmd.ValidatorMonitorIndicesFlag.Name) if cliSlice == nil { @@ -1161,6 +1112,44 @@ func (b *BeaconNode) registerBuilderService(cliCtx *cli.Context) error { return b.services.RegisterService(svc) } +func (b *BeaconNode) registerPrunerService(cliCtx *cli.Context) error { + genesisTimeUnix := params.BeaconConfig().MinGenesisTime + params.BeaconConfig().GenesisDelay + var backfillService *backfill.Service + if err := b.services.FetchService(&backfillService); err != nil { + return err + } + + var opts []pruner.ServiceOption + if cliCtx.IsSet(flags.PrunerRetentionEpochs.Name) { + uv := cliCtx.Uint64(flags.PrunerRetentionEpochs.Name) + opts = append(opts, pruner.WithRetentionPeriod(primitives.Epoch(uv))) + } + + p, err := pruner.New( + cliCtx.Context, + b.db, + genesisTimeUnix, + initSyncWaiter(cliCtx.Context, b.initialSyncComplete), + backfillService.WaitForCompletion, + opts..., + ) + if err != nil { + return err + } + + return b.services.RegisterService(p) +} + +func (b *BeaconNode) RegisterBackfillService(cliCtx *cli.Context, bfs *backfill.Store) error { + pa := peers.NewAssigner(b.fetchP2P().Peers(), b.forkChoicer) + bf, err := backfill.NewService(cliCtx.Context, bfs, b.BlobStorage, b.clockWaiter, b.fetchP2P(), pa, b.BackfillOpts...) + if err != nil { + return errors.Wrap(err, "error initializing backfill service") + } + + return b.services.RegisterService(bf) +} + func hasNetworkFlag(cliCtx *cli.Context) bool { for _, flag := range features.NetworkFlags { for _, name := range flag.Names() { diff --git a/beacon-chain/node/node_test.go b/beacon-chain/node/node_test.go index c7aca7d8d777..d988be8f862b 100644 --- a/beacon-chain/node/node_test.go +++ b/beacon-chain/node/node_test.go @@ -6,12 +6,11 @@ import ( "fmt" "net/http" "net/http/httptest" - "os" "path/filepath" - "strconv" "testing" "time" + "github.com/prysmaticlabs/prysm/v5/api/server/middleware" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/builder" statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" @@ -20,13 +19,8 @@ import ( mockExecution "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/monitor" "github.com/prysmaticlabs/prysm/v5/cmd" - "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/v5/config/features" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - "github.com/prysmaticlabs/prysm/v5/config/params" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime" - "github.com/prysmaticlabs/prysm/v5/runtime/interop" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" logTest "github.com/sirupsen/logrus/hooks/test" @@ -116,55 +110,6 @@ func TestNodeStart_SyncChecker(t *testing.T) { require.LogsContain(t, hook, "Starting beacon node") } -func TestNodeStart_Ok_registerDeterministicGenesisService(t *testing.T) { - numValidators := uint64(1) - hook := logTest.NewGlobal() - app := cli.App{} - tmp := fmt.Sprintf("%s/datadirtest2", t.TempDir()) - set := flag.NewFlagSet("test", 0) - set.String("datadir", tmp, "node data directory") - set.Uint64(flags.InteropNumValidatorsFlag.Name, numValidators, "") - set.String("suggested-fee-recipient", "0x6e35733c5af9B61374A128e6F85f553aF09ff89A", "fee recipient") - require.NoError(t, set.Set("suggested-fee-recipient", "0x6e35733c5af9B61374A128e6F85f553aF09ff89A")) - genesisState, _, err := interop.GenerateGenesisState(context.Background(), 0, numValidators) - require.NoError(t, err, "Could not generate genesis beacon state") - for i := uint64(1); i < 2; i++ { - var someRoot [32]byte - var someKey [fieldparams.BLSPubkeyLength]byte - copy(someRoot[:], strconv.Itoa(int(i))) - copy(someKey[:], strconv.Itoa(int(i))) - genesisState.Validators = append(genesisState.Validators, ðpb.Validator{ - PublicKey: someKey[:], - WithdrawalCredentials: someRoot[:], - EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, - Slashed: false, - ActivationEligibilityEpoch: 1, - ActivationEpoch: 1, - ExitEpoch: 1, - WithdrawableEpoch: 1, - }) - genesisState.Balances = append(genesisState.Balances, params.BeaconConfig().MaxEffectiveBalance) - } - genesisBytes, err := genesisState.MarshalSSZ() - require.NoError(t, err) - require.NoError(t, os.WriteFile("genesis_ssz.json", genesisBytes, 0666)) - set.String("genesis-state", "genesis_ssz.json", "") - ctx, cancel := newCliContextWithCancel(&app, set) - node, err := New(ctx, cancel, WithBlockchainFlagOptions([]blockchain.Option{}), - WithBuilderFlagOptions([]builder.Option{}), - WithExecutionChainOptions([]execution.Option{}), - WithBlobStorage(filesystem.NewEphemeralBlobStorage(t))) - require.NoError(t, err) - node.services = &runtime.ServiceRegistry{} - go func() { - node.Start() - }() - time.Sleep(3 * time.Second) - node.Close() - require.LogsContain(t, hook, "Starting beacon node") - require.NoError(t, os.Remove("genesis_ssz.json")) -} - // TestClearDB tests clearing the database func TestClearDB(t *testing.T) { hook := logTest.NewGlobal() @@ -252,19 +197,19 @@ func Test_hasNetworkFlag(t *testing.T) { } func TestCORS(t *testing.T) { - // Mock CLI context with a test CORS domain - app := cli.App{} - set := flag.NewFlagSet("test", 0) - set.String(flags.GPRCGatewayCorsDomain.Name, "http://allowed-example.com", "") - cliCtx := cli.NewContext(&app, set, nil) - require.NoError(t, cliCtx.Set(flags.GPRCGatewayCorsDomain.Name, "http://allowed-example.com")) - - router := newRouter(cliCtx) - + router := http.NewServeMux() // Ensure a test route exists router.HandleFunc("/some-path", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - }).Methods(http.MethodGet) + if r.Method == http.MethodGet { + w.WriteHeader(http.StatusOK) + } else { + http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) + } + }) + + // Register the CORS middleware on mux Router + allowedOrigins := []string{"http://allowed-example.com"} + handler := middleware.CorsHandler(allowedOrigins)(router) // Define test cases tests := []struct { @@ -285,7 +230,7 @@ func TestCORS(t *testing.T) { rr := httptest.NewRecorder() // Serve HTTP - router.ServeHTTP(rr, req) + handler.ServeHTTP(rr, req) // Check the CORS headers based on the expected outcome if tc.expectAllow && rr.Header().Get("Access-Control-Allow-Origin") != tc.origin { diff --git a/beacon-chain/operations/attestations/BUILD.bazel b/beacon-chain/operations/attestations/BUILD.bazel index c1c42dd9d347..1d25d0b4179b 100644 --- a/beacon-chain/operations/attestations/BUILD.bazel +++ b/beacon-chain/operations/attestations/BUILD.bazel @@ -16,11 +16,13 @@ go_library( "//testing/spectest:__subpackages__", ], deps = [ + "//beacon-chain/cache:go_default_library", "//beacon-chain/operations/attestations/kv:go_default_library", "//cache/lru:go_default_library", "//config/features:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", "//proto/prysm/v1alpha1/attestation/aggregation/attestations:go_default_library", @@ -32,7 +34,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/operations/attestations/attmap/BUILD.bazel b/beacon-chain/operations/attestations/attmap/BUILD.bazel new file mode 100644 index 000000000000..8a9a6989ee7e --- /dev/null +++ b/beacon-chain/operations/attestations/attmap/BUILD.bazel @@ -0,0 +1,13 @@ +load("@prysm//tools/go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["map.go"], + importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations/attmap", + visibility = ["//visibility:public"], + deps = [ + "//proto/prysm/v1alpha1:go_default_library", + "//proto/prysm/v1alpha1/attestation:go_default_library", + "@com_github_pkg_errors//:go_default_library", + ], +) diff --git a/beacon-chain/operations/attestations/attmap/map.go b/beacon-chain/operations/attestations/attmap/map.go new file mode 100644 index 000000000000..9970d12bcf87 --- /dev/null +++ b/beacon-chain/operations/attestations/attmap/map.go @@ -0,0 +1,89 @@ +package attmap + +import ( + "sync" + + "github.com/pkg/errors" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" +) + +// Attestations -- +type Attestations struct { + atts map[attestation.Id]ethpb.Att + sync.RWMutex +} + +// New creates a new instance of the map. +func New() *Attestations { + return &Attestations{atts: make(map[attestation.Id]ethpb.Att)} +} + +// Save stores an attestation in the map. +func (a *Attestations) Save(att ethpb.Att) error { + if att == nil || att.IsNil() { + return nil + } + + id, err := attestation.NewId(att, attestation.Full) + if err != nil { + return errors.Wrap(err, "could not create attestation ID") + } + + a.Lock() + defer a.Unlock() + a.atts[id] = att + + return nil +} + +// SaveMany stores multiple attestation in the map. +func (a *Attestations) SaveMany(atts []ethpb.Att) error { + for _, att := range atts { + if err := a.Save(att); err != nil { + return err + } + } + + return nil +} + +// GetAll retrieves all attestations that are in the map. +func (a *Attestations) GetAll() []ethpb.Att { + a.RLock() + defer a.RUnlock() + + atts := make([]ethpb.Att, len(a.atts)) + i := 0 + for _, att := range a.atts { + atts[i] = att.Clone() + i++ + } + + return atts +} + +// Delete removes an attestation from the map. +func (a *Attestations) Delete(att ethpb.Att) error { + if att == nil || att.IsNil() { + return nil + } + + id, err := attestation.NewId(att, attestation.Full) + if err != nil { + return errors.Wrap(err, "could not create attestation ID") + } + + a.Lock() + defer a.Unlock() + delete(a.atts, id) + + return nil +} + +// Count returns the number of attestations in the map. +func (a *Attestations) Count() int { + a.RLock() + defer a.RUnlock() + return len(a.atts) +} diff --git a/beacon-chain/operations/attestations/kv/BUILD.bazel b/beacon-chain/operations/attestations/kv/BUILD.bazel index b79625e8427e..bb0ff0e5f12e 100644 --- a/beacon-chain/operations/attestations/kv/BUILD.bazel +++ b/beacon-chain/operations/attestations/kv/BUILD.bazel @@ -5,7 +5,6 @@ go_library( srcs = [ "aggregated.go", "block.go", - "forkchoice.go", "kv.go", "seen_bits.go", "unaggregated.go", @@ -14,8 +13,10 @@ go_library( visibility = ["//beacon-chain:__subpackages__"], deps = [ "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/operations/attestations/attmap:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", "//proto/prysm/v1alpha1/attestation/aggregation/attestations:go_default_library", @@ -24,7 +25,6 @@ go_library( "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/operations/attestations/kv/aggregated.go b/beacon-chain/operations/attestations/kv/aggregated.go index 8d6081f280e3..32d329dd1f4f 100644 --- a/beacon-chain/operations/attestations/kv/aggregated.go +++ b/beacon-chain/operations/attestations/kv/aggregated.go @@ -8,12 +8,12 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" attaggregation "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation/aggregation/attestations" "github.com/prysmaticlabs/prysm/v5/runtime/version" log "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // AggregateUnaggregatedAttestations aggregates the unaggregated attestations and saves the @@ -88,7 +88,7 @@ func (c *AttCaches) aggregateParallel(atts map[attestation.Id][]ethpb.Att, leftO log.Error("nil aggregated attestation") continue } - if helpers.IsAggregated(aggregated) { + if aggregated.IsAggregated() { if err := c.SaveAggregatedAttestations([]ethpb.Att{aggregated}); err != nil { log.WithError(err).Error("could not save aggregated attestation") continue @@ -122,7 +122,7 @@ func (c *AttCaches) SaveAggregatedAttestation(att ethpb.Att) error { if err := helpers.ValidateNilAttestation(att); err != nil { return err } - if !helpers.IsAggregated(att) { + if !att.IsAggregated() { return errors.New("attestation is not aggregated") } has, err := c.HasAggregatedAttestation(att) @@ -236,7 +236,7 @@ func (c *AttCaches) AggregatedAttestationsBySlotIndexElectra( c.aggregatedAttLock.RLock() defer c.aggregatedAttLock.RUnlock() for _, as := range c.aggregatedAtt { - if as[0].Version() == version.Electra && slot == as[0].GetData().Slot && as[0].CommitteeBitsVal().BitAt(uint64(committeeIndex)) { + if as[0].Version() >= version.Electra && slot == as[0].GetData().Slot && as[0].CommitteeBitsVal().BitAt(uint64(committeeIndex)) { for _, a := range as { att, ok := a.(*ethpb.AttestationElectra) // This will never fail in practice because we asserted the version @@ -255,7 +255,7 @@ func (c *AttCaches) DeleteAggregatedAttestation(att ethpb.Att) error { if err := helpers.ValidateNilAttestation(att); err != nil { return err } - if !helpers.IsAggregated(att) { + if !att.IsAggregated() { return errors.New("attestation is not aggregated") } diff --git a/beacon-chain/operations/attestations/kv/aggregated_test.go b/beacon-chain/operations/attestations/kv/aggregated_test.go index adddfb07a434..c107ce30bc23 100644 --- a/beacon-chain/operations/attestations/kv/aggregated_test.go +++ b/beacon-chain/operations/attestations/kv/aggregated_test.go @@ -49,12 +49,12 @@ func TestKV_Aggregated_SaveAggregatedAttestation(t *testing.T) { { name: "nil attestation", att: nil, - wantErrString: "attestation can't be nil", + wantErrString: "attestation is nil", }, { name: "nil attestation data", att: ðpb.Attestation{}, - wantErrString: "attestation's data can't be nil", + wantErrString: "attestation is nil", }, { name: "not aggregated", @@ -206,7 +206,7 @@ func TestKV_Aggregated_AggregatedAttestations(t *testing.T) { func TestKV_Aggregated_DeleteAggregatedAttestation(t *testing.T) { t.Run("nil attestation", func(t *testing.T) { cache := NewAttCaches() - assert.ErrorContains(t, "attestation can't be nil", cache.DeleteAggregatedAttestation(nil)) + assert.ErrorContains(t, "attestation is nil", cache.DeleteAggregatedAttestation(nil)) att := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b10101}, Data: ðpb.AttestationData{Slot: 2}}) assert.NoError(t, cache.DeleteAggregatedAttestation(att)) }) @@ -288,7 +288,7 @@ func TestKV_Aggregated_HasAggregatedAttestation(t *testing.T) { name: "nil attestation", input: nil, want: false, - err: errors.New("can't be nil"), + err: errors.New("is nil"), }, { name: "nil attestation data", @@ -296,7 +296,7 @@ func TestKV_Aggregated_HasAggregatedAttestation(t *testing.T) { AggregationBits: bitfield.Bitlist{0b1111}, }, want: false, - err: errors.New("can't be nil"), + err: errors.New("is nil"), }, { name: "empty cache aggregated", diff --git a/beacon-chain/operations/attestations/kv/block.go b/beacon-chain/operations/attestations/kv/block.go index 5f675bfad201..a9f8515318e7 100644 --- a/beacon-chain/operations/attestations/kv/block.go +++ b/beacon-chain/operations/attestations/kv/block.go @@ -8,7 +8,7 @@ import ( // SaveBlockAttestation saves an block attestation in cache. func (c *AttCaches) SaveBlockAttestation(att ethpb.Att) error { - if att == nil { + if att == nil || att.IsNil() { return nil } @@ -53,10 +53,9 @@ func (c *AttCaches) BlockAttestations() []ethpb.Att { // DeleteBlockAttestation deletes a block attestation in cache. func (c *AttCaches) DeleteBlockAttestation(att ethpb.Att) error { - if att == nil { + if att == nil || att.IsNil() { return nil } - id, err := attestation.NewId(att, attestation.Data) if err != nil { return errors.Wrap(err, "could not create attestation ID") diff --git a/beacon-chain/operations/attestations/kv/forkchoice.go b/beacon-chain/operations/attestations/kv/forkchoice.go deleted file mode 100644 index 26bb0634ccbd..000000000000 --- a/beacon-chain/operations/attestations/kv/forkchoice.go +++ /dev/null @@ -1,74 +0,0 @@ -package kv - -import ( - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" -) - -// SaveForkchoiceAttestation saves an forkchoice attestation in cache. -func (c *AttCaches) SaveForkchoiceAttestation(att ethpb.Att) error { - if att == nil { - return nil - } - - id, err := attestation.NewId(att, attestation.Full) - if err != nil { - return errors.Wrap(err, "could not create attestation ID") - } - - c.forkchoiceAttLock.Lock() - defer c.forkchoiceAttLock.Unlock() - c.forkchoiceAtt[id] = att - - return nil -} - -// SaveForkchoiceAttestations saves a list of forkchoice attestations in cache. -func (c *AttCaches) SaveForkchoiceAttestations(atts []ethpb.Att) error { - for _, att := range atts { - if err := c.SaveForkchoiceAttestation(att); err != nil { - return err - } - } - - return nil -} - -// ForkchoiceAttestations returns the forkchoice attestations in cache. -func (c *AttCaches) ForkchoiceAttestations() []ethpb.Att { - c.forkchoiceAttLock.RLock() - defer c.forkchoiceAttLock.RUnlock() - - atts := make([]ethpb.Att, 0, len(c.forkchoiceAtt)) - for _, att := range c.forkchoiceAtt { - atts = append(atts, att.Clone()) - } - - return atts -} - -// DeleteForkchoiceAttestation deletes a forkchoice attestation in cache. -func (c *AttCaches) DeleteForkchoiceAttestation(att ethpb.Att) error { - if att == nil { - return nil - } - - id, err := attestation.NewId(att, attestation.Full) - if err != nil { - return errors.Wrap(err, "could not create attestation ID") - } - - c.forkchoiceAttLock.Lock() - defer c.forkchoiceAttLock.Unlock() - delete(c.forkchoiceAtt, id) - - return nil -} - -// ForkchoiceAttestationCount returns the number of fork choice attestations key in the pool. -func (c *AttCaches) ForkchoiceAttestationCount() int { - c.forkchoiceAttLock.RLock() - defer c.forkchoiceAttLock.RUnlock() - return len(c.forkchoiceAtt) -} diff --git a/beacon-chain/operations/attestations/kv/forkchoice_test.go b/beacon-chain/operations/attestations/kv/forkchoice_test.go index 7f6b4d4b2ce9..29dd4bf521da 100644 --- a/beacon-chain/operations/attestations/kv/forkchoice_test.go +++ b/beacon-chain/operations/attestations/kv/forkchoice_test.go @@ -20,7 +20,7 @@ func TestKV_Forkchoice_CanSaveRetrieve(t *testing.T) { atts := []ethpb.Att{att1, att2, att3} for _, att := range atts { - require.NoError(t, cache.SaveForkchoiceAttestation(att)) + require.NoError(t, cache.saveForkchoiceAttestation(att)) } returned := cache.ForkchoiceAttestations() @@ -41,7 +41,7 @@ func TestKV_Forkchoice_CanDelete(t *testing.T) { atts := []ethpb.Att{att1, att2, att3} for _, att := range atts { - require.NoError(t, cache.SaveForkchoiceAttestation(att)) + require.NoError(t, cache.saveForkchoiceAttestation(att)) } require.NoError(t, cache.DeleteForkchoiceAttestation(att1)) @@ -61,7 +61,7 @@ func TestKV_Forkchoice_CanCount(t *testing.T) { atts := []*ethpb.Attestation{att1, att2, att3} for _, att := range atts { - require.NoError(t, cache.SaveForkchoiceAttestation(att)) + require.NoError(t, cache.saveForkchoiceAttestation(att)) } require.Equal(t, 3, cache.ForkchoiceAttestationCount()) diff --git a/beacon-chain/operations/attestations/kv/kv.go b/beacon-chain/operations/attestations/kv/kv.go index 981525c1e2e2..9a5894a14239 100644 --- a/beacon-chain/operations/attestations/kv/kv.go +++ b/beacon-chain/operations/attestations/kv/kv.go @@ -8,6 +8,7 @@ import ( "time" "github.com/patrickmn/go-cache" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations/attmap" "github.com/prysmaticlabs/prysm/v5/config/params" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" @@ -21,8 +22,7 @@ type AttCaches struct { aggregatedAtt map[attestation.Id][]ethpb.Att unAggregateAttLock sync.RWMutex unAggregatedAtt map[attestation.Id]ethpb.Att - forkchoiceAttLock sync.RWMutex - forkchoiceAtt map[attestation.Id]ethpb.Att + forkchoiceAtt *attmap.Attestations blockAttLock sync.RWMutex blockAtt map[attestation.Id][]ethpb.Att seenAtt *cache.Cache @@ -36,10 +36,35 @@ func NewAttCaches() *AttCaches { pool := &AttCaches{ unAggregatedAtt: make(map[attestation.Id]ethpb.Att), aggregatedAtt: make(map[attestation.Id][]ethpb.Att), - forkchoiceAtt: make(map[attestation.Id]ethpb.Att), + forkchoiceAtt: attmap.New(), blockAtt: make(map[attestation.Id][]ethpb.Att), seenAtt: c, } return pool } + +// saveForkchoiceAttestation saves a forkchoice attestation. +func (c *AttCaches) saveForkchoiceAttestation(att ethpb.Att) error { + return c.forkchoiceAtt.Save(att) +} + +// SaveForkchoiceAttestations saves forkchoice attestations. +func (c *AttCaches) SaveForkchoiceAttestations(att []ethpb.Att) error { + return c.forkchoiceAtt.SaveMany(att) +} + +// ForkchoiceAttestations returns all forkchoice attestations. +func (c *AttCaches) ForkchoiceAttestations() []ethpb.Att { + return c.forkchoiceAtt.GetAll() +} + +// DeleteForkchoiceAttestation deletes a forkchoice attestation. +func (c *AttCaches) DeleteForkchoiceAttestation(att ethpb.Att) error { + return c.forkchoiceAtt.Delete(att) +} + +// ForkchoiceAttestationCount returns the number of forkchoice attestation keys. +func (c *AttCaches) ForkchoiceAttestationCount() int { + return c.forkchoiceAtt.Count() +} diff --git a/beacon-chain/operations/attestations/kv/unaggregated.go b/beacon-chain/operations/attestations/kv/unaggregated.go index f49f666b561f..bbaabbd306c8 100644 --- a/beacon-chain/operations/attestations/kv/unaggregated.go +++ b/beacon-chain/operations/attestations/kv/unaggregated.go @@ -4,20 +4,19 @@ import ( "context" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" ) // SaveUnaggregatedAttestation saves an unaggregated attestation in cache. func (c *AttCaches) SaveUnaggregatedAttestation(att ethpb.Att) error { - if att == nil { + if att == nil || att.IsNil() { return nil } - if helpers.IsAggregated(att) { + if att.IsAggregated() { return errors.New("attestation is aggregated") } @@ -116,7 +115,7 @@ func (c *AttCaches) UnaggregatedAttestationsBySlotIndexElectra( unAggregatedAtts := c.unAggregatedAtt for _, a := range unAggregatedAtts { - if a.Version() == version.Electra && slot == a.GetData().Slot && a.CommitteeBitsVal().BitAt(uint64(committeeIndex)) { + if a.Version() >= version.Electra && slot == a.GetData().Slot && a.CommitteeBitsVal().BitAt(uint64(committeeIndex)) { att, ok := a.(*ethpb.AttestationElectra) // This will never fail in practice because we asserted the version if ok { @@ -130,10 +129,10 @@ func (c *AttCaches) UnaggregatedAttestationsBySlotIndexElectra( // DeleteUnaggregatedAttestation deletes the unaggregated attestations in cache. func (c *AttCaches) DeleteUnaggregatedAttestation(att ethpb.Att) error { - if att == nil { + if att == nil || att.IsNil() { return nil } - if helpers.IsAggregated(att) { + if att.IsAggregated() { return errors.New("attestation is aggregated") } @@ -161,7 +160,7 @@ func (c *AttCaches) DeleteSeenUnaggregatedAttestations() (int, error) { count := 0 for r, att := range c.unAggregatedAtt { - if att == nil || helpers.IsAggregated(att) { + if att == nil || att.IsNil() || att.IsAggregated() { continue } if seen, err := c.hasSeenBit(att); err == nil && seen { diff --git a/beacon-chain/operations/attestations/metrics.go b/beacon-chain/operations/attestations/metrics.go index d9603781be0e..636f3241fe09 100644 --- a/beacon-chain/operations/attestations/metrics.go +++ b/beacon-chain/operations/attestations/metrics.go @@ -30,6 +30,16 @@ var ( Name: "expired_block_atts_total", Help: "The number of expired and deleted block attestations in the pool.", }) + attCount = promauto.NewGauge( + prometheus.GaugeOpts{ + Name: "attestations_in_pool_total", + Help: "The number of attestations in the pool.", + }, + ) + expiredAtts = promauto.NewCounter(prometheus.CounterOpts{ + Name: "expired_atts_total", + Help: "The number of expired and deleted attestations in the pool.", + }) batchForkChoiceAttsT1 = promauto.NewHistogram( prometheus.HistogramOpts{ Name: "aggregate_attestations_t1", @@ -50,3 +60,8 @@ func (s *Service) updateMetrics() { aggregatedAttsCount.Set(float64(s.cfg.Pool.AggregatedAttestationCount())) unaggregatedAttsCount.Set(float64(s.cfg.Pool.UnaggregatedAttestationCount())) } + +func (s *Service) updateMetricsExperimental(numExpired uint64) { + attCount.Set(float64(s.cfg.Cache.Count())) + expiredAtts.Add(float64(numExpired)) +} diff --git a/beacon-chain/operations/attestations/mock/BUILD.bazel b/beacon-chain/operations/attestations/mock/BUILD.bazel index 1976c31f5e1e..cb20f6379bad 100644 --- a/beacon-chain/operations/attestations/mock/BUILD.bazel +++ b/beacon-chain/operations/attestations/mock/BUILD.bazel @@ -7,6 +7,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations/mock", visibility = ["//visibility:public"], deps = [ + "//beacon-chain/operations/attestations:go_default_library", "//consensus-types/primitives:go_default_library", "//proto/prysm/v1alpha1:go_default_library", ], diff --git a/beacon-chain/operations/attestations/mock/mock.go b/beacon-chain/operations/attestations/mock/mock.go index a4101bbe51ee..5d17ad7878ce 100644 --- a/beacon-chain/operations/attestations/mock/mock.go +++ b/beacon-chain/operations/attestations/mock/mock.go @@ -3,13 +3,17 @@ package mock import ( "context" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) +var _ attestations.Pool = &PoolMock{} + // PoolMock -- type PoolMock struct { - AggregatedAtts []*ethpb.Attestation + AggregatedAtts []ethpb.Att + UnaggregatedAtts []ethpb.Att } // AggregateUnaggregatedAttestations -- @@ -23,18 +27,18 @@ func (*PoolMock) AggregateUnaggregatedAttestationsBySlotIndex(_ context.Context, } // SaveAggregatedAttestation -- -func (*PoolMock) SaveAggregatedAttestation(_ *ethpb.Attestation) error { +func (*PoolMock) SaveAggregatedAttestation(_ ethpb.Att) error { panic("implement me") } // SaveAggregatedAttestations -- -func (m *PoolMock) SaveAggregatedAttestations(atts []*ethpb.Attestation) error { +func (m *PoolMock) SaveAggregatedAttestations(atts []ethpb.Att) error { m.AggregatedAtts = append(m.AggregatedAtts, atts...) return nil } // AggregatedAttestations -- -func (m *PoolMock) AggregatedAttestations() []*ethpb.Attestation { +func (m *PoolMock) AggregatedAttestations() []ethpb.Att { return m.AggregatedAtts } @@ -43,13 +47,18 @@ func (*PoolMock) AggregatedAttestationsBySlotIndex(_ context.Context, _ primitiv panic("implement me") } +// AggregatedAttestationsBySlotIndexElectra -- +func (*PoolMock) AggregatedAttestationsBySlotIndexElectra(_ context.Context, _ primitives.Slot, _ primitives.CommitteeIndex) []*ethpb.AttestationElectra { + panic("implement me") +} + // DeleteAggregatedAttestation -- -func (*PoolMock) DeleteAggregatedAttestation(_ *ethpb.Attestation) error { +func (*PoolMock) DeleteAggregatedAttestation(_ ethpb.Att) error { panic("implement me") } // HasAggregatedAttestation -- -func (*PoolMock) HasAggregatedAttestation(_ *ethpb.Attestation) (bool, error) { +func (*PoolMock) HasAggregatedAttestation(_ ethpb.Att) (bool, error) { panic("implement me") } @@ -59,18 +68,19 @@ func (*PoolMock) AggregatedAttestationCount() int { } // SaveUnaggregatedAttestation -- -func (*PoolMock) SaveUnaggregatedAttestation(_ *ethpb.Attestation) error { +func (*PoolMock) SaveUnaggregatedAttestation(_ ethpb.Att) error { panic("implement me") } // SaveUnaggregatedAttestations -- -func (*PoolMock) SaveUnaggregatedAttestations(_ []*ethpb.Attestation) error { - panic("implement me") +func (m *PoolMock) SaveUnaggregatedAttestations(atts []ethpb.Att) error { + m.UnaggregatedAtts = append(m.UnaggregatedAtts, atts...) + return nil } // UnaggregatedAttestations -- -func (*PoolMock) UnaggregatedAttestations() ([]*ethpb.Attestation, error) { - panic("implement me") +func (m *PoolMock) UnaggregatedAttestations() ([]ethpb.Att, error) { + return m.UnaggregatedAtts, nil } // UnaggregatedAttestationsBySlotIndex -- @@ -78,8 +88,13 @@ func (*PoolMock) UnaggregatedAttestationsBySlotIndex(_ context.Context, _ primit panic("implement me") } +// UnaggregatedAttestationsBySlotIndexElectra -- +func (*PoolMock) UnaggregatedAttestationsBySlotIndexElectra(_ context.Context, _ primitives.Slot, _ primitives.CommitteeIndex) []*ethpb.AttestationElectra { + panic("implement me") +} + // DeleteUnaggregatedAttestation -- -func (*PoolMock) DeleteUnaggregatedAttestation(_ *ethpb.Attestation) error { +func (*PoolMock) DeleteUnaggregatedAttestation(_ ethpb.Att) error { panic("implement me") } @@ -94,42 +109,42 @@ func (*PoolMock) UnaggregatedAttestationCount() int { } // SaveBlockAttestation -- -func (*PoolMock) SaveBlockAttestation(_ *ethpb.Attestation) error { +func (*PoolMock) SaveBlockAttestation(_ ethpb.Att) error { panic("implement me") } // SaveBlockAttestations -- -func (*PoolMock) SaveBlockAttestations(_ []*ethpb.Attestation) error { +func (*PoolMock) SaveBlockAttestations(_ []ethpb.Att) error { panic("implement me") } // BlockAttestations -- -func (*PoolMock) BlockAttestations() []*ethpb.Attestation { +func (*PoolMock) BlockAttestations() []ethpb.Att { panic("implement me") } // DeleteBlockAttestation -- -func (*PoolMock) DeleteBlockAttestation(_ *ethpb.Attestation) error { +func (*PoolMock) DeleteBlockAttestation(_ ethpb.Att) error { panic("implement me") } // SaveForkchoiceAttestation -- -func (*PoolMock) SaveForkchoiceAttestation(_ *ethpb.Attestation) error { +func (*PoolMock) SaveForkchoiceAttestation(_ ethpb.Att) error { panic("implement me") } // SaveForkchoiceAttestations -- -func (*PoolMock) SaveForkchoiceAttestations(_ []*ethpb.Attestation) error { +func (*PoolMock) SaveForkchoiceAttestations(_ []ethpb.Att) error { panic("implement me") } // ForkchoiceAttestations -- -func (*PoolMock) ForkchoiceAttestations() []*ethpb.Attestation { +func (*PoolMock) ForkchoiceAttestations() []ethpb.Att { panic("implement me") } // DeleteForkchoiceAttestation -- -func (*PoolMock) DeleteForkchoiceAttestation(_ *ethpb.Attestation) error { +func (*PoolMock) DeleteForkchoiceAttestation(_ ethpb.Att) error { panic("implement me") } diff --git a/beacon-chain/operations/attestations/pool.go b/beacon-chain/operations/attestations/pool.go index 41cf0706c0af..66b02fae0786 100644 --- a/beacon-chain/operations/attestations/pool.go +++ b/beacon-chain/operations/attestations/pool.go @@ -37,7 +37,6 @@ type Pool interface { BlockAttestations() []ethpb.Att DeleteBlockAttestation(att ethpb.Att) error // For attestations to be passed to fork choice. - SaveForkchoiceAttestation(att ethpb.Att) error SaveForkchoiceAttestations(atts []ethpb.Att) error ForkchoiceAttestations() []ethpb.Att DeleteForkchoiceAttestation(att ethpb.Att) error diff --git a/beacon-chain/operations/attestations/prepare_forkchoice.go b/beacon-chain/operations/attestations/prepare_forkchoice.go index 7eef4065c62f..ffc81609d24f 100644 --- a/beacon-chain/operations/attestations/prepare_forkchoice.go +++ b/beacon-chain/operations/attestations/prepare_forkchoice.go @@ -9,11 +9,11 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" attaggregation "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation/aggregation/attestations" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // This prepares fork choice attestations by running batchForkChoiceAtts @@ -61,11 +61,16 @@ func (s *Service) batchForkChoiceAtts(ctx context.Context) error { ctx, span := trace.StartSpan(ctx, "Operations.attestations.batchForkChoiceAtts") defer span.End() - if err := s.cfg.Pool.AggregateUnaggregatedAttestations(ctx); err != nil { - return err + var atts []ethpb.Att + if features.Get().EnableExperimentalAttestationPool { + atts = append(s.cfg.Cache.GetAll(), s.cfg.Cache.ForkchoiceAttestations()...) + } else { + if err := s.cfg.Pool.AggregateUnaggregatedAttestations(ctx); err != nil { + return err + } + atts = append(s.cfg.Pool.AggregatedAttestations(), s.cfg.Pool.BlockAttestations()...) + atts = append(atts, s.cfg.Pool.ForkchoiceAttestations()...) } - atts := append(s.cfg.Pool.AggregatedAttestations(), s.cfg.Pool.BlockAttestations()...) - atts = append(atts, s.cfg.Pool.ForkchoiceAttestations()...) attsById := make(map[attestation.Id][]ethpb.Att, len(atts)) @@ -92,9 +97,11 @@ func (s *Service) batchForkChoiceAtts(ctx context.Context) error { } } - for _, a := range s.cfg.Pool.BlockAttestations() { - if err := s.cfg.Pool.DeleteBlockAttestation(a); err != nil { - return err + if !features.Get().EnableExperimentalAttestationPool { + for _, a := range s.cfg.Pool.BlockAttestations() { + if err := s.cfg.Pool.DeleteBlockAttestation(a); err != nil { + return err + } } } diff --git a/beacon-chain/operations/attestations/prune_expired.go b/beacon-chain/operations/attestations/prune_expired.go index 5bbe29c77fbc..326f33f52653 100644 --- a/beacon-chain/operations/attestations/prune_expired.go +++ b/beacon-chain/operations/attestations/prune_expired.go @@ -9,8 +9,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/time/slots" ) -// pruneAttsPool prunes attestations pool on every slot interval. -func (s *Service) pruneAttsPool() { +// pruneExpired prunes attestations pool on every slot interval. +func (s *Service) pruneExpired() { ticker := time.NewTicker(s.cfg.pruneInterval) defer ticker.Stop() for { @@ -25,6 +25,27 @@ func (s *Service) pruneAttsPool() { } } +// pruneExpiredExperimental prunes attestations on every prune interval. +func (s *Service) pruneExpiredExperimental() { + ticker := time.NewTicker(s.cfg.pruneInterval) + defer ticker.Stop() + for { + select { + case <-ticker.C: + expirySlot, err := s.expirySlot() + if err != nil { + log.WithError(err).Error("Could not get expiry slot") + continue + } + numExpired := s.cfg.Cache.PruneBefore(expirySlot) + s.updateMetricsExperimental(numExpired) + case <-s.ctx.Done(): + log.Debug("Context closed, exiting routine") + return + } + } +} + // This prunes expired attestations from the pool. func (s *Service) pruneExpiredAtts() { aggregatedAtts := s.cfg.Pool.AggregatedAttestations() @@ -84,3 +105,17 @@ func (s *Service) expiredPreDeneb(slot primitives.Slot) bool { currentTime := uint64(prysmTime.Now().Unix()) return currentTime >= expirationTime } + +// Attestations for a slot before the returned slot are considered expired. +func (s *Service) expirySlot() (primitives.Slot, error) { + currSlot := slots.CurrentSlot(s.genesisTime) + currEpoch := slots.ToEpoch(currSlot) + if currEpoch == 0 { + return 0, nil + } + if currEpoch < params.BeaconConfig().DenebForkEpoch { + // Safe to subtract because we exited early for epoch 0. + return currSlot - 31, nil + } + return slots.EpochStart(currEpoch - 1) +} diff --git a/beacon-chain/operations/attestations/prune_expired_test.go b/beacon-chain/operations/attestations/prune_expired_test.go index 0755eadf3a4e..bb4b346579d7 100644 --- a/beacon-chain/operations/attestations/prune_expired_test.go +++ b/beacon-chain/operations/attestations/prune_expired_test.go @@ -50,7 +50,7 @@ func TestPruneExpired_Ticker(t *testing.T) { // Rewind back one epoch worth of time. s.genesisTime = uint64(prysmTime.Now().Unix()) - uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot)) - go s.pruneAttsPool() + go s.pruneExpired() done := make(chan struct{}, 1) async.RunEvery(ctx, 500*time.Millisecond, func() { @@ -145,5 +145,4 @@ func TestPruneExpired_ExpiredDeneb(t *testing.T) { assert.Equal(t, true, s.expired(secondEpochStart), "Should be expired") assert.Equal(t, false, s.expired(thirdEpochStart), "Should not be expired") - } diff --git a/beacon-chain/operations/attestations/service.go b/beacon-chain/operations/attestations/service.go index 8dd57e995a23..9f5ef9eed4ca 100644 --- a/beacon-chain/operations/attestations/service.go +++ b/beacon-chain/operations/attestations/service.go @@ -9,7 +9,9 @@ import ( "time" lru "github.com/hashicorp/golang-lru" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" ) @@ -27,12 +29,13 @@ type Service struct { // Config options for the service. type Config struct { + Cache *cache.AttestationCache Pool Pool pruneInterval time.Duration InitialSyncComplete chan struct{} } -// NewService instantiates a new attestation pool service instance that will +// NewService instantiates a new attestation service instance that will // be registered into a running beacon node. func NewService(ctx context.Context, cfg *Config) (*Service, error) { cache := lruwrpr.New(forkChoiceProcessedAttsSize) @@ -58,7 +61,12 @@ func (s *Service) Start() { return } go s.prepareForkChoiceAtts() - go s.pruneAttsPool() + + if features.Get().EnableExperimentalAttestationPool { + go s.pruneExpiredExperimental() + } else { + go s.pruneExpired() + } } // waitForSync waits until the beacon node is synced to the latest head. diff --git a/beacon-chain/operations/slashings/BUILD.bazel b/beacon-chain/operations/slashings/BUILD.bazel index e8d40e847377..4eca5ce0f58e 100644 --- a/beacon-chain/operations/slashings/BUILD.bazel +++ b/beacon-chain/operations/slashings/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "doc.go", "log.go", "metrics.go", + "pool.go", "service.go", "types.go", ], @@ -19,17 +20,20 @@ go_library( "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", + "//beacon-chain/startup:go_default_library", "//beacon-chain/state:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//container/slice:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", + "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_trailofbits_go_mutexasserts//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -38,18 +42,21 @@ go_test( size = "small", srcs = [ "service_attester_test.go", + "service_new_test.go", "service_proposer_test.go", "service_test.go", ], embed = [":go_default_library"], deps = [ "//beacon-chain/operations/slashings/mock:go_default_library", + "//beacon-chain/startup:go_default_library", "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//crypto/bls:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", diff --git a/beacon-chain/operations/slashings/mock/mock.go b/beacon-chain/operations/slashings/mock/mock.go index b30747a0a4f8..85e4a910cdd0 100644 --- a/beacon-chain/operations/slashings/mock/mock.go +++ b/beacon-chain/operations/slashings/mock/mock.go @@ -35,6 +35,9 @@ func (m *PoolMock) InsertProposerSlashing(_ context.Context, _ state.ReadOnlyBea return nil } +// ConvertToElectra -- +func (*PoolMock) ConvertToElectra() {} + // MarkIncludedAttesterSlashing -- func (*PoolMock) MarkIncludedAttesterSlashing(_ ethpb.AttSlashing) { panic("implement me") diff --git a/beacon-chain/operations/slashings/pool.go b/beacon-chain/operations/slashings/pool.go new file mode 100644 index 000000000000..e315bbf55d21 --- /dev/null +++ b/beacon-chain/operations/slashings/pool.go @@ -0,0 +1,324 @@ +package slashings + +import ( + "context" + "fmt" + "sort" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + coretime "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/container/slice" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/trailofbits/go-mutexasserts" +) + +// NewPool returns an initialized attester slashing and proposer slashing pool. +func NewPool() *Pool { + return &Pool{ + pendingProposerSlashing: make([]*ethpb.ProposerSlashing, 0), + pendingAttesterSlashing: make([]*PendingAttesterSlashing, 0), + included: make(map[primitives.ValidatorIndex]bool), + } +} + +// PendingAttesterSlashings returns attester slashings that are able to be included into a block. +// This method will return the amount of pending attester slashings for a block transition unless parameter `noLimit` is true +// to indicate the request is for noLimit pending items. +func (p *Pool) PendingAttesterSlashings(ctx context.Context, state state.ReadOnlyBeaconState, noLimit bool) []ethpb.AttSlashing { + p.lock.Lock() + defer p.lock.Unlock() + _, span := trace.StartSpan(ctx, "operations.PendingAttesterSlashing") + defer span.End() + + // Update prom metric. + numPendingAttesterSlashings.Set(float64(len(p.pendingAttesterSlashing))) + + included := make(map[primitives.ValidatorIndex]bool) + + // Allocate pending slice with a capacity of maxAttesterSlashings or len(p.pendingAttesterSlashing)) depending on the request. + maxSlashings := params.BeaconConfig().MaxAttesterSlashings + + // EIP-7549: Beginning from Electra, the max attester slashings is reduced to 1. + if state.Version() >= version.Electra { + maxSlashings = params.BeaconConfig().MaxAttesterSlashingsElectra + } + if noLimit { + maxSlashings = uint64(len(p.pendingAttesterSlashing)) + } + pending := make([]ethpb.AttSlashing, 0, maxSlashings) + for i := 0; i < len(p.pendingAttesterSlashing); i++ { + if uint64(len(pending)) >= maxSlashings { + break + } + slashing := p.pendingAttesterSlashing[i] + valid, err := p.validatorSlashingPreconditionCheck(state, slashing.validatorToSlash) + if err != nil { + log.WithError(err).Error("could not validate attester slashing") + continue + } + if included[slashing.validatorToSlash] || !valid { + p.pendingAttesterSlashing = append(p.pendingAttesterSlashing[:i], p.pendingAttesterSlashing[i+1:]...) + i-- + continue + } + attSlashing := slashing.attesterSlashing + slashedVal := slice.IntersectionUint64( + attSlashing.FirstAttestation().GetAttestingIndices(), + attSlashing.SecondAttestation().GetAttestingIndices(), + ) + for _, idx := range slashedVal { + included[primitives.ValidatorIndex(idx)] = true + } + + pending = append(pending, attSlashing) + } + + return pending +} + +// PendingProposerSlashings returns proposer slashings that are able to be included into a block. +// This method will return the amount of pending proposer slashings for a block transition unless the `noLimit` parameter +// is set to true to indicate the request is for noLimit pending items. +func (p *Pool) PendingProposerSlashings(ctx context.Context, state state.ReadOnlyBeaconState, noLimit bool) []*ethpb.ProposerSlashing { + p.lock.Lock() + defer p.lock.Unlock() + _, span := trace.StartSpan(ctx, "operations.PendingProposerSlashing") + defer span.End() + + // Update prom metric. + numPendingProposerSlashings.Set(float64(len(p.pendingProposerSlashing))) + + // Allocate pending slice with a capacity of len(p.pendingProposerSlashing) or maxProposerSlashings depending on the request. + maxSlashings := params.BeaconConfig().MaxProposerSlashings + if noLimit { + maxSlashings = uint64(len(p.pendingProposerSlashing)) + } + pending := make([]*ethpb.ProposerSlashing, 0, maxSlashings) + for i := 0; i < len(p.pendingProposerSlashing); i++ { + if uint64(len(pending)) >= maxSlashings { + break + } + slashing := p.pendingProposerSlashing[i] + valid, err := p.validatorSlashingPreconditionCheck(state, slashing.Header_1.Header.ProposerIndex) + if err != nil { + log.WithError(err).Error("could not validate proposer slashing") + continue + } + if !valid { + p.pendingProposerSlashing = append(p.pendingProposerSlashing[:i], p.pendingProposerSlashing[i+1:]...) + i-- + continue + } + + pending = append(pending, slashing) + } + return pending +} + +// InsertAttesterSlashing into the pool. This method is a no-op if the attester slashing already exists in the pool, +// has been included into a block recently, or the validator is already exited. +func (p *Pool) InsertAttesterSlashing( + ctx context.Context, + state state.ReadOnlyBeaconState, + slashing ethpb.AttSlashing, +) error { + p.lock.Lock() + defer p.lock.Unlock() + ctx, span := trace.StartSpan(ctx, "operations.InsertAttesterSlashing") + defer span.End() + + if err := blocks.VerifyAttesterSlashing(ctx, state, slashing); err != nil { + return errors.Wrap(err, "could not verify attester slashing") + } + + slashedVal := slice.IntersectionUint64(slashing.FirstAttestation().GetAttestingIndices(), slashing.SecondAttestation().GetAttestingIndices()) + cantSlash := make([]uint64, 0, len(slashedVal)) + slashingReason := "" + for _, val := range slashedVal { + // Has this validator index been included recently? + ok, err := p.validatorSlashingPreconditionCheck(state, primitives.ValidatorIndex(val)) + if err != nil { + return err + } + // If the validator has already exited, has already been slashed, or if its index + // has been recently included in the pool of slashings, skip including this indice. + if !ok { + slashingReason = "validator already exited/slashed or already recently included in slashings pool" + cantSlash = append(cantSlash, val) + continue + } + + // Check if the validator already exists in the list of slashings. + // Use binary search to find the answer. + found := sort.Search(len(p.pendingAttesterSlashing), func(i int) bool { + return uint64(p.pendingAttesterSlashing[i].validatorToSlash) >= val + }) + if found != len(p.pendingAttesterSlashing) && uint64(p.pendingAttesterSlashing[found].validatorToSlash) == val { + slashingReason = "validator already exist in list of pending slashings, no need to attempt to slash again" + cantSlash = append(cantSlash, val) + continue + } + + pendingSlashing := &PendingAttesterSlashing{ + attesterSlashing: slashing, + validatorToSlash: primitives.ValidatorIndex(val), + } + // Insert into pending list and sort again. + p.pendingAttesterSlashing = append(p.pendingAttesterSlashing, pendingSlashing) + sort.Slice(p.pendingAttesterSlashing, func(i, j int) bool { + return p.pendingAttesterSlashing[i].validatorToSlash < p.pendingAttesterSlashing[j].validatorToSlash + }) + numPendingAttesterSlashings.Set(float64(len(p.pendingAttesterSlashing))) + } + if len(cantSlash) == len(slashedVal) { + return fmt.Errorf( + "could not slash any of %d validators in submitted slashing: %s", + len(slashedVal), + slashingReason, + ) + } + return nil +} + +// InsertProposerSlashing into the pool. This method is a no-op if the pending slashing already exists, +// has been included recently, the validator is already exited, or the validator was already slashed. +func (p *Pool) InsertProposerSlashing( + ctx context.Context, + state state.ReadOnlyBeaconState, + slashing *ethpb.ProposerSlashing, +) error { + p.lock.Lock() + defer p.lock.Unlock() + _, span := trace.StartSpan(ctx, "operations.InsertProposerSlashing") + defer span.End() + + if err := blocks.VerifyProposerSlashing(state, slashing); err != nil { + return errors.Wrap(err, "could not verify proposer slashing") + } + + idx := slashing.Header_1.Header.ProposerIndex + ok, err := p.validatorSlashingPreconditionCheck(state, idx) + if err != nil { + return err + } + // If the validator has already exited, has already been slashed, or if its index + // has been recently included in the pool of slashings, do not process this new + // slashing. + if !ok { + return fmt.Errorf("validator at index %d cannot be slashed", idx) + } + + // Check if the validator already exists in the list of slashings. + // Use binary search to find the answer. + found := sort.Search(len(p.pendingProposerSlashing), func(i int) bool { + return p.pendingProposerSlashing[i].Header_1.Header.ProposerIndex >= slashing.Header_1.Header.ProposerIndex + }) + if found != len(p.pendingProposerSlashing) && p.pendingProposerSlashing[found].Header_1.Header.ProposerIndex == + slashing.Header_1.Header.ProposerIndex { + return errors.New("slashing object already exists in pending proposer slashings") + } + + // Insert into pending list and sort again. + p.pendingProposerSlashing = append(p.pendingProposerSlashing, slashing) + sort.Slice(p.pendingProposerSlashing, func(i, j int) bool { + return p.pendingProposerSlashing[i].Header_1.Header.ProposerIndex < p.pendingProposerSlashing[j].Header_1.Header.ProposerIndex + }) + numPendingProposerSlashings.Set(float64(len(p.pendingProposerSlashing))) + + return nil +} + +// MarkIncludedAttesterSlashing is used when an attester slashing has been included in a beacon block. +// Every block seen by this node that contains proposer slashings should call this method to include +// the proposer slashings. +func (p *Pool) MarkIncludedAttesterSlashing(as ethpb.AttSlashing) { + p.lock.Lock() + defer p.lock.Unlock() + slashedVal := slice.IntersectionUint64(as.FirstAttestation().GetAttestingIndices(), as.SecondAttestation().GetAttestingIndices()) + for _, val := range slashedVal { + i := sort.Search(len(p.pendingAttesterSlashing), func(i int) bool { + return uint64(p.pendingAttesterSlashing[i].validatorToSlash) >= val + }) + if i != len(p.pendingAttesterSlashing) && uint64(p.pendingAttesterSlashing[i].validatorToSlash) == val { + p.pendingAttesterSlashing = append(p.pendingAttesterSlashing[:i], p.pendingAttesterSlashing[i+1:]...) + } + p.included[primitives.ValidatorIndex(val)] = true + numAttesterSlashingsIncluded.Inc() + } +} + +// MarkIncludedProposerSlashing is used when an proposer slashing has been included in a beacon block. +// Every block seen by this node that contains proposer slashings should call this method to include +// the proposer slashings. +func (p *Pool) MarkIncludedProposerSlashing(ps *ethpb.ProposerSlashing) { + p.lock.Lock() + defer p.lock.Unlock() + i := sort.Search(len(p.pendingProposerSlashing), func(i int) bool { + return p.pendingProposerSlashing[i].Header_1.Header.ProposerIndex >= ps.Header_1.Header.ProposerIndex + }) + if i != len(p.pendingProposerSlashing) && p.pendingProposerSlashing[i].Header_1.Header.ProposerIndex == ps.Header_1.Header.ProposerIndex { + p.pendingProposerSlashing = append(p.pendingProposerSlashing[:i], p.pendingProposerSlashing[i+1:]...) + } + p.included[ps.Header_1.Header.ProposerIndex] = true + numProposerSlashingsIncluded.Inc() +} + +// ConvertToElectra converts all Phase0 attester slashings to Electra attester slashings. +// This functionality is needed at the time of the Electra fork. +func (p *Pool) ConvertToElectra() { + p.lock.Lock() + defer p.lock.Unlock() + + for _, pas := range p.pendingAttesterSlashing { + if pas.attesterSlashing.Version() == version.Phase0 { + first := pas.attesterSlashing.FirstAttestation() + second := pas.attesterSlashing.SecondAttestation() + pas.attesterSlashing = ðpb.AttesterSlashingElectra{ + Attestation_1: ðpb.IndexedAttestationElectra{ + AttestingIndices: first.GetAttestingIndices(), + Data: first.GetData(), + Signature: first.GetSignature(), + }, + Attestation_2: ðpb.IndexedAttestationElectra{ + AttestingIndices: second.GetAttestingIndices(), + Data: second.GetData(), + Signature: second.GetSignature(), + }, + } + } + } +} + +// this function checks a few items about a validator before proceeding with inserting +// a proposer/attester slashing into the pool. First, it checks if the validator +// has been recently included in the pool, then it checks if the validator is slashable. +// Note: this method requires caller to hold the lock. +func (p *Pool) validatorSlashingPreconditionCheck( + state state.ReadOnlyBeaconState, + valIdx primitives.ValidatorIndex, +) (bool, error) { + if !mutexasserts.RWMutexLocked(&p.lock) && !mutexasserts.RWMutexRLocked(&p.lock) { + return false, errors.New("pool.validatorSlashingPreconditionCheck: caller must hold read/write lock") + } + + // Check if the validator index has been included recently. + if p.included[valIdx] { + return false, nil + } + validator, err := state.ValidatorAtIndexReadOnly(valIdx) + if err != nil { + return false, err + } + // Checking if the validator is slashable. + if !helpers.IsSlashableValidatorUsingTrie(validator, coretime.CurrentEpoch(state)) { + return false, nil + } + return true, nil +} diff --git a/beacon-chain/operations/slashings/service.go b/beacon-chain/operations/slashings/service.go index ef7370975efa..c6ef2097bedf 100644 --- a/beacon-chain/operations/slashings/service.go +++ b/beacon-chain/operations/slashings/service.go @@ -2,291 +2,102 @@ package slashings import ( "context" - "fmt" - "sort" + "time" - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/container/slice" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/trailofbits/go-mutexasserts" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/time/slots" ) -// NewPool returns an initialized attester slashing and proposer slashing pool. -func NewPool() *Pool { - return &Pool{ - pendingProposerSlashing: make([]*ethpb.ProposerSlashing, 0), - pendingAttesterSlashing: make([]*PendingAttesterSlashing, 0), - included: make(map[primitives.ValidatorIndex]bool), +// WithElectraTimer includes functional options for the blockchain service related to CLI flags. +func WithElectraTimer(cw startup.ClockWaiter, currentSlotFn func() primitives.Slot) Option { + return func(p *PoolService) error { + p.runElectraTimer = true + p.cw = cw + p.currentSlotFn = currentSlotFn + return nil } } -// PendingAttesterSlashings returns attester slashings that are able to be included into a block. -// This method will return the amount of pending attester slashings for a block transition unless parameter `noLimit` is true -// to indicate the request is for noLimit pending items. -func (p *Pool) PendingAttesterSlashings(ctx context.Context, state state.ReadOnlyBeaconState, noLimit bool) []ethpb.AttSlashing { - p.lock.Lock() - defer p.lock.Unlock() - _, span := trace.StartSpan(ctx, "operations.PendingAttesterSlashing") - defer span.End() - - // Update prom metric. - numPendingAttesterSlashings.Set(float64(len(p.pendingAttesterSlashing))) - - included := make(map[primitives.ValidatorIndex]bool) - - // Allocate pending slice with a capacity of maxAttesterSlashings or len(p.pendingAttesterSlashing)) depending on the request. - maxSlashings := params.BeaconConfig().MaxAttesterSlashings - if noLimit { - maxSlashings = uint64(len(p.pendingAttesterSlashing)) +// NewPoolService returns a service that manages the Pool. +func NewPoolService(ctx context.Context, pool PoolManager, opts ...Option) *PoolService { + ctx, cancel := context.WithCancel(ctx) + p := &PoolService{ + ctx: ctx, + cancel: cancel, + poolManager: pool, } - pending := make([]ethpb.AttSlashing, 0, maxSlashings) - for i := 0; i < len(p.pendingAttesterSlashing); i++ { - if uint64(len(pending)) >= maxSlashings { - break - } - slashing := p.pendingAttesterSlashing[i] - valid, err := p.validatorSlashingPreconditionCheck(state, slashing.validatorToSlash) - if err != nil { - log.WithError(err).Error("could not validate attester slashing") - continue - } - if included[slashing.validatorToSlash] || !valid { - p.pendingAttesterSlashing = append(p.pendingAttesterSlashing[:i], p.pendingAttesterSlashing[i+1:]...) - i-- - continue - } - attSlashing := slashing.attesterSlashing - slashedVal := slice.IntersectionUint64( - attSlashing.FirstAttestation().GetAttestingIndices(), - attSlashing.SecondAttestation().GetAttestingIndices(), - ) - for _, idx := range slashedVal { - included[primitives.ValidatorIndex(idx)] = true - } - pending = append(pending, attSlashing) + for _, opt := range opts { + if err := opt(p); err != nil { + return nil + } } - return pending + return p } -// PendingProposerSlashings returns proposer slashings that are able to be included into a block. -// This method will return the amount of pending proposer slashings for a block transition unless the `noLimit` parameter -// is set to true to indicate the request is for noLimit pending items. -func (p *Pool) PendingProposerSlashings(ctx context.Context, state state.ReadOnlyBeaconState, noLimit bool) []*ethpb.ProposerSlashing { - p.lock.Lock() - defer p.lock.Unlock() - _, span := trace.StartSpan(ctx, "operations.PendingProposerSlashing") - defer span.End() - - // Update prom metric. - numPendingProposerSlashings.Set(float64(len(p.pendingProposerSlashing))) - - // Allocate pending slice with a capacity of len(p.pendingProposerSlashing) or maxProposerSlashings depending on the request. - maxSlashings := params.BeaconConfig().MaxProposerSlashings - if noLimit { - maxSlashings = uint64(len(p.pendingProposerSlashing)) - } - pending := make([]*ethpb.ProposerSlashing, 0, maxSlashings) - for i := 0; i < len(p.pendingProposerSlashing); i++ { - if uint64(len(pending)) >= maxSlashings { - break - } - slashing := p.pendingProposerSlashing[i] - valid, err := p.validatorSlashingPreconditionCheck(state, slashing.Header_1.Header.ProposerIndex) - if err != nil { - log.WithError(err).Error("could not validate proposer slashing") - continue - } - if !valid { - p.pendingProposerSlashing = append(p.pendingProposerSlashing[:i], p.pendingProposerSlashing[i+1:]...) - i-- - continue - } - - pending = append(pending, slashing) - } - return pending +// Start the slashing pool service. +func (p *PoolService) Start() { + go p.run() } -// InsertAttesterSlashing into the pool. This method is a no-op if the attester slashing already exists in the pool, -// has been included into a block recently, or the validator is already exited. -func (p *Pool) InsertAttesterSlashing( - ctx context.Context, - state state.ReadOnlyBeaconState, - slashing ethpb.AttSlashing, -) error { - p.lock.Lock() - defer p.lock.Unlock() - ctx, span := trace.StartSpan(ctx, "operations.InsertAttesterSlashing") - defer span.End() - - if err := blocks.VerifyAttesterSlashing(ctx, state, slashing); err != nil { - return errors.Wrap(err, "could not verify attester slashing") +func (p *PoolService) run() { + if !p.runElectraTimer { + return } - slashedVal := slice.IntersectionUint64(slashing.FirstAttestation().GetAttestingIndices(), slashing.SecondAttestation().GetAttestingIndices()) - cantSlash := make([]uint64, 0, len(slashedVal)) - slashingReason := "" - for _, val := range slashedVal { - // Has this validator index been included recently? - ok, err := p.validatorSlashingPreconditionCheck(state, primitives.ValidatorIndex(val)) - if err != nil { - return err - } - // If the validator has already exited, has already been slashed, or if its index - // has been recently included in the pool of slashings, skip including this indice. - if !ok { - slashingReason = "validator already exited/slashed or already recently included in slashings pool" - cantSlash = append(cantSlash, val) - continue - } - - // Check if the validator already exists in the list of slashings. - // Use binary search to find the answer. - found := sort.Search(len(p.pendingAttesterSlashing), func(i int) bool { - return uint64(p.pendingAttesterSlashing[i].validatorToSlash) >= val - }) - if found != len(p.pendingAttesterSlashing) && uint64(p.pendingAttesterSlashing[found].validatorToSlash) == val { - slashingReason = "validator already exist in list of pending slashings, no need to attempt to slash again" - cantSlash = append(cantSlash, val) - continue - } - - pendingSlashing := &PendingAttesterSlashing{ - attesterSlashing: slashing, - validatorToSlash: primitives.ValidatorIndex(val), - } - // Insert into pending list and sort again. - p.pendingAttesterSlashing = append(p.pendingAttesterSlashing, pendingSlashing) - sort.Slice(p.pendingAttesterSlashing, func(i, j int) bool { - return p.pendingAttesterSlashing[i].validatorToSlash < p.pendingAttesterSlashing[j].validatorToSlash - }) - numPendingAttesterSlashings.Set(float64(len(p.pendingAttesterSlashing))) - } - if len(cantSlash) == len(slashedVal) { - return fmt.Errorf( - "could not slash any of %d validators in submitted slashing: %s", - len(slashedVal), - slashingReason, - ) + electraSlot, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch) + if err != nil { + return } - return nil -} - -// InsertProposerSlashing into the pool. This method is a no-op if the pending slashing already exists, -// has been included recently, the validator is already exited, or the validator was already slashed. -func (p *Pool) InsertProposerSlashing( - ctx context.Context, - state state.ReadOnlyBeaconState, - slashing *ethpb.ProposerSlashing, -) error { - p.lock.Lock() - defer p.lock.Unlock() - _, span := trace.StartSpan(ctx, "operations.InsertProposerSlashing") - defer span.End() - if err := blocks.VerifyProposerSlashing(state, slashing); err != nil { - return errors.Wrap(err, "could not verify proposer slashing") + // If run() is executed after the transition to Electra has already happened, + // there is nothing to convert because the slashing pool is empty at startup. + if p.currentSlotFn() >= electraSlot { + return } - idx := slashing.Header_1.Header.ProposerIndex - ok, err := p.validatorSlashingPreconditionCheck(state, idx) - if err != nil { - return err - } - // If the validator has already exited, has already been slashed, or if its index - // has been recently included in the pool of slashings, do not process this new - // slashing. - if !ok { - return fmt.Errorf("validator at index %d cannot be slashed", idx) - } + p.waitForChainInitialization() - // Check if the validator already exists in the list of slashings. - // Use binary search to find the answer. - found := sort.Search(len(p.pendingProposerSlashing), func(i int) bool { - return p.pendingProposerSlashing[i].Header_1.Header.ProposerIndex >= slashing.Header_1.Header.ProposerIndex - }) - if found != len(p.pendingProposerSlashing) && p.pendingProposerSlashing[found].Header_1.Header.ProposerIndex == - slashing.Header_1.Header.ProposerIndex { - return errors.New("slashing object already exists in pending proposer slashings") + electraTime, err := slots.ToTime(uint64(p.clock.GenesisTime().Unix()), electraSlot) + if err != nil { + return } - // Insert into pending list and sort again. - p.pendingProposerSlashing = append(p.pendingProposerSlashing, slashing) - sort.Slice(p.pendingProposerSlashing, func(i, j int) bool { - return p.pendingProposerSlashing[i].Header_1.Header.ProposerIndex < p.pendingProposerSlashing[j].Header_1.Header.ProposerIndex - }) - numPendingProposerSlashings.Set(float64(len(p.pendingProposerSlashing))) - - return nil -} + t := time.NewTimer(electraTime.Sub(p.clock.Now())) + defer t.Stop() -// MarkIncludedAttesterSlashing is used when an attester slashing has been included in a beacon block. -// Every block seen by this node that contains proposer slashings should call this method to include -// the proposer slashings. -func (p *Pool) MarkIncludedAttesterSlashing(as ethpb.AttSlashing) { - p.lock.Lock() - defer p.lock.Unlock() - slashedVal := slice.IntersectionUint64(as.FirstAttestation().GetAttestingIndices(), as.SecondAttestation().GetAttestingIndices()) - for _, val := range slashedVal { - i := sort.Search(len(p.pendingAttesterSlashing), func(i int) bool { - return uint64(p.pendingAttesterSlashing[i].validatorToSlash) >= val - }) - if i != len(p.pendingAttesterSlashing) && uint64(p.pendingAttesterSlashing[i].validatorToSlash) == val { - p.pendingAttesterSlashing = append(p.pendingAttesterSlashing[:i], p.pendingAttesterSlashing[i+1:]...) - } - p.included[primitives.ValidatorIndex(val)] = true - numAttesterSlashingsIncluded.Inc() + select { + case <-t.C: + log.Info("Converting Phase0 slashings to Electra slashings") + p.poolManager.ConvertToElectra() + return + case <-p.ctx.Done(): + log.Warn("Context cancelled, ConvertToElectra timer will not execute") + return } } -// MarkIncludedProposerSlashing is used when an proposer slashing has been included in a beacon block. -// Every block seen by this node that contains proposer slashings should call this method to include -// the proposer slashings. -func (p *Pool) MarkIncludedProposerSlashing(ps *ethpb.ProposerSlashing) { - p.lock.Lock() - defer p.lock.Unlock() - i := sort.Search(len(p.pendingProposerSlashing), func(i int) bool { - return p.pendingProposerSlashing[i].Header_1.Header.ProposerIndex >= ps.Header_1.Header.ProposerIndex - }) - if i != len(p.pendingProposerSlashing) && p.pendingProposerSlashing[i].Header_1.Header.ProposerIndex == ps.Header_1.Header.ProposerIndex { - p.pendingProposerSlashing = append(p.pendingProposerSlashing[:i], p.pendingProposerSlashing[i+1:]...) +func (p *PoolService) waitForChainInitialization() { + clock, err := p.cw.WaitForClock(p.ctx) + if err != nil { + log.WithError(err).Error("Could not receive chain start notification") } - p.included[ps.Header_1.Header.ProposerIndex] = true - numProposerSlashingsIncluded.Inc() + p.clock = clock + log.WithField("genesisTime", clock.GenesisTime()).Info( + "Slashing pool service received chain initialization event", + ) } -// this function checks a few items about a validator before proceeding with inserting -// a proposer/attester slashing into the pool. First, it checks if the validator -// has been recently included in the pool, then it checks if the validator is slashable. -// Note: this method requires caller to hold the lock. -func (p *Pool) validatorSlashingPreconditionCheck( - state state.ReadOnlyBeaconState, - valIdx primitives.ValidatorIndex, -) (bool, error) { - if !mutexasserts.RWMutexLocked(&p.lock) && !mutexasserts.RWMutexRLocked(&p.lock) { - return false, errors.New("pool.validatorSlashingPreconditionCheck: caller must hold read/write lock") - } +// Stop the slashing pool service. +func (p *PoolService) Stop() error { + p.cancel() + return nil +} - // Check if the validator index has been included recently. - if p.included[valIdx] { - return false, nil - } - validator, err := state.ValidatorAtIndexReadOnly(valIdx) - if err != nil { - return false, err - } - // Checking if the validator is slashable. - if !helpers.IsSlashableValidatorUsingTrie(validator, time.CurrentEpoch(state)) { - return false, nil - } - return true, nil +// Status of the slashing pool service. +func (p *PoolService) Status() error { + return nil } diff --git a/beacon-chain/operations/slashings/service_attester_test.go b/beacon-chain/operations/slashings/service_attester_test.go index 2dab3f107613..cd3b56c259fb 100644 --- a/beacon-chain/operations/slashings/service_attester_test.go +++ b/beacon-chain/operations/slashings/service_attester_test.go @@ -9,23 +9,24 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func validAttesterSlashingForValIdx(t *testing.T, beaconState state.BeaconState, privs []bls.SecretKey, valIdx ...uint64) *ethpb.AttesterSlashing { - var slashings []*ethpb.AttesterSlashing +func validAttesterSlashingForValIdx(t *testing.T, beaconState state.BeaconState, privs []bls.SecretKey, valIdx ...uint64) ethpb.AttSlashing { + var slashings []ethpb.AttSlashing for _, idx := range valIdx { generatedSlashing, err := util.GenerateAttesterSlashingForValidator(beaconState, privs[idx], primitives.ValidatorIndex(idx)) require.NoError(t, err) - slashings = append(slashings, generatedSlashing.(*ethpb.AttesterSlashing)) + slashings = append(slashings, generatedSlashing) } var allSig1 []bls.Signature var allSig2 []bls.Signature for _, slashing := range slashings { - sig1 := slashing.Attestation_1.Signature - sig2 := slashing.Attestation_2.Signature + sig1 := slashing.FirstAttestation().GetSignature() + sig2 := slashing.SecondAttestation().GetSignature() sigFromBytes1, err := bls.SignatureFromBytes(sig1) require.NoError(t, err) sigFromBytes2, err := bls.SignatureFromBytes(sig2) @@ -35,31 +36,52 @@ func validAttesterSlashingForValIdx(t *testing.T, beaconState state.BeaconState, } aggSig1 := bls.AggregateSignatures(allSig1) aggSig2 := bls.AggregateSignatures(allSig2) - aggSlashing := ðpb.AttesterSlashing{ + + if beaconState.Version() >= version.Electra { + return ðpb.AttesterSlashingElectra{ + Attestation_1: ðpb.IndexedAttestationElectra{ + AttestingIndices: valIdx, + Data: slashings[0].FirstAttestation().GetData(), + Signature: aggSig1.Marshal(), + }, + Attestation_2: ðpb.IndexedAttestationElectra{ + AttestingIndices: valIdx, + Data: slashings[0].SecondAttestation().GetData(), + Signature: aggSig2.Marshal(), + }, + } + } + + return ðpb.AttesterSlashing{ Attestation_1: ðpb.IndexedAttestation{ AttestingIndices: valIdx, - Data: slashings[0].Attestation_1.Data, + Data: slashings[0].FirstAttestation().GetData(), Signature: aggSig1.Marshal(), }, Attestation_2: ðpb.IndexedAttestation{ AttestingIndices: valIdx, - Data: slashings[0].Attestation_2.Data, + Data: slashings[0].SecondAttestation().GetData(), Signature: aggSig2.Marshal(), }, } - return aggSlashing } -func attesterSlashingForValIdx(valIdx ...uint64) *ethpb.AttesterSlashing { +func attesterSlashingForValIdx(ver int, valIdx ...uint64) ethpb.AttSlashing { + if ver >= version.Electra { + return ðpb.AttesterSlashingElectra{ + Attestation_1: ðpb.IndexedAttestationElectra{AttestingIndices: valIdx}, + Attestation_2: ðpb.IndexedAttestationElectra{AttestingIndices: valIdx}, + } + } return ðpb.AttesterSlashing{ Attestation_1: ðpb.IndexedAttestation{AttestingIndices: valIdx}, Attestation_2: ðpb.IndexedAttestation{AttestingIndices: valIdx}, } } -func pendingSlashingForValIdx(valIdx ...uint64) *PendingAttesterSlashing { +func pendingSlashingForValIdx(ver int, valIdx ...uint64) *PendingAttesterSlashing { return &PendingAttesterSlashing{ - attesterSlashing: attesterSlashingForValIdx(valIdx...), + attesterSlashing: attesterSlashingForValIdx(ver, valIdx...), validatorToSlash: primitives.ValidatorIndex(valIdx[0]), } } @@ -71,229 +93,245 @@ func TestPool_InsertAttesterSlashing(t *testing.T) { wantErr []bool } type args struct { - slashings []*ethpb.AttesterSlashing + slashings []ethpb.AttSlashing } - - beaconState, privKeys := util.DeterministicGenesisState(t, 64) - pendingSlashings := make([]*PendingAttesterSlashing, 20) - slashings := make([]*ethpb.AttesterSlashing, 20) - for i := 0; i < len(pendingSlashings); i++ { - generatedSl, err := util.GenerateAttesterSlashingForValidator(beaconState, privKeys[i], primitives.ValidatorIndex(i)) - require.NoError(t, err) - pendingSlashings[i] = &PendingAttesterSlashing{ - attesterSlashing: generatedSl, - validatorToSlash: primitives.ValidatorIndex(i), - } - sl, ok := generatedSl.(*ethpb.AttesterSlashing) - require.Equal(t, true, ok, "Attester slashing has the wrong type (expected %T, got %T)", ðpb.AttesterSlashing{}, generatedSl) - slashings[i] = sl - } - require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) - - // We mark the following validators with some preconditions. - exitedVal, err := beaconState.ValidatorAtIndex(primitives.ValidatorIndex(2)) - require.NoError(t, err) - exitedVal.WithdrawableEpoch = 0 - require.NoError(t, beaconState.UpdateValidatorAtIndex(primitives.ValidatorIndex(2), exitedVal)) - futureWithdrawVal, err := beaconState.ValidatorAtIndex(primitives.ValidatorIndex(4)) - require.NoError(t, err) - futureWithdrawVal.WithdrawableEpoch = 17 - require.NoError(t, beaconState.UpdateValidatorAtIndex(primitives.ValidatorIndex(4), futureWithdrawVal)) - slashedVal, err := beaconState.ValidatorAtIndex(primitives.ValidatorIndex(5)) - require.NoError(t, err) - slashedVal.Slashed = true - require.NoError(t, beaconState.UpdateValidatorAtIndex(primitives.ValidatorIndex(5), slashedVal)) - slashedVal2, err := beaconState.ValidatorAtIndex(primitives.ValidatorIndex(21)) - require.NoError(t, err) - slashedVal2.Slashed = true - require.NoError(t, beaconState.UpdateValidatorAtIndex(primitives.ValidatorIndex(21), slashedVal2)) - - aggSlashing1 := validAttesterSlashingForValIdx(t, beaconState, privKeys, 0, 1, 2) - aggSlashing2 := validAttesterSlashingForValIdx(t, beaconState, privKeys, 5, 9, 13) - aggSlashing3 := validAttesterSlashingForValIdx(t, beaconState, privKeys, 15, 20, 21) - aggSlashing4 := validAttesterSlashingForValIdx(t, beaconState, privKeys, 2, 5, 21) - - tests := []struct { + type testCase struct { name string fields fields args args want []*PendingAttesterSlashing err string - }{ - { - name: "Empty list", - fields: fields{ - pending: make([]*PendingAttesterSlashing, 0), - included: make(map[primitives.ValidatorIndex]bool), - wantErr: []bool{false}, - }, - args: args{ - slashings: slashings[0:1], - }, - want: []*PendingAttesterSlashing{ - { - attesterSlashing: slashings[0], - validatorToSlash: 0, + } + + setupFunc := func(beaconState state.BeaconState, privKeys []bls.SecretKey) []testCase { + pendingSlashings := make([]*PendingAttesterSlashing, 20) + slashings := make([]ethpb.AttSlashing, 20) + for i := 0; i < len(pendingSlashings); i++ { + generatedSl, err := util.GenerateAttesterSlashingForValidator(beaconState, privKeys[i], primitives.ValidatorIndex(i)) + require.NoError(t, err) + pendingSlashings[i] = &PendingAttesterSlashing{ + attesterSlashing: generatedSl, + validatorToSlash: primitives.ValidatorIndex(i), + } + slashings[i] = generatedSl + } + require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + + // We mark the following validators with some preconditions. + exitedVal, err := beaconState.ValidatorAtIndex(primitives.ValidatorIndex(2)) + require.NoError(t, err) + exitedVal.WithdrawableEpoch = 0 + require.NoError(t, beaconState.UpdateValidatorAtIndex(primitives.ValidatorIndex(2), exitedVal)) + futureWithdrawVal, err := beaconState.ValidatorAtIndex(primitives.ValidatorIndex(4)) + require.NoError(t, err) + futureWithdrawVal.WithdrawableEpoch = 17 + require.NoError(t, beaconState.UpdateValidatorAtIndex(primitives.ValidatorIndex(4), futureWithdrawVal)) + slashedVal, err := beaconState.ValidatorAtIndex(primitives.ValidatorIndex(5)) + require.NoError(t, err) + slashedVal.Slashed = true + require.NoError(t, beaconState.UpdateValidatorAtIndex(primitives.ValidatorIndex(5), slashedVal)) + slashedVal2, err := beaconState.ValidatorAtIndex(primitives.ValidatorIndex(21)) + require.NoError(t, err) + slashedVal2.Slashed = true + require.NoError(t, beaconState.UpdateValidatorAtIndex(primitives.ValidatorIndex(21), slashedVal2)) + + aggSlashing1 := validAttesterSlashingForValIdx(t, beaconState, privKeys, 0, 1, 2) + aggSlashing2 := validAttesterSlashingForValIdx(t, beaconState, privKeys, 5, 9, 13) + aggSlashing3 := validAttesterSlashingForValIdx(t, beaconState, privKeys, 15, 20, 21) + aggSlashing4 := validAttesterSlashingForValIdx(t, beaconState, privKeys, 2, 5, 21) + + tests := []testCase{ + { + name: "Empty list", + fields: fields{ + pending: make([]*PendingAttesterSlashing, 0), + included: make(map[primitives.ValidatorIndex]bool), + wantErr: []bool{false}, }, - }, - }, - { - name: "Empty list two validators slashed", - fields: fields{ - pending: make([]*PendingAttesterSlashing, 0), - included: make(map[primitives.ValidatorIndex]bool), - wantErr: []bool{false, false}, - }, - args: args{ - slashings: slashings[0:2], - }, - want: pendingSlashings[0:2], - }, - { - name: "Duplicate identical slashing", - fields: fields{ - pending: []*PendingAttesterSlashing{ - pendingSlashings[1], + args: args{ + slashings: slashings[0:1], }, - included: make(map[primitives.ValidatorIndex]bool), - wantErr: []bool{true}, - }, - args: args{ - slashings: slashings[1:2], - }, - want: pendingSlashings[1:2], - }, - { - name: "Slashing for already exit validator", - fields: fields{ - pending: []*PendingAttesterSlashing{}, - included: make(map[primitives.ValidatorIndex]bool), - wantErr: []bool{true}, - }, - args: args{ - slashings: slashings[5:6], - }, - want: []*PendingAttesterSlashing{}, - }, - { - name: "Slashing for withdrawable validator", - fields: fields{ - pending: []*PendingAttesterSlashing{}, - included: make(map[primitives.ValidatorIndex]bool), - wantErr: []bool{true}, - }, - args: args{ - slashings: slashings[2:3], - }, - want: []*PendingAttesterSlashing{}, - }, - { - name: "Slashing for slashed validator", - fields: fields{ - pending: []*PendingAttesterSlashing{}, - included: make(map[primitives.ValidatorIndex]bool), - wantErr: []bool{false}, - }, - args: args{ - slashings: slashings[4:5], - }, - want: pendingSlashings[4:5], - }, - { - name: "Already included", - fields: fields{ - pending: []*PendingAttesterSlashing{}, - included: map[primitives.ValidatorIndex]bool{ - 1: true, + want: []*PendingAttesterSlashing{ + { + attesterSlashing: slashings[0], + validatorToSlash: 0, + }, }, - wantErr: []bool{true}, - }, - args: args{ - slashings: slashings[1:2], }, - want: []*PendingAttesterSlashing{}, - }, - { - name: "Maintains sorted order", - fields: fields{ - pending: []*PendingAttesterSlashing{ - pendingSlashings[0], - pendingSlashings[2], + { + name: "Empty list two validators slashed", + fields: fields{ + pending: make([]*PendingAttesterSlashing, 0), + included: make(map[primitives.ValidatorIndex]bool), + wantErr: []bool{false, false}, }, - included: make(map[primitives.ValidatorIndex]bool), - wantErr: []bool{false}, - }, - args: args{ - slashings: slashings[1:2], - }, - want: pendingSlashings[0:3], - }, - { - name: "Doesn't reject partially slashed slashings", - fields: fields{ - pending: []*PendingAttesterSlashing{}, - included: make(map[primitives.ValidatorIndex]bool), - wantErr: []bool{false, false, false, true}, - }, - args: args{ - slashings: []*ethpb.AttesterSlashing{ - aggSlashing1, - aggSlashing2, - aggSlashing3, - aggSlashing4, + args: args{ + slashings: slashings[0:2], }, + want: pendingSlashings[0:2], }, - want: []*PendingAttesterSlashing{ - { - attesterSlashing: aggSlashing1, - validatorToSlash: 0, + { + name: "Duplicate identical slashing", + fields: fields{ + pending: []*PendingAttesterSlashing{ + pendingSlashings[1], + }, + included: make(map[primitives.ValidatorIndex]bool), + wantErr: []bool{true}, }, - { - attesterSlashing: aggSlashing1, - validatorToSlash: 1, + args: args{ + slashings: slashings[1:2], }, - { - attesterSlashing: aggSlashing2, - validatorToSlash: 9, + want: pendingSlashings[1:2], + }, + { + name: "Slashing for already exit validator", + fields: fields{ + pending: []*PendingAttesterSlashing{}, + included: make(map[primitives.ValidatorIndex]bool), + wantErr: []bool{true}, }, - { - attesterSlashing: aggSlashing2, - validatorToSlash: 13, + args: args{ + slashings: slashings[5:6], }, - { - attesterSlashing: aggSlashing3, - validatorToSlash: 15, + want: []*PendingAttesterSlashing{}, + }, + { + name: "Slashing for withdrawable validator", + fields: fields{ + pending: []*PendingAttesterSlashing{}, + included: make(map[primitives.ValidatorIndex]bool), + wantErr: []bool{true}, }, - { - attesterSlashing: aggSlashing3, - validatorToSlash: 20, + args: args{ + slashings: slashings[2:3], + }, + want: []*PendingAttesterSlashing{}, + }, + { + name: "Slashing for slashed validator", + fields: fields{ + pending: []*PendingAttesterSlashing{}, + included: make(map[primitives.ValidatorIndex]bool), + wantErr: []bool{false}, + }, + args: args{ + slashings: slashings[4:5], + }, + want: pendingSlashings[4:5], + }, + { + name: "Already included", + fields: fields{ + pending: []*PendingAttesterSlashing{}, + included: map[primitives.ValidatorIndex]bool{ + 1: true, + }, + wantErr: []bool{true}, + }, + args: args{ + slashings: slashings[1:2], + }, + want: []*PendingAttesterSlashing{}, + }, + { + name: "Maintains sorted order", + fields: fields{ + pending: []*PendingAttesterSlashing{ + pendingSlashings[0], + pendingSlashings[2], + }, + included: make(map[primitives.ValidatorIndex]bool), + wantErr: []bool{false}, + }, + args: args{ + slashings: slashings[1:2], + }, + want: pendingSlashings[0:3], + }, + { + name: "Doesn't reject partially slashed slashings", + fields: fields{ + pending: []*PendingAttesterSlashing{}, + included: make(map[primitives.ValidatorIndex]bool), + wantErr: []bool{false, false, false, true}, + }, + args: args{ + slashings: []ethpb.AttSlashing{ + aggSlashing1, + aggSlashing2, + aggSlashing3, + aggSlashing4, + }, + }, + want: []*PendingAttesterSlashing{ + { + attesterSlashing: aggSlashing1, + validatorToSlash: 0, + }, + { + attesterSlashing: aggSlashing1, + validatorToSlash: 1, + }, + { + attesterSlashing: aggSlashing2, + validatorToSlash: 9, + }, + { + attesterSlashing: aggSlashing2, + validatorToSlash: 13, + }, + { + attesterSlashing: aggSlashing3, + validatorToSlash: 15, + }, + { + attesterSlashing: aggSlashing3, + validatorToSlash: 20, + }, }, }, - }, + } + + return tests } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - p := &Pool{ - pendingAttesterSlashing: tt.fields.pending, - included: tt.fields.included, - } - var err error - for i := 0; i < len(tt.args.slashings); i++ { - err = p.InsertAttesterSlashing(context.Background(), beaconState, tt.args.slashings[i]) - if tt.fields.wantErr[i] { - assert.NotNil(t, err) - } else { - assert.NoError(t, err) + + runFunc := func(beaconState state.BeaconState, tests []testCase) { + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &Pool{ + pendingAttesterSlashing: tt.fields.pending, + included: tt.fields.included, } - } - assert.Equal(t, len(tt.want), len(p.pendingAttesterSlashing)) + var err error + for i := 0; i < len(tt.args.slashings); i++ { + err = p.InsertAttesterSlashing(context.Background(), beaconState, tt.args.slashings[i]) + if tt.fields.wantErr[i] { + assert.NotNil(t, err) + } else { + assert.NoError(t, err) + } + } + assert.Equal(t, len(tt.want), len(p.pendingAttesterSlashing)) - for i := range p.pendingAttesterSlashing { - assert.Equal(t, tt.want[i].validatorToSlash, p.pendingAttesterSlashing[i].validatorToSlash) - assert.DeepEqual(t, tt.want[i].attesterSlashing, p.pendingAttesterSlashing[i].attesterSlashing, "At index %d", i) - } - }) + for i := range p.pendingAttesterSlashing { + assert.Equal(t, tt.want[i].validatorToSlash, p.pendingAttesterSlashing[i].validatorToSlash) + assert.DeepEqual(t, tt.want[i].attesterSlashing, p.pendingAttesterSlashing[i].attesterSlashing, "At index %d", i) + } + }) + } } + + t.Run("phase0", func(t *testing.T) { + beaconState, privKeys := util.DeterministicGenesisState(t, 64) + tests := setupFunc(beaconState, privKeys) + runFunc(beaconState, tests) + }) + t.Run("electra", func(t *testing.T) { + beaconState, privKeys := util.DeterministicGenesisStateElectra(t, 64) + tests := setupFunc(beaconState, privKeys) + runFunc(beaconState, tests) + }) } func TestPool_InsertAttesterSlashing_SigFailsVerify_ClearPool(t *testing.T) { @@ -337,7 +375,7 @@ func TestPool_MarkIncludedAttesterSlashing(t *testing.T) { included map[primitives.ValidatorIndex]bool } type args struct { - slashing *ethpb.AttesterSlashing + slashing ethpb.AttSlashing } tests := []struct { name string @@ -346,22 +384,45 @@ func TestPool_MarkIncludedAttesterSlashing(t *testing.T) { want fields }{ { - name: "Included, does not exist in pending", + name: "phase0 included, does not exist in pending", fields: fields{ pending: []*PendingAttesterSlashing{ { - attesterSlashing: attesterSlashingForValIdx(1), + attesterSlashing: attesterSlashingForValIdx(version.Phase0, 1), validatorToSlash: 1, }, }, included: make(map[primitives.ValidatorIndex]bool), }, args: args{ - slashing: attesterSlashingForValIdx(3), + slashing: attesterSlashingForValIdx(version.Phase0, 3), }, want: fields{ pending: []*PendingAttesterSlashing{ - pendingSlashingForValIdx(1), + pendingSlashingForValIdx(version.Phase0, 1), + }, + included: map[primitives.ValidatorIndex]bool{ + 3: true, + }, + }, + }, + { + name: "electra included, does not exist in pending", + fields: fields{ + pending: []*PendingAttesterSlashing{ + { + attesterSlashing: attesterSlashingForValIdx(version.Electra, 1), + validatorToSlash: 1, + }, + }, + included: make(map[primitives.ValidatorIndex]bool), + }, + args: args{ + slashing: attesterSlashingForValIdx(version.Electra, 3), + }, + want: fields{ + pending: []*PendingAttesterSlashing{ + pendingSlashingForValIdx(version.Electra, 1), }, included: map[primitives.ValidatorIndex]bool{ 3: true, @@ -372,21 +433,21 @@ func TestPool_MarkIncludedAttesterSlashing(t *testing.T) { name: "Removes from pending list", fields: fields{ pending: []*PendingAttesterSlashing{ - pendingSlashingForValIdx(1), - pendingSlashingForValIdx(2), - pendingSlashingForValIdx(3), + pendingSlashingForValIdx(version.Phase0, 1), + pendingSlashingForValIdx(version.Phase0, 2), + pendingSlashingForValIdx(version.Phase0, 3), }, included: map[primitives.ValidatorIndex]bool{ 0: true, }, }, args: args{ - slashing: attesterSlashingForValIdx(2), + slashing: attesterSlashingForValIdx(version.Phase0, 2), }, want: fields{ pending: []*PendingAttesterSlashing{ - pendingSlashingForValIdx(1), - pendingSlashingForValIdx(3), + pendingSlashingForValIdx(version.Phase0, 1), + pendingSlashingForValIdx(version.Phase0, 3), }, included: map[primitives.ValidatorIndex]bool{ 0: true, @@ -398,37 +459,37 @@ func TestPool_MarkIncludedAttesterSlashing(t *testing.T) { name: "Removes from long pending list", fields: fields{ pending: []*PendingAttesterSlashing{ - pendingSlashingForValIdx(1), - pendingSlashingForValIdx(2), - pendingSlashingForValIdx(3), - pendingSlashingForValIdx(4), - pendingSlashingForValIdx(5), - pendingSlashingForValIdx(6), - pendingSlashingForValIdx(7), - pendingSlashingForValIdx(8), - pendingSlashingForValIdx(9), - pendingSlashingForValIdx(10), - pendingSlashingForValIdx(11), + pendingSlashingForValIdx(version.Phase0, 1), + pendingSlashingForValIdx(version.Phase0, 2), + pendingSlashingForValIdx(version.Phase0, 3), + pendingSlashingForValIdx(version.Phase0, 4), + pendingSlashingForValIdx(version.Phase0, 5), + pendingSlashingForValIdx(version.Phase0, 6), + pendingSlashingForValIdx(version.Phase0, 7), + pendingSlashingForValIdx(version.Phase0, 8), + pendingSlashingForValIdx(version.Phase0, 9), + pendingSlashingForValIdx(version.Phase0, 10), + pendingSlashingForValIdx(version.Phase0, 11), }, included: map[primitives.ValidatorIndex]bool{ 0: true, }, }, args: args{ - slashing: attesterSlashingForValIdx(6), + slashing: attesterSlashingForValIdx(version.Phase0, 6), }, want: fields{ pending: []*PendingAttesterSlashing{ - pendingSlashingForValIdx(1), - pendingSlashingForValIdx(2), - pendingSlashingForValIdx(3), - pendingSlashingForValIdx(4), - pendingSlashingForValIdx(5), - pendingSlashingForValIdx(7), - pendingSlashingForValIdx(8), - pendingSlashingForValIdx(9), - pendingSlashingForValIdx(10), - pendingSlashingForValIdx(11), + pendingSlashingForValIdx(version.Phase0, 1), + pendingSlashingForValIdx(version.Phase0, 2), + pendingSlashingForValIdx(version.Phase0, 3), + pendingSlashingForValIdx(version.Phase0, 4), + pendingSlashingForValIdx(version.Phase0, 5), + pendingSlashingForValIdx(version.Phase0, 7), + pendingSlashingForValIdx(version.Phase0, 8), + pendingSlashingForValIdx(version.Phase0, 9), + pendingSlashingForValIdx(version.Phase0, 10), + pendingSlashingForValIdx(version.Phase0, 11), }, included: map[primitives.ValidatorIndex]bool{ 0: true, @@ -516,6 +577,70 @@ func TestPool_PendingAttesterSlashings(t *testing.T) { } } +func TestPool_PendingAttesterSlashings_AfterElectra(t *testing.T) { + type fields struct { + pending []*PendingAttesterSlashing + all bool + } + params.SetupTestConfigCleanup(t) + beaconState, privKeys := util.DeterministicGenesisStateElectra(t, 64) + + pendingSlashings := make([]*PendingAttesterSlashing, 20) + slashings := make([]ethpb.AttSlashing, 20) + for i := 0; i < len(pendingSlashings); i++ { + sl, err := util.GenerateAttesterSlashingForValidator(beaconState, privKeys[i], primitives.ValidatorIndex(i)) + require.NoError(t, err) + pendingSlashings[i] = &PendingAttesterSlashing{ + attesterSlashing: sl, + validatorToSlash: primitives.ValidatorIndex(i), + } + slashings[i] = sl + } + tests := []struct { + name string + fields fields + want []ethpb.AttSlashing + }{ + { + name: "Empty list", + fields: fields{ + pending: []*PendingAttesterSlashing{}, + }, + want: []ethpb.AttSlashing{}, + }, + { + name: "All pending", + fields: fields{ + pending: pendingSlashings, + all: true, + }, + want: slashings, + }, + { + name: "All eligible", + fields: fields{ + pending: pendingSlashings, + }, + want: slashings[0:1], + }, + { + name: "Multiple indices", + fields: fields{ + pending: pendingSlashings[3:6], + }, + want: slashings[3:4], + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &Pool{ + pendingAttesterSlashing: tt.fields.pending, + } + assert.DeepEqual(t, tt.want, p.PendingAttesterSlashings(context.Background(), beaconState, tt.fields.all)) + }) + } +} + func TestPool_PendingAttesterSlashings_Slashed(t *testing.T) { type fields struct { pending []*PendingAttesterSlashing diff --git a/beacon-chain/operations/slashings/service_new_test.go b/beacon-chain/operations/slashings/service_new_test.go new file mode 100644 index 000000000000..cbc8a92d2460 --- /dev/null +++ b/beacon-chain/operations/slashings/service_new_test.go @@ -0,0 +1,81 @@ +package slashings + +import ( + "context" + "testing" + "time" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +func TestConvertToElectraWithTimer(t *testing.T) { + ctx := context.Background() + + cfg := params.BeaconConfig().Copy() + cfg.ElectraForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + + indices := []uint64{0, 1} + data := ðpb.AttestationData{ + Slot: 1, + CommitteeIndex: 1, + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ðpb.Checkpoint{ + Epoch: 0, + Root: make([]byte, fieldparams.RootLength), + }, + Target: ðpb.Checkpoint{ + Epoch: 0, + Root: make([]byte, fieldparams.RootLength), + }, + } + sig := make([]byte, fieldparams.BLSSignatureLength) + + phase0Slashing := &PendingAttesterSlashing{ + attesterSlashing: ðpb.AttesterSlashing{ + Attestation_1: ðpb.IndexedAttestation{ + AttestingIndices: indices, + Data: data, + Signature: sig, + }, + Attestation_2: ðpb.IndexedAttestation{ + AttestingIndices: indices, + Data: data, + Signature: sig, + }, + }, + } + + // We need run() to execute the conversion immediately, otherwise we'd need a time.Sleep to wait for the Electra fork. + // To do that we need a timer with the current time being at the Electra fork. + now := time.Now() + electraTime := now.Add(time.Duration(uint64(cfg.ElectraForkEpoch)*uint64(params.BeaconConfig().SlotsPerEpoch)*params.BeaconConfig().SecondsPerSlot) * time.Second) + c := startup.NewClock(now, [32]byte{}, startup.WithNower(func() time.Time { return electraTime })) + cw := startup.NewClockSynchronizer() + require.NoError(t, cw.SetClock(c)) + p := NewPool() + // The service has to think that the current slot is before Electra + // because run() exits early after Electra. + s := NewPoolService(ctx, p, WithElectraTimer(cw, func() primitives.Slot { + return primitives.Slot(cfg.ElectraForkEpoch)*params.BeaconConfig().SlotsPerEpoch - 1 + })) + p.pendingAttesterSlashing = append(p.pendingAttesterSlashing, phase0Slashing) + + s.run() + + electraSlashing, ok := p.pendingAttesterSlashing[0].attesterSlashing.(*ethpb.AttesterSlashingElectra) + require.Equal(t, true, ok, "Slashing was not converted to Electra") + assert.DeepEqual(t, phase0Slashing.attesterSlashing.FirstAttestation().GetAttestingIndices(), electraSlashing.FirstAttestation().GetAttestingIndices()) + assert.DeepEqual(t, phase0Slashing.attesterSlashing.FirstAttestation().GetData(), electraSlashing.FirstAttestation().GetData()) + assert.DeepEqual(t, phase0Slashing.attesterSlashing.FirstAttestation().GetSignature(), electraSlashing.FirstAttestation().GetSignature()) + assert.DeepEqual(t, phase0Slashing.attesterSlashing.SecondAttestation().GetAttestingIndices(), electraSlashing.SecondAttestation().GetAttestingIndices()) + assert.DeepEqual(t, phase0Slashing.attesterSlashing.SecondAttestation().GetData(), electraSlashing.SecondAttestation().GetData()) + assert.DeepEqual(t, phase0Slashing.attesterSlashing.SecondAttestation().GetSignature(), electraSlashing.SecondAttestation().GetSignature()) +} diff --git a/beacon-chain/operations/slashings/types.go b/beacon-chain/operations/slashings/types.go index 36e4bc17c637..05e137d59c49 100644 --- a/beacon-chain/operations/slashings/types.go +++ b/beacon-chain/operations/slashings/types.go @@ -4,6 +4,7 @@ import ( "context" "sync" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -31,6 +32,21 @@ type PoolManager interface { PendingProposerSlashings(ctx context.Context, state state.ReadOnlyBeaconState, noLimit bool) []*ethpb.ProposerSlashing MarkIncludedAttesterSlashing(as ethpb.AttSlashing) MarkIncludedProposerSlashing(ps *ethpb.ProposerSlashing) + ConvertToElectra() +} + +// Option for pool service configuration. +type Option func(p *PoolService) error + +// PoolService manages the Pool. +type PoolService struct { + ctx context.Context + cancel context.CancelFunc + poolManager PoolManager + currentSlotFn func() primitives.Slot + cw startup.ClockWaiter + clock *startup.Clock + runElectraTimer bool } // Pool is a concrete implementation of PoolManager. diff --git a/beacon-chain/p2p/BUILD.bazel b/beacon-chain/p2p/BUILD.bazel index ddbbf7b5b105..edf1cf95bc18 100644 --- a/beacon-chain/p2p/BUILD.bazel +++ b/beacon-chain/p2p/BUILD.bazel @@ -17,7 +17,6 @@ go_library( "handshake.go", "info.go", "interfaces.go", - "iterator.go", "log.go", "message_id.go", "monitoring.go", @@ -66,6 +65,7 @@ go_library( "//io/file:go_default_library", "//math:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network:go_default_library", "//network/forks:go_default_library", "//proto/prysm/v1alpha1:go_default_library", @@ -74,6 +74,8 @@ go_library( "//runtime/version:go_default_library", "//time:go_default_library", "//time/slots:go_default_library", + "@com_github_btcsuite_btcd_btcec_v2//:go_default_library", + "@com_github_ethereum_go_ethereum//crypto:go_default_library", "@com_github_ethereum_go_ethereum//p2p/discover:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enode:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enr:go_default_library", @@ -104,7 +106,6 @@ go_library( "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) @@ -162,12 +163,10 @@ go_test( "//proto/eth/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/testing:go_default_library", - "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", "//time:go_default_library", - "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//crypto:go_default_library", "@com_github_ethereum_go_ethereum//p2p/discover:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enode:go_default_library", @@ -179,8 +178,6 @@ go_test( "@com_github_libp2p_go_libp2p//core/network:go_default_library", "@com_github_libp2p_go_libp2p//core/peer:go_default_library", "@com_github_libp2p_go_libp2p//core/protocol:go_default_library", - "@com_github_libp2p_go_libp2p//p2p/host/blank:go_default_library", - "@com_github_libp2p_go_libp2p//p2p/net/swarm/testing:go_default_library", "@com_github_libp2p_go_libp2p//p2p/security/noise:go_default_library", "@com_github_libp2p_go_libp2p_pubsub//:go_default_library", "@com_github_libp2p_go_libp2p_pubsub//pb:go_default_library", diff --git a/beacon-chain/p2p/broadcaster.go b/beacon-chain/p2p/broadcaster.go index d770bff91acc..2cb8459fbfbc 100644 --- a/beacon-chain/p2p/broadcaster.go +++ b/beacon-chain/p2p/broadcaster.go @@ -14,10 +14,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/crypto/hash" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) @@ -110,7 +110,7 @@ func (s *Service) internalBroadcastAttestation(ctx context.Context, subnet uint6 hasPeer := s.hasPeerWithSubnet(attestationToTopic(subnet, forkDigest)) s.subnetLocker(subnet).RUnlock() - span.AddAttributes( + span.SetAttributes( trace.BoolAttribute("hasPeer", hasPeer), trace.Int64Attribute("slot", int64(att.GetData().Slot)), // lint:ignore uintcast -- It's safe to do this for tracing. trace.Int64Attribute("subnet", int64(subnet)), // lint:ignore uintcast -- It's safe to do this for tracing. @@ -163,13 +163,13 @@ func (s *Service) broadcastSyncCommittee(ctx context.Context, subnet uint64, sMs // Ensure we have peers with this subnet. // This adds in a special value to the subnet - // to ensure that we can re-use the same subnet locker. + // to ensure that we can reuse the same subnet locker. wrappedSubIdx := subnet + syncLockerVal s.subnetLocker(wrappedSubIdx).RLock() hasPeer := s.hasPeerWithSubnet(syncCommitteeToTopic(subnet, forkDigest)) s.subnetLocker(wrappedSubIdx).RUnlock() - span.AddAttributes( + span.SetAttributes( trace.BoolAttribute("hasPeer", hasPeer), trace.Int64Attribute("slot", int64(sMsg.Slot)), // lint:ignore uintcast -- It's safe to do this for tracing. trace.Int64Attribute("subnet", int64(subnet)), // lint:ignore uintcast -- It's safe to do this for tracing. @@ -273,7 +273,7 @@ func (s *Service) broadcastObject(ctx context.Context, obj ssz.Marshaler, topic ctx, span := trace.StartSpan(ctx, "p2p.broadcastObject") defer span.End() - span.AddAttributes(trace.StringAttribute("topic", topic)) + span.SetAttributes(trace.StringAttribute("topic", topic)) buf := new(bytes.Buffer) if _, err := s.Encoding().EncodeGossip(buf, obj); err != nil { @@ -282,12 +282,12 @@ func (s *Service) broadcastObject(ctx context.Context, obj ssz.Marshaler, topic return err } - if span.IsRecordingEvents() { + if span.IsRecording() { id := hash.FastSum64(buf.Bytes()) messageLen := int64(buf.Len()) // lint:ignore uintcast -- It's safe to do this for tracing. iid := int64(id) - span.AddMessageSendEvent(iid, messageLen /*uncompressed*/, messageLen /*compressed*/) + span = trace.AddMessageSendEvent(span, iid, messageLen /*uncompressed*/, messageLen /*compressed*/) } if err := s.PublishToTopic(ctx, topic+s.Encoding().ProtocolSuffix(), buf.Bytes()); err != nil { err := errors.Wrap(err, "could not publish message") diff --git a/beacon-chain/p2p/broadcaster_test.go b/beacon-chain/p2p/broadcaster_test.go index aa5253314440..c2c8611c66b2 100644 --- a/beacon-chain/p2p/broadcaster_test.go +++ b/beacon-chain/p2p/broadcaster_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/p2p/discover" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/host" "github.com/prysmaticlabs/go-bitfield" @@ -210,7 +209,7 @@ func TestService_BroadcastAttestation(t *testing.T) { func TestService_BroadcastAttestationWithDiscoveryAttempts(t *testing.T) { // Setup bootnode. - cfg := &Config{} + cfg := &Config{PingInterval: testPingInterval} port := 2000 cfg.UDPPort = uint(port) _, pkey := createAddrAndPrivKey(t) @@ -226,28 +225,25 @@ func TestService_BroadcastAttestationWithDiscoveryAttempts(t *testing.T) { require.NoError(t, err) defer bootListener.Close() - // Use shorter period for testing. - currentPeriod := pollingPeriod - pollingPeriod = 1 * time.Second - defer func() { - pollingPeriod = currentPeriod - }() - bootNode := bootListener.Self() subnet := uint64(5) - var listeners []*discover.UDPv5 + var listeners []*listenerWrapper var hosts []host.Host // setup other nodes. cfg = &Config{ Discv5BootStrapAddrs: []string{bootNode.String()}, - MaxPeers: 30, + MaxPeers: 2, + PingInterval: testPingInterval, } // Setup 2 different hosts for i := 1; i <= 2; i++ { h, pkey, ipAddr := createHost(t, port+i) cfg.UDPPort = uint(port + i) cfg.TCPPort = uint(port + i) + if len(listeners) > 0 { + cfg.Discv5BootStrapAddrs = append(cfg.Discv5BootStrapAddrs, listeners[len(listeners)-1].Self().String()) + } s := &Service{ cfg: cfg, genesisTime: genesisTime, diff --git a/beacon-chain/p2p/config.go b/beacon-chain/p2p/config.go index 3da7d055cbb2..943d2d3fa673 100644 --- a/beacon-chain/p2p/config.go +++ b/beacon-chain/p2p/config.go @@ -1,6 +1,8 @@ package p2p import ( + "time" + statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" @@ -15,6 +17,7 @@ type Config struct { NoDiscovery bool EnableUPnP bool StaticPeerID bool + DisableLivenessCheck bool StaticPeers []string Discv5BootStrapAddrs []string RelayNodeAddr string @@ -27,6 +30,7 @@ type Config struct { QUICPort uint TCPPort uint UDPPort uint + PingInterval time.Duration MaxPeers uint QueueSize uint AllowListCIDR string diff --git a/beacon-chain/p2p/connection_gater.go b/beacon-chain/p2p/connection_gater.go index a573bea81cc6..8147d07b6c4c 100644 --- a/beacon-chain/p2p/connection_gater.go +++ b/beacon-chain/p2p/connection_gater.go @@ -33,7 +33,7 @@ func (*Service) InterceptPeerDial(_ peer.ID) (allow bool) { // multiaddr for the given peer. func (s *Service) InterceptAddrDial(pid peer.ID, m multiaddr.Multiaddr) (allow bool) { // Disallow bad peers from dialing in. - if s.peers.IsBad(pid) { + if s.peers.IsBad(pid) != nil { return false } return filterConnections(s.addrFilter, m) diff --git a/beacon-chain/p2p/connection_gater_test.go b/beacon-chain/p2p/connection_gater_test.go index a5df92513810..a2e34417c360 100644 --- a/beacon-chain/p2p/connection_gater_test.go +++ b/beacon-chain/p2p/connection_gater_test.go @@ -50,7 +50,7 @@ func TestPeer_AtMaxLimit(t *testing.T) { }() for i := 0; i < highWatermarkBuffer; i++ { - addPeer(t, s.peers, peers.PeerConnected) + addPeer(t, s.peers, peers.Connected, false) } // create alternate host @@ -159,7 +159,7 @@ func TestService_RejectInboundPeersBeyondLimit(t *testing.T) { inboundLimit += 1 // Add in up to inbound peer limit. for i := 0; i < int(inboundLimit); i++ { - addPeer(t, s.peers, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + addPeer(t, s.peers, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED), false) } valid = s.InterceptAccept(&maEndpoints{raddr: multiAddress}) if valid { diff --git a/beacon-chain/p2p/dial_relay_node.go b/beacon-chain/p2p/dial_relay_node.go index 91564f08ee6e..22b55367424b 100644 --- a/beacon-chain/p2p/dial_relay_node.go +++ b/beacon-chain/p2p/dial_relay_node.go @@ -5,7 +5,7 @@ import ( "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/peer" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) // MakePeer from multiaddress string. diff --git a/beacon-chain/p2p/dial_relay_node_test.go b/beacon-chain/p2p/dial_relay_node_test.go index 96cc4892cf37..2971fa87fd4c 100644 --- a/beacon-chain/p2p/dial_relay_node_test.go +++ b/beacon-chain/p2p/dial_relay_node_test.go @@ -5,8 +5,8 @@ import ( "fmt" "testing" - bh "github.com/libp2p/go-libp2p/p2p/host/blank" - swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing" + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/network" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -29,8 +29,10 @@ func TestDialRelayNode_InvalidPeerString(t *testing.T) { func TestDialRelayNode_OK(t *testing.T) { ctx := context.Background() - relay := bh.NewBlankHost(swarmt.GenSwarm(t)) - host := bh.NewBlankHost(swarmt.GenSwarm(t)) + relay, err := libp2p.New(libp2p.ResourceManager(&network.NullResourceManager{})) + require.NoError(t, err) + host, err := libp2p.New(libp2p.ResourceManager(&network.NullResourceManager{})) + require.NoError(t, err) relayAddr := fmt.Sprintf("%s/p2p/%s", relay.Addrs()[0], relay.ID().String()) assert.NoError(t, dialRelayNode(ctx, host, relayAddr), "Unexpected error when dialing relay node") diff --git a/beacon-chain/p2p/discovery.go b/beacon-chain/p2p/discovery.go index 67341e73c674..980fde6fdb6b 100644 --- a/beacon-chain/p2p/discovery.go +++ b/beacon-chain/p2p/discovery.go @@ -22,8 +22,14 @@ import ( ecdsaprysm "github.com/prysmaticlabs/prysm/v5/crypto/ecdsa" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" + "github.com/sirupsen/logrus" ) +type ListenerRebooter interface { + Listener + RebootListener() error +} + // Listener defines the discovery V5 network interface that is used // to communicate with other peers. type Listener interface { @@ -42,123 +48,314 @@ const ( udp6 ) +const quickProtocolEnrKey = "quic" + type quicProtocol uint16 // quicProtocol is the "quic" key, which holds the QUIC port of the node. -func (quicProtocol) ENRKey() string { return "quic" } +func (quicProtocol) ENRKey() string { return quickProtocolEnrKey } + +type listenerWrapper struct { + mu sync.RWMutex + listener *discover.UDPv5 + listenerCreator func() (*discover.UDPv5, error) +} + +func newListener(listenerCreator func() (*discover.UDPv5, error)) (*listenerWrapper, error) { + rawListener, err := listenerCreator() + if err != nil { + return nil, errors.Wrap(err, "could not create new listener") + } + return &listenerWrapper{ + listener: rawListener, + listenerCreator: listenerCreator, + }, nil +} + +func (l *listenerWrapper) Self() *enode.Node { + l.mu.RLock() + defer l.mu.RUnlock() + return l.listener.Self() +} + +func (l *listenerWrapper) Close() { + l.mu.RLock() + defer l.mu.RUnlock() + l.listener.Close() +} + +func (l *listenerWrapper) Lookup(id enode.ID) []*enode.Node { + l.mu.RLock() + defer l.mu.RUnlock() + return l.listener.Lookup(id) +} + +func (l *listenerWrapper) Resolve(node *enode.Node) *enode.Node { + l.mu.RLock() + defer l.mu.RUnlock() + return l.listener.Resolve(node) +} + +func (l *listenerWrapper) RandomNodes() enode.Iterator { + l.mu.RLock() + defer l.mu.RUnlock() + return l.listener.RandomNodes() +} + +func (l *listenerWrapper) Ping(node *enode.Node) error { + l.mu.RLock() + defer l.mu.RUnlock() + return l.listener.Ping(node) +} -// RefreshENR uses an epoch to refresh the enr entry for our node -// with the tracked committee ids for the epoch, allowing our node -// to be dynamically discoverable by others given our tracked committee ids. -func (s *Service) RefreshENR() { - // return early if discv5 isn't running +func (l *listenerWrapper) RequestENR(node *enode.Node) (*enode.Node, error) { + l.mu.RLock() + defer l.mu.RUnlock() + return l.listener.RequestENR(node) +} + +func (l *listenerWrapper) LocalNode() *enode.LocalNode { + l.mu.RLock() + defer l.mu.RUnlock() + return l.listener.LocalNode() +} + +func (l *listenerWrapper) RebootListener() error { + l.mu.Lock() + defer l.mu.Unlock() + + // Close current listener + l.listener.Close() + + newListener, err := l.listenerCreator() + if err != nil { + return err + } + + l.listener = newListener + return nil +} + +// RefreshPersistentSubnets checks that we are tracking our local persistent subnets for a variety of gossip topics. +// This routine verifies and updates our attestation and sync committee subnets if they have been rotated. +func (s *Service) RefreshPersistentSubnets() { + // Return early if discv5 service isn't running. if s.dv5Listener == nil || !s.isInitialized() { return } - currEpoch := slots.ToEpoch(slots.CurrentSlot(uint64(s.genesisTime.Unix()))) - if err := initializePersistentSubnets(s.dv5Listener.LocalNode().ID(), currEpoch); err != nil { + + // Get the current epoch. + currentSlot := slots.CurrentSlot(uint64(s.genesisTime.Unix())) + currentEpoch := slots.ToEpoch(currentSlot) + + // Get our node ID. + nodeID := s.dv5Listener.LocalNode().ID() + + // Get our node record. + record := s.dv5Listener.Self().Record() + + // Get the version of our metadata. + metadataVersion := s.Metadata().Version() + + // Initialize persistent subnets. + if err := initializePersistentSubnets(nodeID, currentEpoch); err != nil { log.WithError(err).Error("Could not initialize persistent subnets") return } + // Get the current attestation subnet bitfield. bitV := bitfield.NewBitvector64() - committees := cache.SubnetIDs.GetAllSubnets() - for _, idx := range committees { + attestationCommittees := cache.SubnetIDs.GetAllSubnets() + for _, idx := range attestationCommittees { bitV.SetBitAt(idx, true) } - currentBitV, err := attBitvector(s.dv5Listener.Self().Record()) + + // Get the attestation subnet bitfield we store in our record. + inRecordBitV, err := attBitvector(record) if err != nil { log.WithError(err).Error("Could not retrieve att bitfield") return } - // Compare current epoch with our fork epochs + // Get the attestation subnet bitfield in our metadata. + inMetadataBitV := s.Metadata().AttnetsBitfield() + + // Is our attestation bitvector record up to date? + isBitVUpToDate := bytes.Equal(bitV, inRecordBitV) && bytes.Equal(bitV, inMetadataBitV) + + // Compare current epoch with Altair fork epoch altairForkEpoch := params.BeaconConfig().AltairForkEpoch - switch { - case currEpoch < altairForkEpoch: + + if currentEpoch < altairForkEpoch { // Phase 0 behaviour. - if bytes.Equal(bitV, currentBitV) { - // return early if bitfield hasn't changed + if isBitVUpToDate { + // Return early if bitfield hasn't changed. return } + + // Some data changed. Update the record and the metadata. s.updateSubnetRecordWithMetadata(bitV) - default: - // Retrieve sync subnets from application level - // cache. - bitS := bitfield.Bitvector4{byte(0x00)} - committees = cache.SyncSubnetIDs.GetAllSubnets(currEpoch) - for _, idx := range committees { - bitS.SetBitAt(idx, true) - } - currentBitS, err := syncBitvector(s.dv5Listener.Self().Record()) - if err != nil { - log.WithError(err).Error("Could not retrieve sync bitfield") - return - } - if bytes.Equal(bitV, currentBitV) && bytes.Equal(bitS, currentBitS) && - s.Metadata().Version() == version.Altair { - // return early if bitfields haven't changed - return - } - s.updateSubnetRecordWithMetadataV2(bitV, bitS) + + // Ping all peers. + s.pingPeersAndLogEnr() + + return + } + + // Get the current sync subnet bitfield. + bitS := bitfield.Bitvector4{byte(0x00)} + syncCommittees := cache.SyncSubnetIDs.GetAllSubnets(currentEpoch) + for _, idx := range syncCommittees { + bitS.SetBitAt(idx, true) + } + + // Get the sync subnet bitfield we store in our record. + inRecordBitS, err := syncBitvector(record) + if err != nil { + log.WithError(err).Error("Could not retrieve sync bitfield") + return + } + + // Get the sync subnet bitfield in our metadata. + currentBitSInMetadata := s.Metadata().SyncnetsBitfield() + + // Is our sync bitvector record up to date? + isBitSUpToDate := bytes.Equal(bitS, inRecordBitS) && bytes.Equal(bitS, currentBitSInMetadata) + + if metadataVersion == version.Altair && isBitVUpToDate && isBitSUpToDate { + // Nothing to do, return early. + return } - // ping all peers to inform them of new metadata - s.pingPeers() + + // Some data have changed, update our record and metadata. + s.updateSubnetRecordWithMetadataV2(bitV, bitS) + + // Ping all peers to inform them of new metadata + s.pingPeersAndLogEnr() } // listen for new nodes watches for new nodes in the network and adds them to the peerstore. func (s *Service) listenForNewNodes() { - iterator := filterNodes(s.ctx, s.dv5Listener.RandomNodes(), s.filterPeer) + const ( + minLogInterval = 1 * time.Minute + thresholdLimit = 5 + ) + + peersSummary := func(threshold uint) (uint, uint) { + // Retrieve how many active peers we have. + activePeers := s.Peers().Active() + activePeerCount := uint(len(activePeers)) + + // Compute how many peers we are missing to reach the threshold. + if activePeerCount >= threshold { + return activePeerCount, 0 + } + + missingPeerCount := threshold - activePeerCount + + return activePeerCount, missingPeerCount + } + + var lastLogTime time.Time + + iterator := s.dv5Listener.RandomNodes() defer iterator.Close() + connectivityTicker := time.NewTicker(1 * time.Minute) + thresholdCount := 0 for { - // Exit if service's context is canceled. - if s.ctx.Err() != nil { - break - } + select { + case <-s.ctx.Done(): + return - if s.isPeerAtLimit(false /* inbound */) { - // Pause the main loop for a period to stop looking - // for new peers. - log.Trace("Not looking for peers, at peer limit") - time.Sleep(pollingPeriod) - continue - } - wantedCount := s.wantedPeerDials() - if wantedCount == 0 { - log.Trace("Not looking for peers, at peer limit") - time.Sleep(pollingPeriod) - continue - } - // Restrict dials if limit is applied. - if flags.MaxDialIsActive() { - wantedCount = min(wantedCount, flags.Get().MaxConcurrentDials) - } - wantedNodes := enode.ReadNodes(iterator, wantedCount) - wg := new(sync.WaitGroup) - for i := 0; i < len(wantedNodes); i++ { - node := wantedNodes[i] - peerInfo, _, err := convertToAddrInfo(node) - if err != nil { - log.WithError(err).Error("Could not convert to peer info") + case <-connectivityTicker.C: + // Skip the connectivity check if not enabled. + if !features.Get().EnableDiscoveryReboot { continue } - if peerInfo == nil { + if !s.isBelowOutboundPeerThreshold() { + // Reset counter if we are beyond the threshold + thresholdCount = 0 continue } - // Make sure that peer is not dialed too often, for each connection attempt there's a backoff period. - s.Peers().RandomizeBackOff(peerInfo.ID) - wg.Add(1) - go func(info *peer.AddrInfo) { - if err := s.connectWithPeer(s.ctx, *info); err != nil { - log.WithError(err).Tracef("Could not connect with peer %s", info.String()) + thresholdCount++ + + // Reboot listener if connectivity drops + if thresholdCount > thresholdLimit { + outBoundConnectedCount := len(s.peers.OutboundConnected()) + log.WithField("outboundConnectionCount", outBoundConnectedCount).Warn("Rebooting discovery listener, reached threshold.") + if err := s.dv5Listener.RebootListener(); err != nil { + log.WithError(err).Error("Could not reboot listener") + continue } - wg.Done() - }(peerInfo) + + iterator = s.dv5Listener.RandomNodes() + thresholdCount = 0 + } + default: + if s.isPeerAtLimit(false /* inbound */) { + // Pause the main loop for a period to stop looking + // for new peers. + log.Trace("Not looking for peers, at peer limit") + time.Sleep(pollingPeriod) + continue + } + + // Compute the number of new peers we want to dial. + activePeerCount, missingPeerCount := peersSummary(s.cfg.MaxPeers) + + fields := logrus.Fields{ + "currentPeerCount": activePeerCount, + "targetPeerCount": s.cfg.MaxPeers, + } + + if missingPeerCount == 0 { + log.Trace("Not looking for peers, at peer limit") + time.Sleep(pollingPeriod) + continue + } + + if time.Since(lastLogTime) > minLogInterval { + lastLogTime = time.Now() + log.WithFields(fields).Debug("Searching for new active peers") + } + + // Restrict dials if limit is applied. + if flags.MaxDialIsActive() { + maxConcurrentDials := uint(flags.Get().MaxConcurrentDials) + missingPeerCount = min(missingPeerCount, maxConcurrentDials) + } + + // Search for new peers. + wantedNodes := searchForPeers(iterator, batchPeriod, missingPeerCount, s.filterPeer) + + wg := new(sync.WaitGroup) + for i := 0; i < len(wantedNodes); i++ { + node := wantedNodes[i] + peerInfo, _, err := convertToAddrInfo(node) + if err != nil { + log.WithError(err).Error("Could not convert to peer info") + continue + } + + if peerInfo == nil { + continue + } + + // Make sure that peer is not dialed too often, for each connection attempt there's a backoff period. + s.Peers().RandomizeBackOff(peerInfo.ID) + wg.Add(1) + go func(info *peer.AddrInfo) { + if err := s.connectWithPeer(s.ctx, *info); err != nil { + log.WithError(err).Tracef("Could not connect with peer %s", info.String()) + } + wg.Done() + }(peerInfo) + } + wg.Wait() } - wg.Wait() } } @@ -221,8 +418,10 @@ func (s *Service) createListener( } dv5Cfg := discover.Config{ - PrivateKey: privKey, - Bootnodes: bootNodes, + PrivateKey: privKey, + Bootnodes: bootNodes, + PingInterval: s.cfg.PingInterval, + NoFindnodeLivenessCheck: s.cfg.DisableLivenessCheck, } listener, err := discover.ListenV5(conn, localNode, dv5Cfg) @@ -299,14 +498,17 @@ func (s *Service) createLocalNode( func (s *Service) startDiscoveryV5( addr net.IP, privKey *ecdsa.PrivateKey, -) (*discover.UDPv5, error) { - listener, err := s.createListener(addr, privKey) +) (*listenerWrapper, error) { + createListener := func() (*discover.UDPv5, error) { + return s.createListener(addr, privKey) + } + wrappedListener, err := newListener(createListener) if err != nil { return nil, errors.Wrap(err, "could not create listener") } - record := listener.Self() + record := wrappedListener.Self() log.WithField("ENR", record.String()).Info("Started discovery v5") - return listener, nil + return wrappedListener, nil } // filterPeer validates each node that we retrieve from our dht. We @@ -340,12 +542,14 @@ func (s *Service) filterPeer(node *enode.Node) bool { } // Ignore bad nodes. - if s.peers.IsBad(peerData.ID) { + if s.peers.IsBad(peerData.ID) != nil { return false } // Ignore nodes that are already active. if s.peers.IsActive(peerData.ID) { + // Constantly update enr for known peers + s.peers.UpdateENR(node.Record(), peerData.ID) return false } @@ -398,15 +602,20 @@ func (s *Service) isPeerAtLimit(inbound bool) bool { return activePeers >= maxPeers || numOfConns >= maxPeers } -func (s *Service) wantedPeerDials() int { +// isBelowOutboundPeerThreshold checks if the number of outbound peers that +// we are connected to satisfies the minimum expected outbound peer count +// according to our peer limit. +func (s *Service) isBelowOutboundPeerThreshold() bool { maxPeers := int(s.cfg.MaxPeers) - - activePeers := len(s.Peers().Active()) - wantedCount := 0 - if maxPeers > activePeers { - wantedCount = maxPeers - activePeers + inBoundLimit := s.Peers().InboundLimit() + // Impossible Condition + if maxPeers < inBoundLimit { + return false } - return wantedCount + outboundFloor := maxPeers - inBoundLimit + outBoundThreshold := outboundFloor / 2 + outBoundCount := len(s.Peers().OutboundConnected()) + return outBoundCount < outBoundThreshold } // PeersFromStringAddrs converts peer raw ENRs into multiaddrs for p2p. diff --git a/beacon-chain/p2p/discovery_test.go b/beacon-chain/p2p/discovery_test.go index 8860a2d0fad5..ac816bd2a16c 100644 --- a/beacon-chain/p2p/discovery_test.go +++ b/beacon-chain/p2p/discovery_test.go @@ -3,8 +3,9 @@ package p2p import ( "context" "crypto/ecdsa" + "crypto/rand" "fmt" - "math/rand" + mathRand "math/rand" "net" "os" "path" @@ -16,6 +17,8 @@ import ( "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/libp2p/go-libp2p" + "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" @@ -30,13 +33,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/wrapper" leakybucket "github.com/prysmaticlabs/prysm/v5/container/leaky-bucket" + ecdsaprysm "github.com/prysmaticlabs/prysm/v5/crypto/ecdsa" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" prysmNetwork "github.com/prysmaticlabs/prysm/v5/network" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/time/slots" logTest "github.com/sirupsen/logrus/hooks/test" ) @@ -47,7 +49,7 @@ func createAddrAndPrivKey(t *testing.T) (net.IP, *ecdsa.PrivateKey) { require.NoError(t, err, "Could not get ip") ipAddr := net.ParseIP(ip) temp := t.TempDir() - randNum := rand.Int() + randNum := mathRand.Int() tempPath := path.Join(temp, strconv.Itoa(randNum)) require.NoError(t, os.Mkdir(tempPath, 0700)) pkey, err := privKey(&Config{DataDir: tempPath}) @@ -85,7 +87,7 @@ func TestStartDiscV5_DiscoverAllPeers(t *testing.T) { genesisTime := time.Now() genesisValidatorsRoot := make([]byte, 32) s := &Service{ - cfg: &Config{UDPPort: uint(port)}, + cfg: &Config{UDPPort: uint(port), PingInterval: testPingInterval, DisableLivenessCheck: true}, genesisTime: genesisTime, genesisValidatorsRoot: genesisValidatorsRoot, } @@ -93,14 +95,20 @@ func TestStartDiscV5_DiscoverAllPeers(t *testing.T) { require.NoError(t, err) defer bootListener.Close() + // Allow bootnode's table to have its initial refresh. This allows + // inbound nodes to be added in. + time.Sleep(5 * time.Second) + bootNode := bootListener.Self() - var listeners []*discover.UDPv5 + var listeners []*listenerWrapper for i := 1; i <= 5; i++ { port = 3000 + i cfg := &Config{ Discv5BootStrapAddrs: []string{bootNode.String()}, UDPPort: uint(port), + PingInterval: testPingInterval, + DisableLivenessCheck: true, } ipAddr, pkey := createAddrAndPrivKey(t) s = &Service{ @@ -131,6 +139,7 @@ func TestStartDiscV5_DiscoverAllPeers(t *testing.T) { } func TestCreateLocalNode(t *testing.T) { + params.SetupTestConfigCleanup(t) testCases := []struct { name string cfg *Config @@ -231,6 +240,37 @@ func TestCreateLocalNode(t *testing.T) { } } +func TestRebootDiscoveryListener(t *testing.T) { + port := 1024 + ipAddr, pkey := createAddrAndPrivKey(t) + s := &Service{ + genesisTime: time.Now(), + genesisValidatorsRoot: bytesutil.PadTo([]byte{'A'}, 32), + cfg: &Config{UDPPort: uint(port)}, + } + createListener := func() (*discover.UDPv5, error) { + return s.createListener(ipAddr, pkey) + } + listener, err := newListener(createListener) + require.NoError(t, err) + currentPubkey := listener.Self().Pubkey() + currentID := listener.Self().ID() + currentPort := listener.Self().UDP() + currentAddr := listener.Self().IP() + + assert.NoError(t, listener.RebootListener()) + + newPubkey := listener.Self().Pubkey() + newID := listener.Self().ID() + newPort := listener.Self().UDP() + newAddr := listener.Self().IP() + + assert.Equal(t, true, currentPubkey.Equal(newPubkey)) + assert.Equal(t, currentID, newID) + assert.Equal(t, currentPort, newPort) + assert.Equal(t, currentAddr.String(), newAddr.String()) +} + func TestMultiAddrsConversion_InvalidIPAddr(t *testing.T) { addr := net.ParseIP("invalidIP") _, pkey := createAddrAndPrivKey(t) @@ -314,10 +354,10 @@ func TestStaticPeering_PeersAreAdded(t *testing.T) { } func TestHostIsResolved(t *testing.T) { - // As defined in RFC 2606 , example.org is a - // reserved example domain name. - exampleHost := "example.org" - exampleIP := "93.184.215.14" + // ip.addr.tools - construct domain names that resolve to any given IP address + // ex: 192-0-2-1.ip.addr.tools resolves to 192.0.2.1. + exampleHost := "96-7-129-13.ip.addr.tools" + exampleIP := "96.7.129.13" s := &Service{ cfg: &Config{ @@ -347,19 +387,44 @@ func TestInboundPeerLimit(t *testing.T) { } for i := 0; i < 30; i++ { - _ = addPeer(t, s.peers, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + _ = addPeer(t, s.peers, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED), false) } require.Equal(t, true, s.isPeerAtLimit(false), "not at limit for outbound peers") require.Equal(t, false, s.isPeerAtLimit(true), "at limit for inbound peers") for i := 0; i < highWatermarkBuffer; i++ { - _ = addPeer(t, s.peers, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + _ = addPeer(t, s.peers, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED), false) } require.Equal(t, true, s.isPeerAtLimit(true), "not at limit for inbound peers") } +func TestOutboundPeerThreshold(t *testing.T) { + fakePeer := testp2p.NewTestP2P(t) + s := &Service{ + cfg: &Config{MaxPeers: 30}, + ipLimiter: leakybucket.NewCollector(ipLimit, ipBurst, 1*time.Second, false), + peers: peers.NewStatus(context.Background(), &peers.StatusConfig{ + PeerLimit: 30, + ScorerParams: &scorers.Config{}, + }), + host: fakePeer.BHost, + } + + for i := 0; i < 2; i++ { + _ = addPeer(t, s.peers, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED), true) + } + + require.Equal(t, true, s.isBelowOutboundPeerThreshold(), "not at outbound peer threshold") + + for i := 0; i < 3; i++ { + _ = addPeer(t, s.peers, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED), true) + } + + require.Equal(t, false, s.isBelowOutboundPeerThreshold(), "still at outbound peer threshold") +} + func TestUDPMultiAddress(t *testing.T) { port := 6500 ipAddr, pkey := createAddrAndPrivKey(t) @@ -370,7 +435,11 @@ func TestUDPMultiAddress(t *testing.T) { genesisTime: genesisTime, genesisValidatorsRoot: genesisValidatorsRoot, } - listener, err := s.createListener(ipAddr, pkey) + + createListener := func() (*discover.UDPv5, error) { + return s.createListener(ipAddr, pkey) + } + listener, err := newListener(createListener) require.NoError(t, err) defer listener.Close() s.dv5Listener = listener @@ -417,7 +486,7 @@ func TestCorrectUDPVersion(t *testing.T) { } // addPeer is a helper to add a peer with a given connection state) -func addPeer(t *testing.T, p *peers.Status, state peerdata.PeerConnectionState) peer.ID { +func addPeer(t *testing.T, p *peers.Status, state peerdata.ConnectionState, outbound bool) peer.ID { // Set up some peers with different states mhBytes := []byte{0x11, 0x04} idBytes := make([]byte, 4) @@ -426,7 +495,11 @@ func addPeer(t *testing.T, p *peers.Status, state peerdata.PeerConnectionState) mhBytes = append(mhBytes, idBytes...) id, err := peer.IDFromBytes(mhBytes) require.NoError(t, err) - p.Add(new(enr.Record), id, nil, network.DirInbound) + dir := network.DirInbound + if outbound { + dir = network.DirOutbound + } + p.Add(new(enr.Record), id, nil, dir) p.SetConnectionState(id, state) p.SetMetadata(id, wrapper.WrappedMetadataV0(ðpb.MetaDataV0{ SeqNumber: 0, @@ -435,177 +508,266 @@ func addPeer(t *testing.T, p *peers.Status, state peerdata.PeerConnectionState) return id } -func TestRefreshENR_ForkBoundaries(t *testing.T) { +func createAndConnectPeer(t *testing.T, p2pService *testp2p.TestP2P, offset int) { + // Create the private key. + privateKeyBytes := make([]byte, 32) + for i := 0; i < 32; i++ { + privateKeyBytes[i] = byte(offset + i) + } + + privateKey, err := crypto.UnmarshalSecp256k1PrivateKey(privateKeyBytes) + require.NoError(t, err) + + // Create the peer. + peer := testp2p.NewTestP2P(t, libp2p.Identity(privateKey)) + + // Add the peer and connect it. + p2pService.Peers().Add(&enr.Record{}, peer.PeerID(), nil, network.DirOutbound) + p2pService.Peers().SetConnectionState(peer.PeerID(), peers.Connected) + p2pService.Connect(peer) +} + +// Define the ping count. +var actualPingCount int + +type check struct { + pingCount int + metadataSequenceNumber uint64 + attestationSubnets []uint64 + syncSubnets []uint64 + custodySubnetCount *uint64 +} + +func checkPingCountCacheMetadataRecord( + t *testing.T, + service *Service, + expected check, +) { + // Check the ping count. + require.Equal(t, expected.pingCount, actualPingCount) + + // Check the attestation subnets in the cache. + actualAttestationSubnets := cache.SubnetIDs.GetAllSubnets() + require.DeepSSZEqual(t, expected.attestationSubnets, actualAttestationSubnets) + + // Check the metadata sequence number. + actualMetadataSequenceNumber := service.metaData.SequenceNumber() + require.Equal(t, expected.metadataSequenceNumber, actualMetadataSequenceNumber) + + // Compute expected attestation subnets bits. + expectedBitV := bitfield.NewBitvector64() + exists := false + + for _, idx := range expected.attestationSubnets { + exists = true + expectedBitV.SetBitAt(idx, true) + } + + // Check attnets in ENR. + var actualBitVENR bitfield.Bitvector64 + err := service.dv5Listener.LocalNode().Node().Record().Load(enr.WithEntry(attSubnetEnrKey, &actualBitVENR)) + require.NoError(t, err) + require.DeepSSZEqual(t, expectedBitV, actualBitVENR) + + // Check attnets in metadata. + if !exists { + expectedBitV = nil + } + + actualBitVMetadata := service.metaData.AttnetsBitfield() + require.DeepSSZEqual(t, expectedBitV, actualBitVMetadata) + + if expected.syncSubnets != nil { + // Compute expected sync subnets bits. + expectedBitS := bitfield.NewBitvector4() + exists = false + + for _, idx := range expected.syncSubnets { + exists = true + expectedBitS.SetBitAt(idx, true) + } + + // Check syncnets in ENR. + var actualBitSENR bitfield.Bitvector4 + err := service.dv5Listener.LocalNode().Node().Record().Load(enr.WithEntry(syncCommsSubnetEnrKey, &actualBitSENR)) + require.NoError(t, err) + require.DeepSSZEqual(t, expectedBitS, actualBitSENR) + + // Check syncnets in metadata. + if !exists { + expectedBitS = nil + } + + actualBitSMetadata := service.metaData.SyncnetsBitfield() + require.DeepSSZEqual(t, expectedBitS, actualBitSMetadata) + } +} + +func TestRefreshPersistentSubnets(t *testing.T) { params.SetupTestConfigCleanup(t) + // Clean up caches after usage. defer cache.SubnetIDs.EmptyAllCaches() + defer cache.SyncSubnetIDs.EmptyAllCaches() - tests := []struct { - name string - svcBuilder func(t *testing.T) *Service - postValidation func(t *testing.T, s *Service) + const altairForkEpoch = 5 + + // Set up epochs. + defaultCfg := params.BeaconConfig() + cfg := defaultCfg.Copy() + cfg.AltairForkEpoch = altairForkEpoch + params.OverrideBeaconConfig(cfg) + + // Compute the number of seconds per epoch. + secondsPerSlot := params.BeaconConfig().SecondsPerSlot + slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch + secondsPerEpoch := secondsPerSlot * uint64(slotsPerEpoch) + + testCases := []struct { + name string + epochSinceGenesis uint64 + checks []check }{ { - name: "metadata no change", - svcBuilder: func(t *testing.T) *Service { - port := 2000 - ipAddr, pkey := createAddrAndPrivKey(t) - s := &Service{ - genesisTime: time.Now(), - genesisValidatorsRoot: bytesutil.PadTo([]byte{'A'}, 32), - cfg: &Config{UDPPort: uint(port)}, - } - listener, err := s.createListener(ipAddr, pkey) - assert.NoError(t, err) - s.dv5Listener = listener - s.metaData = wrapper.WrappedMetadataV0(new(ethpb.MetaDataV0)) - s.updateSubnetRecordWithMetadata([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) - return s - }, - postValidation: func(t *testing.T, s *Service) { - currEpoch := slots.ToEpoch(slots.CurrentSlot(uint64(s.genesisTime.Unix()))) - subs, err := computeSubscribedSubnets(s.dv5Listener.LocalNode().ID(), currEpoch) - assert.NoError(t, err) - - bitV := bitfield.NewBitvector64() - for _, idx := range subs { - bitV.SetBitAt(idx, true) - } - assert.DeepEqual(t, bitV, s.metaData.AttnetsBitfield()) - }, - }, - { - name: "metadata updated", - svcBuilder: func(t *testing.T) *Service { - port := 2000 - ipAddr, pkey := createAddrAndPrivKey(t) - s := &Service{ - genesisTime: time.Now(), - genesisValidatorsRoot: bytesutil.PadTo([]byte{'A'}, 32), - cfg: &Config{UDPPort: uint(port)}, - } - listener, err := s.createListener(ipAddr, pkey) - assert.NoError(t, err) - s.dv5Listener = listener - s.metaData = wrapper.WrappedMetadataV0(new(ethpb.MetaDataV0)) - s.updateSubnetRecordWithMetadata([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}) - cache.SubnetIDs.AddPersistentCommittee([]uint64{1, 2, 3, 23}, 0) - return s - }, - postValidation: func(t *testing.T, s *Service) { - assert.DeepEqual(t, bitfield.Bitvector64{0xe, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0}, s.metaData.AttnetsBitfield()) - }, - }, - { - name: "metadata updated at fork epoch", - svcBuilder: func(t *testing.T) *Service { - port := 2000 - ipAddr, pkey := createAddrAndPrivKey(t) - s := &Service{ - genesisTime: time.Now().Add(-5 * oneEpochDuration()), - genesisValidatorsRoot: bytesutil.PadTo([]byte{'A'}, 32), - cfg: &Config{UDPPort: uint(port)}, - } - listener, err := s.createListener(ipAddr, pkey) - assert.NoError(t, err) - - // Update params - cfg := params.BeaconConfig().Copy() - cfg.AltairForkEpoch = 5 - params.OverrideBeaconConfig(cfg) - params.BeaconConfig().InitializeForkSchedule() - - s.dv5Listener = listener - s.metaData = wrapper.WrappedMetadataV0(new(ethpb.MetaDataV0)) - s.updateSubnetRecordWithMetadata([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}) - cache.SubnetIDs.AddPersistentCommittee([]uint64{1, 2, 3, 23}, 0) - return s - }, - postValidation: func(t *testing.T, s *Service) { - assert.Equal(t, version.Altair, s.metaData.Version()) - assert.DeepEqual(t, bitfield.Bitvector4{0x00}, s.metaData.MetadataObjV1().Syncnets) - assert.DeepEqual(t, bitfield.Bitvector64{0xe, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0}, s.metaData.AttnetsBitfield()) - }, - }, - { - name: "metadata updated at fork epoch with no bitfield", - svcBuilder: func(t *testing.T) *Service { - port := 2000 - ipAddr, pkey := createAddrAndPrivKey(t) - s := &Service{ - genesisTime: time.Now().Add(-5 * oneEpochDuration()), - genesisValidatorsRoot: bytesutil.PadTo([]byte{'A'}, 32), - cfg: &Config{UDPPort: uint(port)}, - } - listener, err := s.createListener(ipAddr, pkey) - assert.NoError(t, err) - - // Update params - cfg := params.BeaconConfig().Copy() - cfg.AltairForkEpoch = 5 - params.OverrideBeaconConfig(cfg) - params.BeaconConfig().InitializeForkSchedule() - - s.dv5Listener = listener - s.metaData = wrapper.WrappedMetadataV0(new(ethpb.MetaDataV0)) - s.updateSubnetRecordWithMetadata([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) - return s - }, - postValidation: func(t *testing.T, s *Service) { - assert.Equal(t, version.Altair, s.metaData.Version()) - assert.DeepEqual(t, bitfield.Bitvector4{0x00}, s.metaData.MetadataObjV1().Syncnets) - currEpoch := slots.ToEpoch(slots.CurrentSlot(uint64(s.genesisTime.Unix()))) - subs, err := computeSubscribedSubnets(s.dv5Listener.LocalNode().ID(), currEpoch) - assert.NoError(t, err) - - bitV := bitfield.NewBitvector64() - for _, idx := range subs { - bitV.SetBitAt(idx, true) - } - assert.DeepEqual(t, bitV, s.metaData.AttnetsBitfield()) + name: "Phase0", + epochSinceGenesis: 0, + checks: []check{ + { + pingCount: 0, + metadataSequenceNumber: 0, + attestationSubnets: []uint64{}, + }, + { + pingCount: 1, + metadataSequenceNumber: 1, + attestationSubnets: []uint64{40, 41}, + }, + { + pingCount: 1, + metadataSequenceNumber: 1, + attestationSubnets: []uint64{40, 41}, + }, + { + pingCount: 1, + metadataSequenceNumber: 1, + attestationSubnets: []uint64{40, 41}, + }, }, }, { - name: "metadata updated past fork epoch with bitfields", - svcBuilder: func(t *testing.T) *Service { - port := 2000 - ipAddr, pkey := createAddrAndPrivKey(t) - s := &Service{ - genesisTime: time.Now().Add(-6 * oneEpochDuration()), - genesisValidatorsRoot: bytesutil.PadTo([]byte{'A'}, 32), - cfg: &Config{UDPPort: uint(port)}, - } - listener, err := s.createListener(ipAddr, pkey) - assert.NoError(t, err) - - // Update params - cfg := params.BeaconConfig().Copy() - cfg.AltairForkEpoch = 5 - params.OverrideBeaconConfig(cfg) - params.BeaconConfig().InitializeForkSchedule() - - s.dv5Listener = listener - s.metaData = wrapper.WrappedMetadataV0(new(ethpb.MetaDataV0)) - s.updateSubnetRecordWithMetadata([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) - cache.SubnetIDs.AddPersistentCommittee([]uint64{1, 2, 3, 23}, 0) - cache.SyncSubnetIDs.AddSyncCommitteeSubnets([]byte{'A'}, 0, []uint64{0, 1}, 0) - return s - }, - postValidation: func(t *testing.T, s *Service) { - assert.Equal(t, version.Altair, s.metaData.Version()) - assert.DeepEqual(t, bitfield.Bitvector4{0x03}, s.metaData.MetadataObjV1().Syncnets) - assert.DeepEqual(t, bitfield.Bitvector64{0xe, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0}, s.metaData.AttnetsBitfield()) + name: "Altair", + epochSinceGenesis: altairForkEpoch, + checks: []check{ + { + pingCount: 0, + metadataSequenceNumber: 0, + attestationSubnets: []uint64{}, + syncSubnets: nil, + }, + { + pingCount: 1, + metadataSequenceNumber: 1, + attestationSubnets: []uint64{40, 41}, + syncSubnets: nil, + }, + { + pingCount: 2, + metadataSequenceNumber: 2, + attestationSubnets: []uint64{40, 41}, + syncSubnets: []uint64{1, 2}, + }, + { + pingCount: 2, + metadataSequenceNumber: 2, + attestationSubnets: []uint64{40, 41}, + syncSubnets: []uint64{1, 2}, + }, }, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := tt.svcBuilder(t) - s.RefreshENR() - tt.postValidation(t, s) - s.dv5Listener.Close() + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + const peerOffset = 1 + + // Initialize the ping count. + actualPingCount = 0 + + // Create the private key. + privateKeyBytes := make([]byte, 32) + for i := 0; i < 32; i++ { + privateKeyBytes[i] = byte(i) + } + + unmarshalledPrivateKey, err := crypto.UnmarshalSecp256k1PrivateKey(privateKeyBytes) + require.NoError(t, err) + + privateKey, err := ecdsaprysm.ConvertFromInterfacePrivKey(unmarshalledPrivateKey) + require.NoError(t, err) + + // Create a p2p service. + p2p := testp2p.NewTestP2P(t) + + // Create and connect a peer. + createAndConnectPeer(t, p2p, peerOffset) + + // Create a service. + service := &Service{ + pingMethod: func(_ context.Context, _ peer.ID) error { + actualPingCount++ + return nil + }, + cfg: &Config{UDPPort: 2000}, + peers: p2p.Peers(), + genesisTime: time.Now().Add(-time.Duration(tc.epochSinceGenesis*secondsPerEpoch) * time.Second), + genesisValidatorsRoot: bytesutil.PadTo([]byte{'A'}, 32), + } + + // Set the listener and the metadata. + createListener := func() (*discover.UDPv5, error) { + return service.createListener(nil, privateKey) + } + + listener, err := newListener(createListener) + require.NoError(t, err) + + service.dv5Listener = listener + service.metaData = wrapper.WrappedMetadataV0(new(ethpb.MetaDataV0)) + + // Run a check. + checkPingCountCacheMetadataRecord(t, service, tc.checks[0]) + + // Refresh the persistent subnets. + service.RefreshPersistentSubnets() + time.Sleep(10 * time.Millisecond) + + // Run a check. + checkPingCountCacheMetadataRecord(t, service, tc.checks[1]) + + // Add a sync committee subnet. + cache.SyncSubnetIDs.AddSyncCommitteeSubnets([]byte{'a'}, altairForkEpoch, []uint64{1, 2}, 1*time.Hour) + + // Refresh the persistent subnets. + service.RefreshPersistentSubnets() + time.Sleep(10 * time.Millisecond) + + // Run a check. + checkPingCountCacheMetadataRecord(t, service, tc.checks[2]) + + // Refresh the persistent subnets. + service.RefreshPersistentSubnets() + time.Sleep(10 * time.Millisecond) + + // Run a check. + checkPingCountCacheMetadataRecord(t, service, tc.checks[3]) + + // Clean the test. + service.dv5Listener.Close() cache.SubnetIDs.EmptyAllCaches() cache.SyncSubnetIDs.EmptyAllCaches() }) } + + // Reset the config. + params.OverrideBeaconConfig(defaultCfg) } diff --git a/beacon-chain/p2p/encoder/ssz_test.go b/beacon-chain/p2p/encoder/ssz_test.go index 17c93286fc2b..6e12af4e7014 100644 --- a/beacon-chain/p2p/encoder/ssz_test.go +++ b/beacon-chain/p2p/encoder/ssz_test.go @@ -110,7 +110,7 @@ type BeaconStateElectraCreator struct{} type PowBlockCreator struct{} type HistoricalSummaryCreator struct{} type BlobIdentifierCreator struct{} -type PendingBalanceDepositCreator struct{} +type PendingDepositCreator struct{} type PendingPartialWithdrawalCreator struct{} type PendingConsolidationCreator struct{} type StatusCreator struct{} @@ -279,8 +279,8 @@ func (BeaconStateElectraCreator) Create() MarshalerProtoMessage { return ðpb. func (PowBlockCreator) Create() MarshalerProtoMessage { return ðpb.PowBlock{} } func (HistoricalSummaryCreator) Create() MarshalerProtoMessage { return ðpb.HistoricalSummary{} } func (BlobIdentifierCreator) Create() MarshalerProtoMessage { return ðpb.BlobIdentifier{} } -func (PendingBalanceDepositCreator) Create() MarshalerProtoMessage { - return ðpb.PendingBalanceDeposit{} +func (PendingDepositCreator) Create() MarshalerProtoMessage { + return ðpb.PendingDeposit{} } func (PendingPartialWithdrawalCreator) Create() MarshalerProtoMessage { return ðpb.PendingPartialWithdrawal{} @@ -397,7 +397,7 @@ var creators = []MarshalerProtoCreator{ PowBlockCreator{}, HistoricalSummaryCreator{}, BlobIdentifierCreator{}, - PendingBalanceDepositCreator{}, + PendingDepositCreator{}, PendingPartialWithdrawalCreator{}, PendingConsolidationCreator{}, StatusCreator{}, diff --git a/beacon-chain/p2p/fork_test.go b/beacon-chain/p2p/fork_test.go index d5780f719901..0d192653506a 100644 --- a/beacon-chain/p2p/fork_test.go +++ b/beacon-chain/p2p/fork_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" ma "github.com/multiformats/go-multiaddr" @@ -35,8 +34,10 @@ func TestStartDiscv5_DifferentForkDigests(t *testing.T) { genesisValidatorsRoot := make([]byte, fieldparams.RootLength) s := &Service{ cfg: &Config{ - UDPPort: uint(port), - StateNotifier: &mock.MockStateNotifier{}, + UDPPort: uint(port), + StateNotifier: &mock.MockStateNotifier{}, + PingInterval: testPingInterval, + DisableLivenessCheck: true, }, genesisTime: genesisTime, genesisValidatorsRoot: genesisValidatorsRoot, @@ -45,14 +46,20 @@ func TestStartDiscv5_DifferentForkDigests(t *testing.T) { require.NoError(t, err) defer bootListener.Close() + // Allow bootnode's table to have its initial refresh. This allows + // inbound nodes to be added in. + time.Sleep(5 * time.Second) + bootNode := bootListener.Self() cfg := &Config{ Discv5BootStrapAddrs: []string{bootNode.String()}, UDPPort: uint(port), StateNotifier: &mock.MockStateNotifier{}, + PingInterval: testPingInterval, + DisableLivenessCheck: true, } - var listeners []*discover.UDPv5 + var listeners []*listenerWrapper for i := 1; i <= 5; i++ { port := 3000 + i cfg.UDPPort = uint(port) @@ -125,7 +132,7 @@ func TestStartDiscv5_SameForkDigests_DifferentNextForkData(t *testing.T) { genesisTime := time.Now() genesisValidatorsRoot := make([]byte, 32) s := &Service{ - cfg: &Config{UDPPort: uint(port)}, + cfg: &Config{UDPPort: uint(port), PingInterval: testPingInterval, DisableLivenessCheck: true}, genesisTime: genesisTime, genesisValidatorsRoot: genesisValidatorsRoot, } @@ -133,18 +140,23 @@ func TestStartDiscv5_SameForkDigests_DifferentNextForkData(t *testing.T) { require.NoError(t, err) defer bootListener.Close() + // Allow bootnode's table to have its initial refresh. This allows + // inbound nodes to be added in. + time.Sleep(5 * time.Second) + bootNode := bootListener.Self() cfg := &Config{ Discv5BootStrapAddrs: []string{bootNode.String()}, UDPPort: uint(port), + PingInterval: testPingInterval, + DisableLivenessCheck: true, } - var listeners []*discover.UDPv5 + var listeners []*listenerWrapper for i := 1; i <= 5; i++ { port := 3000 + i cfg.UDPPort = uint(port) ipAddr, pkey := createAddrAndPrivKey(t) - c := params.BeaconConfig().Copy() nextForkEpoch := primitives.Epoch(i) c.ForkVersionSchedule[[4]byte{'A', 'B', 'C', 'D'}] = nextForkEpoch diff --git a/beacon-chain/p2p/fork_watcher.go b/beacon-chain/p2p/fork_watcher.go index 3d02d57bb6f1..2b9a206c30d3 100644 --- a/beacon-chain/p2p/fork_watcher.go +++ b/beacon-chain/p2p/fork_watcher.go @@ -18,7 +18,8 @@ func (s *Service) forkWatcher() { currEpoch == params.BeaconConfig().BellatrixForkEpoch || currEpoch == params.BeaconConfig().CapellaForkEpoch || currEpoch == params.BeaconConfig().DenebForkEpoch || - currEpoch == params.BeaconConfig().ElectraForkEpoch { + currEpoch == params.BeaconConfig().ElectraForkEpoch || + currEpoch == params.BeaconConfig().FuluForkEpoch { // If we are in the fork epoch, we update our enr with // the updated fork digest. These repeatedly does // this over the epoch, which might be slightly wasteful diff --git a/beacon-chain/p2p/gossip_topic_mappings.go b/beacon-chain/p2p/gossip_topic_mappings.go index d88a4499ce2b..9f66a25b6d57 100644 --- a/beacon-chain/p2p/gossip_topic_mappings.go +++ b/beacon-chain/p2p/gossip_topic_mappings.go @@ -29,6 +29,9 @@ var gossipTopicMappings = map[string]func() proto.Message{ func GossipTopicMappings(topic string, epoch primitives.Epoch) proto.Message { switch topic { case BlockSubnetTopicFormat: + if epoch >= params.BeaconConfig().FuluForkEpoch { + return ðpb.SignedBeaconBlockFulu{} + } if epoch >= params.BeaconConfig().ElectraForkEpoch { return ðpb.SignedBeaconBlockElectra{} } @@ -47,7 +50,7 @@ func GossipTopicMappings(topic string, epoch primitives.Epoch) proto.Message { return gossipMessage(topic) case AttestationSubnetTopicFormat: if epoch >= params.BeaconConfig().ElectraForkEpoch { - return ðpb.AttestationElectra{} + return ðpb.SingleAttestation{} } return gossipMessage(topic) case AttesterSlashingSubnetTopicFormat: @@ -91,17 +94,25 @@ func init() { for k, v := range gossipTopicMappings { GossipTypeMapping[reflect.TypeOf(v())] = k } + // Specially handle Altair objects. GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockAltair{})] = BlockSubnetTopicFormat + // Specially handle Bellatrix objects. GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockBellatrix{})] = BlockSubnetTopicFormat + // Specially handle Capella objects. GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockCapella{})] = BlockSubnetTopicFormat + // Specially handle Deneb objects. GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockDeneb{})] = BlockSubnetTopicFormat + // Specially handle Electra objects. GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockElectra{})] = BlockSubnetTopicFormat - GossipTypeMapping[reflect.TypeOf(ðpb.AttestationElectra{})] = AttestationSubnetTopicFormat + GossipTypeMapping[reflect.TypeOf(ðpb.SingleAttestation{})] = AttestationSubnetTopicFormat GossipTypeMapping[reflect.TypeOf(ðpb.AttesterSlashingElectra{})] = AttesterSlashingSubnetTopicFormat GossipTypeMapping[reflect.TypeOf(ðpb.SignedAggregateAttestationAndProofElectra{})] = AggregateAndProofSubnetTopicFormat + + // Specially handle Fulu objects. + GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockFulu{})] = BlockSubnetTopicFormat } diff --git a/beacon-chain/p2p/gossip_topic_mappings_test.go b/beacon-chain/p2p/gossip_topic_mappings_test.go index 2c134f425fa6..3bf5c938a54b 100644 --- a/beacon-chain/p2p/gossip_topic_mappings_test.go +++ b/beacon-chain/p2p/gossip_topic_mappings_test.go @@ -30,17 +30,20 @@ func TestGossipTopicMappings_CorrectType(t *testing.T) { capellaForkEpoch := primitives.Epoch(300) denebForkEpoch := primitives.Epoch(400) electraForkEpoch := primitives.Epoch(500) + fuluForkEpoch := primitives.Epoch(600) bCfg.AltairForkEpoch = altairForkEpoch bCfg.BellatrixForkEpoch = bellatrixForkEpoch bCfg.CapellaForkEpoch = capellaForkEpoch bCfg.DenebForkEpoch = denebForkEpoch bCfg.ElectraForkEpoch = electraForkEpoch + bCfg.FuluForkEpoch = fuluForkEpoch bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.AltairForkVersion)] = primitives.Epoch(100) bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.BellatrixForkVersion)] = primitives.Epoch(200) bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.CapellaForkVersion)] = primitives.Epoch(300) bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.DenebForkVersion)] = primitives.Epoch(400) bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.ElectraForkVersion)] = primitives.Epoch(500) + bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.FuluForkVersion)] = primitives.Epoch(600) params.OverrideBeaconConfig(bCfg) // Phase 0 @@ -118,7 +121,7 @@ func TestGossipTopicMappings_CorrectType(t *testing.T) { _, ok = pMessage.(*ethpb.SignedBeaconBlockElectra) assert.Equal(t, true, ok) pMessage = GossipTopicMappings(AttestationSubnetTopicFormat, electraForkEpoch) - _, ok = pMessage.(*ethpb.AttestationElectra) + _, ok = pMessage.(*ethpb.SingleAttestation) assert.Equal(t, true, ok) pMessage = GossipTopicMappings(AttesterSlashingSubnetTopicFormat, electraForkEpoch) _, ok = pMessage.(*ethpb.AttesterSlashingElectra) diff --git a/beacon-chain/p2p/handshake.go b/beacon-chain/p2p/handshake.go index 97d2af8eed72..df19f861ee5d 100644 --- a/beacon-chain/p2p/handshake.go +++ b/beacon-chain/p2p/handshake.go @@ -2,7 +2,6 @@ package p2p import ( "context" - "errors" "fmt" "io" "sync" @@ -10,6 +9,7 @@ import ( "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/peerdata" prysmTime "github.com/prysmaticlabs/prysm/v5/time" @@ -25,6 +25,46 @@ func peerMultiaddrString(conn network.Conn) string { return fmt.Sprintf("%s/p2p/%s", conn.RemoteMultiaddr().String(), conn.RemotePeer().String()) } +func (s *Service) connectToPeer(conn network.Conn) { + s.peers.SetConnectionState(conn.RemotePeer(), peers.Connected) + // Go through the handshake process. + log.WithFields(logrus.Fields{ + "direction": conn.Stat().Direction.String(), + "multiAddr": peerMultiaddrString(conn), + "activePeers": len(s.peers.Active()), + }).Debug("Initiate peer connection") +} + +func (s *Service) disconnectFromPeerOnError( + conn network.Conn, + goodByeFunc func(ctx context.Context, id peer.ID) error, + badPeerErr error, +) { + // Get the remote peer ID. + remotePeerID := conn.RemotePeer() + + // Set the peer to disconnecting state. + s.peers.SetConnectionState(remotePeerID, peers.Disconnecting) + + // Only attempt a goodbye if we are still connected to the peer. + if s.host.Network().Connectedness(remotePeerID) == network.Connected { + if err := goodByeFunc(context.TODO(), remotePeerID); err != nil { + log.WithError(err).Error("Unable to disconnect from peer") + } + } + + log. + WithError(badPeerErr). + WithFields(logrus.Fields{ + "multiaddr": peerMultiaddrString(conn), + "direction": conn.Stat().Direction.String(), + "remainingActivePeers": len(s.peers.Active()), + }). + Debug("Initiate peer disconnection") + + s.peers.SetConnectionState(remotePeerID, peers.Disconnected) +} + // AddConnectionHandler adds a callback function which handles the connection with a // newly added peer. It performs a handshake with that peer by sending a hello request // and validating the response from the peer. @@ -57,18 +97,9 @@ func (s *Service) AddConnectionHandler(reqFunc, goodByeFunc func(ctx context.Con } s.host.Network().Notify(&network.NotifyBundle{ - ConnectedF: func(net network.Network, conn network.Conn) { + ConnectedF: func(_ network.Network, conn network.Conn) { remotePeer := conn.RemotePeer() - disconnectFromPeer := func() { - s.peers.SetConnectionState(remotePeer, peers.PeerDisconnecting) - // Only attempt a goodbye if we are still connected to the peer. - if s.host.Network().Connectedness(remotePeer) == network.Connected { - if err := goodByeFunc(context.TODO(), remotePeer); err != nil { - log.WithError(err).Error("Unable to disconnect from peer") - } - } - s.peers.SetConnectionState(remotePeer, peers.PeerDisconnected) - } + // Connection handler must be non-blocking as part of libp2p design. go func() { if peerHandshaking(remotePeer) { @@ -77,28 +108,21 @@ func (s *Service) AddConnectionHandler(reqFunc, goodByeFunc func(ctx context.Con return } defer peerFinished(remotePeer) + // Handle the various pre-existing conditions that will result in us not handshaking. peerConnectionState, err := s.peers.ConnectionState(remotePeer) - if err == nil && (peerConnectionState == peers.PeerConnected || peerConnectionState == peers.PeerConnecting) { + if err == nil && (peerConnectionState == peers.Connected || peerConnectionState == peers.Connecting) { log.WithField("currentState", peerConnectionState).WithField("reason", "already active").Trace("Ignoring connection request") return } + s.peers.Add(nil /* ENR */, remotePeer, conn.RemoteMultiaddr(), conn.Stat().Direction) + // Defensive check in the event we still get a bad peer. - if s.peers.IsBad(remotePeer) { - log.WithField("reason", "bad peer").Trace("Ignoring connection request") - disconnectFromPeer() + if err := s.peers.IsBad(remotePeer); err != nil { + s.disconnectFromPeerOnError(conn, goodByeFunc, err) return } - validPeerConnection := func() { - s.peers.SetConnectionState(conn.RemotePeer(), peers.PeerConnected) - // Go through the handshake process. - log.WithFields(logrus.Fields{ - "direction": conn.Stat().Direction, - "multiAddr": peerMultiaddrString(conn), - "activePeers": len(s.peers.Active()), - }).Debug("Peer connected") - } // Do not perform handshake on inbound dials. if conn.Stat().Direction == network.DirInbound { @@ -117,63 +141,80 @@ func (s *Service) AddConnectionHandler(reqFunc, goodByeFunc func(ctx context.Con // If peer hasn't sent a status request, we disconnect with them if _, err := s.peers.ChainState(remotePeer); errors.Is(err, peerdata.ErrPeerUnknown) || errors.Is(err, peerdata.ErrNoPeerStatus) { statusMessageMissing.Inc() - disconnectFromPeer() + s.disconnectFromPeerOnError(conn, goodByeFunc, errors.Wrap(err, "chain state")) return } + if peerExists { updated, err := s.peers.ChainStateLastUpdated(remotePeer) if err != nil { - disconnectFromPeer() + s.disconnectFromPeerOnError(conn, goodByeFunc, errors.Wrap(err, "chain state last updated")) return } - // exit if we don't receive any current status messages from - // peer. - if updated.IsZero() || !updated.After(currentTime) { - disconnectFromPeer() + + // Exit if we don't receive any current status messages from peer. + if updated.IsZero() { + s.disconnectFromPeerOnError(conn, goodByeFunc, errors.New("is zero")) + return + } + + if updated.Before(currentTime) { + s.disconnectFromPeerOnError(conn, goodByeFunc, errors.New("did not update")) return } } - validPeerConnection() + + s.connectToPeer(conn) return } - s.peers.SetConnectionState(conn.RemotePeer(), peers.PeerConnecting) + s.peers.SetConnectionState(conn.RemotePeer(), peers.Connecting) if err := reqFunc(context.TODO(), conn.RemotePeer()); err != nil && !errors.Is(err, io.EOF) { - log.WithError(err).Trace("Handshake failed") - disconnectFromPeer() + s.disconnectFromPeerOnError(conn, goodByeFunc, err) return } - validPeerConnection() + + s.connectToPeer(conn) }() }, }) } -// AddDisconnectionHandler disconnects from peers. It handles updating the peer status. +// AddDisconnectionHandler disconnects from peers. It handles updating the peer status. // This also calls the handler responsible for maintaining other parts of the sync or p2p system. func (s *Service) AddDisconnectionHandler(handler func(ctx context.Context, id peer.ID) error) { s.host.Network().Notify(&network.NotifyBundle{ DisconnectedF: func(net network.Network, conn network.Conn) { - log := log.WithField("multiAddr", peerMultiaddrString(conn)) + peerID := conn.RemotePeer() + + log.WithFields(logrus.Fields{ + "multiAddr": peerMultiaddrString(conn), + "direction": conn.Stat().Direction.String(), + }) // Must be handled in a goroutine as this callback cannot be blocking. go func() { // Exit early if we are still connected to the peer. - if net.Connectedness(conn.RemotePeer()) == network.Connected { + if net.Connectedness(peerID) == network.Connected { return } - priorState, err := s.peers.ConnectionState(conn.RemotePeer()) + + priorState, err := s.peers.ConnectionState(peerID) if err != nil { // Can happen if the peer has already disconnected, so... - priorState = peers.PeerDisconnected + priorState = peers.Disconnected } - s.peers.SetConnectionState(conn.RemotePeer(), peers.PeerDisconnecting) + + s.peers.SetConnectionState(peerID, peers.Disconnecting) if err := handler(context.TODO(), conn.RemotePeer()); err != nil { log.WithError(err).Error("Disconnect handler failed") } - s.peers.SetConnectionState(conn.RemotePeer(), peers.PeerDisconnected) + + s.peers.SetConnectionState(peerID, peers.Disconnected) + // Only log disconnections if we were fully connected. - if priorState == peers.PeerConnected { - log.WithField("activePeers", len(s.peers.Active())).Debug("Peer disconnected") + if priorState == peers.Connected { + activePeersCount := len(s.peers.Active()) + log.WithField("remainingActivePeers", activePeersCount).Debug("Peer disconnected") } }() }, diff --git a/beacon-chain/p2p/interfaces.go b/beacon-chain/p2p/interfaces.go index a41d1768ab55..2f9a1d0ce2ad 100644 --- a/beacon-chain/p2p/interfaces.go +++ b/beacon-chain/p2p/interfaces.go @@ -82,7 +82,7 @@ type PeerManager interface { Host() host.Host ENR() *enr.Record DiscoveryAddresses() ([]multiaddr.Multiaddr, error) - RefreshENR() + RefreshPersistentSubnets() FindPeersWithSubnet(ctx context.Context, topic string, subIndex uint64, threshold int) (bool, error) AddPingMethod(reqFunc func(ctx context.Context, id peer.ID) error) } diff --git a/beacon-chain/p2p/iterator.go b/beacon-chain/p2p/iterator.go deleted file mode 100644 index cd5451ba3048..000000000000 --- a/beacon-chain/p2p/iterator.go +++ /dev/null @@ -1,36 +0,0 @@ -package p2p - -import ( - "context" - - "github.com/ethereum/go-ethereum/p2p/enode" -) - -// filterNodes wraps an iterator such that Next only returns nodes for which -// the 'check' function returns true. This custom implementation also -// checks for context deadlines so that in the event the parent context has -// expired, we do exit from the search rather than perform more network -// lookups for additional peers. -func filterNodes(ctx context.Context, it enode.Iterator, check func(*enode.Node) bool) enode.Iterator { - return &filterIter{ctx, it, check} -} - -type filterIter struct { - context.Context - enode.Iterator - check func(*enode.Node) bool -} - -// Next looks up for the next valid node according to our -// filter criteria. -func (f *filterIter) Next() bool { - for f.Iterator.Next() { - if f.Context.Err() != nil { - return false - } - if f.check(f.Node()) { - return true - } - } - return false -} diff --git a/beacon-chain/p2p/message_id.go b/beacon-chain/p2p/message_id.go index 9ea7091a8642..28355f919789 100644 --- a/beacon-chain/p2p/message_id.go +++ b/beacon-chain/p2p/message_id.go @@ -29,7 +29,7 @@ func MsgID(genesisValidatorsRoot []byte, pmsg *pubsubpb.Message) string { // never be hit. msg := make([]byte, 20) copy(msg, "invalid") - return string(msg) + return bytesutil.UnsafeCastToString(msg) } digest, err := ExtractGossipDigest(*pmsg.Topic) if err != nil { @@ -37,7 +37,7 @@ func MsgID(genesisValidatorsRoot []byte, pmsg *pubsubpb.Message) string { // never be hit. msg := make([]byte, 20) copy(msg, "invalid") - return string(msg) + return bytesutil.UnsafeCastToString(msg) } _, fEpoch, err := forks.RetrieveForkDataFromDigest(digest, genesisValidatorsRoot) if err != nil { @@ -45,7 +45,7 @@ func MsgID(genesisValidatorsRoot []byte, pmsg *pubsubpb.Message) string { // never be hit. msg := make([]byte, 20) copy(msg, "invalid") - return string(msg) + return bytesutil.UnsafeCastToString(msg) } if fEpoch >= params.BeaconConfig().AltairForkEpoch { return postAltairMsgID(pmsg, fEpoch) @@ -54,11 +54,11 @@ func MsgID(genesisValidatorsRoot []byte, pmsg *pubsubpb.Message) string { if err != nil { combinedData := append(params.BeaconConfig().MessageDomainInvalidSnappy[:], pmsg.Data...) h := hash.Hash(combinedData) - return string(h[:20]) + return bytesutil.UnsafeCastToString(h[:20]) } combinedData := append(params.BeaconConfig().MessageDomainValidSnappy[:], decodedData...) h := hash.Hash(combinedData) - return string(h[:20]) + return bytesutil.UnsafeCastToString(h[:20]) } // Spec: @@ -93,13 +93,13 @@ func postAltairMsgID(pmsg *pubsubpb.Message, fEpoch primitives.Epoch) string { // should never happen msg := make([]byte, 20) copy(msg, "invalid") - return string(msg) + return bytesutil.UnsafeCastToString(msg) } if uint64(totalLength) > gossipPubSubSize { // this should never happen msg := make([]byte, 20) copy(msg, "invalid") - return string(msg) + return bytesutil.UnsafeCastToString(msg) } combinedData := make([]byte, 0, totalLength) combinedData = append(combinedData, params.BeaconConfig().MessageDomainInvalidSnappy[:]...) @@ -107,7 +107,7 @@ func postAltairMsgID(pmsg *pubsubpb.Message, fEpoch primitives.Epoch) string { combinedData = append(combinedData, topic...) combinedData = append(combinedData, pmsg.Data...) h := hash.Hash(combinedData) - return string(h[:20]) + return bytesutil.UnsafeCastToString(h[:20]) } totalLength, err := math.AddInt( len(params.BeaconConfig().MessageDomainValidSnappy), @@ -120,7 +120,7 @@ func postAltairMsgID(pmsg *pubsubpb.Message, fEpoch primitives.Epoch) string { // should never happen msg := make([]byte, 20) copy(msg, "invalid") - return string(msg) + return bytesutil.UnsafeCastToString(msg) } combinedData := make([]byte, 0, totalLength) combinedData = append(combinedData, params.BeaconConfig().MessageDomainValidSnappy[:]...) @@ -128,5 +128,5 @@ func postAltairMsgID(pmsg *pubsubpb.Message, fEpoch primitives.Epoch) string { combinedData = append(combinedData, topic...) combinedData = append(combinedData, decodedData...) h := hash.Hash(combinedData) - return string(h[:20]) + return bytesutil.UnsafeCastToString(h[:20]) } diff --git a/beacon-chain/p2p/peers/peerdata/store.go b/beacon-chain/p2p/peers/peerdata/store.go index d22d888826ae..1e3f49a38493 100644 --- a/beacon-chain/p2p/peers/peerdata/store.go +++ b/beacon-chain/p2p/peers/peerdata/store.go @@ -23,8 +23,8 @@ var ( ErrNoPeerStatus = errors.New("no chain status for peer") ) -// PeerConnectionState is the state of the connection. -type PeerConnectionState ethpb.ConnectionState +// ConnectionState is the state of the connection. +type ConnectionState ethpb.ConnectionState // StoreConfig holds peer store parameters. type StoreConfig struct { @@ -49,7 +49,7 @@ type PeerData struct { // Network related data. Address ma.Multiaddr Direction network.Direction - ConnState PeerConnectionState + ConnState ConnectionState Enr *enr.Record NextValidTime time.Time // Chain related data. diff --git a/beacon-chain/p2p/peers/peers_test.go b/beacon-chain/p2p/peers/peers_test.go index 47774b307d49..36dc339044ca 100644 --- a/beacon-chain/p2p/peers/peers_test.go +++ b/beacon-chain/p2p/peers/peers_test.go @@ -2,6 +2,7 @@ package peers_test import ( "io" + "os" "testing" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" @@ -28,5 +29,5 @@ func TestMain(m *testing.M) { defer func() { flags.Init(resetFlags) }() - m.Run() + os.Exit(m.Run()) } diff --git a/beacon-chain/p2p/peers/scorers/BUILD.bazel b/beacon-chain/p2p/peers/scorers/BUILD.bazel index e6eb6a277c8e..463ade4fa264 100644 --- a/beacon-chain/p2p/peers/scorers/BUILD.bazel +++ b/beacon-chain/p2p/peers/scorers/BUILD.bazel @@ -20,6 +20,7 @@ go_library( "//crypto/rand:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_libp2p_go_libp2p//core/peer:go_default_library", + "@com_github_pkg_errors//:go_default_library", ], ) diff --git a/beacon-chain/p2p/peers/scorers/bad_responses.go b/beacon-chain/p2p/peers/scorers/bad_responses.go index 73d74ecfc0a6..9e834e25780f 100644 --- a/beacon-chain/p2p/peers/scorers/bad_responses.go +++ b/beacon-chain/p2p/peers/scorers/bad_responses.go @@ -4,6 +4,7 @@ import ( "time" "github.com/libp2p/go-libp2p/core/peer" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/peerdata" ) @@ -61,7 +62,7 @@ func (s *BadResponsesScorer) Score(pid peer.ID) float64 { // scoreNoLock is a lock-free version of Score. func (s *BadResponsesScorer) scoreNoLock(pid peer.ID) float64 { - if s.isBadPeerNoLock(pid) { + if s.isBadPeerNoLock(pid) != nil { return BadPeerScore } score := float64(0) @@ -116,18 +117,24 @@ func (s *BadResponsesScorer) Increment(pid peer.ID) { // IsBadPeer states if the peer is to be considered bad. // If the peer is unknown this will return `false`, which makes using this function easier than returning an error. -func (s *BadResponsesScorer) IsBadPeer(pid peer.ID) bool { +func (s *BadResponsesScorer) IsBadPeer(pid peer.ID) error { s.store.RLock() defer s.store.RUnlock() + return s.isBadPeerNoLock(pid) } // isBadPeerNoLock is lock-free version of IsBadPeer. -func (s *BadResponsesScorer) isBadPeerNoLock(pid peer.ID) bool { +func (s *BadResponsesScorer) isBadPeerNoLock(pid peer.ID) error { if peerData, ok := s.store.PeerData(pid); ok { - return peerData.BadResponses >= s.config.Threshold + if peerData.BadResponses >= s.config.Threshold { + return errors.Errorf("peer exceeded bad responses threshold: got %d, threshold %d", peerData.BadResponses, s.config.Threshold) + } + + return nil } - return false + + return nil } // BadPeers returns the peers that are considered bad. @@ -137,7 +144,7 @@ func (s *BadResponsesScorer) BadPeers() []peer.ID { badPeers := make([]peer.ID, 0) for pid := range s.store.Peers() { - if s.isBadPeerNoLock(pid) { + if s.isBadPeerNoLock(pid) != nil { badPeers = append(badPeers, pid) } } diff --git a/beacon-chain/p2p/peers/scorers/bad_responses_test.go b/beacon-chain/p2p/peers/scorers/bad_responses_test.go index 186a50f55d98..094be28d5f5a 100644 --- a/beacon-chain/p2p/peers/scorers/bad_responses_test.go +++ b/beacon-chain/p2p/peers/scorers/bad_responses_test.go @@ -33,19 +33,19 @@ func TestScorers_BadResponses_Score(t *testing.T) { assert.Equal(t, 0., scorer.Score(pid), "Unexpected score for unregistered peer") scorer.Increment(pid) - assert.Equal(t, false, scorer.IsBadPeer(pid)) + assert.NoError(t, scorer.IsBadPeer(pid)) assert.Equal(t, -2.5, scorer.Score(pid)) scorer.Increment(pid) - assert.Equal(t, false, scorer.IsBadPeer(pid)) + assert.NoError(t, scorer.IsBadPeer(pid)) assert.Equal(t, float64(-5), scorer.Score(pid)) scorer.Increment(pid) - assert.Equal(t, false, scorer.IsBadPeer(pid)) + assert.NoError(t, scorer.IsBadPeer(pid)) assert.Equal(t, float64(-7.5), scorer.Score(pid)) scorer.Increment(pid) - assert.Equal(t, true, scorer.IsBadPeer(pid)) + assert.NotNil(t, scorer.IsBadPeer(pid)) assert.Equal(t, -100.0, scorer.Score(pid)) } @@ -152,17 +152,17 @@ func TestScorers_BadResponses_IsBadPeer(t *testing.T) { }) scorer := peerStatuses.Scorers().BadResponsesScorer() pid := peer.ID("peer1") - assert.Equal(t, false, scorer.IsBadPeer(pid)) + assert.NoError(t, scorer.IsBadPeer(pid)) peerStatuses.Add(nil, pid, nil, network.DirUnknown) - assert.Equal(t, false, scorer.IsBadPeer(pid)) + assert.NoError(t, scorer.IsBadPeer(pid)) for i := 0; i < scorers.DefaultBadResponsesThreshold; i++ { scorer.Increment(pid) if i == scorers.DefaultBadResponsesThreshold-1 { - assert.Equal(t, true, scorer.IsBadPeer(pid), "Unexpected peer status") + assert.NotNil(t, scorer.IsBadPeer(pid), "Unexpected peer status") } else { - assert.Equal(t, false, scorer.IsBadPeer(pid), "Unexpected peer status") + assert.NoError(t, scorer.IsBadPeer(pid), "Unexpected peer status") } } } @@ -185,11 +185,11 @@ func TestScorers_BadResponses_BadPeers(t *testing.T) { scorer.Increment(pids[2]) scorer.Increment(pids[4]) } - assert.Equal(t, false, scorer.IsBadPeer(pids[0]), "Invalid peer status") - assert.Equal(t, true, scorer.IsBadPeer(pids[1]), "Invalid peer status") - assert.Equal(t, true, scorer.IsBadPeer(pids[2]), "Invalid peer status") - assert.Equal(t, false, scorer.IsBadPeer(pids[3]), "Invalid peer status") - assert.Equal(t, true, scorer.IsBadPeer(pids[4]), "Invalid peer status") + assert.NoError(t, scorer.IsBadPeer(pids[0]), "Invalid peer status") + assert.NotNil(t, scorer.IsBadPeer(pids[1]), "Invalid peer status") + assert.NotNil(t, scorer.IsBadPeer(pids[2]), "Invalid peer status") + assert.NoError(t, scorer.IsBadPeer(pids[3]), "Invalid peer status") + assert.NotNil(t, scorer.IsBadPeer(pids[4]), "Invalid peer status") want := []peer.ID{pids[1], pids[2], pids[4]} badPeers := scorer.BadPeers() sort.Slice(badPeers, func(i, j int) bool { diff --git a/beacon-chain/p2p/peers/scorers/block_providers.go b/beacon-chain/p2p/peers/scorers/block_providers.go index 649ff57009e0..9840b9c08157 100644 --- a/beacon-chain/p2p/peers/scorers/block_providers.go +++ b/beacon-chain/p2p/peers/scorers/block_providers.go @@ -177,8 +177,8 @@ func (s *BlockProviderScorer) processedBlocksNoLock(pid peer.ID) uint64 { // Block provider scorer cannot guarantee that lower score of a peer is indeed a sign of a bad peer. // Therefore this scorer never marks peers as bad, and relies on scores to probabilistically sort // out low-scorers (see WeightSorted method). -func (*BlockProviderScorer) IsBadPeer(_ peer.ID) bool { - return false +func (*BlockProviderScorer) IsBadPeer(_ peer.ID) error { + return nil } // BadPeers returns the peers that are considered bad. diff --git a/beacon-chain/p2p/peers/scorers/block_providers_test.go b/beacon-chain/p2p/peers/scorers/block_providers_test.go index bcb2c8d45e36..70b29c05a3df 100644 --- a/beacon-chain/p2p/peers/scorers/block_providers_test.go +++ b/beacon-chain/p2p/peers/scorers/block_providers_test.go @@ -119,7 +119,7 @@ func TestScorers_BlockProvider_Score(t *testing.T) { } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.name, func(*testing.T) { peerStatuses := peers.NewStatus(ctx, &peers.StatusConfig{ PeerLimit: 30, ScorerParams: &scorers.Config{ @@ -224,7 +224,7 @@ func TestScorers_BlockProvider_Sorted(t *testing.T) { }{ { name: "no peers", - update: func(s *scorers.BlockProviderScorer) {}, + update: func(*scorers.BlockProviderScorer) {}, have: []peer.ID{}, want: []peer.ID{}, }, @@ -451,7 +451,7 @@ func TestScorers_BlockProvider_FormatScorePretty(t *testing.T) { }) } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.name, func(*testing.T) { peerStatuses := peerStatusGen() scorer := peerStatuses.Scorers().BlockProviderScorer() if tt.update != nil { @@ -481,8 +481,8 @@ func TestScorers_BlockProvider_BadPeerMarking(t *testing.T) { }) scorer := peerStatuses.Scorers().BlockProviderScorer() - assert.Equal(t, false, scorer.IsBadPeer("peer1"), "Unexpected status for unregistered peer") + assert.NoError(t, scorer.IsBadPeer("peer1"), "Unexpected status for unregistered peer") scorer.IncrementProcessedBlocks("peer1", 64) - assert.Equal(t, false, scorer.IsBadPeer("peer1")) + assert.NoError(t, scorer.IsBadPeer("peer1")) assert.Equal(t, 0, len(scorer.BadPeers())) } diff --git a/beacon-chain/p2p/peers/scorers/gossip_scorer.go b/beacon-chain/p2p/peers/scorers/gossip_scorer.go index 5482ebde74e4..1adec7b9eb87 100644 --- a/beacon-chain/p2p/peers/scorers/gossip_scorer.go +++ b/beacon-chain/p2p/peers/scorers/gossip_scorer.go @@ -2,6 +2,7 @@ package scorers import ( "github.com/libp2p/go-libp2p/core/peer" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/peerdata" pbrpc "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) @@ -51,19 +52,24 @@ func (s *GossipScorer) scoreNoLock(pid peer.ID) float64 { } // IsBadPeer states if the peer is to be considered bad. -func (s *GossipScorer) IsBadPeer(pid peer.ID) bool { +func (s *GossipScorer) IsBadPeer(pid peer.ID) error { s.store.RLock() defer s.store.RUnlock() return s.isBadPeerNoLock(pid) } // isBadPeerNoLock is lock-free version of IsBadPeer. -func (s *GossipScorer) isBadPeerNoLock(pid peer.ID) bool { +func (s *GossipScorer) isBadPeerNoLock(pid peer.ID) error { peerData, ok := s.store.PeerData(pid) if !ok { - return false + return nil } - return peerData.GossipScore < gossipThreshold + + if peerData.GossipScore < gossipThreshold { + return errors.Errorf("gossip score below threshold: got %f - threshold %f", peerData.GossipScore, gossipThreshold) + } + + return nil } // BadPeers returns the peers that are considered bad. @@ -73,7 +79,7 @@ func (s *GossipScorer) BadPeers() []peer.ID { badPeers := make([]peer.ID, 0) for pid := range s.store.Peers() { - if s.isBadPeerNoLock(pid) { + if s.isBadPeerNoLock(pid) != nil { badPeers = append(badPeers, pid) } } diff --git a/beacon-chain/p2p/peers/scorers/gossip_scorer_test.go b/beacon-chain/p2p/peers/scorers/gossip_scorer_test.go index 98fccf38d1d6..f8cbb21e07fe 100644 --- a/beacon-chain/p2p/peers/scorers/gossip_scorer_test.go +++ b/beacon-chain/p2p/peers/scorers/gossip_scorer_test.go @@ -21,7 +21,7 @@ func TestScorers_Gossip_Score(t *testing.T) { }{ { name: "nonexistent peer", - update: func(scorer *scorers.GossipScorer) { + update: func(*scorers.GossipScorer) { }, check: func(scorer *scorers.GossipScorer) { assert.Equal(t, 0.0, scorer.Score("peer1"), "Unexpected score") @@ -34,7 +34,7 @@ func TestScorers_Gossip_Score(t *testing.T) { }, check: func(scorer *scorers.GossipScorer) { assert.Equal(t, -101.0, scorer.Score("peer1"), "Unexpected score") - assert.Equal(t, true, scorer.IsBadPeer("peer1"), "Unexpected good peer") + assert.NotNil(t, scorer.IsBadPeer("peer1"), "Unexpected good peer") }, }, { @@ -44,7 +44,7 @@ func TestScorers_Gossip_Score(t *testing.T) { }, check: func(scorer *scorers.GossipScorer) { assert.Equal(t, 10.0, scorer.Score("peer1"), "Unexpected score") - assert.Equal(t, false, scorer.IsBadPeer("peer1"), "Unexpected bad peer") + assert.Equal(t, nil, scorer.IsBadPeer("peer1"), "Unexpected bad peer") _, _, topicMap, err := scorer.GossipData("peer1") assert.NoError(t, err) assert.Equal(t, uint64(100), topicMap["a"].TimeInMesh, "incorrect time in mesh") @@ -53,7 +53,7 @@ func TestScorers_Gossip_Score(t *testing.T) { } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.name, func(*testing.T) { peerStatuses := peers.NewStatus(ctx, &peers.StatusConfig{ ScorerParams: &scorers.Config{}, }) diff --git a/beacon-chain/p2p/peers/scorers/peer_status.go b/beacon-chain/p2p/peers/scorers/peer_status.go index 5153c0c784dc..6003bb4b71c7 100644 --- a/beacon-chain/p2p/peers/scorers/peer_status.go +++ b/beacon-chain/p2p/peers/scorers/peer_status.go @@ -46,7 +46,7 @@ func (s *PeerStatusScorer) Score(pid peer.ID) float64 { // scoreNoLock is a lock-free version of Score. func (s *PeerStatusScorer) scoreNoLock(pid peer.ID) float64 { - if s.isBadPeerNoLock(pid) { + if s.isBadPeerNoLock(pid) != nil { return BadPeerScore } score := float64(0) @@ -67,30 +67,34 @@ func (s *PeerStatusScorer) scoreNoLock(pid peer.ID) float64 { } // IsBadPeer states if the peer is to be considered bad. -func (s *PeerStatusScorer) IsBadPeer(pid peer.ID) bool { +func (s *PeerStatusScorer) IsBadPeer(pid peer.ID) error { s.store.RLock() defer s.store.RUnlock() + return s.isBadPeerNoLock(pid) } // isBadPeerNoLock is lock-free version of IsBadPeer. -func (s *PeerStatusScorer) isBadPeerNoLock(pid peer.ID) bool { +func (s *PeerStatusScorer) isBadPeerNoLock(pid peer.ID) error { peerData, ok := s.store.PeerData(pid) if !ok { - return false + return nil } + // Mark peer as bad, if the latest error is one of the terminal ones. terminalErrs := []error{ p2ptypes.ErrWrongForkDigestVersion, p2ptypes.ErrInvalidFinalizedRoot, p2ptypes.ErrInvalidRequest, } + for _, err := range terminalErrs { if errors.Is(peerData.ChainStateValidationError, err) { - return true + return err } } - return false + + return nil } // BadPeers returns the peers that are considered bad. @@ -100,7 +104,7 @@ func (s *PeerStatusScorer) BadPeers() []peer.ID { badPeers := make([]peer.ID, 0) for pid := range s.store.Peers() { - if s.isBadPeerNoLock(pid) { + if s.isBadPeerNoLock(pid) != nil { badPeers = append(badPeers, pid) } } diff --git a/beacon-chain/p2p/peers/scorers/peer_status_test.go b/beacon-chain/p2p/peers/scorers/peer_status_test.go index 241749068d60..8fad8f93a264 100644 --- a/beacon-chain/p2p/peers/scorers/peer_status_test.go +++ b/beacon-chain/p2p/peers/scorers/peer_status_test.go @@ -122,7 +122,7 @@ func TestScorers_PeerStatus_Score(t *testing.T) { } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.name, func(*testing.T) { peerStatuses := peers.NewStatus(ctx, &peers.StatusConfig{ ScorerParams: &scorers.Config{}, }) @@ -140,12 +140,12 @@ func TestScorers_PeerStatus_IsBadPeer(t *testing.T) { ScorerParams: &scorers.Config{}, }) pid := peer.ID("peer1") - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer(pid)) - assert.Equal(t, false, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid)) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer(pid)) + assert.NoError(t, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid)) peerStatuses.Scorers().PeerStatusScorer().SetPeerStatus(pid, &pb.Status{}, p2ptypes.ErrWrongForkDigestVersion) - assert.Equal(t, true, peerStatuses.Scorers().IsBadPeer(pid)) - assert.Equal(t, true, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid)) + assert.NotNil(t, peerStatuses.Scorers().IsBadPeer(pid)) + assert.NotNil(t, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid)) } func TestScorers_PeerStatus_BadPeers(t *testing.T) { @@ -155,22 +155,22 @@ func TestScorers_PeerStatus_BadPeers(t *testing.T) { pid1 := peer.ID("peer1") pid2 := peer.ID("peer2") pid3 := peer.ID("peer3") - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer(pid1)) - assert.Equal(t, false, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid1)) - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer(pid2)) - assert.Equal(t, false, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid2)) - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer(pid3)) - assert.Equal(t, false, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid3)) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer(pid1)) + assert.NoError(t, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid1)) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer(pid2)) + assert.NoError(t, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid2)) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer(pid3)) + assert.NoError(t, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid3)) peerStatuses.Scorers().PeerStatusScorer().SetPeerStatus(pid1, &pb.Status{}, p2ptypes.ErrWrongForkDigestVersion) peerStatuses.Scorers().PeerStatusScorer().SetPeerStatus(pid2, &pb.Status{}, nil) peerStatuses.Scorers().PeerStatusScorer().SetPeerStatus(pid3, &pb.Status{}, p2ptypes.ErrWrongForkDigestVersion) - assert.Equal(t, true, peerStatuses.Scorers().IsBadPeer(pid1)) - assert.Equal(t, true, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid1)) - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer(pid2)) - assert.Equal(t, false, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid2)) - assert.Equal(t, true, peerStatuses.Scorers().IsBadPeer(pid3)) - assert.Equal(t, true, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid3)) + assert.NotNil(t, peerStatuses.Scorers().IsBadPeer(pid1)) + assert.NotNil(t, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid1)) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer(pid2)) + assert.NoError(t, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid2)) + assert.NotNil(t, peerStatuses.Scorers().IsBadPeer(pid3)) + assert.NotNil(t, peerStatuses.Scorers().PeerStatusScorer().IsBadPeer(pid3)) assert.Equal(t, 2, len(peerStatuses.Scorers().PeerStatusScorer().BadPeers())) assert.Equal(t, 2, len(peerStatuses.Scorers().BadPeers())) } diff --git a/beacon-chain/p2p/peers/scorers/scorers_test.go b/beacon-chain/p2p/peers/scorers/scorers_test.go index b0fc552a52b7..0e0254893d85 100644 --- a/beacon-chain/p2p/peers/scorers/scorers_test.go +++ b/beacon-chain/p2p/peers/scorers/scorers_test.go @@ -3,6 +3,7 @@ package scorers_test import ( "io" "math" + "os" "testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/scorers" @@ -28,7 +29,7 @@ func TestMain(m *testing.M) { defer func() { flags.Init(resetFlags) }() - m.Run() + os.Exit(m.Run()) } // roundScore returns score rounded in accordance with the score manager's rounding factor. diff --git a/beacon-chain/p2p/peers/scorers/service.go b/beacon-chain/p2p/peers/scorers/service.go index 4ae91fc499ab..108315882cc5 100644 --- a/beacon-chain/p2p/peers/scorers/service.go +++ b/beacon-chain/p2p/peers/scorers/service.go @@ -6,6 +6,7 @@ import ( "time" "github.com/libp2p/go-libp2p/core/peer" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/peerdata" "github.com/prysmaticlabs/prysm/v5/config/features" ) @@ -24,7 +25,7 @@ const BadPeerScore = gossipThreshold // Scorer defines minimum set of methods every peer scorer must expose. type Scorer interface { Score(pid peer.ID) float64 - IsBadPeer(pid peer.ID) bool + IsBadPeer(pid peer.ID) error BadPeers() []peer.ID } @@ -124,26 +125,29 @@ func (s *Service) ScoreNoLock(pid peer.ID) float64 { } // IsBadPeer traverses all the scorers to see if any of them classifies peer as bad. -func (s *Service) IsBadPeer(pid peer.ID) bool { +func (s *Service) IsBadPeer(pid peer.ID) error { s.store.RLock() defer s.store.RUnlock() return s.IsBadPeerNoLock(pid) } // IsBadPeerNoLock is a lock-free version of IsBadPeer. -func (s *Service) IsBadPeerNoLock(pid peer.ID) bool { - if s.scorers.badResponsesScorer.isBadPeerNoLock(pid) { - return true +func (s *Service) IsBadPeerNoLock(pid peer.ID) error { + if err := s.scorers.badResponsesScorer.isBadPeerNoLock(pid); err != nil { + return errors.Wrap(err, "bad responses scorer") } - if s.scorers.peerStatusScorer.isBadPeerNoLock(pid) { - return true + + if err := s.scorers.peerStatusScorer.isBadPeerNoLock(pid); err != nil { + return errors.Wrap(err, "peer status scorer") } + if features.Get().EnablePeerScorer { - if s.scorers.gossipScorer.isBadPeerNoLock(pid) { - return true + if err := s.scorers.gossipScorer.isBadPeerNoLock(pid); err != nil { + return errors.Wrap(err, "gossip scorer") } } - return false + + return nil } // BadPeers returns the peers that are considered bad by any of registered scorers. @@ -153,7 +157,7 @@ func (s *Service) BadPeers() []peer.ID { badPeers := make([]peer.ID, 0) for pid := range s.store.Peers() { - if s.IsBadPeerNoLock(pid) { + if s.IsBadPeerNoLock(pid) != nil { badPeers = append(badPeers, pid) } } diff --git a/beacon-chain/p2p/peers/scorers/service_test.go b/beacon-chain/p2p/peers/scorers/service_test.go index f7f7aa9c5079..2e28838d30cf 100644 --- a/beacon-chain/p2p/peers/scorers/service_test.go +++ b/beacon-chain/p2p/peers/scorers/service_test.go @@ -100,7 +100,7 @@ func TestScorers_Service_Score(t *testing.T) { return scores } - pack := func(scorer *scorers.Service, s1, s2, s3 float64) map[string]float64 { + pack := func(_ *scorers.Service, s1, s2, s3 float64) map[string]float64 { return map[string]float64{ "peer1": roundScore(s1), "peer2": roundScore(s2), @@ -237,7 +237,7 @@ func TestScorers_Service_loop(t *testing.T) { for i := 0; i < s1.Params().Threshold+5; i++ { s1.Increment(pid1) } - assert.Equal(t, true, s1.IsBadPeer(pid1), "Peer should be marked as bad") + assert.NotNil(t, s1.IsBadPeer(pid1), "Peer should be marked as bad") s2.IncrementProcessedBlocks("peer1", 221) assert.Equal(t, uint64(221), s2.ProcessedBlocks("peer1")) @@ -252,7 +252,7 @@ func TestScorers_Service_loop(t *testing.T) { for { select { case <-ticker.C: - if s1.IsBadPeer(pid1) == false && s2.ProcessedBlocks("peer1") == 0 { + if s1.IsBadPeer(pid1) == nil && s2.ProcessedBlocks("peer1") == 0 { return } case <-ctx.Done(): @@ -263,7 +263,7 @@ func TestScorers_Service_loop(t *testing.T) { }() <-done - assert.Equal(t, false, s1.IsBadPeer(pid1), "Peer should not be marked as bad") + assert.NoError(t, s1.IsBadPeer(pid1), "Peer should not be marked as bad") assert.Equal(t, uint64(0), s2.ProcessedBlocks("peer1"), "No blocks are expected") } @@ -278,10 +278,10 @@ func TestScorers_Service_IsBadPeer(t *testing.T) { }, }) - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer("peer1")) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer("peer1")) peerStatuses.Scorers().BadResponsesScorer().Increment("peer1") peerStatuses.Scorers().BadResponsesScorer().Increment("peer1") - assert.Equal(t, true, peerStatuses.Scorers().IsBadPeer("peer1")) + assert.NotNil(t, peerStatuses.Scorers().IsBadPeer("peer1")) } func TestScorers_Service_BadPeers(t *testing.T) { @@ -295,16 +295,16 @@ func TestScorers_Service_BadPeers(t *testing.T) { }, }) - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer("peer1")) - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer("peer2")) - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer("peer3")) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer("peer1")) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer("peer2")) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer("peer3")) assert.Equal(t, 0, len(peerStatuses.Scorers().BadPeers())) for _, pid := range []peer.ID{"peer1", "peer3"} { peerStatuses.Scorers().BadResponsesScorer().Increment(pid) peerStatuses.Scorers().BadResponsesScorer().Increment(pid) } - assert.Equal(t, true, peerStatuses.Scorers().IsBadPeer("peer1")) - assert.Equal(t, false, peerStatuses.Scorers().IsBadPeer("peer2")) - assert.Equal(t, true, peerStatuses.Scorers().IsBadPeer("peer3")) + assert.NotNil(t, peerStatuses.Scorers().IsBadPeer("peer1")) + assert.NoError(t, peerStatuses.Scorers().IsBadPeer("peer2")) + assert.NotNil(t, peerStatuses.Scorers().IsBadPeer("peer3")) assert.Equal(t, 2, len(peerStatuses.Scorers().BadPeers())) } diff --git a/beacon-chain/p2p/peers/status.go b/beacon-chain/p2p/peers/status.go index 3dda2df28815..a2dea993e142 100644 --- a/beacon-chain/p2p/peers/status.go +++ b/beacon-chain/p2p/peers/status.go @@ -34,6 +34,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" + "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/peerdata" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/scorers" @@ -49,14 +50,14 @@ import ( ) const ( - // PeerDisconnected means there is no connection to the peer. - PeerDisconnected peerdata.PeerConnectionState = iota - // PeerDisconnecting means there is an on-going attempt to disconnect from the peer. - PeerDisconnecting - // PeerConnected means the peer has an active connection. - PeerConnected - // PeerConnecting means there is an on-going attempt to connect to the peer. - PeerConnecting + // Disconnected means there is no connection to the peer. + Disconnected peerdata.ConnectionState = iota + // Disconnecting means there is an on-going attempt to disconnect from the peer. + Disconnecting + // Connected means the peer has an active connection. + Connected + // Connecting means there is an on-going attempt to connect to the peer. + Connecting ) const ( @@ -117,6 +118,15 @@ func NewStatus(ctx context.Context, config *StatusConfig) *Status { } } +func (p *Status) UpdateENR(record *enr.Record, pid peer.ID) { + p.store.Lock() + defer p.store.Unlock() + + if peerData, ok := p.store.PeerData(pid); ok { + peerData.Enr = record + } +} + // Scorers exposes peer scoring management service. func (p *Status) Scorers() *scorers.Service { return p.scorers @@ -150,7 +160,7 @@ func (p *Status) Add(record *enr.Record, pid peer.ID, address ma.Multiaddr, dire Address: address, Direction: direction, // Peers start disconnected; state will be updated when the handshake process begins. - ConnState: PeerDisconnected, + ConnState: Disconnected, } if record != nil { peerData.Enr = record @@ -212,7 +222,7 @@ func (p *Status) IsActive(pid peer.ID) bool { defer p.store.RUnlock() peerData, ok := p.store.PeerData(pid) - return ok && (peerData.ConnState == PeerConnected || peerData.ConnState == PeerConnecting) + return ok && (peerData.ConnState == Connected || peerData.ConnState == Connecting) } // IsAboveInboundLimit checks if we are above our current inbound @@ -222,7 +232,7 @@ func (p *Status) IsAboveInboundLimit() bool { defer p.store.RUnlock() totalInbound := 0 for _, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnected && + if peerData.ConnState == Connected && peerData.Direction == network.DirInbound { totalInbound += 1 } @@ -286,7 +296,7 @@ func (p *Status) SubscribedToSubnet(index uint64) []peer.ID { peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { // look at active peers - connectedStatus := peerData.ConnState == PeerConnecting || peerData.ConnState == PeerConnected + connectedStatus := peerData.ConnState == Connecting || peerData.ConnState == Connected if connectedStatus && peerData.MetaData != nil && !peerData.MetaData.IsNil() && peerData.MetaData.AttnetsBitfield() != nil { indices := indicesFromBitfield(peerData.MetaData.AttnetsBitfield()) for _, idx := range indices { @@ -301,7 +311,7 @@ func (p *Status) SubscribedToSubnet(index uint64) []peer.ID { } // SetConnectionState sets the connection state of the given remote peer. -func (p *Status) SetConnectionState(pid peer.ID, state peerdata.PeerConnectionState) { +func (p *Status) SetConnectionState(pid peer.ID, state peerdata.ConnectionState) { p.store.Lock() defer p.store.Unlock() @@ -311,14 +321,14 @@ func (p *Status) SetConnectionState(pid peer.ID, state peerdata.PeerConnectionSt // ConnectionState gets the connection state of the given remote peer. // This will error if the peer does not exist. -func (p *Status) ConnectionState(pid peer.ID) (peerdata.PeerConnectionState, error) { +func (p *Status) ConnectionState(pid peer.ID) (peerdata.ConnectionState, error) { p.store.RLock() defer p.store.RUnlock() if peerData, ok := p.store.PeerData(pid); ok { return peerData.ConnState, nil } - return PeerDisconnected, peerdata.ErrPeerUnknown + return Disconnected, peerdata.ErrPeerUnknown } // ChainStateLastUpdated gets the last time the chain state of the given remote peer was updated. @@ -335,19 +345,29 @@ func (p *Status) ChainStateLastUpdated(pid peer.ID) (time.Time, error) { // IsBad states if the peer is to be considered bad (by *any* of the registered scorers). // If the peer is unknown this will return `false`, which makes using this function easier than returning an error. -func (p *Status) IsBad(pid peer.ID) bool { +func (p *Status) IsBad(pid peer.ID) error { p.store.RLock() defer p.store.RUnlock() + return p.isBad(pid) } // isBad is the lock-free version of IsBad. -func (p *Status) isBad(pid peer.ID) bool { +func (p *Status) isBad(pid peer.ID) error { // Do not disconnect from trusted peers. if p.store.IsTrustedPeer(pid) { - return false + return nil } - return p.isfromBadIP(pid) || p.scorers.IsBadPeerNoLock(pid) + + if err := p.isfromBadIP(pid); err != nil { + return errors.Wrap(err, "peer is from a bad IP") + } + + if err := p.scorers.IsBadPeerNoLock(pid); err != nil { + return errors.Wrap(err, "is bad peer no lock") + } + + return nil } // NextValidTime gets the earliest possible time it is to contact/dial @@ -411,7 +431,7 @@ func (p *Status) Connecting() []peer.ID { defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnecting { + if peerData.ConnState == Connecting { peers = append(peers, pid) } } @@ -424,7 +444,7 @@ func (p *Status) Connected() []peer.ID { defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnected { + if peerData.ConnState == Connected { peers = append(peers, pid) } } @@ -450,7 +470,7 @@ func (p *Status) InboundConnected() []peer.ID { defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnected && peerData.Direction == network.DirInbound { + if peerData.ConnState == Connected && peerData.Direction == network.DirInbound { peers = append(peers, pid) } } @@ -463,7 +483,7 @@ func (p *Status) InboundConnectedWithProtocol(protocol InternetProtocol) []peer. defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnected && peerData.Direction == network.DirInbound && strings.Contains(peerData.Address.String(), string(protocol)) { + if peerData.ConnState == Connected && peerData.Direction == network.DirInbound && strings.Contains(peerData.Address.String(), string(protocol)) { peers = append(peers, pid) } } @@ -489,7 +509,7 @@ func (p *Status) OutboundConnected() []peer.ID { defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnected && peerData.Direction == network.DirOutbound { + if peerData.ConnState == Connected && peerData.Direction == network.DirOutbound { peers = append(peers, pid) } } @@ -502,7 +522,7 @@ func (p *Status) OutboundConnectedWithProtocol(protocol InternetProtocol) []peer defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnected && peerData.Direction == network.DirOutbound && strings.Contains(peerData.Address.String(), string(protocol)) { + if peerData.ConnState == Connected && peerData.Direction == network.DirOutbound && strings.Contains(peerData.Address.String(), string(protocol)) { peers = append(peers, pid) } } @@ -515,7 +535,7 @@ func (p *Status) Active() []peer.ID { defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnecting || peerData.ConnState == PeerConnected { + if peerData.ConnState == Connecting || peerData.ConnState == Connected { peers = append(peers, pid) } } @@ -528,7 +548,7 @@ func (p *Status) Disconnecting() []peer.ID { defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerDisconnecting { + if peerData.ConnState == Disconnecting { peers = append(peers, pid) } } @@ -541,7 +561,7 @@ func (p *Status) Disconnected() []peer.ID { defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerDisconnected { + if peerData.ConnState == Disconnected { peers = append(peers, pid) } } @@ -554,7 +574,7 @@ func (p *Status) Inactive() []peer.ID { defer p.store.RUnlock() peers := make([]peer.ID, 0) for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerDisconnecting || peerData.ConnState == PeerDisconnected { + if peerData.ConnState == Disconnecting || peerData.ConnState == Disconnected { peers = append(peers, pid) } } @@ -592,7 +612,7 @@ func (p *Status) Prune() { return } notBadPeer := func(pid peer.ID) bool { - return !p.isBad(pid) + return p.isBad(pid) == nil } notTrustedPeer := func(pid peer.ID) bool { return !p.isTrustedPeers(pid) @@ -605,7 +625,7 @@ func (p *Status) Prune() { // Select disconnected peers with a smaller bad response count. for pid, peerData := range p.store.Peers() { // Should not prune trusted peer or prune the peer dara and unset trusted peer. - if peerData.ConnState == PeerDisconnected && notBadPeer(pid) && notTrustedPeer(pid) { + if peerData.ConnState == Disconnected && notBadPeer(pid) && notTrustedPeer(pid) { peersToPrune = append(peersToPrune, &peerResp{ pid: pid, score: p.Scorers().ScoreNoLock(pid), @@ -657,7 +677,7 @@ func (p *Status) deprecatedPrune() { // Select disconnected peers with a smaller bad response count. for pid, peerData := range p.store.Peers() { // Should not prune trusted peer or prune the peer dara and unset trusted peer. - if peerData.ConnState == PeerDisconnected && notBadPeer(peerData) && notTrustedPeer(pid) { + if peerData.ConnState == Disconnected && notBadPeer(peerData) && notTrustedPeer(pid) { peersToPrune = append(peersToPrune, &peerResp{ pid: pid, badResp: peerData.BadResponses, @@ -814,7 +834,7 @@ func (p *Status) PeersToPrune() []peer.ID { peersToPrune := make([]*peerResp, 0) // Select connected and inbound peers to prune. for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnected && + if peerData.ConnState == Connected && peerData.Direction == network.DirInbound && !p.store.IsTrustedPeer(pid) { peersToPrune = append(peersToPrune, &peerResp{ pid: pid, @@ -880,7 +900,7 @@ func (p *Status) deprecatedPeersToPrune() []peer.ID { peersToPrune := make([]*peerResp, 0) // Select connected and inbound peers to prune. for pid, peerData := range p.store.Peers() { - if peerData.ConnState == PeerConnected && + if peerData.ConnState == Connected && peerData.Direction == network.DirInbound && !p.store.IsTrustedPeer(pid) { peersToPrune = append(peersToPrune, &peerResp{ pid: pid, @@ -982,24 +1002,28 @@ func (p *Status) isTrustedPeers(pid peer.ID) bool { // this method assumes the store lock is acquired before // executing the method. -func (p *Status) isfromBadIP(pid peer.ID) bool { +func (p *Status) isfromBadIP(pid peer.ID) error { peerData, ok := p.store.PeerData(pid) if !ok { - return false + return nil } + if peerData.Address == nil { - return false + return nil } + ip, err := manet.ToIP(peerData.Address) if err != nil { - return true + return errors.Wrap(err, "to ip") } + if val, ok := p.ipTracker[ip.String()]; ok { if val > CollocationLimit { - return true + return errors.Errorf("collocation limit exceeded: got %d - limit %d", val, CollocationLimit) } } - return false + + return nil } func (p *Status) addIpToTracker(pid peer.ID) { diff --git a/beacon-chain/p2p/peers/status_test.go b/beacon-chain/p2p/peers/status_test.go index ae57af71f107..db9b17f5698d 100644 --- a/beacon-chain/p2p/peers/status_test.go +++ b/beacon-chain/p2p/peers/status_test.go @@ -215,7 +215,7 @@ func TestPeerSubscribedToSubnet(t *testing.T) { // Add some peers with different states numPeers := 2 for i := 0; i < numPeers; i++ { - addPeer(t, p, peers.PeerConnected) + addPeer(t, p, peers.Connected) } expectedPeer := p.All()[1] bitV := bitfield.NewBitvector64() @@ -230,7 +230,7 @@ func TestPeerSubscribedToSubnet(t *testing.T) { })) numPeers = 3 for i := 0; i < numPeers; i++ { - addPeer(t, p, peers.PeerDisconnected) + addPeer(t, p, peers.Disconnected) } ps := p.SubscribedToSubnet(2) assert.Equal(t, 1, len(ps), "Unexpected num of peers") @@ -259,7 +259,7 @@ func TestPeerImplicitAdd(t *testing.T) { id, err := peer.Decode("16Uiu2HAkyWZ4Ni1TpvDS8dPxsozmHY85KaiFjodQuV6Tz5tkHVeR") require.NoError(t, err) - connectionState := peers.PeerConnecting + connectionState := peers.Connecting p.SetConnectionState(id, connectionState) resConnectionState, err := p.ConnectionState(id) @@ -347,7 +347,7 @@ func TestPeerBadResponses(t *testing.T) { require.NoError(t, err) } - assert.Equal(t, false, p.IsBad(id), "Peer marked as bad when should be good") + assert.NoError(t, p.IsBad(id), "Peer marked as bad when should be good") address, err := ma.NewMultiaddr("/ip4/213.202.254.180/tcp/13000") require.NoError(t, err, "Failed to create address") @@ -358,25 +358,25 @@ func TestPeerBadResponses(t *testing.T) { resBadResponses, err := scorer.Count(id) require.NoError(t, err) assert.Equal(t, 0, resBadResponses, "Unexpected bad responses") - assert.Equal(t, false, p.IsBad(id), "Peer marked as bad when should be good") + assert.NoError(t, p.IsBad(id), "Peer marked as bad when should be good") scorer.Increment(id) resBadResponses, err = scorer.Count(id) require.NoError(t, err) assert.Equal(t, 1, resBadResponses, "Unexpected bad responses") - assert.Equal(t, false, p.IsBad(id), "Peer marked as bad when should be good") + assert.NoError(t, p.IsBad(id), "Peer marked as bad when should be good") scorer.Increment(id) resBadResponses, err = scorer.Count(id) require.NoError(t, err) assert.Equal(t, 2, resBadResponses, "Unexpected bad responses") - assert.Equal(t, true, p.IsBad(id), "Peer not marked as bad when it should be") + assert.NotNil(t, p.IsBad(id), "Peer not marked as bad when it should be") scorer.Increment(id) resBadResponses, err = scorer.Count(id) require.NoError(t, err) assert.Equal(t, 3, resBadResponses, "Unexpected bad responses") - assert.Equal(t, true, p.IsBad(id), "Peer not marked as bad when it should be") + assert.NotNil(t, p.IsBad(id), "Peer not marked as bad when it should be") } func TestAddMetaData(t *testing.T) { @@ -393,7 +393,7 @@ func TestAddMetaData(t *testing.T) { // Add some peers with different states numPeers := 5 for i := 0; i < numPeers; i++ { - addPeer(t, p, peers.PeerConnected) + addPeer(t, p, peers.Connected) } newPeer := p.All()[2] @@ -422,19 +422,19 @@ func TestPeerConnectionStatuses(t *testing.T) { // Add some peers with different states numPeersDisconnected := 11 for i := 0; i < numPeersDisconnected; i++ { - addPeer(t, p, peers.PeerDisconnected) + addPeer(t, p, peers.Disconnected) } numPeersConnecting := 7 for i := 0; i < numPeersConnecting; i++ { - addPeer(t, p, peers.PeerConnecting) + addPeer(t, p, peers.Connecting) } numPeersConnected := 43 for i := 0; i < numPeersConnected; i++ { - addPeer(t, p, peers.PeerConnected) + addPeer(t, p, peers.Connected) } numPeersDisconnecting := 4 for i := 0; i < numPeersDisconnecting; i++ { - addPeer(t, p, peers.PeerDisconnecting) + addPeer(t, p, peers.Disconnecting) } // Now confirm the states @@ -463,7 +463,7 @@ func TestPeerValidTime(t *testing.T) { numPeersConnected := 6 for i := 0; i < numPeersConnected; i++ { - addPeer(t, p, peers.PeerConnected) + addPeer(t, p, peers.Connected) } allPeers := p.All() @@ -510,10 +510,10 @@ func TestPrune(t *testing.T) { for i := 0; i < p.MaxPeerLimit()+100; i++ { if i%7 == 0 { // Peer added as disconnected. - _ = addPeer(t, p, peers.PeerDisconnected) + _ = addPeer(t, p, peers.Disconnected) } // Peer added to peer handler. - _ = addPeer(t, p, peers.PeerConnected) + _ = addPeer(t, p, peers.Connected) } disPeers := p.Disconnected() @@ -571,23 +571,23 @@ func TestPeerIPTracker(t *testing.T) { if err != nil { t.Fatal(err) } - badPeers = append(badPeers, createPeer(t, p, addr, network.DirUnknown, peerdata.PeerConnectionState(ethpb.ConnectionState_DISCONNECTED))) + badPeers = append(badPeers, createPeer(t, p, addr, network.DirUnknown, peerdata.ConnectionState(ethpb.ConnectionState_DISCONNECTED))) } for _, pr := range badPeers { - assert.Equal(t, true, p.IsBad(pr), "peer with bad ip is not bad") + assert.NotNil(t, p.IsBad(pr), "peer with bad ip is not bad") } // Add in bad peers, so that our records are trimmed out // from the peer store. for i := 0; i < p.MaxPeerLimit()+100; i++ { // Peer added to peer handler. - pid := addPeer(t, p, peers.PeerDisconnected) + pid := addPeer(t, p, peers.Disconnected) p.Scorers().BadResponsesScorer().Increment(pid) } p.Prune() for _, pr := range badPeers { - assert.Equal(t, false, p.IsBad(pr), "peer with good ip is regarded as bad") + assert.NoError(t, p.IsBad(pr), "peer with good ip is regarded as bad") } } @@ -601,8 +601,11 @@ func TestTrimmedOrderedPeers(t *testing.T) { }, }) - expectedTarget := primitives.Epoch(2) - maxPeers := 3 + const ( + expectedTarget = primitives.Epoch(2) + maxPeers = 3 + ) + var mockroot2 [32]byte var mockroot3 [32]byte var mockroot4 [32]byte @@ -611,36 +614,41 @@ func TestTrimmedOrderedPeers(t *testing.T) { copy(mockroot3[:], "three") copy(mockroot4[:], "four") copy(mockroot5[:], "five") + // Peer 1 - pid1 := addPeer(t, p, peers.PeerConnected) + pid1 := addPeer(t, p, peers.Connected) p.SetChainState(pid1, &pb.Status{ HeadSlot: 3 * params.BeaconConfig().SlotsPerEpoch, FinalizedEpoch: 3, FinalizedRoot: mockroot3[:], }) + // Peer 2 - pid2 := addPeer(t, p, peers.PeerConnected) + pid2 := addPeer(t, p, peers.Connected) p.SetChainState(pid2, &pb.Status{ HeadSlot: 4 * params.BeaconConfig().SlotsPerEpoch, FinalizedEpoch: 4, FinalizedRoot: mockroot4[:], }) + // Peer 3 - pid3 := addPeer(t, p, peers.PeerConnected) + pid3 := addPeer(t, p, peers.Connected) p.SetChainState(pid3, &pb.Status{ HeadSlot: 5 * params.BeaconConfig().SlotsPerEpoch, FinalizedEpoch: 5, FinalizedRoot: mockroot5[:], }) + // Peer 4 - pid4 := addPeer(t, p, peers.PeerConnected) + pid4 := addPeer(t, p, peers.Connected) p.SetChainState(pid4, &pb.Status{ HeadSlot: 2 * params.BeaconConfig().SlotsPerEpoch, FinalizedEpoch: 2, FinalizedRoot: mockroot2[:], }) + // Peer 5 - pid5 := addPeer(t, p, peers.PeerConnected) + pid5 := addPeer(t, p, peers.Connected) p.SetChainState(pid5, &pb.Status{ HeadSlot: 2 * params.BeaconConfig().SlotsPerEpoch, FinalizedEpoch: 2, @@ -680,12 +688,12 @@ func TestAtInboundPeerLimit(t *testing.T) { }) for i := 0; i < 15; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirOutbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirOutbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } assert.Equal(t, false, p.IsAboveInboundLimit(), "Inbound limit exceeded") for i := 0; i < 31; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirInbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirInbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } assert.Equal(t, true, p.IsAboveInboundLimit(), "Inbound limit not exceeded") } @@ -705,7 +713,7 @@ func TestPrunePeers(t *testing.T) { }) for i := 0; i < 15; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirOutbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirOutbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } // Assert there are no prunable peers. peersToPrune := p.PeersToPrune() @@ -713,7 +721,7 @@ func TestPrunePeers(t *testing.T) { for i := 0; i < 18; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirInbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirInbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } // Assert there are the correct prunable peers. @@ -723,7 +731,7 @@ func TestPrunePeers(t *testing.T) { // Add in more peers. for i := 0; i < 13; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirInbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirInbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } // Set up bad scores for inbound peers. @@ -767,7 +775,7 @@ func TestPrunePeers_TrustedPeers(t *testing.T) { for i := 0; i < 15; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirOutbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirOutbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } // Assert there are no prunable peers. peersToPrune := p.PeersToPrune() @@ -775,7 +783,7 @@ func TestPrunePeers_TrustedPeers(t *testing.T) { for i := 0; i < 18; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirInbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirInbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } // Assert there are the correct prunable peers. @@ -785,7 +793,7 @@ func TestPrunePeers_TrustedPeers(t *testing.T) { // Add in more peers. for i := 0; i < 13; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirInbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirInbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } var trustedPeers []peer.ID @@ -821,7 +829,7 @@ func TestPrunePeers_TrustedPeers(t *testing.T) { // Add more peers to check if trusted peers can be pruned after they are deleted from trusted peer set. for i := 0; i < 9; i++ { // Peer added to peer handler. - createPeer(t, p, nil, network.DirInbound, peerdata.PeerConnectionState(ethpb.ConnectionState_CONNECTED)) + createPeer(t, p, nil, network.DirInbound, peerdata.ConnectionState(ethpb.ConnectionState_CONNECTED)) } // Delete trusted peers. @@ -865,14 +873,14 @@ func TestStatus_BestPeer(t *testing.T) { headSlot primitives.Slot finalizedEpoch primitives.Epoch } + tests := []struct { - name string - peers []*peerConfig - limitPeers int - ourFinalizedEpoch primitives.Epoch - targetEpoch primitives.Epoch - // targetEpochSupport denotes how many peers support returned epoch. - targetEpochSupport int + name string + peers []*peerConfig + limitPeers int + ourFinalizedEpoch primitives.Epoch + targetEpoch primitives.Epoch + targetEpochSupport int // Denotes how many peers support returned epoch. }{ { name: "head slot matches finalized epoch", @@ -885,6 +893,7 @@ func TestStatus_BestPeer(t *testing.T) { {finalizedEpoch: 3, headSlot: 3 * params.BeaconConfig().SlotsPerEpoch}, }, limitPeers: 15, + ourFinalizedEpoch: 0, targetEpoch: 4, targetEpochSupport: 4, }, @@ -902,6 +911,7 @@ func TestStatus_BestPeer(t *testing.T) { {finalizedEpoch: 3, headSlot: 4 * params.BeaconConfig().SlotsPerEpoch}, }, limitPeers: 15, + ourFinalizedEpoch: 0, targetEpoch: 4, targetEpochSupport: 4, }, @@ -916,6 +926,7 @@ func TestStatus_BestPeer(t *testing.T) { {finalizedEpoch: 3, headSlot: 42 * params.BeaconConfig().SlotsPerEpoch}, }, limitPeers: 15, + ourFinalizedEpoch: 0, targetEpoch: 4, targetEpochSupport: 4, }, @@ -930,8 +941,8 @@ func TestStatus_BestPeer(t *testing.T) { {finalizedEpoch: 3, headSlot: 46 * params.BeaconConfig().SlotsPerEpoch}, {finalizedEpoch: 6, headSlot: 6 * params.BeaconConfig().SlotsPerEpoch}, }, - ourFinalizedEpoch: 5, limitPeers: 15, + ourFinalizedEpoch: 5, targetEpoch: 6, targetEpochSupport: 1, }, @@ -950,8 +961,8 @@ func TestStatus_BestPeer(t *testing.T) { {finalizedEpoch: 7, headSlot: 7 * params.BeaconConfig().SlotsPerEpoch}, {finalizedEpoch: 8, headSlot: 8 * params.BeaconConfig().SlotsPerEpoch}, }, - ourFinalizedEpoch: 5, limitPeers: 15, + ourFinalizedEpoch: 5, targetEpoch: 6, targetEpochSupport: 5, }, @@ -970,8 +981,8 @@ func TestStatus_BestPeer(t *testing.T) { {finalizedEpoch: 7, headSlot: 7 * params.BeaconConfig().SlotsPerEpoch}, {finalizedEpoch: 8, headSlot: 8 * params.BeaconConfig().SlotsPerEpoch}, }, - ourFinalizedEpoch: 5, limitPeers: 4, + ourFinalizedEpoch: 5, targetEpoch: 6, targetEpochSupport: 4, }, @@ -986,8 +997,8 @@ func TestStatus_BestPeer(t *testing.T) { {finalizedEpoch: 8, headSlot: 8 * params.BeaconConfig().SlotsPerEpoch}, {finalizedEpoch: 8, headSlot: 8 * params.BeaconConfig().SlotsPerEpoch}, }, - ourFinalizedEpoch: 5, limitPeers: 15, + ourFinalizedEpoch: 5, targetEpoch: 8, targetEpochSupport: 3, }, @@ -1002,7 +1013,7 @@ func TestStatus_BestPeer(t *testing.T) { }, }) for _, peerConfig := range tt.peers { - p.SetChainState(addPeer(t, p, peers.PeerConnected), &pb.Status{ + p.SetChainState(addPeer(t, p, peers.Connected), &pb.Status{ FinalizedEpoch: peerConfig.finalizedEpoch, HeadSlot: peerConfig.headSlot, }) @@ -1028,7 +1039,7 @@ func TestBestFinalized_returnsMaxValue(t *testing.T) { for i := 0; i <= maxPeers+100; i++ { p.Add(new(enr.Record), peer.ID(rune(i)), nil, network.DirOutbound) - p.SetConnectionState(peer.ID(rune(i)), peers.PeerConnected) + p.SetConnectionState(peer.ID(rune(i)), peers.Connected) p.SetChainState(peer.ID(rune(i)), &pb.Status{ FinalizedEpoch: 10, }) @@ -1051,7 +1062,7 @@ func TestStatus_BestNonFinalized(t *testing.T) { peerSlots := []primitives.Slot{32, 32, 32, 32, 235, 233, 258, 268, 270} for i, headSlot := range peerSlots { p.Add(new(enr.Record), peer.ID(rune(i)), nil, network.DirOutbound) - p.SetConnectionState(peer.ID(rune(i)), peers.PeerConnected) + p.SetConnectionState(peer.ID(rune(i)), peers.Connected) p.SetChainState(peer.ID(rune(i)), &pb.Status{ HeadSlot: headSlot, }) @@ -1074,17 +1085,17 @@ func TestStatus_CurrentEpoch(t *testing.T) { }, }) // Peer 1 - pid1 := addPeer(t, p, peers.PeerConnected) + pid1 := addPeer(t, p, peers.Connected) p.SetChainState(pid1, &pb.Status{ HeadSlot: params.BeaconConfig().SlotsPerEpoch * 4, }) // Peer 2 - pid2 := addPeer(t, p, peers.PeerConnected) + pid2 := addPeer(t, p, peers.Connected) p.SetChainState(pid2, &pb.Status{ HeadSlot: params.BeaconConfig().SlotsPerEpoch * 5, }) // Peer 3 - pid3 := addPeer(t, p, peers.PeerConnected) + pid3 := addPeer(t, p, peers.Connected) p.SetChainState(pid3, &pb.Status{ HeadSlot: params.BeaconConfig().SlotsPerEpoch * 4, }) @@ -1103,8 +1114,8 @@ func TestInbound(t *testing.T) { }) addr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/33333") require.NoError(t, err) - inbound := createPeer(t, p, addr, network.DirInbound, peers.PeerConnected) - createPeer(t, p, addr, network.DirOutbound, peers.PeerConnected) + inbound := createPeer(t, p, addr, network.DirInbound, peers.Connected) + createPeer(t, p, addr, network.DirOutbound, peers.Connected) result := p.Inbound() require.Equal(t, 1, len(result)) @@ -1123,8 +1134,8 @@ func TestInboundConnected(t *testing.T) { addr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/33333") require.NoError(t, err) - inbound := createPeer(t, p, addr, network.DirInbound, peers.PeerConnected) - createPeer(t, p, addr, network.DirInbound, peers.PeerConnecting) + inbound := createPeer(t, p, addr, network.DirInbound, peers.Connected) + createPeer(t, p, addr, network.DirInbound, peers.Connecting) result := p.InboundConnected() require.Equal(t, 1, len(result)) @@ -1157,7 +1168,7 @@ func TestInboundConnectedWithProtocol(t *testing.T) { multiaddr, err := ma.NewMultiaddr(addr) require.NoError(t, err) - peer := createPeer(t, p, multiaddr, network.DirInbound, peers.PeerConnected) + peer := createPeer(t, p, multiaddr, network.DirInbound, peers.Connected) expectedTCP[peer.String()] = true } @@ -1166,7 +1177,7 @@ func TestInboundConnectedWithProtocol(t *testing.T) { multiaddr, err := ma.NewMultiaddr(addr) require.NoError(t, err) - peer := createPeer(t, p, multiaddr, network.DirInbound, peers.PeerConnected) + peer := createPeer(t, p, multiaddr, network.DirInbound, peers.Connected) expectedQUIC[peer.String()] = true } @@ -1203,8 +1214,8 @@ func TestOutbound(t *testing.T) { }) addr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/33333") require.NoError(t, err) - createPeer(t, p, addr, network.DirInbound, peers.PeerConnected) - outbound := createPeer(t, p, addr, network.DirOutbound, peers.PeerConnected) + createPeer(t, p, addr, network.DirInbound, peers.Connected) + outbound := createPeer(t, p, addr, network.DirOutbound, peers.Connected) result := p.Outbound() require.Equal(t, 1, len(result)) @@ -1223,8 +1234,8 @@ func TestOutboundConnected(t *testing.T) { addr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/33333") require.NoError(t, err) - inbound := createPeer(t, p, addr, network.DirOutbound, peers.PeerConnected) - createPeer(t, p, addr, network.DirOutbound, peers.PeerConnecting) + inbound := createPeer(t, p, addr, network.DirOutbound, peers.Connected) + createPeer(t, p, addr, network.DirOutbound, peers.Connecting) result := p.OutboundConnected() require.Equal(t, 1, len(result)) @@ -1257,7 +1268,7 @@ func TestOutboundConnectedWithProtocol(t *testing.T) { multiaddr, err := ma.NewMultiaddr(addr) require.NoError(t, err) - peer := createPeer(t, p, multiaddr, network.DirOutbound, peers.PeerConnected) + peer := createPeer(t, p, multiaddr, network.DirOutbound, peers.Connected) expectedTCP[peer.String()] = true } @@ -1266,7 +1277,7 @@ func TestOutboundConnectedWithProtocol(t *testing.T) { multiaddr, err := ma.NewMultiaddr(addr) require.NoError(t, err) - peer := createPeer(t, p, multiaddr, network.DirOutbound, peers.PeerConnected) + peer := createPeer(t, p, multiaddr, network.DirOutbound, peers.Connected) expectedQUIC[peer.String()] = true } @@ -1293,7 +1304,7 @@ func TestOutboundConnectedWithProtocol(t *testing.T) { } // addPeer is a helper to add a peer with a given connection state) -func addPeer(t *testing.T, p *peers.Status, state peerdata.PeerConnectionState) peer.ID { +func addPeer(t *testing.T, p *peers.Status, state peerdata.ConnectionState) peer.ID { // Set up some peers with different states mhBytes := []byte{0x11, 0x04} idBytes := make([]byte, 4) @@ -1312,7 +1323,7 @@ func addPeer(t *testing.T, p *peers.Status, state peerdata.PeerConnectionState) } func createPeer(t *testing.T, p *peers.Status, addr ma.Multiaddr, - dir network.Direction, state peerdata.PeerConnectionState) peer.ID { + dir network.Direction, state peerdata.ConnectionState) peer.ID { mhBytes := []byte{0x11, 0x04} idBytes := make([]byte, 4) _, err := rand.Read(idBytes) diff --git a/beacon-chain/p2p/pubsub.go b/beacon-chain/p2p/pubsub.go index 3549841c9034..f978b9e7e548 100644 --- a/beacon-chain/p2p/pubsub.go +++ b/beacon-chain/p2p/pubsub.go @@ -165,14 +165,14 @@ func (s *Service) pubsubOptions() []pubsub.Option { func parsePeersEnr(peers []string) ([]peer.AddrInfo, error) { addrs, err := PeersFromStringAddrs(peers) if err != nil { - return nil, fmt.Errorf("Cannot convert peers raw ENRs into multiaddresses: %w", err) + return nil, fmt.Errorf("cannot convert peers raw ENRs into multiaddresses: %w", err) } if len(addrs) == 0 { - return nil, fmt.Errorf("Converting peers raw ENRs into multiaddresses resulted in an empty list") + return nil, fmt.Errorf("converting peers raw ENRs into multiaddresses resulted in an empty list") } directAddrInfos, err := peer.AddrInfosFromP2pAddrs(addrs...) if err != nil { - return nil, fmt.Errorf("Cannot convert peers multiaddresses into AddrInfos: %w", err) + return nil, fmt.Errorf("cannot convert peers multiaddresses into AddrInfos: %w", err) } return directAddrInfos, nil } @@ -182,6 +182,7 @@ func pubsubGossipParam() pubsub.GossipSubParams { gParams := pubsub.DefaultGossipSubParams() gParams.Dlo = gossipSubDlo gParams.D = gossipSubD + gParams.Dhi = gossipSubDhi gParams.HeartbeatInterval = gossipSubHeartbeatInterval gParams.HistoryLength = gossipSubMcacheLen gParams.HistoryGossip = gossipSubMcacheGossip diff --git a/beacon-chain/p2p/pubsub_filter.go b/beacon-chain/p2p/pubsub_filter.go index e02371c587f9..205397b857e4 100644 --- a/beacon-chain/p2p/pubsub_filter.go +++ b/beacon-chain/p2p/pubsub_filter.go @@ -10,15 +10,25 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/encoder" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/network/forks" + "github.com/sirupsen/logrus" ) var _ pubsub.SubscriptionFilter = (*Service)(nil) // It is set at this limit to handle the possibility // of double topic subscriptions at fork boundaries. -// -> 64 Attestation Subnets * 2. -// -> 4 Sync Committee Subnets * 2. -// -> Block,Aggregate,ProposerSlashing,AttesterSlashing,Exits,SyncContribution * 2. +// -> BeaconBlock * 2 = 2 +// -> BeaconAggregateAndProof * 2 = 2 +// -> VoluntaryExit * 2 = 2 +// -> ProposerSlashing * 2 = 2 +// -> AttesterSlashing * 2 = 2 +// -> 64 Beacon Attestation * 2 = 128 +// -> SyncContributionAndProof * 2 = 2 +// -> 4 SyncCommitteeSubnets * 2 = 8 +// -> BlsToExecutionChange * 2 = 2 +// -> 6 BlobSidecar * 2 = 12 +// ------------------------------------- +// TOTAL = 162 const pubsubSubscriptionRequestLimit = 200 // CanSubscribe returns true if the topic is of interest and we could subscribe to it. @@ -67,6 +77,11 @@ func (s *Service) CanSubscribe(topic string) bool { log.WithError(err).Error("Could not determine Electra fork digest") return false } + fuluForkDigest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().FuluForkEpoch, s.genesisValidatorsRoot) + if err != nil { + log.WithError(err).Error("Could not determine Fulu fork digest") + return false + } switch parts[2] { case fmt.Sprintf("%x", phase0ForkDigest): case fmt.Sprintf("%x", altairForkDigest): @@ -74,6 +89,7 @@ func (s *Service) CanSubscribe(topic string) bool { case fmt.Sprintf("%x", capellaForkDigest): case fmt.Sprintf("%x", denebForkDigest): case fmt.Sprintf("%x", electraForkDigest): + case fmt.Sprintf("%x", fuluForkDigest): default: return false } @@ -95,8 +111,15 @@ func (s *Service) CanSubscribe(topic string) bool { // FilterIncomingSubscriptions is invoked for all RPCs containing subscription notifications. // This method returns only the topics of interest and may return an error if the subscription // request contains too many topics. -func (s *Service) FilterIncomingSubscriptions(_ peer.ID, subs []*pubsubpb.RPC_SubOpts) ([]*pubsubpb.RPC_SubOpts, error) { +func (s *Service) FilterIncomingSubscriptions(peerID peer.ID, subs []*pubsubpb.RPC_SubOpts) ([]*pubsubpb.RPC_SubOpts, error) { if len(subs) > pubsubSubscriptionRequestLimit { + subsCount := len(subs) + log.WithFields(logrus.Fields{ + "peerID": peerID, + "subscriptionCounts": subsCount, + "subscriptionLimit": pubsubSubscriptionRequestLimit, + }).Debug("Too many incoming subscriptions, filtering them") + return nil, pubsub.ErrTooManySubscriptions } diff --git a/beacon-chain/p2p/pubsub_tracer.go b/beacon-chain/p2p/pubsub_tracer.go index 84ed1b1240f6..898ba6d13cd6 100644 --- a/beacon-chain/p2p/pubsub_tracer.go +++ b/beacon-chain/p2p/pubsub_tracer.go @@ -108,6 +108,7 @@ func (g gossipTracer) setMetricFromRPC(act action, subCtr prometheus.Counter, pu ctrlCtr.WithLabelValues("prune").Add(float64(len(rpc.Control.Prune))) ctrlCtr.WithLabelValues("ihave").Add(float64(len(rpc.Control.Ihave))) ctrlCtr.WithLabelValues("iwant").Add(float64(len(rpc.Control.Iwant))) + ctrlCtr.WithLabelValues("idontwant").Add(float64(len(rpc.Control.Idontwant))) } for _, msg := range rpc.Publish { // For incoming messages from pubsub, we do not record metrics for them as these values diff --git a/beacon-chain/p2p/sender.go b/beacon-chain/p2p/sender.go index cacf5da124ff..0a47345effa2 100644 --- a/beacon-chain/p2p/sender.go +++ b/beacon-chain/p2p/sender.go @@ -10,8 +10,8 @@ import ( "github.com/pkg/errors" ssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // Send a message to a specific peer. The returned stream may be used for reading, but has been @@ -25,7 +25,7 @@ func (s *Service) Send(ctx context.Context, message interface{}, baseTopic strin return nil, err } topic := baseTopic + s.Encoding().ProtocolSuffix() - span.AddAttributes(trace.StringAttribute("topic", topic)) + span.SetAttributes(trace.StringAttribute("topic", topic)) log.WithFields(logrus.Fields{ "topic": topic, diff --git a/beacon-chain/p2p/service.go b/beacon-chain/p2p/service.go index 8192d9b0b67f..877ec4a0c012 100644 --- a/beacon-chain/p2p/service.go +++ b/beacon-chain/p2p/service.go @@ -27,12 +27,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" leakybucket "github.com/prysmaticlabs/prysm/v5/container/leaky-bucket" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" prysmnetwork "github.com/prysmaticlabs/prysm/v5/network" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/metadata" "github.com/prysmaticlabs/prysm/v5/runtime" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) var _ runtime.Service = (*Service)(nil) @@ -43,6 +43,10 @@ var _ runtime.Service = (*Service)(nil) // defined below. var pollingPeriod = 6 * time.Second +// When looking for new nodes, if not enough nodes are found, +// we stop after this spent time. +var batchPeriod = 2 * time.Second + // Refresh rate of ENR set at twice per slot. var refreshRate = slots.DivideSlotBy(2) @@ -71,7 +75,7 @@ type Service struct { subnetsLock map[uint64]*sync.RWMutex subnetsLockLock sync.Mutex // Lock access to subnetsLock initializationLock sync.Mutex - dv5Listener Listener + dv5Listener ListenerRebooter startupErr error ctx context.Context host host.Host @@ -202,12 +206,13 @@ func (s *Service) Start() { s.startupErr = err return } - err = s.connectToBootnodes() - if err != nil { - log.WithError(err).Error("Could not add bootnode to the exclusion list") + + if err := s.connectToBootnodes(); err != nil { + log.WithError(err).Error("Could not connect to boot nodes") s.startupErr = err return } + s.dv5Listener = listener go s.listenForNewNodes() } @@ -226,7 +231,7 @@ func (s *Service) Start() { } // Initialize metadata according to the // current epoch. - s.RefreshENR() + s.RefreshPersistentSubnets() // Periodic functions. async.RunEvery(s.ctx, params.BeaconConfig().TtfbTimeoutDuration(), func() { @@ -234,7 +239,7 @@ func (s *Service) Start() { }) async.RunEvery(s.ctx, 30*time.Minute, s.Peers().Prune) async.RunEvery(s.ctx, time.Duration(params.BeaconConfig().RespTimeout)*time.Second, s.updateMetrics) - async.RunEvery(s.ctx, refreshRate, s.RefreshENR) + async.RunEvery(s.ctx, refreshRate, s.RefreshPersistentSubnets) async.RunEvery(s.ctx, 1*time.Minute, func() { inboundQUICCount := len(s.peers.InboundConnectedWithProtocol(peers.QUIC)) inboundTCPCount := len(s.peers.InboundConnectedWithProtocol(peers.TCP)) @@ -384,12 +389,17 @@ func (s *Service) AddPingMethod(reqFunc func(ctx context.Context, id peer.ID) er s.pingMethodLock.Unlock() } -func (s *Service) pingPeers() { +func (s *Service) pingPeersAndLogEnr() { s.pingMethodLock.RLock() defer s.pingMethodLock.RUnlock() + + localENR := s.dv5Listener.Self() + log.WithField("ENR", localENR).Info("New node record") + if s.pingMethod == nil { return } + for _, pid := range s.peers.Connected() { go func(id peer.ID) { if err := s.pingMethod(s.ctx, id); err != nil { @@ -462,8 +472,8 @@ func (s *Service) connectWithPeer(ctx context.Context, info peer.AddrInfo) error if info.ID == s.host.ID() { return nil } - if s.Peers().IsBad(info.ID) { - return errors.New("refused to connect to bad peer") + if err := s.Peers().IsBad(info.ID); err != nil { + return errors.Wrap(err, "refused to connect to bad peer") } ctx, cancel := context.WithTimeout(ctx, maxDialTimeout) defer cancel() diff --git a/beacon-chain/p2p/service_test.go b/beacon-chain/p2p/service_test.go index c09ad1db6407..016cf113211f 100644 --- a/beacon-chain/p2p/service_test.go +++ b/beacon-chain/p2p/service_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/host" @@ -29,6 +28,8 @@ import ( logTest "github.com/sirupsen/logrus/hooks/test" ) +const testPingInterval = 100 * time.Millisecond + type mockListener struct { localNode *enode.LocalNode } @@ -69,6 +70,8 @@ func (mockListener) RandomNodes() enode.Iterator { panic("implement me") } +func (mockListener) RebootListener() error { panic("implement me") } + func createHost(t *testing.T, port int) (host.Host, *ecdsa.PrivateKey, net.IP) { _, pkey := createAddrAndPrivKey(t) ipAddr := net.ParseIP("127.0.0.1") @@ -185,7 +188,7 @@ func TestListenForNewNodes(t *testing.T) { params.SetupTestConfigCleanup(t) // Setup bootnode. notifier := &mock.MockStateNotifier{} - cfg := &Config{StateNotifier: notifier} + cfg := &Config{StateNotifier: notifier, PingInterval: testPingInterval, DisableLivenessCheck: true} port := 2000 cfg.UDPPort = uint(port) _, pkey := createAddrAndPrivKey(t) @@ -201,6 +204,10 @@ func TestListenForNewNodes(t *testing.T) { require.NoError(t, err) defer bootListener.Close() + // Allow bootnode's table to have its initial refresh. This allows + // inbound nodes to be added in. + time.Sleep(5 * time.Second) + // Use shorter period for testing. currentPeriod := pollingPeriod pollingPeriod = 1 * time.Second @@ -210,12 +217,14 @@ func TestListenForNewNodes(t *testing.T) { bootNode := bootListener.Self() - var listeners []*discover.UDPv5 + var listeners []*listenerWrapper var hosts []host.Host // setup other nodes. cs := startup.NewClockSynchronizer() cfg = &Config{ Discv5BootStrapAddrs: []string{bootNode.String()}, + PingInterval: testPingInterval, + DisableLivenessCheck: true, MaxPeers: 30, ClockWaiter: cs, } diff --git a/beacon-chain/p2p/subnets.go b/beacon-chain/p2p/subnets.go index 37ccea8ad998..3bdde2eb249d 100644 --- a/beacon-chain/p2p/subnets.go +++ b/beacon-chain/p2p/subnets.go @@ -2,6 +2,7 @@ package p2p import ( "context" + "math" "strings" "sync" "time" @@ -19,22 +20,24 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/wrapper" "github.com/prysmaticlabs/prysm/v5/crypto/hash" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" - mathutil "github.com/prysmaticlabs/prysm/v5/math" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" + "github.com/sirupsen/logrus" ) -var attestationSubnetCount = params.BeaconConfig().AttestationSubnetCount -var syncCommsSubnetCount = params.BeaconConfig().SyncCommitteeSubnetCount +var ( + attestationSubnetCount = params.BeaconConfig().AttestationSubnetCount + syncCommsSubnetCount = params.BeaconConfig().SyncCommitteeSubnetCount -var attSubnetEnrKey = params.BeaconNetworkConfig().AttSubnetKey -var syncCommsSubnetEnrKey = params.BeaconNetworkConfig().SyncCommsSubnetKey + attSubnetEnrKey = params.BeaconNetworkConfig().AttSubnetKey + syncCommsSubnetEnrKey = params.BeaconNetworkConfig().SyncCommsSubnetKey +) // The value used with the subnet, in order // to create an appropriate key to retrieve // the relevant lock. This is used to differentiate -// sync subnets from attestation subnets. This is deliberately -// chosen as more than 64(attestation subnet count). +// sync subnets from others. This is deliberately +// chosen as more than 64 (attestation subnet count). const syncLockerVal = 100 // The value used with the blob sidecar subnet, in order @@ -44,6 +47,81 @@ const syncLockerVal = 100 // chosen more than sync and attestation subnet combined. const blobSubnetLockerVal = 110 +// nodeFilter return a function that filters nodes based on the subnet topic and subnet index. +func (s *Service) nodeFilter(topic string, index uint64) (func(node *enode.Node) bool, error) { + switch { + case strings.Contains(topic, GossipAttestationMessage): + return s.filterPeerForAttSubnet(index), nil + case strings.Contains(topic, GossipSyncCommitteeMessage): + return s.filterPeerForSyncSubnet(index), nil + case strings.Contains(topic, GossipBlobSidecarMessage): + return s.filterPeerForBlobSubnet(), nil + default: + return nil, errors.Errorf("no subnet exists for provided topic: %s", topic) + } +} + +// searchForPeers performs a network search for peers subscribed to a particular subnet. +// It exits as soon as one of these conditions is met: +// - It looped through `batchSize` nodes. +// - It found `peersToFindCount“ peers corresponding to the `filter` criteria. +// - Iterator is exhausted. +func searchForPeers( + iterator enode.Iterator, + batchPeriod time.Duration, + peersToFindCount uint, + filter func(node *enode.Node) bool, +) []*enode.Node { + nodeFromNodeID := make(map[enode.ID]*enode.Node) + start := time.Now() + + for time.Since(start) < batchPeriod && uint(len(nodeFromNodeID)) < peersToFindCount && iterator.Next() { + node := iterator.Node() + + // Filter out nodes that do not meet the criteria. + if !filter(node) { + continue + } + + // Remove duplicates, keeping the node with higher seq. + prevNode, ok := nodeFromNodeID[node.ID()] + if ok && prevNode.Seq() > node.Seq() { + continue + } + + nodeFromNodeID[node.ID()] = node + } + + // Convert the map to a slice. + nodes := make([]*enode.Node, 0, len(nodeFromNodeID)) + for _, node := range nodeFromNodeID { + nodes = append(nodes, node) + } + + return nodes +} + +// dialPeer dials a peer in a separate goroutine. +func (s *Service) dialPeer(ctx context.Context, wg *sync.WaitGroup, node *enode.Node) { + info, _, err := convertToAddrInfo(node) + if err != nil { + return + } + + if info == nil { + return + } + + wg.Add(1) + go func() { + if err := s.connectWithPeer(ctx, *info); err != nil { + log.WithError(err).Tracef("Could not connect with peer %s", info.String()) + } + + wg.Done() + }() +} + // FindPeersWithSubnet performs a network search for peers // subscribed to a particular subnet. Then it tries to connect // with those peers. This method will block until either: @@ -52,67 +130,104 @@ const blobSubnetLockerVal = 110 // On some edge cases, this method may hang indefinitely while peers // are actually found. In such a case, the user should cancel the context // and re-run the method again. -func (s *Service) FindPeersWithSubnet(ctx context.Context, topic string, - index uint64, threshold int) (bool, error) { +func (s *Service) FindPeersWithSubnet( + ctx context.Context, + topic string, + index uint64, + threshold int, +) (bool, error) { + const minLogInterval = 1 * time.Minute + ctx, span := trace.StartSpan(ctx, "p2p.FindPeersWithSubnet") defer span.End() - span.AddAttributes(trace.Int64Attribute("index", int64(index))) // lint:ignore uintcast -- It's safe to do this for tracing. + span.SetAttributes(trace.Int64Attribute("index", int64(index))) // lint:ignore uintcast -- It's safe to do this for tracing. if s.dv5Listener == nil { - // return if discovery isn't set + // Return if discovery isn't set return false, nil } topic += s.Encoding().ProtocolSuffix() iterator := s.dv5Listener.RandomNodes() defer iterator.Close() - switch { - case strings.Contains(topic, GossipAttestationMessage): - iterator = filterNodes(ctx, iterator, s.filterPeerForAttSubnet(index)) - case strings.Contains(topic, GossipSyncCommitteeMessage): - iterator = filterNodes(ctx, iterator, s.filterPeerForSyncSubnet(index)) - default: - return false, errors.New("no subnet exists for provided topic") + + filter, err := s.nodeFilter(topic, index) + if err != nil { + return false, errors.Wrap(err, "node filter") + } + + peersSummary := func(topic string, threshold int) (int, int) { + // Retrieve how many peers we have for this topic. + peerCountForTopic := len(s.pubsub.ListPeers(topic)) + + // Compute how many peers we are missing to reach the threshold. + missingPeerCountForTopic := max(0, threshold-peerCountForTopic) + + return peerCountForTopic, missingPeerCountForTopic + } + + // Compute how many peers we are missing to reach the threshold. + peerCountForTopic, missingPeerCountForTopic := peersSummary(topic, threshold) + + // Exit early if we have enough peers. + if missingPeerCountForTopic == 0 { + return true, nil } + log := log.WithFields(logrus.Fields{ + "topic": topic, + "targetPeerCount": threshold, + }) + + log.WithField("currentPeerCount", peerCountForTopic).Debug("Searching for new peers for a subnet - start") + + lastLogTime := time.Now() + wg := new(sync.WaitGroup) for { - currNum := len(s.pubsub.ListPeers(topic)) - if currNum >= threshold { - break - } + // If the context is done, we can exit the loop. This is the unhappy path. if err := ctx.Err(); err != nil { - return false, errors.Errorf("unable to find requisite number of peers for topic %s - "+ - "only %d out of %d peers were able to be found", topic, currNum, threshold) + return false, errors.Errorf( + "unable to find requisite number of peers for topic %s - only %d out of %d peers available after searching", + topic, peerCountForTopic, threshold, + ) } - nodeCount := int(params.BeaconNetworkConfig().MinimumPeersInSubnetSearch) + + // Search for new peers in the network. + nodes := searchForPeers(iterator, batchPeriod, uint(missingPeerCountForTopic), filter) + // Restrict dials if limit is applied. + maxConcurrentDials := math.MaxInt if flags.MaxDialIsActive() { - nodeCount = min(nodeCount, flags.Get().MaxConcurrentDials) + maxConcurrentDials = flags.Get().MaxConcurrentDials } - nodes := enode.ReadNodes(iterator, nodeCount) - for _, node := range nodes { - info, _, err := convertToAddrInfo(node) - if err != nil { - continue - } - if info == nil { - continue + // Dial the peers in batches. + for start := 0; start < len(nodes); start += maxConcurrentDials { + stop := min(start+maxConcurrentDials, len(nodes)) + for _, node := range nodes[start:stop] { + s.dialPeer(ctx, wg, node) } - wg.Add(1) - go func() { - if err := s.connectWithPeer(ctx, *info); err != nil { - log.WithError(err).Tracef("Could not connect with peer %s", info.String()) - } - wg.Done() - }() + // Wait for all dials to be completed. + wg.Wait() + } + + peerCountForTopic, missingPeerCountForTopic := peersSummary(topic, threshold) + + // If we have enough peers, we can exit the loop. This is the happy path. + if missingPeerCountForTopic == 0 { + break + } + + if time.Since(lastLogTime) > minLogInterval { + lastLogTime = time.Now() + log.WithField("currentPeerCount", peerCountForTopic).Debug("Searching for new peers for a subnet - continue") } - // Wait for all dials to be completed. - wg.Wait() } + + log.WithField("currentPeerCount", threshold).Debug("Searching for new peers for a subnet - success") return true, nil } @@ -153,14 +268,28 @@ func (s *Service) filterPeerForSyncSubnet(index uint64) func(node *enode.Node) b } } +// returns a method with filters peers specifically for a particular blob subnet. +// All peers are supposed to be subscribed to all blob subnets. +func (s *Service) filterPeerForBlobSubnet() func(_ *enode.Node) bool { + return func(_ *enode.Node) bool { + return true + } +} + // lower threshold to broadcast object compared to searching // for a subnet. So that even in the event of poor peer // connectivity, we can still broadcast an attestation. -func (s *Service) hasPeerWithSubnet(topic string) bool { +func (s *Service) hasPeerWithSubnet(subnetTopic string) bool { // In the event peer threshold is lower, we will choose the lower // threshold. - minPeers := mathutil.Min(1, uint64(flags.Get().MinimumPeersPerSubnet)) - return len(s.pubsub.ListPeers(topic+s.Encoding().ProtocolSuffix())) >= int(minPeers) // lint:ignore uintcast -- Min peers can be safely cast to int. + minPeers := min(1, flags.Get().MinimumPeersPerSubnet) + topic := subnetTopic + s.Encoding().ProtocolSuffix() + peersWithSubnet := s.pubsub.ListPeers(topic) + peersWithSubnetCount := len(peersWithSubnet) + + enoughPeers := peersWithSubnetCount >= minPeers + + return enoughPeers } // Updates the service's discv5 listener record's attestation subnet @@ -354,11 +483,11 @@ func syncBitvector(record *enr.Record) (bitfield.Bitvector4, error) { } // The subnet locker is a map which keeps track of all -// mutexes stored per subnet. This locker is re-used -// between both the attestation and sync subnets. In -// order to differentiate between attestation and sync -// subnets. Sync subnets are stored by (subnet+syncLockerVal). This -// is to prevent conflicts while allowing both subnets +// mutexes stored per subnet. This locker is reused +// between both the attestation, sync and blob subnets. +// Sync subnets are stored by (subnet+syncLockerVal). +// Blob subnets are stored by (subnet+blobSubnetLockerVal). +// This is to prevent conflicts while allowing subnets // to use a single locker. func (s *Service) subnetLocker(i uint64) *sync.RWMutex { s.subnetsLockLock.Lock() diff --git a/beacon-chain/p2p/subnets_test.go b/beacon-chain/p2p/subnets_test.go index 668324025d52..5de61f378499 100644 --- a/beacon-chain/p2p/subnets_test.go +++ b/beacon-chain/p2p/subnets_test.go @@ -66,7 +66,7 @@ func TestStartDiscV5_FindPeersWithSubnet(t *testing.T) { genesisTime := time.Now() bootNodeService := &Service{ - cfg: &Config{UDPPort: 2000, TCPPort: 3000, QUICPort: 3000}, + cfg: &Config{UDPPort: 2000, TCPPort: 3000, QUICPort: 3000, DisableLivenessCheck: true, PingInterval: testPingInterval}, genesisTime: genesisTime, genesisValidatorsRoot: genesisValidatorsRoot, } @@ -78,6 +78,10 @@ func TestStartDiscV5_FindPeersWithSubnet(t *testing.T) { require.NoError(t, err) defer bootListener.Close() + // Allow bootnode's table to have its initial refresh. This allows + // inbound nodes to be added in. + time.Sleep(5 * time.Second) + bootNodeENR := bootListener.Self().String() // Create 3 nodes, each subscribed to a different subnet. @@ -92,6 +96,8 @@ func TestStartDiscV5_FindPeersWithSubnet(t *testing.T) { UDPPort: uint(2000 + i), TCPPort: uint(3000 + i), QUICPort: uint(3000 + i), + PingInterval: testPingInterval, + DisableLivenessCheck: true, }) require.NoError(t, err) @@ -133,6 +139,8 @@ func TestStartDiscV5_FindPeersWithSubnet(t *testing.T) { cfg := &Config{ Discv5BootStrapAddrs: []string{bootNodeENR}, + PingInterval: testPingInterval, + DisableLivenessCheck: true, MaxPeers: 30, UDPPort: 2010, TCPPort: 3010, diff --git a/beacon-chain/p2p/testing/BUILD.bazel b/beacon-chain/p2p/testing/BUILD.bazel index e6c2e8fe9030..55a5357ac2c0 100644 --- a/beacon-chain/p2p/testing/BUILD.bazel +++ b/beacon-chain/p2p/testing/BUILD.bazel @@ -22,9 +22,12 @@ go_library( "//beacon-chain/p2p/peers/scorers:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/metadata:go_default_library", + "//testing/require:go_default_library", "@com_github_ethereum_go_ethereum//crypto:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enode:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enr:go_default_library", + "@com_github_libp2p_go_libp2p//:go_default_library", + "@com_github_libp2p_go_libp2p//config:go_default_library", "@com_github_libp2p_go_libp2p//core:go_default_library", "@com_github_libp2p_go_libp2p//core/connmgr:go_default_library", "@com_github_libp2p_go_libp2p//core/control:go_default_library", @@ -34,8 +37,7 @@ go_library( "@com_github_libp2p_go_libp2p//core/peer:go_default_library", "@com_github_libp2p_go_libp2p//core/peerstore:go_default_library", "@com_github_libp2p_go_libp2p//core/protocol:go_default_library", - "@com_github_libp2p_go_libp2p//p2p/host/blank:go_default_library", - "@com_github_libp2p_go_libp2p//p2p/net/swarm/testing:go_default_library", + "@com_github_libp2p_go_libp2p//p2p/transport/tcp:go_default_library", "@com_github_libp2p_go_libp2p_pubsub//:go_default_library", "@com_github_multiformats_go_multiaddr//:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", diff --git a/beacon-chain/p2p/testing/fuzz_p2p.go b/beacon-chain/p2p/testing/fuzz_p2p.go index 13ba2c1a23f8..b8d91b84a454 100644 --- a/beacon-chain/p2p/testing/fuzz_p2p.go +++ b/beacon-chain/p2p/testing/fuzz_p2p.go @@ -27,148 +27,148 @@ func NewFuzzTestP2P() *FakeP2P { } // Encoding -- fake. -func (_ *FakeP2P) Encoding() encoder.NetworkEncoding { +func (*FakeP2P) Encoding() encoder.NetworkEncoding { return &encoder.SszNetworkEncoder{} } // AddConnectionHandler -- fake. -func (_ *FakeP2P) AddConnectionHandler(_, _ func(ctx context.Context, id peer.ID) error) { +func (*FakeP2P) AddConnectionHandler(_, _ func(ctx context.Context, id peer.ID) error) { } // AddDisconnectionHandler -- fake. -func (_ *FakeP2P) AddDisconnectionHandler(_ func(ctx context.Context, id peer.ID) error) { +func (*FakeP2P) AddDisconnectionHandler(_ func(ctx context.Context, id peer.ID) error) { } // AddPingMethod -- fake. -func (_ *FakeP2P) AddPingMethod(_ func(ctx context.Context, id peer.ID) error) { +func (*FakeP2P) AddPingMethod(_ func(ctx context.Context, id peer.ID) error) { } // PeerID -- fake. -func (_ *FakeP2P) PeerID() peer.ID { +func (*FakeP2P) PeerID() peer.ID { return "fake" } // ENR returns the enr of the local peer. -func (_ *FakeP2P) ENR() *enr.Record { +func (*FakeP2P) ENR() *enr.Record { return new(enr.Record) } // DiscoveryAddresses -- fake -func (_ *FakeP2P) DiscoveryAddresses() ([]multiaddr.Multiaddr, error) { +func (*FakeP2P) DiscoveryAddresses() ([]multiaddr.Multiaddr, error) { return nil, nil } // FindPeersWithSubnet mocks the p2p func. -func (_ *FakeP2P) FindPeersWithSubnet(_ context.Context, _ string, _ uint64, _ int) (bool, error) { +func (*FakeP2P) FindPeersWithSubnet(_ context.Context, _ string, _ uint64, _ int) (bool, error) { return false, nil } -// RefreshENR mocks the p2p func. -func (_ *FakeP2P) RefreshENR() {} +// RefreshPersistentSubnets mocks the p2p func. +func (*FakeP2P) RefreshPersistentSubnets() {} // LeaveTopic -- fake. -func (_ *FakeP2P) LeaveTopic(_ string) error { +func (*FakeP2P) LeaveTopic(_ string) error { return nil } // Metadata -- fake. -func (_ *FakeP2P) Metadata() metadata.Metadata { +func (*FakeP2P) Metadata() metadata.Metadata { return nil } // Peers -- fake. -func (_ *FakeP2P) Peers() *peers.Status { +func (*FakeP2P) Peers() *peers.Status { return nil } // PublishToTopic -- fake. -func (_ *FakeP2P) PublishToTopic(_ context.Context, _ string, _ []byte, _ ...pubsub.PubOpt) error { +func (*FakeP2P) PublishToTopic(_ context.Context, _ string, _ []byte, _ ...pubsub.PubOpt) error { return nil } // Send -- fake. -func (_ *FakeP2P) Send(_ context.Context, _ interface{}, _ string, _ peer.ID) (network.Stream, error) { +func (*FakeP2P) Send(_ context.Context, _ interface{}, _ string, _ peer.ID) (network.Stream, error) { return nil, nil } // PubSub -- fake. -func (_ *FakeP2P) PubSub() *pubsub.PubSub { +func (*FakeP2P) PubSub() *pubsub.PubSub { return nil } // MetadataSeq -- fake. -func (_ *FakeP2P) MetadataSeq() uint64 { +func (*FakeP2P) MetadataSeq() uint64 { return 0 } // SetStreamHandler -- fake. -func (_ *FakeP2P) SetStreamHandler(_ string, _ network.StreamHandler) { +func (*FakeP2P) SetStreamHandler(_ string, _ network.StreamHandler) { } // SubscribeToTopic -- fake. -func (_ *FakeP2P) SubscribeToTopic(_ string, _ ...pubsub.SubOpt) (*pubsub.Subscription, error) { +func (*FakeP2P) SubscribeToTopic(_ string, _ ...pubsub.SubOpt) (*pubsub.Subscription, error) { return nil, nil } // JoinTopic -- fake. -func (_ *FakeP2P) JoinTopic(_ string, _ ...pubsub.TopicOpt) (*pubsub.Topic, error) { +func (*FakeP2P) JoinTopic(_ string, _ ...pubsub.TopicOpt) (*pubsub.Topic, error) { return nil, nil } // Host -- fake. -func (_ *FakeP2P) Host() host.Host { +func (*FakeP2P) Host() host.Host { return nil } // Disconnect -- fake. -func (_ *FakeP2P) Disconnect(_ peer.ID) error { +func (*FakeP2P) Disconnect(_ peer.ID) error { return nil } // Broadcast -- fake. -func (_ *FakeP2P) Broadcast(_ context.Context, _ proto.Message) error { +func (*FakeP2P) Broadcast(_ context.Context, _ proto.Message) error { return nil } // BroadcastAttestation -- fake. -func (_ *FakeP2P) BroadcastAttestation(_ context.Context, _ uint64, _ ethpb.Att) error { +func (*FakeP2P) BroadcastAttestation(_ context.Context, _ uint64, _ ethpb.Att) error { return nil } // BroadcastSyncCommitteeMessage -- fake. -func (_ *FakeP2P) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *ethpb.SyncCommitteeMessage) error { +func (*FakeP2P) BroadcastSyncCommitteeMessage(_ context.Context, _ uint64, _ *ethpb.SyncCommitteeMessage) error { return nil } // BroadcastBlob -- fake. -func (_ *FakeP2P) BroadcastBlob(_ context.Context, _ uint64, _ *ethpb.BlobSidecar) error { +func (*FakeP2P) BroadcastBlob(_ context.Context, _ uint64, _ *ethpb.BlobSidecar) error { return nil } // InterceptPeerDial -- fake. -func (_ *FakeP2P) InterceptPeerDial(peer.ID) (allow bool) { +func (*FakeP2P) InterceptPeerDial(peer.ID) (allow bool) { return true } // InterceptAddrDial -- fake. -func (_ *FakeP2P) InterceptAddrDial(peer.ID, multiaddr.Multiaddr) (allow bool) { +func (*FakeP2P) InterceptAddrDial(peer.ID, multiaddr.Multiaddr) (allow bool) { return true } // InterceptAccept -- fake. -func (_ *FakeP2P) InterceptAccept(_ network.ConnMultiaddrs) (allow bool) { +func (*FakeP2P) InterceptAccept(_ network.ConnMultiaddrs) (allow bool) { return true } // InterceptSecured -- fake. -func (_ *FakeP2P) InterceptSecured(network.Direction, peer.ID, network.ConnMultiaddrs) (allow bool) { +func (*FakeP2P) InterceptSecured(network.Direction, peer.ID, network.ConnMultiaddrs) (allow bool) { return true } // InterceptUpgraded -- fake. -func (_ *FakeP2P) InterceptUpgraded(network.Conn) (allow bool, reason control.DisconnectReason) { +func (*FakeP2P) InterceptUpgraded(network.Conn) (allow bool, reason control.DisconnectReason) { return true, 0 } diff --git a/beacon-chain/p2p/testing/mock_host.go b/beacon-chain/p2p/testing/mock_host.go index 38d66533f3cc..88c75930a656 100644 --- a/beacon-chain/p2p/testing/mock_host.go +++ b/beacon-chain/p2p/testing/mock_host.go @@ -18,12 +18,12 @@ type MockHost struct { } // ID -- -func (_ *MockHost) ID() peer.ID { +func (*MockHost) ID() peer.ID { return "" } // Peerstore -- -func (_ *MockHost) Peerstore() peerstore.Peerstore { +func (*MockHost) Peerstore() peerstore.Peerstore { return nil } @@ -33,46 +33,46 @@ func (m *MockHost) Addrs() []ma.Multiaddr { } // Network -- -func (_ *MockHost) Network() network.Network { +func (*MockHost) Network() network.Network { return nil } // Mux -- -func (_ *MockHost) Mux() protocol.Switch { +func (*MockHost) Mux() protocol.Switch { return nil } // Connect -- -func (_ *MockHost) Connect(_ context.Context, _ peer.AddrInfo) error { +func (*MockHost) Connect(_ context.Context, _ peer.AddrInfo) error { return nil } // SetStreamHandler -- -func (_ *MockHost) SetStreamHandler(_ protocol.ID, _ network.StreamHandler) {} +func (*MockHost) SetStreamHandler(_ protocol.ID, _ network.StreamHandler) {} // SetStreamHandlerMatch -- -func (_ *MockHost) SetStreamHandlerMatch(protocol.ID, func(id protocol.ID) bool, network.StreamHandler) { +func (*MockHost) SetStreamHandlerMatch(protocol.ID, func(id protocol.ID) bool, network.StreamHandler) { } // RemoveStreamHandler -- -func (_ *MockHost) RemoveStreamHandler(_ protocol.ID) {} +func (*MockHost) RemoveStreamHandler(_ protocol.ID) {} // NewStream -- -func (_ *MockHost) NewStream(_ context.Context, _ peer.ID, _ ...protocol.ID) (network.Stream, error) { +func (*MockHost) NewStream(_ context.Context, _ peer.ID, _ ...protocol.ID) (network.Stream, error) { return nil, nil } // Close -- -func (_ *MockHost) Close() error { +func (*MockHost) Close() error { return nil } // ConnManager -- -func (_ *MockHost) ConnManager() connmgr.ConnManager { +func (*MockHost) ConnManager() connmgr.ConnManager { return nil } // EventBus -- -func (_ *MockHost) EventBus() event.Bus { +func (*MockHost) EventBus() event.Bus { return nil } diff --git a/beacon-chain/p2p/testing/mock_peermanager.go b/beacon-chain/p2p/testing/mock_peermanager.go index ffe7d04808b9..a59c76c1739f 100644 --- a/beacon-chain/p2p/testing/mock_peermanager.go +++ b/beacon-chain/p2p/testing/mock_peermanager.go @@ -20,7 +20,7 @@ type MockPeerManager struct { } // Disconnect . -func (_ *MockPeerManager) Disconnect(peer.ID) error { +func (*MockPeerManager) Disconnect(peer.ID) error { return nil } @@ -35,25 +35,25 @@ func (m *MockPeerManager) Host() host.Host { } // ENR . -func (m MockPeerManager) ENR() *enr.Record { +func (m *MockPeerManager) ENR() *enr.Record { return m.Enr } // DiscoveryAddresses . -func (m MockPeerManager) DiscoveryAddresses() ([]multiaddr.Multiaddr, error) { +func (m *MockPeerManager) DiscoveryAddresses() ([]multiaddr.Multiaddr, error) { if m.FailDiscoveryAddr { return nil, errors.New("fail") } return m.DiscoveryAddr, nil } -// RefreshENR . -func (_ MockPeerManager) RefreshENR() {} +// RefreshPersistentSubnets . +func (*MockPeerManager) RefreshPersistentSubnets() {} // FindPeersWithSubnet . -func (_ MockPeerManager) FindPeersWithSubnet(_ context.Context, _ string, _ uint64, _ int) (bool, error) { +func (*MockPeerManager) FindPeersWithSubnet(_ context.Context, _ string, _ uint64, _ int) (bool, error) { return true, nil } // AddPingMethod . -func (_ MockPeerManager) AddPingMethod(_ func(ctx context.Context, id peer.ID) error) {} +func (*MockPeerManager) AddPingMethod(_ func(ctx context.Context, id peer.ID) error) {} diff --git a/beacon-chain/p2p/testing/mock_peersprovider.go b/beacon-chain/p2p/testing/mock_peersprovider.go index d41e4a55b2d2..db36deab8b9e 100644 --- a/beacon-chain/p2p/testing/mock_peersprovider.go +++ b/beacon-chain/p2p/testing/mock_peersprovider.go @@ -16,6 +16,11 @@ import ( log "github.com/sirupsen/logrus" ) +const ( + MockRawPeerId0 = "16Uiu2HAkyWZ4Ni1TpvDS8dPxsozmHY85KaiFjodQuV6Tz5tkHVeR" + MockRawPeerId1 = "16Uiu2HAm4HgJ9N1o222xK61o7LSgToYWoAy1wNTJRkh9gLZapVAy" +) + // MockPeersProvider implements PeersProvider for testing. type MockPeersProvider struct { lock sync.Mutex @@ -50,7 +55,7 @@ func (m *MockPeersProvider) Peers() *peers.Status { }, }) // Pretend we are connected to two peers - id0, err := peer.Decode("16Uiu2HAkyWZ4Ni1TpvDS8dPxsozmHY85KaiFjodQuV6Tz5tkHVeR") + id0, err := peer.Decode(MockRawPeerId0) if err != nil { log.WithError(err).Debug("Cannot decode") } @@ -59,9 +64,9 @@ func (m *MockPeersProvider) Peers() *peers.Status { log.WithError(err).Debug("Cannot decode") } m.peers.Add(createENR(), id0, ma0, network.DirInbound) - m.peers.SetConnectionState(id0, peers.PeerConnected) + m.peers.SetConnectionState(id0, peers.Connected) m.peers.SetChainState(id0, &pb.Status{FinalizedEpoch: 10}) - id1, err := peer.Decode("16Uiu2HAm4HgJ9N1o222xK61o7LSgToYWoAy1wNTJRkh9gLZapVAy") + id1, err := peer.Decode(MockRawPeerId1) if err != nil { log.WithError(err).Debug("Cannot decode") } @@ -70,7 +75,7 @@ func (m *MockPeersProvider) Peers() *peers.Status { log.WithError(err).Debug("Cannot decode") } m.peers.Add(createENR(), id1, ma1, network.DirOutbound) - m.peers.SetConnectionState(id1, peers.PeerConnected) + m.peers.SetConnectionState(id1, peers.Connected) m.peers.SetChainState(id1, &pb.Status{FinalizedEpoch: 11}) } return m.peers diff --git a/beacon-chain/p2p/testing/p2p.go b/beacon-chain/p2p/testing/p2p.go index 19a6c2c9aac3..f6d6117ded10 100644 --- a/beacon-chain/p2p/testing/p2p.go +++ b/beacon-chain/p2p/testing/p2p.go @@ -10,16 +10,18 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/libp2p/go-libp2p" pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/libp2p/go-libp2p/config" core "github.com/libp2p/go-libp2p/core" "github.com/libp2p/go-libp2p/core/control" "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/protocol" - bhost "github.com/libp2p/go-libp2p/p2p/host/blank" - swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing" + "github.com/libp2p/go-libp2p/p2p/transport/tcp" "github.com/multiformats/go-multiaddr" ssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/encoder" @@ -27,19 +29,24 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/scorers" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/metadata" + "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/sirupsen/logrus" "google.golang.org/protobuf/proto" ) // We have to declare this again here to prevent a circular dependency // with the main p2p package. -const metatadataV1Topic = "/eth2/beacon_chain/req/metadata/1" -const metatadataV2Topic = "/eth2/beacon_chain/req/metadata/2" +const ( + metadataV1Topic = "/eth2/beacon_chain/req/metadata/1" + metadataV2Topic = "/eth2/beacon_chain/req/metadata/2" + metadataV3Topic = "/eth2/beacon_chain/req/metadata/3" +) // TestP2P represents a p2p implementation that can be used for testing. type TestP2P struct { t *testing.T BHost host.Host + EnodeID enode.ID pubsub *pubsub.PubSub joinedTopics map[string]*pubsub.Topic BroadcastCalled atomic.Bool @@ -50,9 +57,21 @@ type TestP2P struct { } // NewTestP2P initializes a new p2p test service. -func NewTestP2P(t *testing.T) *TestP2P { +func NewTestP2P(t *testing.T, userOptions ...config.Option) *TestP2P { ctx := context.Background() - h := bhost.NewBlankHost(swarmt.GenSwarm(t, swarmt.OptDisableQUIC)) + options := []config.Option{ + libp2p.ResourceManager(&network.NullResourceManager{}), + libp2p.Transport(tcp.NewTCPTransport), + libp2p.DefaultListenAddrs, + } + + // Favour user options if provided. + if len(userOptions) > 0 { + options = append(userOptions, options...) + } + + h, err := libp2p.New(options...) + require.NoError(t, err) ps, err := pubsub.NewFloodSub(ctx, h, pubsub.WithMessageSigning(false), pubsub.WithStrictSignatureVerification(false), @@ -86,13 +105,17 @@ func (p *TestP2P) Connect(b *TestP2P) { } func connect(a, b host.Host) error { - pinfo := b.Peerstore().PeerInfo(b.ID()) + pinfo := peer.AddrInfo{ + ID: b.ID(), + Addrs: b.Addrs(), + } return a.Connect(context.Background(), pinfo) } // ReceiveRPC simulates an incoming RPC. func (p *TestP2P) ReceiveRPC(topic string, msg proto.Message) { - h := bhost.NewBlankHost(swarmt.GenSwarm(p.t)) + h, err := libp2p.New(libp2p.ResourceManager(&network.NullResourceManager{})) + require.NoError(p.t, err) if err := connect(h, p.BHost); err != nil { p.t.Fatalf("Failed to connect two peers for RPC: %v", err) } @@ -122,7 +145,8 @@ func (p *TestP2P) ReceiveRPC(topic string, msg proto.Message) { // ReceivePubSub simulates an incoming message over pubsub on a given topic. func (p *TestP2P) ReceivePubSub(topic string, msg proto.Message) { - h := bhost.NewBlankHost(swarmt.GenSwarm(p.t)) + h, err := libp2p.New(libp2p.ResourceManager(&network.NullResourceManager{})) + require.NoError(p.t, err) ps, err := pubsub.NewFloodSub(context.Background(), h, pubsub.WithMessageSigning(false), pubsub.WithStrictSignatureVerification(false), @@ -232,7 +256,7 @@ func (p *TestP2P) LeaveTopic(topic string) error { } // Encoding returns ssz encoding. -func (_ *TestP2P) Encoding() encoder.NetworkEncoding { +func (*TestP2P) Encoding() encoder.NetworkEncoding { return &encoder.SszNetworkEncoder{} } @@ -259,34 +283,39 @@ func (p *TestP2P) Host() host.Host { } // ENR returns the enr of the local peer. -func (_ *TestP2P) ENR() *enr.Record { +func (*TestP2P) ENR() *enr.Record { return new(enr.Record) } +// NodeID returns the node id of the local peer. +func (p *TestP2P) NodeID() enode.ID { + return p.EnodeID +} + // DiscoveryAddresses -- -func (_ *TestP2P) DiscoveryAddresses() ([]multiaddr.Multiaddr, error) { +func (*TestP2P) DiscoveryAddresses() ([]multiaddr.Multiaddr, error) { return nil, nil } // AddConnectionHandler handles the connection with a newly connected peer. func (p *TestP2P) AddConnectionHandler(f, _ func(ctx context.Context, id peer.ID) error) { p.BHost.Network().Notify(&network.NotifyBundle{ - ConnectedF: func(net network.Network, conn network.Conn) { + ConnectedF: func(_ network.Network, conn network.Conn) { // Must be handled in a goroutine as this callback cannot be blocking. go func() { p.peers.Add(new(enr.Record), conn.RemotePeer(), conn.RemoteMultiaddr(), conn.Stat().Direction) ctx := context.Background() - p.peers.SetConnectionState(conn.RemotePeer(), peers.PeerConnecting) + p.peers.SetConnectionState(conn.RemotePeer(), peers.Connecting) if err := f(ctx, conn.RemotePeer()); err != nil { logrus.WithError(err).Error("Could not send successful hello rpc request") if err := p.Disconnect(conn.RemotePeer()); err != nil { logrus.WithError(err).Errorf("Unable to close peer %s", conn.RemotePeer()) } - p.peers.SetConnectionState(conn.RemotePeer(), peers.PeerDisconnected) + p.peers.SetConnectionState(conn.RemotePeer(), peers.Disconnected) return } - p.peers.SetConnectionState(conn.RemotePeer(), peers.PeerConnected) + p.peers.SetConnectionState(conn.RemotePeer(), peers.Connected) }() }, }) @@ -295,14 +324,14 @@ func (p *TestP2P) AddConnectionHandler(f, _ func(ctx context.Context, id peer.ID // AddDisconnectionHandler -- func (p *TestP2P) AddDisconnectionHandler(f func(ctx context.Context, id peer.ID) error) { p.BHost.Network().Notify(&network.NotifyBundle{ - DisconnectedF: func(net network.Network, conn network.Conn) { + DisconnectedF: func(_ network.Network, conn network.Conn) { // Must be handled in a goroutine as this callback cannot be blocking. go func() { - p.peers.SetConnectionState(conn.RemotePeer(), peers.PeerDisconnecting) + p.peers.SetConnectionState(conn.RemotePeer(), peers.Disconnecting) if err := f(context.Background(), conn.RemotePeer()); err != nil { logrus.WithError(err).Debug("Unable to invoke callback") } - p.peers.SetConnectionState(conn.RemotePeer(), peers.PeerDisconnected) + p.peers.SetConnectionState(conn.RemotePeer(), peers.Disconnected) }() }, }) @@ -310,6 +339,8 @@ func (p *TestP2P) AddDisconnectionHandler(f func(ctx context.Context, id peer.ID // Send a message to a specific peer. func (p *TestP2P) Send(ctx context.Context, msg interface{}, topic string, pid peer.ID) (network.Stream, error) { + metadataTopics := map[string]bool{metadataV1Topic: true, metadataV2Topic: true, metadataV3Topic: true} + t := topic if t == "" { return nil, fmt.Errorf("protocol doesn't exist for proto message: %v", msg) @@ -319,7 +350,7 @@ func (p *TestP2P) Send(ctx context.Context, msg interface{}, topic string, pid p return nil, err } - if topic != metatadataV1Topic && topic != metatadataV2Topic { + if !metadataTopics[topic] { castedMsg, ok := msg.(ssz.Marshaler) if !ok { p.t.Fatalf("%T doesn't support ssz marshaler", msg) @@ -346,7 +377,7 @@ func (p *TestP2P) Send(ctx context.Context, msg interface{}, topic string, pid p } // Started always returns true. -func (_ *TestP2P) Started() bool { +func (*TestP2P) Started() bool { return true } @@ -356,12 +387,12 @@ func (p *TestP2P) Peers() *peers.Status { } // FindPeersWithSubnet mocks the p2p func. -func (_ *TestP2P) FindPeersWithSubnet(_ context.Context, _ string, _ uint64, _ int) (bool, error) { +func (*TestP2P) FindPeersWithSubnet(_ context.Context, _ string, _ uint64, _ int) (bool, error) { return false, nil } -// RefreshENR mocks the p2p func. -func (_ *TestP2P) RefreshENR() {} +// RefreshPersistentSubnets mocks the p2p func. +func (*TestP2P) RefreshPersistentSubnets() {} // ForkDigest mocks the p2p func. func (p *TestP2P) ForkDigest() ([4]byte, error) { @@ -379,31 +410,31 @@ func (p *TestP2P) MetadataSeq() uint64 { } // AddPingMethod mocks the p2p func. -func (_ *TestP2P) AddPingMethod(_ func(ctx context.Context, id peer.ID) error) { +func (*TestP2P) AddPingMethod(_ func(ctx context.Context, id peer.ID) error) { // no-op } // InterceptPeerDial . -func (_ *TestP2P) InterceptPeerDial(peer.ID) (allow bool) { +func (*TestP2P) InterceptPeerDial(peer.ID) (allow bool) { return true } // InterceptAddrDial . -func (_ *TestP2P) InterceptAddrDial(peer.ID, multiaddr.Multiaddr) (allow bool) { +func (*TestP2P) InterceptAddrDial(peer.ID, multiaddr.Multiaddr) (allow bool) { return true } // InterceptAccept . -func (_ *TestP2P) InterceptAccept(_ network.ConnMultiaddrs) (allow bool) { +func (*TestP2P) InterceptAccept(_ network.ConnMultiaddrs) (allow bool) { return true } // InterceptSecured . -func (_ *TestP2P) InterceptSecured(network.Direction, peer.ID, network.ConnMultiaddrs) (allow bool) { +func (*TestP2P) InterceptSecured(network.Direction, peer.ID, network.ConnMultiaddrs) (allow bool) { return true } // InterceptUpgraded . -func (_ *TestP2P) InterceptUpgraded(network.Conn) (allow bool, reason control.DisconnectReason) { +func (*TestP2P) InterceptUpgraded(network.Conn) (allow bool, reason control.DisconnectReason) { return true, 0 } diff --git a/beacon-chain/p2p/types/object_mapping.go b/beacon-chain/p2p/types/object_mapping.go index e8646b34ee7a..584dfe1e64bf 100644 --- a/beacon-chain/p2p/types/object_mapping.go +++ b/beacon-chain/p2p/types/object_mapping.go @@ -67,7 +67,12 @@ func InitializeDataMaps() { }, bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion): func() (interfaces.ReadOnlySignedBeaconBlock, error) { return blocks.NewSignedBeaconBlock( - ðpb.SignedBeaconBlockElectra{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadElectra{}}}}, + ðpb.SignedBeaconBlockElectra{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadDeneb{}}}}, + ) + }, + bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion): func() (interfaces.ReadOnlySignedBeaconBlock, error) { + return blocks.NewSignedBeaconBlock( + ðpb.SignedBeaconBlockFulu{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadDeneb{}}}}, ) }, } @@ -92,6 +97,9 @@ func InitializeDataMaps() { bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion): func() (metadata.Metadata, error) { return wrapper.WrappedMetadataV1(ðpb.MetaDataV1{}), nil }, + bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion): func() (metadata.Metadata, error) { + return wrapper.WrappedMetadataV1(ðpb.MetaDataV1{}), nil + }, } // Reset our attestation map. @@ -112,7 +120,10 @@ func InitializeDataMaps() { return ðpb.Attestation{}, nil }, bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion): func() (ethpb.Att, error) { - return ðpb.AttestationElectra{}, nil + return ðpb.SingleAttestation{}, nil + }, + bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion): func() (ethpb.Att, error) { + return ðpb.SingleAttestation{}, nil }, } @@ -136,5 +147,8 @@ func InitializeDataMaps() { bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion): func() (ethpb.SignedAggregateAttAndProof, error) { return ðpb.SignedAggregateAttestationAndProofElectra{}, nil }, + bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion): func() (ethpb.SignedAggregateAttAndProof, error) { + return ðpb.SignedAggregateAttestationAndProofElectra{}, nil + }, } } diff --git a/beacon-chain/p2p/utils.go b/beacon-chain/p2p/utils.go index 3295423b8ff1..e4b73cfac97f 100644 --- a/beacon-chain/p2p/utils.go +++ b/beacon-chain/p2p/utils.go @@ -12,10 +12,15 @@ import ( "path" "time" + "github.com/btcsuite/btcd/btcec/v2" + gCrypto "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/peer" "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/wrapper" ecdsaprysm "github.com/prysmaticlabs/prysm/v5/crypto/ecdsa" "github.com/prysmaticlabs/prysm/v5/io/file" @@ -62,6 +67,7 @@ func privKey(cfg *Config) (*ecdsa.PrivateKey, error) { } if defaultKeysExist { + log.WithField("filePath", defaultKeyPath).Info("Reading static P2P private key from a file. To generate a new random private key at every start, please remove this file.") return privKeyFromFile(defaultKeyPath) } @@ -71,8 +77,8 @@ func privKey(cfg *Config) (*ecdsa.PrivateKey, error) { return nil, err } - // If the StaticPeerID flag is not set, return the private key. - if !cfg.StaticPeerID { + // If the StaticPeerID flag is not set and if peerDAS is not enabled, return the private key. + if !(cfg.StaticPeerID || params.PeerDASEnabled()) { return ecdsaprysm.ConvertFromInterfacePrivKey(priv) } @@ -89,7 +95,7 @@ func privKey(cfg *Config) (*ecdsa.PrivateKey, error) { return nil, err } - log.Info("Wrote network key to file") + log.WithField("path", defaultKeyPath).Info("Wrote network key to file") // Read the key from the defaultKeyPath file just written // for the strongest guarantee that the next start will be the same as this one. return privKeyFromFile(defaultKeyPath) @@ -173,3 +179,27 @@ func verifyConnectivity(addr string, port uint, protocol string) { } } } + +// ConvertPeerIDToNodeID converts a peer ID (libp2p) to a node ID (devp2p). +func ConvertPeerIDToNodeID(pid peer.ID) (enode.ID, error) { + // Retrieve the public key object of the peer under "crypto" form. + pubkeyObjCrypto, err := pid.ExtractPublicKey() + if err != nil { + return [32]byte{}, errors.Wrapf(err, "extract public key from peer ID `%s`", pid) + } + + // Extract the bytes representation of the public key. + compressedPubKeyBytes, err := pubkeyObjCrypto.Raw() + if err != nil { + return [32]byte{}, errors.Wrap(err, "public key raw") + } + + // Retrieve the public key object of the peer under "SECP256K1" form. + pubKeyObjSecp256k1, err := btcec.ParsePubKey(compressedPubKeyBytes) + if err != nil { + return [32]byte{}, errors.Wrap(err, "parse public key") + } + + newPubkey := &ecdsa.PublicKey{Curve: gCrypto.S256(), X: pubKeyObjSecp256k1.X(), Y: pubKeyObjSecp256k1.Y()} + return enode.PubkeyToIDV4(newPubkey), nil +} diff --git a/beacon-chain/p2p/utils_test.go b/beacon-chain/p2p/utils_test.go index 7cbb4d40abe4..d50d4b959e6a 100644 --- a/beacon-chain/p2p/utils_test.go +++ b/beacon-chain/p2p/utils_test.go @@ -1,11 +1,11 @@ package p2p import ( - "fmt" "testing" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/libp2p/go-libp2p/core/peer" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -27,7 +27,7 @@ func TestVerifyConnectivity(t *testing.T) { {"123.123.123.123", 19000, false, "Dialing an unreachable IP: 123.123.123.123:19000"}, } for _, tc := range cases { - t.Run(fmt.Sprintf(tc.name), + t.Run(tc.name, func(t *testing.T) { verifyConnectivity(tc.address, tc.port, "tcp") logMessage := "IP address is not accessible" @@ -64,3 +64,19 @@ func TestSerializeENR(t *testing.T) { assert.ErrorContains(t, "could not serialize nil record", err) }) } + +func TestConvertPeerIDToNodeID(t *testing.T) { + const ( + peerIDStr = "16Uiu2HAmRrhnqEfybLYimCiAYer2AtZKDGamQrL1VwRCyeh2YiFc" + expectedNodeIDStr = "eed26c5d2425ab95f57246a5dca87317c41cacee4bcafe8bbe57e5965527c290" + ) + + peerID, err := peer.Decode(peerIDStr) + require.NoError(t, err) + + actualNodeID, err := ConvertPeerIDToNodeID(peerID) + require.NoError(t, err) + + actualNodeIDStr := actualNodeID.String() + require.Equal(t, expectedNodeIDStr, actualNodeIDStr) +} diff --git a/beacon-chain/rpc/BUILD.bazel b/beacon-chain/rpc/BUILD.bazel index b71d0ba51db5..2015e7b5ce51 100644 --- a/beacon-chain/rpc/BUILD.bazel +++ b/beacon-chain/rpc/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "endpoints.go", "log.go", + "metrics.go", "service.go", ], importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc", @@ -55,7 +56,6 @@ go_library( "//io/logs:go_default_library", "//monitoring/tracing:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//tracing/opentracing:go_default_library", @@ -88,7 +88,6 @@ go_test( "//beacon-chain/sync/initial-sync/testing:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", ], diff --git a/beacon-chain/rpc/core/BUILD.bazel b/beacon-chain/rpc/core/BUILD.bazel index 221b83286eb7..b59af8635330 100644 --- a/beacon-chain/rpc/core/BUILD.bazel +++ b/beacon-chain/rpc/core/BUILD.bazel @@ -36,13 +36,13 @@ go_library( "//consensus-types/validator:go_default_library", "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "//time:go_default_library", "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", ], diff --git a/beacon-chain/rpc/core/service.go b/beacon-chain/rpc/core/service.go index 3b1639d2eca8..0a6dd6e1142d 100644 --- a/beacon-chain/rpc/core/service.go +++ b/beacon-chain/rpc/core/service.go @@ -21,7 +21,7 @@ type Service struct { Broadcaster p2p.Broadcaster SyncCommitteePool synccommittee.Pool OperationNotifier opfeed.Notifier - AttestationCache *cache.AttestationCache + AttestationCache *cache.AttestationDataCache StateGen stategen.StateManager P2P p2p.Broadcaster ReplayerBuilder stategen.ReplayerBuilder diff --git a/beacon-chain/rpc/core/validator.go b/beacon-chain/rpc/core/validator.go index 171b55d57419..b533684c2701 100644 --- a/beacon-chain/rpc/core/validator.go +++ b/beacon-chain/rpc/core/validator.go @@ -25,12 +25,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" prysmTime "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "golang.org/x/sync/errgroup" ) @@ -381,21 +381,12 @@ func (s *Service) SubmitSignedAggregateSelectionProof( ctx, span := trace.StartSpan(ctx, "coreService.SubmitSignedAggregateSelectionProof") defer span.End() - if agg == nil { + if agg == nil || agg.IsNil() { return &RpcError{Err: errors.New("signed aggregate request can't be nil"), Reason: BadRequest} } attAndProof := agg.AggregateAttestationAndProof() - if attAndProof == nil { - return &RpcError{Err: errors.New("signed aggregate request can't be nil"), Reason: BadRequest} - } att := attAndProof.AggregateVal() - if att == nil { - return &RpcError{Err: errors.New("signed aggregate request can't be nil"), Reason: BadRequest} - } data := att.GetData() - if data == nil { - return &RpcError{Err: errors.New("signed aggregate request can't be nil"), Reason: BadRequest} - } emptySig := make([]byte, fieldparams.BLSSignatureLength) if bytes.Equal(agg.GetSignature(), emptySig) || bytes.Equal(attAndProof.GetSelectionProof(), emptySig) { return &RpcError{Err: errors.New("signed signatures can't be zero hashes"), Reason: BadRequest} @@ -869,16 +860,9 @@ func (s *Service) ValidatorActiveSetChanges( } } - activeValidatorCount, err := helpers.ActiveValidatorCount(ctx, requestedState, coreTime.CurrentEpoch(requestedState)) - if err != nil { - return nil, &RpcError{ - Err: errors.Wrap(err, "could not get active validator count"), - Reason: Internal, - } - } vs := requestedState.Validators() activatedIndices := validators.ActivatedValidatorIndices(coreTime.CurrentEpoch(requestedState), vs) - exitedIndices, err := validators.ExitedValidatorIndices(coreTime.CurrentEpoch(requestedState), vs, activeValidatorCount) + exitedIndices, err := validators.ExitedValidatorIndices(coreTime.CurrentEpoch(requestedState), vs) if err != nil { return nil, &RpcError{ Err: errors.Wrap(err, "could not determine exited validator indices"), @@ -886,7 +870,7 @@ func (s *Service) ValidatorActiveSetChanges( } } slashedIndices := validators.SlashedValidatorIndices(coreTime.CurrentEpoch(requestedState), vs) - ejectedIndices, err := validators.EjectedValidatorIndices(coreTime.CurrentEpoch(requestedState), vs, activeValidatorCount) + ejectedIndices, err := validators.EjectedValidatorIndices(coreTime.CurrentEpoch(requestedState), vs) if err != nil { return nil, &RpcError{ Err: errors.Wrap(err, "could not determine ejected validator indices"), diff --git a/beacon-chain/rpc/endpoints.go b/beacon-chain/rpc/endpoints.go index 9a67d2d8f38c..e240a1807b29 100644 --- a/beacon-chain/rpc/endpoints.go +++ b/beacon-chain/rpc/endpoints.go @@ -3,7 +3,6 @@ package rpc import ( "net/http" - "github.com/gorilla/mux" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prysmaticlabs/prysm/v5/api" @@ -30,23 +29,53 @@ import ( type endpoint struct { template string name string - middleware []mux.MiddlewareFunc + middleware []middleware.Middleware handler http.HandlerFunc methods []string } +// responseWriter is the wrapper to http Response writer. +type responseWriter struct { + http.ResponseWriter + statusCode int +} + +// WriteHeader wraps the WriteHeader method of the underlying http.ResponseWriter to capture the status code. +// Refer for WriteHeader doc: https://pkg.go.dev/net/http@go1.23.3#ResponseWriter. +func (w *responseWriter) WriteHeader(statusCode int) { + w.statusCode = statusCode + w.ResponseWriter.WriteHeader(statusCode) +} + func (e *endpoint) handlerWithMiddleware() http.HandlerFunc { handler := http.Handler(e.handler) for _, m := range e.middleware { handler = m(handler) } - return promhttp.InstrumentHandlerDuration( + + handler = promhttp.InstrumentHandlerDuration( httpRequestLatency.MustCurryWith(prometheus.Labels{"endpoint": e.name}), promhttp.InstrumentHandlerCounter( httpRequestCount.MustCurryWith(prometheus.Labels{"endpoint": e.name}), handler, ), ) + + return func(w http.ResponseWriter, r *http.Request) { + // SSE errors are handled separately to avoid interference with the streaming + // mechanism and ensure accurate error tracking. + if e.template == "/eth/v1/events" { + handler.ServeHTTP(w, r) + return + } + + rw := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK} + handler.ServeHTTP(rw, r) + + if rw.statusCode >= 400 { + httpErrorCount.WithLabelValues(r.URL.Path, http.StatusText(rw.statusCode), r.Method).Inc() + } + } } func (s *Service) endpoints( @@ -93,7 +122,7 @@ func (s *Service) rewardsEndpoints(blocker lookup.Blocker, stater lookup.Stater, { template: "/eth/v1/beacon/rewards/blocks/{block_id}", name: namespace + ".BlockRewards", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.BlockRewards, @@ -102,7 +131,7 @@ func (s *Service) rewardsEndpoints(blocker lookup.Blocker, stater lookup.Stater, { template: "/eth/v1/beacon/rewards/attestations/{epoch}", name: namespace + ".AttestationRewards", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -112,7 +141,7 @@ func (s *Service) rewardsEndpoints(blocker lookup.Blocker, stater lookup.Stater, { template: "/eth/v1/beacon/rewards/sync_committee/{block_id}", name: namespace + ".SyncCommitteeRewards", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -132,9 +161,10 @@ func (s *Service) builderEndpoints(stater lookup.Stater) []endpoint { const namespace = "builder" return []endpoint{ { + // Deprecated: use SSE from /eth/v1/events for `Payload Attributes` instead template: "/eth/v1/builder/states/{state_id}/expected_withdrawals", name: namespace + ".ExpectedWithdrawals", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.ExpectedWithdrawals, @@ -143,9 +173,12 @@ func (s *Service) builderEndpoints(stater lookup.Stater) []endpoint { } } -func (*Service) blobEndpoints(blocker lookup.Blocker) []endpoint { +func (s *Service) blobEndpoints(blocker lookup.Blocker) []endpoint { server := &blob.Server{ - Blocker: blocker, + Blocker: blocker, + OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, + FinalizationFetcher: s.cfg.FinalizationFetcher, + TimeFetcher: s.cfg.GenesisTimeFetcher, } const namespace = "blob" @@ -153,7 +186,7 @@ func (*Service) blobEndpoints(blocker lookup.Blocker) []endpoint { { template: "/eth/v1/beacon/blob_sidecars/{block_id}", name: namespace + ".Blobs", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.Blobs, @@ -173,6 +206,7 @@ func (s *Service) validatorEndpoints( TimeFetcher: s.cfg.GenesisTimeFetcher, SyncChecker: s.cfg.SyncService, OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, + AttestationCache: s.cfg.AttestationCache, AttestationsPool: s.cfg.AttestationsPool, PeerManager: s.cfg.PeerManager, Broadcaster: s.cfg.Broadcaster, @@ -192,18 +226,28 @@ func (s *Service) validatorEndpoints( const namespace = "validator" return []endpoint{ { + // Deprecated: use /eth/v2/validator/aggregate_attestation instead template: "/eth/v1/validator/aggregate_attestation", name: namespace + ".GetAggregateAttestation", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetAggregateAttestation, methods: []string{http.MethodGet}, }, + { + template: "/eth/v2/validator/aggregate_attestation", + name: namespace + ".GetAggregateAttestationV2", + middleware: []middleware.Middleware{ + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.GetAggregateAttestationV2, + methods: []string{http.MethodGet}, + }, { template: "/eth/v1/validator/contribution_and_proofs", name: namespace + ".SubmitContributionAndProofs", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -211,19 +255,30 @@ func (s *Service) validatorEndpoints( methods: []string{http.MethodPost}, }, { + // Deprecated: use /eth/v2/validator/aggregate_and_proofs instead template: "/eth/v1/validator/aggregate_and_proofs", name: namespace + ".SubmitAggregateAndProofs", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.SubmitAggregateAndProofs, methods: []string{http.MethodPost}, }, + { + template: "/eth/v2/validator/aggregate_and_proofs", + name: namespace + ".SubmitAggregateAndProofsV2", + middleware: []middleware.Middleware{ + middleware.ContentTypeHandler([]string{api.JsonMediaType}), + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.SubmitAggregateAndProofsV2, + methods: []string{http.MethodPost}, + }, { template: "/eth/v1/validator/sync_committee_contribution", name: namespace + ".ProduceSyncCommitteeContribution", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.ProduceSyncCommitteeContribution, @@ -232,7 +287,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/sync_committee_subscriptions", name: namespace + ".SubmitSyncCommitteeSubscription", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -242,7 +297,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/beacon_committee_subscriptions", name: namespace + ".SubmitBeaconCommitteeSubscription", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -252,7 +307,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/attestation_data", name: namespace + ".GetAttestationData", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetAttestationData, @@ -261,7 +316,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/register_validator", name: namespace + ".RegisterValidator", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -271,7 +326,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/duties/attester/{epoch}", name: namespace + ".GetAttesterDuties", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -281,7 +336,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/duties/proposer/{epoch}", name: namespace + ".GetProposerDuties", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetProposerDuties, @@ -290,7 +345,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/duties/sync/{epoch}", name: namespace + ".GetSyncCommitteeDuties", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -300,7 +355,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/prepare_beacon_proposer", name: namespace + ".PrepareBeaconProposer", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -310,7 +365,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/liveness/{epoch}", name: namespace + ".GetLiveness", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -320,7 +375,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v2/validator/blocks/{slot}", name: namespace + ".ProduceBlockV2", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.ProduceBlockV2, @@ -329,7 +384,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/blinded_blocks/{slot}", name: namespace + ".ProduceBlindedBlock", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.ProduceBlindedBlock, @@ -338,7 +393,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v3/validator/blocks/{slot}", name: namespace + ".ProduceBlockV3", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.ProduceBlockV3, @@ -347,7 +402,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/beacon_committee_selections", name: namespace + ".BeaconCommitteeSelections", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), }, handler: server.BeaconCommitteeSelections, @@ -356,7 +411,7 @@ func (s *Service) validatorEndpoints( { template: "/eth/v1/validator/sync_committee_selections", name: namespace + ".SyncCommittee Selections", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), }, handler: server.SyncCommitteeSelections, @@ -384,7 +439,7 @@ func (s *Service) nodeEndpoints() []endpoint { { template: "/eth/v1/node/syncing", name: namespace + ".GetSyncStatus", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetSyncStatus, @@ -393,7 +448,7 @@ func (s *Service) nodeEndpoints() []endpoint { { template: "/eth/v1/node/identity", name: namespace + ".GetIdentity", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetIdentity, @@ -402,7 +457,7 @@ func (s *Service) nodeEndpoints() []endpoint { { template: "/eth/v1/node/peers/{peer_id}", name: namespace + ".GetPeer", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetPeer, @@ -411,7 +466,7 @@ func (s *Service) nodeEndpoints() []endpoint { { template: "/eth/v1/node/peers", name: namespace + ".GetPeers", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetPeers, @@ -420,7 +475,7 @@ func (s *Service) nodeEndpoints() []endpoint { { template: "/eth/v1/node/peer_count", name: namespace + ".GetPeerCount", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetPeerCount, @@ -429,7 +484,7 @@ func (s *Service) nodeEndpoints() []endpoint { { template: "/eth/v1/node/version", name: namespace + ".GetVersion", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetVersion, @@ -438,7 +493,7 @@ func (s *Service) nodeEndpoints() []endpoint { { template: "/eth/v1/node/health", name: namespace + ".GetHealth", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetHealth, @@ -455,30 +510,32 @@ func (s *Service) beaconEndpoints( coreService *core.Service, ) []endpoint { server := &beacon.Server{ - CanonicalHistory: ch, - BeaconDB: s.cfg.BeaconDB, - AttestationsPool: s.cfg.AttestationsPool, - SlashingsPool: s.cfg.SlashingsPool, - ChainInfoFetcher: s.cfg.ChainInfoFetcher, - GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, - BlockNotifier: s.cfg.BlockNotifier, - OperationNotifier: s.cfg.OperationNotifier, - Broadcaster: s.cfg.Broadcaster, - BlockReceiver: s.cfg.BlockReceiver, - StateGenService: s.cfg.StateGen, - Stater: stater, - Blocker: blocker, - OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, - HeadFetcher: s.cfg.HeadFetcher, - TimeFetcher: s.cfg.GenesisTimeFetcher, - VoluntaryExitsPool: s.cfg.ExitPool, - V1Alpha1ValidatorServer: validatorServer, - SyncChecker: s.cfg.SyncService, - ExecutionPayloadReconstructor: s.cfg.ExecutionPayloadReconstructor, - BLSChangesPool: s.cfg.BLSChangesPool, - FinalizationFetcher: s.cfg.FinalizationFetcher, - ForkchoiceFetcher: s.cfg.ForkchoiceFetcher, - CoreService: coreService, + CanonicalHistory: ch, + BeaconDB: s.cfg.BeaconDB, + AttestationCache: s.cfg.AttestationCache, + AttestationsPool: s.cfg.AttestationsPool, + SlashingsPool: s.cfg.SlashingsPool, + ChainInfoFetcher: s.cfg.ChainInfoFetcher, + GenesisTimeFetcher: s.cfg.GenesisTimeFetcher, + BlockNotifier: s.cfg.BlockNotifier, + OperationNotifier: s.cfg.OperationNotifier, + Broadcaster: s.cfg.Broadcaster, + BlockReceiver: s.cfg.BlockReceiver, + StateGenService: s.cfg.StateGen, + Stater: stater, + Blocker: blocker, + OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, + HeadFetcher: s.cfg.HeadFetcher, + TimeFetcher: s.cfg.GenesisTimeFetcher, + VoluntaryExitsPool: s.cfg.ExitPool, + V1Alpha1ValidatorServer: validatorServer, + SyncChecker: s.cfg.SyncService, + ExecutionReconstructor: s.cfg.ExecutionReconstructor, + BLSChangesPool: s.cfg.BLSChangesPool, + FinalizationFetcher: s.cfg.FinalizationFetcher, + ForkchoiceFetcher: s.cfg.ForkchoiceFetcher, + CoreService: coreService, + AttestationStateFetcher: s.cfg.AttestationReceiver, } const namespace = "beacon" @@ -486,7 +543,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/committees", name: namespace + ".GetCommittees", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetCommittees, @@ -495,7 +552,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/fork", name: namespace + ".GetStateFork", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetStateFork, @@ -504,7 +561,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/root", name: namespace + ".GetStateRoot", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetStateRoot, @@ -513,7 +570,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/sync_committees", name: namespace + ".GetSyncCommittees", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetSyncCommittees, @@ -522,16 +579,17 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/randao", name: namespace + ".GetRandao", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetRandao, methods: []string{http.MethodGet}, }, { + // Deprecated: use /eth/v2/beacon/blocks instead template: "/eth/v1/beacon/blocks", name: namespace + ".PublishBlock", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -539,9 +597,10 @@ func (s *Service) beaconEndpoints( methods: []string{http.MethodPost}, }, { + // Deprecated: use /eth/v2/beacon/blinded_blocks instead template: "/eth/v1/beacon/blinded_blocks", name: namespace + ".PublishBlindedBlock", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -551,7 +610,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v2/beacon/blocks", name: namespace + ".PublishBlockV2", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -561,7 +620,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v2/beacon/blinded_blocks", name: namespace + ".PublishBlindedBlockV2", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -571,25 +630,35 @@ func (s *Service) beaconEndpoints( { template: "/eth/v2/beacon/blocks/{block_id}", name: namespace + ".GetBlockV2", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.GetBlockV2, methods: []string{http.MethodGet}, }, { + // Deprecated: use /eth/v2/beacon/blocks/{block_id}/attestations instead template: "/eth/v1/beacon/blocks/{block_id}/attestations", name: namespace + ".GetBlockAttestations", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetBlockAttestations, methods: []string{http.MethodGet}, }, + { + template: "/eth/v2/beacon/blocks/{block_id}/attestations", + name: namespace + ".GetBlockAttestationsV2", + middleware: []middleware.Middleware{ + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.GetBlockAttestationsV2, + methods: []string{http.MethodGet}, + }, { template: "/eth/v1/beacon/blinded_blocks/{block_id}", name: namespace + ".GetBlindedBlock", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.GetBlindedBlock, @@ -598,35 +667,55 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/blocks/{block_id}/root", name: namespace + ".GetBlockRoot", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetBlockRoot, methods: []string{http.MethodGet}, }, { + // Deprecated: use /eth/v2/beacon/pool/attestations instead template: "/eth/v1/beacon/pool/attestations", name: namespace + ".ListAttestations", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.ListAttestations, methods: []string{http.MethodGet}, }, + { + template: "/eth/v2/beacon/pool/attestations", + name: namespace + ".ListAttestationsV2", + middleware: []middleware.Middleware{ + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.ListAttestationsV2, + methods: []string{http.MethodGet}, + }, { template: "/eth/v1/beacon/pool/attestations", name: namespace + ".SubmitAttestations", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.SubmitAttestations, methods: []string{http.MethodPost}, }, + { + template: "/eth/v2/beacon/pool/attestations", + name: namespace + ".SubmitAttestationsV2", + middleware: []middleware.Middleware{ + middleware.ContentTypeHandler([]string{api.JsonMediaType}), + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.SubmitAttestationsV2, + methods: []string{http.MethodPost}, + }, { template: "/eth/v1/beacon/pool/voluntary_exits", name: namespace + ".ListVoluntaryExits", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.ListVoluntaryExits, @@ -635,7 +724,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/pool/voluntary_exits", name: namespace + ".SubmitVoluntaryExit", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -645,7 +734,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/pool/sync_committees", name: namespace + ".SubmitSyncCommitteeSignatures", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -655,7 +744,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/pool/bls_to_execution_changes", name: namespace + ".ListBLSToExecutionChanges", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.ListBLSToExecutionChanges, @@ -664,7 +753,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/pool/bls_to_execution_changes", name: namespace + ".SubmitBLSToExecutionChanges", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -672,28 +761,48 @@ func (s *Service) beaconEndpoints( methods: []string{http.MethodPost}, }, { + // Deprecated: use /eth/v2/beacon/pool/attester_slashings instead template: "/eth/v1/beacon/pool/attester_slashings", name: namespace + ".GetAttesterSlashings", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetAttesterSlashings, methods: []string{http.MethodGet}, }, + { + template: "/eth/v2/beacon/pool/attester_slashings", + name: namespace + ".GetAttesterSlashingsV2", + middleware: []middleware.Middleware{ + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.GetAttesterSlashingsV2, + methods: []string{http.MethodGet}, + }, { template: "/eth/v1/beacon/pool/attester_slashings", - name: namespace + ".SubmitAttesterSlashing", - middleware: []mux.MiddlewareFunc{ + name: namespace + ".SubmitAttesterSlashings", + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, - handler: server.SubmitAttesterSlashing, + handler: server.SubmitAttesterSlashings, + methods: []string{http.MethodPost}, + }, + { + template: "/eth/v2/beacon/pool/attester_slashings", + name: namespace + ".SubmitAttesterSlashingsV2", + middleware: []middleware.Middleware{ + middleware.ContentTypeHandler([]string{api.JsonMediaType}), + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.SubmitAttesterSlashingsV2, methods: []string{http.MethodPost}, }, { template: "/eth/v1/beacon/pool/proposer_slashings", name: namespace + ".GetProposerSlashings", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetProposerSlashings, @@ -702,7 +811,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/pool/proposer_slashings", name: namespace + ".SubmitProposerSlashing", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -712,7 +821,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/headers", name: namespace + ".GetBlockHeaders", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetBlockHeaders, @@ -721,7 +830,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/headers/{block_id}", name: namespace + ".GetBlockHeader", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetBlockHeader, @@ -730,7 +839,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/genesis", name: namespace + ".GetGenesis", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetGenesis, @@ -739,7 +848,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/finality_checkpoints", name: namespace + ".GetFinalityCheckpoints", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetFinalityCheckpoints, @@ -748,7 +857,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/validators", name: namespace + ".GetValidators", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -758,7 +867,7 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/validators/{validator_id}", name: namespace + ".GetValidator", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetValidator, @@ -767,13 +876,41 @@ func (s *Service) beaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/validator_balances", name: namespace + ".GetValidatorBalances", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetValidatorBalances, methods: []string{http.MethodGet, http.MethodPost}, }, + { + // Deprecated: no longer needed post Electra + template: "/eth/v1/beacon/deposit_snapshot", + name: namespace + ".GetDepositSnapshot", + middleware: []middleware.Middleware{ + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.GetDepositSnapshot, + methods: []string{http.MethodGet}, + }, + { + template: "/eth/v1/beacon/states/{state_id}/pending_deposits", + name: namespace + ".GetPendingDeposits", + middleware: []middleware.Middleware{ + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.GetPendingDeposits, + methods: []string{http.MethodGet}, + }, + { + template: "/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals", + name: namespace + ".GetPendingPartialWithdrawals", + middleware: []middleware.Middleware{ + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.GetPendingPartialWithdrawals, + methods: []string{http.MethodGet}, + }, } } @@ -783,7 +920,7 @@ func (*Service) configEndpoints() []endpoint { { template: "/eth/v1/config/deposit_contract", name: namespace + ".GetDepositContract", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: config.GetDepositContract, @@ -792,7 +929,7 @@ func (*Service) configEndpoints() []endpoint { { template: "/eth/v1/config/fork_schedule", name: namespace + ".GetForkSchedule", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: config.GetForkSchedule, @@ -801,7 +938,7 @@ func (*Service) configEndpoints() []endpoint { { template: "/eth/v1/config/spec", name: namespace + ".GetSpec", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: config.GetSpec, @@ -812,9 +949,11 @@ func (*Service) configEndpoints() []endpoint { func (s *Service) lightClientEndpoints(blocker lookup.Blocker, stater lookup.Stater) []endpoint { server := &lightclient.Server{ - Blocker: blocker, - Stater: stater, - HeadFetcher: s.cfg.HeadFetcher, + Blocker: blocker, + Stater: stater, + HeadFetcher: s.cfg.HeadFetcher, + ChainInfoFetcher: s.cfg.ChainInfoFetcher, + BeaconDB: s.cfg.BeaconDB, } const namespace = "lightclient" @@ -822,7 +961,7 @@ func (s *Service) lightClientEndpoints(blocker lookup.Blocker, stater lookup.Sta { template: "/eth/v1/beacon/light_client/bootstrap/{block_root}", name: namespace + ".GetLightClientBootstrap", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.GetLightClientBootstrap, @@ -831,7 +970,7 @@ func (s *Service) lightClientEndpoints(blocker lookup.Blocker, stater lookup.Sta { template: "/eth/v1/beacon/light_client/updates", name: namespace + ".GetLightClientUpdatesByRange", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.GetLightClientUpdatesByRange, @@ -840,7 +979,7 @@ func (s *Service) lightClientEndpoints(blocker lookup.Blocker, stater lookup.Sta { template: "/eth/v1/beacon/light_client/finality_update", name: namespace + ".GetLightClientFinalityUpdate", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.GetLightClientFinalityUpdate, @@ -849,7 +988,7 @@ func (s *Service) lightClientEndpoints(blocker lookup.Blocker, stater lookup.Sta { template: "/eth/v1/beacon/light_client/optimistic_update", name: namespace + ".GetLightClientOptimisticUpdate", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.GetLightClientOptimisticUpdate, @@ -875,7 +1014,7 @@ func (s *Service) debugEndpoints(stater lookup.Stater) []endpoint { { template: "/eth/v2/debug/beacon/states/{state_id}", name: namespace + ".GetBeaconStateV2", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType, api.OctetStreamMediaType}), }, handler: server.GetBeaconStateV2, @@ -884,7 +1023,7 @@ func (s *Service) debugEndpoints(stater lookup.Stater) []endpoint { { template: "/eth/v2/debug/beacon/heads", name: namespace + ".GetForkChoiceHeadsV2", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetForkChoiceHeadsV2, @@ -893,7 +1032,7 @@ func (s *Service) debugEndpoints(stater lookup.Stater) []endpoint { { template: "/eth/v1/debug/fork_choice", name: namespace + ".GetForkChoice", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetForkChoice, @@ -916,7 +1055,7 @@ func (s *Service) eventsEndpoints() []endpoint { { template: "/eth/v1/events", name: namespace + ".StreamEvents", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.EventStreamMediaType}), }, handler: server.StreamEvents, @@ -942,6 +1081,8 @@ func (s *Service) prysmBeaconEndpoints( ChainInfoFetcher: s.cfg.ChainInfoFetcher, FinalizationFetcher: s.cfg.FinalizationFetcher, CoreService: coreService, + Broadcaster: s.cfg.Broadcaster, + BlobReceiver: s.cfg.BlobReceiver, } const namespace = "prysm.beacon" @@ -949,7 +1090,7 @@ func (s *Service) prysmBeaconEndpoints( { template: "/prysm/v1/beacon/weak_subjectivity", name: namespace + ".GetWeakSubjectivity", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetWeakSubjectivity, @@ -958,7 +1099,7 @@ func (s *Service) prysmBeaconEndpoints( { template: "/eth/v1/beacon/states/{state_id}/validator_count", name: namespace + ".GetValidatorCount", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetValidatorCount, @@ -967,7 +1108,7 @@ func (s *Service) prysmBeaconEndpoints( { template: "/prysm/v1/beacon/states/{state_id}/validator_count", name: namespace + ".GetValidatorCount", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetValidatorCount, @@ -976,7 +1117,7 @@ func (s *Service) prysmBeaconEndpoints( { template: "/prysm/v1/beacon/individual_votes", name: namespace + ".GetIndividualVotes", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -986,12 +1127,22 @@ func (s *Service) prysmBeaconEndpoints( { template: "/prysm/v1/beacon/chain_head", name: namespace + ".GetChainHead", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetChainHead, methods: []string{http.MethodGet}, }, + { + template: "/prysm/v1/beacon/blobs", + name: namespace + ".PublishBlobs", + middleware: []middleware.Middleware{ + middleware.ContentTypeHandler([]string{api.JsonMediaType}), + middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), + }, + handler: server.PublishBlobs, + methods: []string{http.MethodPost}, + }, } } @@ -1013,7 +1164,7 @@ func (s *Service) prysmNodeEndpoints() []endpoint { { template: "/prysm/node/trusted_peers", name: namespace + ".ListTrustedPeer", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.ListTrustedPeer, @@ -1022,7 +1173,7 @@ func (s *Service) prysmNodeEndpoints() []endpoint { { template: "/prysm/v1/node/trusted_peers", name: namespace + ".ListTrustedPeer", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.ListTrustedPeer, @@ -1031,7 +1182,7 @@ func (s *Service) prysmNodeEndpoints() []endpoint { { template: "/prysm/node/trusted_peers", name: namespace + ".AddTrustedPeer", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -1041,7 +1192,7 @@ func (s *Service) prysmNodeEndpoints() []endpoint { { template: "/prysm/v1/node/trusted_peers", name: namespace + ".AddTrustedPeer", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -1051,7 +1202,7 @@ func (s *Service) prysmNodeEndpoints() []endpoint { { template: "/prysm/node/trusted_peers/{peer_id}", name: namespace + ".RemoveTrustedPeer", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.RemoveTrustedPeer, @@ -1060,7 +1211,7 @@ func (s *Service) prysmNodeEndpoints() []endpoint { { template: "/prysm/v1/node/trusted_peers/{peer_id}", name: namespace + ".RemoveTrustedPeer", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.RemoveTrustedPeer, @@ -1081,7 +1232,7 @@ func (s *Service) prysmValidatorEndpoints(stater lookup.Stater, coreService *cor { template: "/prysm/validators/performance", name: namespace + ".GetPerformance", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -1091,7 +1242,7 @@ func (s *Service) prysmValidatorEndpoints(stater lookup.Stater, coreService *cor { template: "/prysm/v1/validators/performance", name: namespace + ".GetPerformance", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.ContentTypeHandler([]string{api.JsonMediaType}), middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, @@ -1101,7 +1252,7 @@ func (s *Service) prysmValidatorEndpoints(stater lookup.Stater, coreService *cor { template: "/prysm/v1/validators/participation", name: namespace + ".GetParticipation", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetParticipation, @@ -1110,7 +1261,7 @@ func (s *Service) prysmValidatorEndpoints(stater lookup.Stater, coreService *cor { template: "/prysm/v1/validators/active_set_changes", name: namespace + ".GetActiveSetChanges", - middleware: []mux.MiddlewareFunc{ + middleware: []middleware.Middleware{ middleware.AcceptHeaderHandler([]string{api.JsonMediaType}), }, handler: server.GetActiveSetChanges, diff --git a/beacon-chain/rpc/endpoints_test.go b/beacon-chain/rpc/endpoints_test.go index 6b7799303f31..80bcc23259b7 100644 --- a/beacon-chain/rpc/endpoints_test.go +++ b/beacon-chain/rpc/endpoints_test.go @@ -1,7 +1,9 @@ package rpc import ( + "maps" "net/http" + "slices" "testing" "github.com/prysmaticlabs/prysm/v5/testing/assert" @@ -15,36 +17,40 @@ func Test_endpoints(t *testing.T) { } beaconRoutes := map[string][]string{ - "/eth/v1/beacon/genesis": {http.MethodGet}, - "/eth/v1/beacon/states/{state_id}/root": {http.MethodGet}, - "/eth/v1/beacon/states/{state_id}/fork": {http.MethodGet}, - "/eth/v1/beacon/states/{state_id}/finality_checkpoints": {http.MethodGet}, - "/eth/v1/beacon/states/{state_id}/validators": {http.MethodGet, http.MethodPost}, - "/eth/v1/beacon/states/{state_id}/validators/{validator_id}": {http.MethodGet}, - "/eth/v1/beacon/states/{state_id}/validator_balances": {http.MethodGet, http.MethodPost}, - "/eth/v1/beacon/states/{state_id}/committees": {http.MethodGet}, - "/eth/v1/beacon/states/{state_id}/sync_committees": {http.MethodGet}, - "/eth/v1/beacon/states/{state_id}/randao": {http.MethodGet}, - "/eth/v1/beacon/headers": {http.MethodGet}, - "/eth/v1/beacon/headers/{block_id}": {http.MethodGet}, - "/eth/v1/beacon/blinded_blocks": {http.MethodPost}, - "/eth/v2/beacon/blinded_blocks": {http.MethodPost}, - "/eth/v1/beacon/blocks": {http.MethodPost}, - "/eth/v2/beacon/blocks": {http.MethodPost}, - "/eth/v1/beacon/blocks/{block_id}": {http.MethodGet}, - "/eth/v2/beacon/blocks/{block_id}": {http.MethodGet}, - "/eth/v1/beacon/blocks/{block_id}/root": {http.MethodGet}, - "/eth/v1/beacon/blocks/{block_id}/attestations": {http.MethodGet}, - "/eth/v1/beacon/blob_sidecars/{block_id}": {http.MethodGet}, - "/eth/v1/beacon/deposit_snapshot": {http.MethodGet}, - "/eth/v1/beacon/blinded_blocks/{block_id}": {http.MethodGet}, - "/eth/v1/beacon/pool/attestations": {http.MethodGet, http.MethodPost}, - "/eth/v1/beacon/pool/attester_slashings": {http.MethodGet, http.MethodPost}, - "/eth/v1/beacon/pool/proposer_slashings": {http.MethodGet, http.MethodPost}, - "/eth/v1/beacon/pool/sync_committees": {http.MethodPost}, - "/eth/v1/beacon/pool/voluntary_exits": {http.MethodGet, http.MethodPost}, - "/eth/v1/beacon/pool/bls_to_execution_changes": {http.MethodGet, http.MethodPost}, - "/prysm/v1/beacon/individual_votes": {http.MethodPost}, + "/eth/v1/beacon/genesis": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/root": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/fork": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/finality_checkpoints": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/validators": {http.MethodGet, http.MethodPost}, + "/eth/v1/beacon/states/{state_id}/validators/{validator_id}": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/validator_balances": {http.MethodGet, http.MethodPost}, + "/eth/v1/beacon/states/{state_id}/committees": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/sync_committees": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/randao": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/pending_deposits": {http.MethodGet}, + "/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals": {http.MethodGet}, + "/eth/v1/beacon/headers": {http.MethodGet}, + "/eth/v1/beacon/headers/{block_id}": {http.MethodGet}, + "/eth/v1/beacon/blinded_blocks": {http.MethodPost}, + "/eth/v2/beacon/blinded_blocks": {http.MethodPost}, + "/eth/v1/beacon/blocks": {http.MethodPost}, + "/eth/v2/beacon/blocks": {http.MethodPost}, + "/eth/v2/beacon/blocks/{block_id}": {http.MethodGet}, + "/eth/v1/beacon/blocks/{block_id}/root": {http.MethodGet}, + "/eth/v1/beacon/blocks/{block_id}/attestations": {http.MethodGet}, + "/eth/v2/beacon/blocks/{block_id}/attestations": {http.MethodGet}, + "/eth/v1/beacon/blob_sidecars/{block_id}": {http.MethodGet}, + "/eth/v1/beacon/deposit_snapshot": {http.MethodGet}, + "/eth/v1/beacon/blinded_blocks/{block_id}": {http.MethodGet}, + "/eth/v1/beacon/pool/attestations": {http.MethodGet, http.MethodPost}, + "/eth/v2/beacon/pool/attestations": {http.MethodGet, http.MethodPost}, + "/eth/v1/beacon/pool/attester_slashings": {http.MethodGet, http.MethodPost}, + "/eth/v2/beacon/pool/attester_slashings": {http.MethodGet, http.MethodPost}, + "/eth/v1/beacon/pool/proposer_slashings": {http.MethodGet, http.MethodPost}, + "/eth/v1/beacon/pool/sync_committees": {http.MethodPost}, + "/eth/v1/beacon/pool/voluntary_exits": {http.MethodGet, http.MethodPost}, + "/eth/v1/beacon/pool/bls_to_execution_changes": {http.MethodGet, http.MethodPost}, + "/prysm/v1/beacon/individual_votes": {http.MethodPost}, } lightClientRoutes := map[string][]string{ @@ -69,7 +75,6 @@ func Test_endpoints(t *testing.T) { } debugRoutes := map[string][]string{ - "/eth/v1/debug/beacon/states/{state_id}": {http.MethodGet}, "/eth/v2/debug/beacon/states/{state_id}": {http.MethodGet}, "/eth/v2/debug/beacon/heads": {http.MethodGet}, "/eth/v1/debug/fork_choice": {http.MethodGet}, @@ -98,7 +103,9 @@ func Test_endpoints(t *testing.T) { "/eth/v1/validator/blinded_blocks/{slot}": {http.MethodGet}, "/eth/v1/validator/attestation_data": {http.MethodGet}, "/eth/v1/validator/aggregate_attestation": {http.MethodGet}, + "/eth/v2/validator/aggregate_attestation": {http.MethodGet}, "/eth/v1/validator/aggregate_and_proofs": {http.MethodPost}, + "/eth/v2/validator/aggregate_and_proofs": {http.MethodPost}, "/eth/v1/validator/beacon_committee_subscriptions": {http.MethodPost}, "/eth/v1/validator/sync_committee_subscriptions": {http.MethodPost}, "/eth/v1/validator/beacon_committee_selections": {http.MethodPost}, @@ -115,6 +122,7 @@ func Test_endpoints(t *testing.T) { "/eth/v1/beacon/states/{state_id}/validator_count": {http.MethodGet}, "/prysm/v1/beacon/states/{state_id}/validator_count": {http.MethodGet}, "/prysm/v1/beacon/chain_head": {http.MethodGet}, + "/prysm/v1/beacon/blobs": {http.MethodPost}, } prysmNodeRoutes := map[string][]string{ @@ -133,22 +141,18 @@ func Test_endpoints(t *testing.T) { s := &Service{cfg: &Config{}} - routesMap := combineMaps(beaconRoutes, builderRoutes, configRoutes, debugRoutes, eventsRoutes, nodeRoutes, validatorRoutes, rewardsRoutes, lightClientRoutes, blobRoutes, prysmValidatorRoutes, prysmNodeRoutes, prysmBeaconRoutes) - actual := s.endpoints(true, nil, nil, nil, nil, nil, nil) - for _, e := range actual { - methods, ok := routesMap[e.template] - assert.Equal(t, true, ok, "endpoint "+e.template+" not found") - if ok { - for _, em := range e.methods { - methodFound := false - for _, m := range methods { - if m == em { - methodFound = true - break - } - } - assert.Equal(t, true, methodFound, "method "+em+" for endpoint "+e.template+" not found") - } + endpoints := s.endpoints(true, nil, nil, nil, nil, nil, nil) + actualRoutes := make(map[string][]string, len(endpoints)) + for _, e := range endpoints { + if _, ok := actualRoutes[e.template]; ok { + actualRoutes[e.template] = append(actualRoutes[e.template], e.methods...) + } else { + actualRoutes[e.template] = e.methods } } + expectedRoutes := combineMaps(beaconRoutes, builderRoutes, configRoutes, debugRoutes, eventsRoutes, nodeRoutes, validatorRoutes, rewardsRoutes, lightClientRoutes, blobRoutes, prysmValidatorRoutes, prysmNodeRoutes, prysmBeaconRoutes) + + assert.Equal(t, true, maps.EqualFunc(expectedRoutes, actualRoutes, func(actualMethods []string, expectedMethods []string) bool { + return slices.Equal(expectedMethods, actualMethods) + })) } diff --git a/beacon-chain/rpc/eth/beacon/BUILD.bazel b/beacon-chain/rpc/eth/beacon/BUILD.bazel index d9a8037e3e71..e7c08b083908 100644 --- a/beacon-chain/rpc/eth/beacon/BUILD.bazel +++ b/beacon-chain/rpc/eth/beacon/BUILD.bazel @@ -17,6 +17,7 @@ go_library( "//api/server:go_default_library", "//api/server/structs:go_default_library", "//beacon-chain/blockchain:go_default_library", + "//beacon-chain/cache:go_default_library", "//beacon-chain/cache/depositsnapshot:go_default_library", "//beacon-chain/core/altair:go_default_library", "//beacon-chain/core/blocks:go_default_library", @@ -52,16 +53,16 @@ go_library( "//consensus-types/validator:go_default_library", "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", + "@com_github_ethereum_go_ethereum//crypto/kzg4844:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -119,8 +120,8 @@ go_test( "//testing/require:go_default_library", "//testing/util:go_default_library", "//time/slots:go_default_library", + "@com_github_crate_crypto_go_kzg_4844//:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", diff --git a/beacon-chain/rpc/eth/beacon/handlers.go b/beacon-chain/rpc/eth/beacon/handlers.go index 4f3cf8d9658c..ffbbfc9f2bcf 100644 --- a/beacon-chain/rpc/eth/beacon/handlers.go +++ b/beacon-chain/rpc/eth/beacon/handlers.go @@ -11,7 +11,7 @@ import ( "strings" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/pkg/errors" ssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/prysm/v5/api" @@ -29,12 +29,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) const ( @@ -49,12 +49,108 @@ var ( errMarshalSSZ = errors.New("could not marshal block into SSZ") ) +type blockDecoder func([]byte) (*eth.GenericSignedBeaconBlock, error) + +func decodingError(v string, err error) error { + return fmt.Errorf("could not decode request body into %s consensus block: %w", v, err) +} + +type signedBlockContentPeeker struct { + Block json.RawMessage `json:"signed_block"` +} +type slotPeeker struct { + Block struct { + Slot primitives.Slot `json:"slot,string"` + } `json:"message"` +} + +func versionHeaderFromRequest(body []byte) (string, error) { + // check is required for post deneb fork blocks contents + p := &signedBlockContentPeeker{} + if err := json.Unmarshal(body, p); err != nil { + return "", errors.Wrap(err, "unable to peek slot from block contents") + } + data := body + if len(p.Block) > 0 { + data = p.Block + } + sp := &slotPeeker{} + if err := json.Unmarshal(data, sp); err != nil { + return "", errors.Wrap(err, "unable to peek slot from block") + } + ce := slots.ToEpoch(sp.Block.Slot) + if ce >= params.BeaconConfig().FuluForkEpoch { + return version.String(version.Fulu), nil + } else if ce >= params.BeaconConfig().ElectraForkEpoch { + return version.String(version.Electra), nil + } else if ce >= params.BeaconConfig().DenebForkEpoch { + return version.String(version.Deneb), nil + } else if ce >= params.BeaconConfig().CapellaForkEpoch { + return version.String(version.Capella), nil + } else if ce >= params.BeaconConfig().BellatrixForkEpoch { + return version.String(version.Bellatrix), nil + } else if ce >= params.BeaconConfig().AltairForkEpoch { + return version.String(version.Altair), nil + } else { + return version.String(version.Phase0), nil + } +} + +// validateVersionHeader checks if the version header is required and retrieves it +// from the request. If the version header is not provided and not required, it attempts +// to derive it from the request body. +func validateVersionHeader(r *http.Request, body []byte, versionRequired bool) (string, error) { + versionHeader := r.Header.Get(api.VersionHeader) + if versionRequired && versionHeader == "" { + return "", fmt.Errorf("%s header is required", api.VersionHeader) + } + + if !versionRequired && versionHeader == "" { + var err error + versionHeader, err = versionHeaderFromRequest(body) + if err != nil { + return "", errors.Wrap(err, "could not decode request body for version header") + } + } + + return versionHeader, nil +} + +func readRequestBody(r *http.Request) ([]byte, error) { + return io.ReadAll(r.Body) +} + +// GenericConverter is an example interface that your block structs could implement. +type GenericConverter interface { + ToGeneric() (*eth.GenericSignedBeaconBlock, error) +} + +// decodeGenericJSON uses generics to unmarshal JSON into a type T that also +// provides a ToGeneric() method to produce a *eth.GenericSignedBeaconBlock. +func decodeGenericJSON[T GenericConverter](body []byte, forkVersion string) (*eth.GenericSignedBeaconBlock, error) { + // Create a pointer to the zero value of T. + blockPtr := new(T) + + // Unmarshal JSON into blockPtr. + if err := unmarshalStrict(body, blockPtr); err != nil { + return nil, decodingError(forkVersion, err) + } + + // Call the ToGeneric method on the underlying value. + consensusBlock, err := (*blockPtr).ToGeneric() + if err != nil { + return nil, decodingError(forkVersion, err) + } + + return consensusBlock, nil +} + // GetBlockV2 retrieves block details for given block ID. func (s *Server) GetBlockV2(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockV2") defer span.End() - blockId := mux.Vars(r)["block_id"] + blockId := r.PathValue("block_id") if blockId == "" { httputil.HandleError(w, "block_id is required in URL params", http.StatusBadRequest) return @@ -66,7 +162,7 @@ func (s *Server) GetBlockV2(w http.ResponseWriter, r *http.Request) { // Deal with block unblinding. if blk.Version() >= version.Bellatrix && blk.IsBlinded() { - blk, err = s.ExecutionPayloadReconstructor.ReconstructFullBlock(ctx, blk) + blk, err = s.ExecutionReconstructor.ReconstructFullBlock(ctx, blk) if err != nil { httputil.HandleError(w, errors.Wrapf(err, "could not reconstruct full execution payload to create signed beacon block").Error(), http.StatusBadRequest) return @@ -85,7 +181,7 @@ func (s *Server) GetBlindedBlock(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlindedBlock") defer span.End() - blockId := mux.Vars(r)["block_id"] + blockId := r.PathValue("block_id") if blockId == "" { httputil.HandleError(w, "block_id is required in URL params", http.StatusBadRequest) return @@ -196,21 +292,16 @@ func (s *Server) getBlockResponseBodyJson(ctx context.Context, blk interfaces.Re }, nil } +// Deprecated: use GetBlockAttestationsV2 instead // GetBlockAttestations retrieves attestation included in requested block. func (s *Server) GetBlockAttestations(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockAttestations") defer span.End() - blockId := mux.Vars(r)["block_id"] - if blockId == "" { - httputil.HandleError(w, "block_id is required in URL params", http.StatusBadRequest) + blk, isOptimistic, root := s.blockData(ctx, w, r) + if blk == nil { return } - blk, err := s.Blocker.Block(ctx, []byte(blockId)) - if !shared.WriteBlockFetchError(w, blk, err) { - return - } - consensusAtts := blk.Block().Body().Attestations() atts := make([]*structs.Attestation, len(consensusAtts)) for i, att := range consensusAtts { @@ -222,25 +313,89 @@ func (s *Server) GetBlockAttestations(w http.ResponseWriter, r *http.Request) { return } } - root, err := blk.Block().HashTreeRoot() - if err != nil { - httputil.HandleError(w, "Could not get block root: "+err.Error(), http.StatusInternalServerError) + resp := &structs.GetBlockAttestationsResponse{ + Data: atts, + ExecutionOptimistic: isOptimistic, + Finalized: s.FinalizationFetcher.IsFinalized(ctx, root), + } + httputil.WriteJson(w, resp) +} + +// GetBlockAttestationsV2 retrieves attestation included in requested block. +func (s *Server) GetBlockAttestationsV2(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockAttestationsV2") + defer span.End() + + blk, isOptimistic, root := s.blockData(ctx, w, r) + if blk == nil { return } - isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) + consensusAtts := blk.Block().Body().Attestations() + + v := blk.Block().Version() + var attStructs []interface{} + if v >= version.Electra { + for _, att := range consensusAtts { + a, ok := att.(*eth.AttestationElectra) + if !ok { + httputil.HandleError(w, fmt.Sprintf("unable to convert consensus attestations electra of type %T", att), http.StatusInternalServerError) + return + } + attStruct := structs.AttElectraFromConsensus(a) + attStructs = append(attStructs, attStruct) + } + } else { + for _, att := range consensusAtts { + a, ok := att.(*eth.Attestation) + if !ok { + httputil.HandleError(w, fmt.Sprintf("unable to convert consensus attestation of type %T", att), http.StatusInternalServerError) + return + } + attStruct := structs.AttFromConsensus(a) + attStructs = append(attStructs, attStruct) + } + } + + attBytes, err := json.Marshal(attStructs) if err != nil { - httputil.HandleError(w, "Could not check if block is optimistic: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, fmt.Sprintf("failed to marshal attestations: %v", err), http.StatusInternalServerError) return } - - resp := &structs.GetBlockAttestationsResponse{ - Data: atts, + resp := &structs.GetBlockAttestationsV2Response{ + Version: version.String(v), ExecutionOptimistic: isOptimistic, Finalized: s.FinalizationFetcher.IsFinalized(ctx, root), + Data: attBytes, } + w.Header().Set(api.VersionHeader, version.String(v)) httputil.WriteJson(w, resp) } +func (s *Server) blockData(ctx context.Context, w http.ResponseWriter, r *http.Request) (interfaces.ReadOnlySignedBeaconBlock, bool, [32]byte) { + blockId := r.PathValue("block_id") + if blockId == "" { + httputil.HandleError(w, "block_id is required in URL params", http.StatusBadRequest) + return nil, false, [32]byte{} + } + blk, err := s.Blocker.Block(ctx, []byte(blockId)) + if !shared.WriteBlockFetchError(w, blk, err) { + return nil, false, [32]byte{} + } + + root, err := blk.Block().HashTreeRoot() + if err != nil { + httputil.HandleError(w, "Could not get block root: "+err.Error(), http.StatusInternalServerError) + return nil, false, [32]byte{} + } + isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, root) + if err != nil { + httputil.HandleError(w, "Could not check if block is optimistic: "+err.Error(), http.StatusInternalServerError) + return nil, false, [32]byte{} + } + return blk, isOptimistic, root +} + +// Deprecated: use PublishBlindedBlockV2 instead // PublishBlindedBlock instructs the beacon node to use the components of the `SignedBlindedBeaconBlock` to construct // and publish a SignedBeaconBlock by swapping out the transactions_root for the corresponding full list of `transactions`. // The beacon node should broadcast a newly constructed SignedBeaconBlock to the beacon network, to be included in the @@ -286,256 +441,192 @@ func (s *Server) PublishBlindedBlockV2(w http.ResponseWriter, r *http.Request) { } } +// publishBlindedBlockSSZ reads SSZ-encoded data and publishes a blinded block. func (s *Server) publishBlindedBlockSSZ(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) { - body, err := io.ReadAll(r.Body) + body, err := readRequestBody(r) if err != nil { httputil.HandleError(w, "Could not read request body: "+err.Error(), http.StatusInternalServerError) return } - versionHeader := r.Header.Get(api.VersionHeader) - if versionRequired && versionHeader == "" { - httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest) - } - denebBlock := ð.SignedBlindedBeaconBlockDeneb{} - if err = denebBlock.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_BlindedDeneb{ - BlindedDeneb: denebBlock, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) - return - } - if versionHeader == version.String(version.Deneb) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Deneb), err.Error()), - http.StatusBadRequest, - ) + versionHeader, err := validateVersionHeader(r, body, versionRequired) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - capellaBlock := ð.SignedBlindedBeaconBlockCapella{} - if err = capellaBlock.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_BlindedCapella{ - BlindedCapella: capellaBlock, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) - return - } - if versionHeader == version.String(version.Capella) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Capella), err.Error()), - http.StatusBadRequest, - ) + genericBlock, err := decodeBlindedBlockSSZ(versionHeader, body) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - bellatrixBlock := ð.SignedBlindedBeaconBlockBellatrix{} - if err = bellatrixBlock.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_BlindedBellatrix{ - BlindedBellatrix: bellatrixBlock, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) + if err := s.validateBroadcast(ctx, r, genericBlock); err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - if versionHeader == version.String(version.Bellatrix) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Bellatrix), err.Error()), - http.StatusBadRequest, - ) - return + s.proposeBlock(ctx, w, genericBlock) +} + +// decodeBlindedBlockSSZ dispatches to the correct SSZ decoder based on versionHeader. +func decodeBlindedBlockSSZ(versionHeader string, body []byte) (*eth.GenericSignedBeaconBlock, error) { + if decoder, exists := blindedSSZDecoders[versionHeader]; exists { + return decoder(body) } + return nil, fmt.Errorf("body does not represent a valid blinded block type") +} - altairBlock := ð.SignedBeaconBlockAltair{} - if err = altairBlock.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Altair{ - Altair: altairBlock, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) - return +var blindedSSZDecoders = map[string]blockDecoder{ + version.String(version.Fulu): decodeBlindedFuluSSZ, + version.String(version.Electra): decodeBlindedElectraSSZ, + version.String(version.Deneb): decodeBlindedDenebSSZ, + version.String(version.Capella): decodeBlindedCapellaSSZ, + version.String(version.Bellatrix): decodeBlindedBellatrixSSZ, + version.String(version.Altair): decodeAltairSSZ, + version.String(version.Phase0): decodePhase0SSZ, +} + +func decodeBlindedFuluSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + fuluBlock := ð.SignedBlindedBeaconBlockFulu{} + if err := fuluBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError(version.String(version.Fulu), err) } - if versionHeader == version.String(version.Altair) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Altair), err.Error()), - http.StatusBadRequest, - ) - return + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_BlindedFulu{ + BlindedFulu: fuluBlock, + }, + }, nil +} + +func decodeBlindedElectraSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + electraBlock := ð.SignedBlindedBeaconBlockElectra{} + if err := electraBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError(version.String(version.Electra), err) } + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_BlindedElectra{ + BlindedElectra: electraBlock, + }, + }, nil +} - phase0Block := ð.SignedBeaconBlock{} - if err = phase0Block.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Phase0{ - Phase0: phase0Block, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) - return +func decodeBlindedDenebSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + denebBlock := ð.SignedBlindedBeaconBlockDeneb{} + if err := denebBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError(version.String(version.Deneb), err) } - if versionHeader == version.String(version.Phase0) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Phase0), err.Error()), - http.StatusBadRequest, - ) - return + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_BlindedDeneb{ + BlindedDeneb: denebBlock, + }, + }, nil +} + +func decodeBlindedCapellaSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + capellaBlock := ð.SignedBlindedBeaconBlockCapella{} + if err := capellaBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError(version.String(version.Capella), err) } + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_BlindedCapella{ + BlindedCapella: capellaBlock, + }, + }, nil +} - httputil.HandleError(w, "Body does not represent a valid block type", http.StatusBadRequest) +func decodeBlindedBellatrixSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + bellatrixBlock := ð.SignedBlindedBeaconBlockBellatrix{} + if err := bellatrixBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError(version.String(version.Bellatrix), err) + } + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_BlindedBellatrix{ + BlindedBellatrix: bellatrixBlock, + }, + }, nil } +// publishBlindedBlock reads JSON-encoded data and publishes a blinded block. func (s *Server) publishBlindedBlock(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) { - body, err := io.ReadAll(r.Body) + body, err := readRequestBody(r) if err != nil { httputil.HandleError(w, "Could not read request body", http.StatusInternalServerError) return } - versionHeader := r.Header.Get(api.VersionHeader) - if versionRequired && versionHeader == "" { - httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest) - } - var consensusBlock *eth.GenericSignedBeaconBlock - - var denebBlock *structs.SignedBlindedBeaconBlockDeneb - if err = unmarshalStrict(body, &denebBlock); err == nil { - consensusBlock, err = denebBlock.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Deneb) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Deneb), err.Error()), - http.StatusBadRequest, - ) + versionHeader, err := validateVersionHeader(r, body, versionRequired) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - var capellaBlock *structs.SignedBlindedBeaconBlockCapella - if err = unmarshalStrict(body, &capellaBlock); err == nil { - consensusBlock, err = capellaBlock.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Capella) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Capella), err.Error()), - http.StatusBadRequest, - ) + genericBlock, err := decodeBlindedBlockJSON(versionHeader, body) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - var bellatrixBlock *structs.SignedBlindedBeaconBlockBellatrix - if err = unmarshalStrict(body, &bellatrixBlock); err == nil { - consensusBlock, err = bellatrixBlock.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Bellatrix) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Bellatrix), err.Error()), - http.StatusBadRequest, - ) + if err := s.validateBroadcast(ctx, r, genericBlock); err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } + s.proposeBlock(ctx, w, genericBlock) +} - var altairBlock *structs.SignedBeaconBlockAltair - if err = unmarshalStrict(body, &altairBlock); err == nil { - consensusBlock, err = altairBlock.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Altair) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Altair), err.Error()), - http.StatusBadRequest, - ) - return +// decodeBlindedBlockJSON dispatches to the correct JSON decoder based on versionHeader. +func decodeBlindedBlockJSON(versionHeader string, body []byte) (*eth.GenericSignedBeaconBlock, error) { + if decoder, exists := blindedJSONDecoders[versionHeader]; exists { + return decoder(body) } + return nil, fmt.Errorf("body does not represent a valid blinded block type") +} - var phase0Block *structs.SignedBeaconBlock - if err = unmarshalStrict(body, &phase0Block); err == nil { - consensusBlock, err = phase0Block.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Phase0) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Phase0), err.Error()), - http.StatusBadRequest, - ) - return - } +var blindedJSONDecoders = map[string]blockDecoder{ + version.String(version.Fulu): decodeBlindedFuluJSON, + version.String(version.Electra): decodeBlindedElectraJSON, + version.String(version.Deneb): decodeBlindedDenebJSON, + version.String(version.Capella): decodeBlindedCapellaJSON, + version.String(version.Bellatrix): decodeBlindedBellatrixJSON, + version.String(version.Altair): decodeAltairJSON, + version.String(version.Phase0): decodePhase0JSON, +} + +func decodeBlindedFuluJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBlindedBeaconBlockFulu]( + body, + version.String(version.Fulu), + ) +} + +func decodeBlindedElectraJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBlindedBeaconBlockElectra]( + body, + version.String(version.Electra), + ) +} - httputil.HandleError(w, "Body does not represent a valid block type", http.StatusBadRequest) +func decodeBlindedDenebJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBlindedBeaconBlockDeneb]( + body, + version.String(version.Deneb), + ) +} + +func decodeBlindedCapellaJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBlindedBeaconBlockCapella]( + body, + version.String(version.Capella), + ) } +func decodeBlindedBellatrixJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBlindedBeaconBlockBellatrix]( + body, + version.String(version.Bellatrix), + ) +} + +// Deprecated: use PublishBlockV2 instead // PublishBlock instructs the beacon node to broadcast a newly signed beacon block to the beacon network, // to be included in the beacon chain. A success response (20x) indicates that the block // passed gossip validation and was successfully broadcast onto the network. @@ -579,276 +670,281 @@ func (s *Server) PublishBlockV2(w http.ResponseWriter, r *http.Request) { } } +// publishBlockSSZ handles publishing an SSZ-encoded block to the beacon node. func (s *Server) publishBlockSSZ(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) { - body, err := io.ReadAll(r.Body) + body, err := readRequestBody(r) if err != nil { httputil.HandleError(w, "Could not read request body", http.StatusInternalServerError) return } - versionHeader := r.Header.Get(api.VersionHeader) - if versionRequired && versionHeader == "" { - httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest) + + versionHeader, err := validateVersionHeader(r, body, versionRequired) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - denebBlock := ð.SignedBeaconBlockContentsDeneb{} - if err = denebBlock.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Deneb{ - Deneb: denebBlock, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - if errors.Is(err, errEquivocatedBlock) { - b, err := blocks.NewSignedBeaconBlock(genericBlock) - if err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - if err := s.broadcastSeenBlockSidecars(ctx, b, genericBlock.GetDeneb().Blobs, genericBlock.GetDeneb().KzgProofs); err != nil { - log.WithError(err).Error("Failed to broadcast blob sidecars") - } + // Decode SSZ into a generic block. + genericBlock, err := decodeSSZToGenericBlock(versionHeader, body) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) + return + } + + // Validate and optionally broadcast sidecars on equivocation. + if err := s.validateBroadcast(ctx, r, genericBlock); err != nil { + if errors.Is(err, errEquivocatedBlock) { + b, err := blocks.NewSignedBeaconBlock(genericBlock) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) + return + } + if err = broadcastSidecarsIfSupported(ctx, s, b, genericBlock, versionHeader); err != nil { + log.WithError(err).Error("Failed to broadcast blob sidecars") } - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return } - s.proposeBlock(ctx, w, genericBlock) + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - if versionHeader == version.String(version.Deneb) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Deneb), err.Error()), - http.StatusBadRequest, + + s.proposeBlock(ctx, w, genericBlock) +} + +var sszDecoders = map[string]blockDecoder{ + version.String(version.Fulu): decodeFuluSSZ, + version.String(version.Electra): decodeElectraSSZ, + version.String(version.Deneb): decodeDenebSSZ, + version.String(version.Capella): decodeCapellaSSZ, + version.String(version.Bellatrix): decodeBellatrixSSZ, + version.String(version.Altair): decodeAltairSSZ, + version.String(version.Phase0): decodePhase0SSZ, +} + +// decodeSSZToGenericBlock uses a lookup table to map a version string to the proper decoder. +func decodeSSZToGenericBlock(versionHeader string, body []byte) (*eth.GenericSignedBeaconBlock, error) { + if decoder, found := sszDecoders[versionHeader]; found { + return decoder(body) + } + return nil, errors.New("body does not represent a valid block type") +} + +func decodeFuluSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + fuluBlock := ð.SignedBeaconBlockContentsFulu{} + if err := fuluBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError( + version.String(version.Fulu), err, ) - return } + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Fulu{Fulu: fuluBlock}, + }, nil +} - capellaBlock := ð.SignedBeaconBlockCapella{} - if err = capellaBlock.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Capella{ - Capella: capellaBlock, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) - return +func decodeElectraSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + electraBlock := ð.SignedBeaconBlockContentsElectra{} + if err := electraBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError( + version.String(version.Electra), err, + ) } - if versionHeader == version.String(version.Capella) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Capella), err.Error()), - http.StatusBadRequest, + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Electra{Electra: electraBlock}, + }, nil +} + +func decodeDenebSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + denebBlock := ð.SignedBeaconBlockContentsDeneb{} + if err := denebBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError( + version.String(version.Deneb), + err, ) - return } + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Deneb{ + Deneb: denebBlock, + }, + }, nil +} - bellatrixBlock := ð.SignedBeaconBlockBellatrix{} - if err = bellatrixBlock.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Bellatrix{ - Bellatrix: bellatrixBlock, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) - return +func decodeCapellaSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + capellaBlock := ð.SignedBeaconBlockCapella{} + if err := capellaBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError( + version.String(version.Capella), + err, + ) } - if versionHeader == version.String(version.Bellatrix) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Bellatrix), err.Error()), - http.StatusBadRequest, + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Capella{ + Capella: capellaBlock, + }, + }, nil +} + +func decodeBellatrixSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { + bellatrixBlock := ð.SignedBeaconBlockBellatrix{} + if err := bellatrixBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError( + version.String(version.Bellatrix), + err, ) - return } + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Bellatrix{ + Bellatrix: bellatrixBlock, + }, + }, nil +} +func decodeAltairSSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { altairBlock := ð.SignedBeaconBlockAltair{} - if err = altairBlock.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Altair{ - Altair: altairBlock, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) - return - } - if versionHeader == version.String(version.Altair) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Altair), err.Error()), - http.StatusBadRequest, + if err := altairBlock.UnmarshalSSZ(body); err != nil { + return nil, decodingError( + version.String(version.Altair), + err, ) - return } + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Altair{ + Altair: altairBlock, + }, + }, nil +} +func decodePhase0SSZ(body []byte) (*eth.GenericSignedBeaconBlock, error) { phase0Block := ð.SignedBeaconBlock{} - if err = phase0Block.UnmarshalSSZ(body); err == nil { - genericBlock := ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Phase0{ - Phase0: phase0Block, - }, - } - if err = s.validateBroadcast(ctx, r, genericBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, genericBlock) - return - } - if versionHeader == version.String(version.Phase0) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Phase0), err.Error()), - http.StatusBadRequest, + if err := phase0Block.UnmarshalSSZ(body); err != nil { + return nil, decodingError( + version.String(version.Phase0), err, ) - return } - - httputil.HandleError(w, "Body does not represent a valid block type", http.StatusBadRequest) + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Phase0{Phase0: phase0Block}, + }, nil } +// publishBlock handles publishing a JSON-encoded block to the beacon node. func (s *Server) publishBlock(ctx context.Context, w http.ResponseWriter, r *http.Request, versionRequired bool) { - body, err := io.ReadAll(r.Body) + body, err := readRequestBody(r) if err != nil { httputil.HandleError(w, "Could not read request body", http.StatusInternalServerError) return } - versionHeader := r.Header.Get(api.VersionHeader) - if versionRequired && versionHeader == "" { - httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest) - return - } - - var consensusBlock *eth.GenericSignedBeaconBlock - - var denebBlockContents *structs.SignedBeaconBlockContentsDeneb - if err = unmarshalStrict(body, &denebBlockContents); err == nil { - consensusBlock, err = denebBlockContents.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - if errors.Is(err, errEquivocatedBlock) { - b, err := blocks.NewSignedBeaconBlock(consensusBlock) - if err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - if err := s.broadcastSeenBlockSidecars(ctx, b, consensusBlock.GetDeneb().Blobs, consensusBlock.GetDeneb().KzgProofs); err != nil { - log.WithError(err).Error("Failed to broadcast blob sidecars") - } - } - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Deneb) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Deneb), err.Error()), - http.StatusBadRequest, - ) + + versionHeader, err := validateVersionHeader(r, body, versionRequired) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - var capellaBlock *structs.SignedBeaconBlockCapella - if err = unmarshalStrict(body, &capellaBlock); err == nil { - consensusBlock, err = capellaBlock.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Capella) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Capella), err.Error()), - http.StatusBadRequest, - ) + // Decode JSON into a generic block. + genericBlock, decodeErr := decodeJSONToGenericBlock(versionHeader, body) + if decodeErr != nil { + httputil.HandleError(w, decodeErr.Error(), http.StatusBadRequest) return } - var bellatrixBlock *structs.SignedBeaconBlockBellatrix - if err = unmarshalStrict(body, &bellatrixBlock); err == nil { - consensusBlock, err = bellatrixBlock.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { + // Validate and optionally broadcast sidecars on equivocation. + if err := s.validateBroadcast(ctx, r, genericBlock); err != nil { + if errors.Is(err, errEquivocatedBlock) { + b, err := blocks.NewSignedBeaconBlock(genericBlock) + if err != nil { httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Bellatrix) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Bellatrix), err.Error()), - http.StatusBadRequest, - ) - return - } - var altairBlock *structs.SignedBeaconBlockAltair - if err = unmarshalStrict(body, &altairBlock); err == nil { - consensusBlock, err = altairBlock.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return + if err := broadcastSidecarsIfSupported(ctx, s, b, genericBlock, versionHeader); err != nil { + log.WithError(err).Error("Failed to broadcast blob sidecars") } - s.proposeBlock(ctx, w, consensusBlock) - return } - } - if versionHeader == version.String(version.Altair) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Altair), err.Error()), - http.StatusBadRequest, - ) + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - var phase0Block *structs.SignedBeaconBlock - if err = unmarshalStrict(body, &phase0Block); err == nil { - consensusBlock, err = phase0Block.ToGeneric() - if err == nil { - if err = s.validateBroadcast(ctx, r, consensusBlock); err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - s.proposeBlock(ctx, w, consensusBlock) - return - } - } - if versionHeader == version.String(version.Phase0) { - httputil.HandleError( - w, - fmt.Sprintf("Could not decode request body into %s consensus block: %v", version.String(version.Phase0), err.Error()), - http.StatusBadRequest, - ) - return + s.proposeBlock(ctx, w, genericBlock) +} + +var jsonDecoders = map[string]blockDecoder{ + version.String(version.Fulu): decodeFuluJSON, + version.String(version.Electra): decodeElectraJSON, + version.String(version.Deneb): decodeDenebJSON, + version.String(version.Capella): decodeCapellaJSON, + version.String(version.Bellatrix): decodeBellatrixJSON, + version.String(version.Altair): decodeAltairJSON, + version.String(version.Phase0): decodePhase0JSON, +} + +// decodeJSONToGenericBlock uses a lookup table to map a version string to the proper decoder. +func decodeJSONToGenericBlock(versionHeader string, body []byte) (*eth.GenericSignedBeaconBlock, error) { + if decoder, found := jsonDecoders[versionHeader]; found { + return decoder(body) } + return nil, fmt.Errorf("body does not represent a valid block type") +} + +func decodeFuluJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBeaconBlockContentsFulu]( + body, + version.String(version.Fulu), + ) +} - httputil.HandleError(w, "Body does not represent a valid block type", http.StatusBadRequest) +func decodeElectraJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBeaconBlockContentsElectra]( + body, + version.String(version.Electra), + ) +} + +func decodeDenebJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBeaconBlockContentsDeneb]( + body, + version.String(version.Deneb), + ) +} + +func decodeCapellaJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBeaconBlockCapella]( + body, + version.String(version.Capella), + ) +} + +func decodeBellatrixJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBeaconBlockBellatrix]( + body, + version.String(version.Bellatrix), + ) +} + +func decodeAltairJSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBeaconBlockAltair]( + body, + version.String(version.Altair), + ) +} + +func decodePhase0JSON(body []byte) (*eth.GenericSignedBeaconBlock, error) { + return decodeGenericJSON[*structs.SignedBeaconBlock]( + body, + version.String(version.Phase0), + ) +} + +// broadcastSidecarsIfSupported broadcasts blob sidecars when an equivocated block occurs. +func broadcastSidecarsIfSupported(ctx context.Context, s *Server, b interfaces.SignedBeaconBlock, gb *eth.GenericSignedBeaconBlock, versionHeader string) error { + switch versionHeader { + case version.String(version.Fulu): + return s.broadcastSeenBlockSidecars(ctx, b, gb.GetFulu().Blobs, gb.GetFulu().KzgProofs) + case version.String(version.Electra): + return s.broadcastSeenBlockSidecars(ctx, b, gb.GetElectra().Blobs, gb.GetElectra().KzgProofs) + case version.String(version.Deneb): + return s.broadcastSeenBlockSidecars(ctx, b, gb.GetDeneb().Blobs, gb.GetDeneb().KzgProofs) + default: + // other forks before Deneb do not support blob sidecars + return nil + } } func (s *Server) proposeBlock(ctx context.Context, w http.ResponseWriter, blk *eth.GenericSignedBeaconBlock) { @@ -868,21 +964,17 @@ func unmarshalStrict(data []byte, v interface{}) error { func (s *Server) validateBroadcast(ctx context.Context, r *http.Request, blk *eth.GenericSignedBeaconBlock) error { switch r.URL.Query().Get(broadcastValidationQueryParam) { case broadcastValidationConsensus: - b, err := blocks.NewSignedBeaconBlock(blk.Block) - if err != nil { - return errors.Wrapf(err, "could not create signed beacon block") - } - if err = s.validateConsensus(ctx, b); err != nil { + if err := s.validateConsensus(ctx, blk); err != nil { return errors.Wrap(err, "consensus validation failed") } case broadcastValidationConsensusAndEquivocation: + if err := s.validateConsensus(r.Context(), blk); err != nil { + return errors.Wrap(err, "consensus validation failed") + } b, err := blocks.NewSignedBeaconBlock(blk.Block) if err != nil { return errors.Wrapf(err, "could not create signed beacon block") } - if err = s.validateConsensus(r.Context(), b); err != nil { - return errors.Wrap(err, "consensus validation failed") - } if err = s.validateEquivocation(b.Block()); err != nil { return errors.Wrap(err, "equivocation validation failed") } @@ -892,7 +984,12 @@ func (s *Server) validateBroadcast(ctx context.Context, r *http.Request, blk *et return nil } -func (s *Server) validateConsensus(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) error { +func (s *Server) validateConsensus(ctx context.Context, b *eth.GenericSignedBeaconBlock) error { + blk, err := blocks.NewSignedBeaconBlock(b.Block) + if err != nil { + return errors.Wrapf(err, "could not create signed beacon block") + } + parentBlockRoot := blk.Block().ParentRoot() parentBlock, err := s.Blocker.Block(ctx, parentBlockRoot[:]) if err != nil { @@ -912,6 +1009,27 @@ func (s *Server) validateConsensus(ctx context.Context, blk interfaces.ReadOnlyS if err != nil { return errors.Wrap(err, "could not execute state transition") } + + var blobs [][]byte + var proofs [][]byte + switch blk.Version() { + case version.Deneb: + blobs = b.GetDeneb().Blobs + proofs = b.GetDeneb().KzgProofs + case version.Electra: + blobs = b.GetElectra().Blobs + proofs = b.GetElectra().KzgProofs + case version.Fulu: + blobs = b.GetFulu().Blobs + proofs = b.GetFulu().KzgProofs + default: + return nil + } + + if err := s.validateBlobSidecars(blk, blobs, proofs); err != nil { + return err + } + return nil } @@ -922,6 +1040,26 @@ func (s *Server) validateEquivocation(blk interfaces.ReadOnlyBeaconBlock) error return nil } +func (s *Server) validateBlobSidecars(blk interfaces.SignedBeaconBlock, blobs [][]byte, proofs [][]byte) error { + if blk.Version() < version.Deneb { + return nil + } + kzgs, err := blk.Block().Body().BlobKzgCommitments() + if err != nil { + return errors.Wrap(err, "could not get blob kzg commitments") + } + if len(blobs) != len(proofs) || len(blobs) != len(kzgs) { + return errors.New("number of blobs, proofs, and commitments do not match") + } + for i, blob := range blobs { + b := kzg4844.Blob(blob) + if err := kzg4844.VerifyBlobProof(&b, kzg4844.Commitment(kzgs[i]), kzg4844.Proof(proofs[i])); err != nil { + return errors.Wrap(err, "could not verify blob proof") + } + } + return nil +} + // GetBlockRoot retrieves the root of a block. func (s *Server) GetBlockRoot(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockRoot") @@ -929,7 +1067,7 @@ func (s *Server) GetBlockRoot(w http.ResponseWriter, r *http.Request) { var err error var root []byte - blockID := mux.Vars(r)["block_id"] + blockID := r.PathValue("block_id") if blockID == "" { httputil.HandleError(w, "block_id is required in URL params", http.StatusBadRequest) return @@ -1041,7 +1179,8 @@ func (s *Server) GetBlockRoot(w http.ResponseWriter, r *http.Request) { func (s *Server) GetStateFork(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetStateFork") defer span.End() - stateId := mux.Vars(r)["state_id"] + + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return @@ -1081,7 +1220,7 @@ func (s *Server) GetCommittees(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetCommittees") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return @@ -1266,7 +1405,7 @@ func (s *Server) GetBlockHeader(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetBlockHeader") defer span.End() - blockID := mux.Vars(r)["block_id"] + blockID := r.PathValue("block_id") if blockID == "" { httputil.HandleError(w, "block_id is required in URL params", http.StatusBadRequest) return @@ -1324,7 +1463,7 @@ func (s *Server) GetFinalityCheckpoints(w http.ResponseWriter, r *http.Request) ctx, span := trace.StartSpan(r.Context(), "beacon.GetFinalityCheckpoints") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return @@ -1398,16 +1537,13 @@ func (s *Server) GetGenesis(w http.ResponseWriter, r *http.Request) { httputil.WriteJson(w, resp) } +// Deprecated: no longer needed post Electra // GetDepositSnapshot retrieves the EIP-4881 Deposit Tree Snapshot. Either a JSON or, // if the Accept header was added, bytes serialized by SSZ will be returned. func (s *Server) GetDepositSnapshot(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetDepositSnapshot") defer span.End() - if s.BeaconDB == nil { - httputil.HandleError(w, "Could not retrieve beaconDB", http.StatusInternalServerError) - return - } eth1data, err := s.BeaconDB.ExecutionChainData(ctx) if err != nil { httputil.HandleError(w, "Could not retrieve execution chain data: "+err.Error(), http.StatusInternalServerError) @@ -1419,7 +1555,7 @@ func (s *Server) GetDepositSnapshot(w http.ResponseWriter, r *http.Request) { } snapshot := eth1data.DepositSnapshot if snapshot == nil || len(snapshot.Finalized) == 0 { - httputil.HandleError(w, "No Finalized Snapshot Available", http.StatusNotFound) + httputil.HandleError(w, "No finalized snapshot available", http.StatusNotFound) return } if len(snapshot.Finalized) > depositsnapshot.DepositContractDepth { @@ -1476,3 +1612,129 @@ func (s *Server) broadcastSeenBlockSidecars( } return nil } + +// GetPendingDeposits returns pending deposits for state with given 'stateId'. +// Should return 400 if the state retrieved is prior to Electra. +// Supports both JSON and SSZ responses based on Accept header. +func (s *Server) GetPendingDeposits(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "beacon.GetPendingDeposits") + defer span.End() + + stateId := r.PathValue("state_id") + if stateId == "" { + httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) + return + } + st, err := s.Stater.State(ctx, []byte(stateId)) + if err != nil { + shared.WriteStateFetchError(w, err) + return + } + if st.Version() < version.Electra { + httputil.HandleError(w, "state_id is prior to electra", http.StatusBadRequest) + return + } + pd, err := st.PendingDeposits() + if err != nil { + httputil.HandleError(w, "Could not get pending deposits: "+err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set(api.VersionHeader, version.String(st.Version())) + if httputil.RespondWithSsz(r) { + sszData, err := serializeItems(pd) + if err != nil { + httputil.HandleError(w, "Failed to serialize pending deposits: "+err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteSsz(w, sszData, "pending_deposits.ssz") + } else { + isOptimistic, err := helpers.IsOptimistic(ctx, []byte(stateId), s.OptimisticModeFetcher, s.Stater, s.ChainInfoFetcher, s.BeaconDB) + if err != nil { + httputil.HandleError(w, "Could not check optimistic status: "+err.Error(), http.StatusInternalServerError) + return + } + blockRoot, err := st.LatestBlockHeader().HashTreeRoot() + if err != nil { + httputil.HandleError(w, "Could not calculate root of latest block header: "+err.Error(), http.StatusInternalServerError) + return + } + isFinalized := s.FinalizationFetcher.IsFinalized(ctx, blockRoot) + resp := structs.GetPendingDepositsResponse{ + Version: version.String(st.Version()), + ExecutionOptimistic: isOptimistic, + Finalized: isFinalized, + Data: structs.PendingDepositsFromConsensus(pd), + } + httputil.WriteJson(w, resp) + } +} + +// GetPendingPartialWithdrawals returns pending partial withdrawals for state with given 'stateId'. +// Should return 400 if the state retrieved is prior to Electra. +// Supports both JSON and SSZ responses based on Accept header. +func (s *Server) GetPendingPartialWithdrawals(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "beacon.GetPendingPartialWithdrawals") + defer span.End() + + stateId := r.PathValue("state_id") + if stateId == "" { + httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) + return + } + st, err := s.Stater.State(ctx, []byte(stateId)) + if err != nil { + shared.WriteStateFetchError(w, err) + return + } + if st.Version() < version.Electra { + httputil.HandleError(w, "state_id is prior to electra", http.StatusBadRequest) + return + } + ppw, err := st.PendingPartialWithdrawals() + if err != nil { + httputil.HandleError(w, "Could not get pending partial withdrawals: "+err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set(api.VersionHeader, version.String(st.Version())) + if httputil.RespondWithSsz(r) { + sszData, err := serializeItems(ppw) + if err != nil { + httputil.HandleError(w, "Failed to serialize pending partial withdrawals: "+err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteSsz(w, sszData, "pending_partial_withdrawals.ssz") + } else { + isOptimistic, err := helpers.IsOptimistic(ctx, []byte(stateId), s.OptimisticModeFetcher, s.Stater, s.ChainInfoFetcher, s.BeaconDB) + if err != nil { + httputil.HandleError(w, "Could not check optimistic status: "+err.Error(), http.StatusInternalServerError) + return + } + blockRoot, err := st.LatestBlockHeader().HashTreeRoot() + if err != nil { + httputil.HandleError(w, "Could not calculate root of latest block header: "+err.Error(), http.StatusInternalServerError) + return + } + isFinalized := s.FinalizationFetcher.IsFinalized(ctx, blockRoot) + resp := structs.GetPendingPartialWithdrawalsResponse{ + Version: version.String(st.Version()), + ExecutionOptimistic: isOptimistic, + Finalized: isFinalized, + Data: structs.PendingPartialWithdrawalsFromConsensus(ppw), + } + httputil.WriteJson(w, resp) + } +} + +// SerializeItems serializes a slice of items, each of which implements the MarshalSSZ method, +// into a single byte array. +func serializeItems[T interface{ MarshalSSZ() ([]byte, error) }](items []T) ([]byte, error) { + var result []byte + for _, item := range items { + b, err := item.MarshalSSZ() + if err != nil { + return nil, err + } + result = append(result, b...) + } + return result, nil +} diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool.go b/beacon-chain/rpc/eth/beacon/handlers_pool.go index e78a91ca9aed..d22e40beea76 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool.go @@ -3,13 +3,15 @@ package beacon import ( "context" "encoding/json" - "errors" "fmt" "io" "net/http" + "strconv" "strings" "time" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" @@ -23,15 +25,16 @@ import ( consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) const broadcastBLSChangesRateLimit = 128 +// Deprecated: use ListAttestationsV2 instead // ListAttestations retrieves attestations known by the node but // not necessarily incorporated into any block. Allows filtering by committee index or slot. func (s *Server) ListAttestations(w http.ResponseWriter, r *http.Request) { @@ -47,46 +50,138 @@ func (s *Server) ListAttestations(w http.ResponseWriter, r *http.Request) { return } - attestations := s.AttestationsPool.AggregatedAttestations() - unaggAtts, err := s.AttestationsPool.UnaggregatedAttestations() - if err != nil { - httputil.HandleError(w, "Could not get unaggregated attestations: "+err.Error(), http.StatusInternalServerError) - return - } - attestations = append(attestations, unaggAtts...) - isEmptyReq := rawSlot == "" && rawCommitteeIndex == "" - if isEmptyReq { - allAtts := make([]*structs.Attestation, len(attestations)) - for i, att := range attestations { - a, ok := att.(*eth.Attestation) - if ok { - allAtts[i] = structs.AttFromConsensus(a) - } else { - httputil.HandleError(w, fmt.Sprintf("unable to convert attestations of type %T", att), http.StatusInternalServerError) - return - } + var attestations []eth.Att + if features.Get().EnableExperimentalAttestationPool { + attestations = s.AttestationCache.GetAll() + } else { + attestations = s.AttestationsPool.AggregatedAttestations() + unaggAtts, err := s.AttestationsPool.UnaggregatedAttestations() + if err != nil { + httputil.HandleError(w, "Could not get unaggregated attestations: "+err.Error(), http.StatusInternalServerError) + return } - httputil.WriteJson(w, &structs.ListAttestationsResponse{Data: allAtts}) - return + attestations = append(attestations, unaggAtts...) } - bothDefined := rawSlot != "" && rawCommitteeIndex != "" filteredAtts := make([]*structs.Attestation, 0, len(attestations)) + for _, a := range attestations { + var includeAttestation bool + att, ok := a.(*eth.Attestation) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Unable to convert attestation of type %T", a), http.StatusInternalServerError) + return + } + + includeAttestation = shouldIncludeAttestation(att.GetData(), rawSlot, slot, rawCommitteeIndex, committeeIndex) + if includeAttestation { + attStruct := structs.AttFromConsensus(att) + filteredAtts = append(filteredAtts, attStruct) + } + } + + attsData, err := json.Marshal(filteredAtts) + if err != nil { + httputil.HandleError(w, "Could not marshal attestations: "+err.Error(), http.StatusInternalServerError) + return + } + + httputil.WriteJson(w, &structs.ListAttestationsResponse{ + Data: attsData, + }) +} + +// ListAttestationsV2 retrieves attestations known by the node but +// not necessarily incorporated into any block. Allows filtering by committee index or slot. +func (s *Server) ListAttestationsV2(w http.ResponseWriter, r *http.Request) { + _, span := trace.StartSpan(r.Context(), "beacon.ListAttestationsV2") + defer span.End() + + rawSlot, slot, ok := shared.UintFromQuery(w, r, "slot", false) + if !ok { + return + } + rawCommitteeIndex, committeeIndex, ok := shared.UintFromQuery(w, r, "committee_index", false) + if !ok { + return + } + v := slots.ToForkVersion(primitives.Slot(slot)) + if rawSlot == "" { + v = slots.ToForkVersion(s.TimeFetcher.CurrentSlot()) + } + + var attestations []eth.Att + if features.Get().EnableExperimentalAttestationPool { + attestations = s.AttestationCache.GetAll() + } else { + attestations = s.AttestationsPool.AggregatedAttestations() + unaggAtts, err := s.AttestationsPool.UnaggregatedAttestations() + if err != nil { + httputil.HandleError(w, "Could not get unaggregated attestations: "+err.Error(), http.StatusInternalServerError) + return + } + attestations = append(attestations, unaggAtts...) + } + + filteredAtts := make([]interface{}, 0, len(attestations)) for _, att := range attestations { - committeeIndexMatch := rawCommitteeIndex != "" && att.GetData().CommitteeIndex == primitives.CommitteeIndex(committeeIndex) - slotMatch := rawSlot != "" && att.GetData().Slot == primitives.Slot(slot) - shouldAppend := (bothDefined && committeeIndexMatch && slotMatch) || (!bothDefined && (committeeIndexMatch || slotMatch)) - if shouldAppend { - a, ok := att.(*eth.Attestation) - if ok { - filteredAtts = append(filteredAtts, structs.AttFromConsensus(a)) - } else { - httputil.HandleError(w, fmt.Sprintf("unable to convert attestations of type %T", att), http.StatusInternalServerError) + var includeAttestation bool + if v >= version.Electra && att.Version() >= version.Electra { + attElectra, ok := att.(*eth.AttestationElectra) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Unable to convert attestation of type %T", att), http.StatusInternalServerError) + return + } + + includeAttestation = shouldIncludeAttestation(attElectra.GetData(), rawSlot, slot, rawCommitteeIndex, committeeIndex) + if includeAttestation { + attStruct := structs.AttElectraFromConsensus(attElectra) + filteredAtts = append(filteredAtts, attStruct) + } + } else if v < version.Electra && att.Version() < version.Electra { + attOld, ok := att.(*eth.Attestation) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Unable to convert attestation of type %T", att), http.StatusInternalServerError) return } + + includeAttestation = shouldIncludeAttestation(attOld.GetData(), rawSlot, slot, rawCommitteeIndex, committeeIndex) + if includeAttestation { + attStruct := structs.AttFromConsensus(attOld) + filteredAtts = append(filteredAtts, attStruct) + } } } - httputil.WriteJson(w, &structs.ListAttestationsResponse{Data: filteredAtts}) + + attsData, err := json.Marshal(filteredAtts) + if err != nil { + httputil.HandleError(w, "Could not marshal attestations: "+err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set(api.VersionHeader, version.String(v)) + httputil.WriteJson(w, &structs.ListAttestationsResponse{ + Version: version.String(v), + Data: attsData, + }) +} + +// Helper function to determine if an attestation should be included +func shouldIncludeAttestation( + data *eth.AttestationData, + rawSlot string, + slot uint64, + rawCommitteeIndex string, + committeeIndex uint64, +) bool { + committeeIndexMatch := true + slotMatch := true + if rawCommitteeIndex != "" && data.CommitteeIndex != primitives.CommitteeIndex(committeeIndex) { + committeeIndexMatch = false + } + if rawSlot != "" && data.Slot != primitives.Slot(slot) { + slotMatch = false + } + return committeeIndexMatch && slotMatch } // SubmitAttestations submits an attestation object to node. If the attestation passes all validation @@ -105,14 +200,184 @@ func (s *Server) SubmitAttestations(w http.ResponseWriter, r *http.Request) { httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest) return } - if len(req.Data) == 0 { + + attFailures, failedBroadcasts, err := s.handleAttestations(ctx, req.Data) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) + return + } + + if len(failedBroadcasts) > 0 { + httputil.HandleError( + w, + fmt.Sprintf("Attestations at index %s could not be broadcasted", strings.Join(failedBroadcasts, ", ")), + http.StatusInternalServerError, + ) + return + } + + if len(attFailures) > 0 { + failuresErr := &server.IndexedVerificationFailureError{ + Code: http.StatusBadRequest, + Message: "One or more attestations failed validation", + Failures: attFailures, + } + httputil.WriteError(w, failuresErr) + } +} + +// SubmitAttestationsV2 submits an attestation object to node. If the attestation passes all validation +// constraints, node MUST publish the attestation on an appropriate subnet. +func (s *Server) SubmitAttestationsV2(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "beacon.SubmitAttestationsV2") + defer span.End() + + versionHeader := r.Header.Get(api.VersionHeader) + if versionHeader == "" { + httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest) + return + } + v, err := version.FromString(versionHeader) + if err != nil { + httputil.HandleError(w, "Invalid version: "+err.Error(), http.StatusBadRequest) + return + } + + var req structs.SubmitAttestationsRequest + err = json.NewDecoder(r.Body).Decode(&req.Data) + switch { + case errors.Is(err, io.EOF): httputil.HandleError(w, "No data submitted", http.StatusBadRequest) return + case err != nil: + httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest) + return } - var validAttestations []*eth.Attestation var attFailures []*server.IndexedVerificationFailure - for i, sourceAtt := range req.Data { + var failedBroadcasts []string + + if v >= version.Electra { + attFailures, failedBroadcasts, err = s.handleAttestationsElectra(ctx, req.Data) + } else { + attFailures, failedBroadcasts, err = s.handleAttestations(ctx, req.Data) + } + if err != nil { + httputil.HandleError(w, fmt.Sprintf("Failed to handle attestations: %v", err), http.StatusBadRequest) + return + } + + if len(failedBroadcasts) > 0 { + httputil.HandleError( + w, + fmt.Sprintf("Attestations at index %s could not be broadcasted", strings.Join(failedBroadcasts, ", ")), + http.StatusInternalServerError, + ) + return + } + + if len(attFailures) > 0 { + failuresErr := &server.IndexedVerificationFailureError{ + Code: http.StatusBadRequest, + Message: "One or more attestations failed validation", + Failures: attFailures, + } + httputil.WriteError(w, failuresErr) + } +} + +func (s *Server) handleAttestationsElectra( + ctx context.Context, + data json.RawMessage, +) (attFailures []*server.IndexedVerificationFailure, failedBroadcasts []string, err error) { + var sourceAttestations []*structs.SingleAttestation + + if err = json.Unmarshal(data, &sourceAttestations); err != nil { + return nil, nil, errors.Wrap(err, "failed to unmarshal attestation") + } + + if len(sourceAttestations) == 0 { + return nil, nil, errors.New("no data submitted") + } + + var validAttestations []*eth.SingleAttestation + for i, sourceAtt := range sourceAttestations { + att, err := sourceAtt.ToConsensus() + if err != nil { + attFailures = append(attFailures, &server.IndexedVerificationFailure{ + Index: i, + Message: "Could not convert request attestation to consensus attestation: " + err.Error(), + }) + continue + } + if _, err = bls.SignatureFromBytes(att.Signature); err != nil { + attFailures = append(attFailures, &server.IndexedVerificationFailure{ + Index: i, + Message: "Incorrect attestation signature: " + err.Error(), + }) + continue + } + validAttestations = append(validAttestations, att) + } + + for i, singleAtt := range validAttestations { + s.OperationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.SingleAttReceived, + Data: &operation.SingleAttReceivedData{ + Attestation: singleAtt, + }, + }) + + targetState, err := s.AttestationStateFetcher.AttestationTargetState(ctx, singleAtt.Data.Target) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get target state for attestation") + } + committee, err := corehelpers.BeaconCommitteeFromState(ctx, targetState, singleAtt.Data.Slot, singleAtt.CommitteeId) + if err != nil { + return nil, nil, errors.Wrap(err, "could not get committee for attestation") + } + att := singleAtt.ToAttestationElectra(committee) + + wantedEpoch := slots.ToEpoch(att.Data.Slot) + vals, err := s.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch) + if err != nil { + failedBroadcasts = append(failedBroadcasts, strconv.Itoa(i)) + continue + } + subnet := corehelpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), att.GetCommitteeIndex(), att.Data.Slot) + if err = s.Broadcaster.BroadcastAttestation(ctx, subnet, singleAtt); err != nil { + log.WithError(err).Errorf("could not broadcast attestation at index %d", i) + failedBroadcasts = append(failedBroadcasts, strconv.Itoa(i)) + continue + } + + if features.Get().EnableExperimentalAttestationPool { + if err = s.AttestationCache.Add(att); err != nil { + log.WithError(err).Error("could not save attestation") + } + } else { + if err = s.AttestationsPool.SaveUnaggregatedAttestation(att); err != nil { + log.WithError(err).Error("could not save attestation") + } + } + } + + return attFailures, failedBroadcasts, nil +} + +func (s *Server) handleAttestations(ctx context.Context, data json.RawMessage) (attFailures []*server.IndexedVerificationFailure, failedBroadcasts []string, err error) { + var sourceAttestations []*structs.Attestation + + if err = json.Unmarshal(data, &sourceAttestations); err != nil { + return nil, nil, errors.Wrap(err, "failed to unmarshal attestation") + } + + if len(sourceAttestations) == 0 { + return nil, nil, errors.New("no data submitted") + } + + var validAttestations []*eth.Attestation + for i, sourceAtt := range sourceAttestations { att, err := sourceAtt.ToConsensus() if err != nil { attFailures = append(attFailures, &server.IndexedVerificationFailure{ @@ -128,11 +393,14 @@ func (s *Server) SubmitAttestations(w http.ResponseWriter, r *http.Request) { }) continue } + validAttestations = append(validAttestations, att) + } + for i, att := range validAttestations { // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node // of a received unaggregated attestation. // Note we can't send for aggregated att because we don't have selection proof. - if !corehelpers.IsAggregated(att) { + if !att.IsAggregated() { s.OperationNotifier.OperationFeed().Send(&feed.Event{ Type: operation.UnaggregatedAttReceived, Data: &operation.UnAggregatedAttReceivedData{ @@ -141,25 +409,25 @@ func (s *Server) SubmitAttestations(w http.ResponseWriter, r *http.Request) { }) } - validAttestations = append(validAttestations, att) - } - - failedBroadcasts := make([]string, 0) - for i, att := range validAttestations { - // Determine subnet to broadcast attestation to wantedEpoch := slots.ToEpoch(att.Data.Slot) vals, err := s.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch) if err != nil { - httputil.HandleError(w, "Could not get head validator indices: "+err.Error(), http.StatusInternalServerError) - return + failedBroadcasts = append(failedBroadcasts, strconv.Itoa(i)) + continue } - subnet := corehelpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), att.Data.CommitteeIndex, att.Data.Slot) + subnet := corehelpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), att.Data.CommitteeIndex, att.Data.Slot) if err = s.Broadcaster.BroadcastAttestation(ctx, subnet, att); err != nil { log.WithError(err).Errorf("could not broadcast attestation at index %d", i) + failedBroadcasts = append(failedBroadcasts, strconv.Itoa(i)) + continue } - if corehelpers.IsAggregated(att) { + if features.Get().EnableExperimentalAttestationPool { + if err = s.AttestationCache.Add(att); err != nil { + log.WithError(err).Error("could not save attestation") + } + } else if att.IsAggregated() { if err = s.AttestationsPool.SaveAggregatedAttestation(att); err != nil { log.WithError(err).Error("could not save aggregated attestation") } @@ -169,23 +437,8 @@ func (s *Server) SubmitAttestations(w http.ResponseWriter, r *http.Request) { } } } - if len(failedBroadcasts) > 0 { - httputil.HandleError( - w, - fmt.Sprintf("Attestations at index %s could not be broadcasted", strings.Join(failedBroadcasts, ", ")), - http.StatusInternalServerError, - ) - return - } - if len(attFailures) > 0 { - failuresErr := &server.IndexedVerificationFailureError{ - Code: http.StatusBadRequest, - Message: "One or more attestations failed validation", - Failures: attFailures, - } - httputil.WriteError(w, failuresErr) - } + return attFailures, failedBroadcasts, nil } // ListVoluntaryExits retrieves voluntary exits known by the node but @@ -455,6 +708,7 @@ func (s *Server) ListBLSToExecutionChanges(w http.ResponseWriter, r *http.Reques }) } +// Deprecated: use GetAttesterSlashingsV2 instead // GetAttesterSlashings retrieves attester slashings known by the node but // not necessarily incorporated into any block. func (s *Server) GetAttesterSlashings(w http.ResponseWriter, r *http.Request) { @@ -467,25 +721,78 @@ func (s *Server) GetAttesterSlashings(w http.ResponseWriter, r *http.Request) { return } sourceSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, headState, true /* return unlimited slashings */) - ss := make([]*eth.AttesterSlashing, 0, len(sourceSlashings)) + slashings := make([]*structs.AttesterSlashing, len(sourceSlashings)) + for i, slashing := range sourceSlashings { + as, ok := slashing.(*eth.AttesterSlashing) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Unable to convert slashing of type %T", slashing), http.StatusInternalServerError) + return + } + slashings[i] = structs.AttesterSlashingFromConsensus(as) + } + attBytes, err := json.Marshal(slashings) + if err != nil { + httputil.HandleError(w, fmt.Sprintf("Failed to marshal slashings: %v", err), http.StatusInternalServerError) + return + } + httputil.WriteJson(w, &structs.GetAttesterSlashingsResponse{Data: attBytes}) +} + +// GetAttesterSlashingsV2 retrieves attester slashings known by the node but +// not necessarily incorporated into any block, supporting both AttesterSlashing and AttesterSlashingElectra. +func (s *Server) GetAttesterSlashingsV2(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "beacon.GetAttesterSlashingsV2") + defer span.End() + + v := slots.ToForkVersion(s.TimeFetcher.CurrentSlot()) + headState, err := s.ChainInfoFetcher.HeadStateReadOnly(ctx) + if err != nil { + httputil.HandleError(w, "Could not get head state: "+err.Error(), http.StatusInternalServerError) + return + } + var attStructs []interface{} + sourceSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, headState, true /* return unlimited slashings */) + for _, slashing := range sourceSlashings { - s, ok := slashing.(*eth.AttesterSlashing) - if ok { - ss = append(ss, s) + var attStruct interface{} + if v >= version.Electra && slashing.Version() >= version.Electra { + a, ok := slashing.(*eth.AttesterSlashingElectra) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Unable to convert slashing of type %T to an Electra slashing", slashing), http.StatusInternalServerError) + return + } + attStruct = structs.AttesterSlashingElectraFromConsensus(a) + } else if v < version.Electra && slashing.Version() < version.Electra { + a, ok := slashing.(*eth.AttesterSlashing) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Unable to convert slashing of type %T to a Phase0 slashing", slashing), http.StatusInternalServerError) + return + } + attStruct = structs.AttesterSlashingFromConsensus(a) } else { - httputil.HandleError(w, fmt.Sprintf("unable to convert slashing of type %T", slashing), http.StatusInternalServerError) - return + continue } + attStructs = append(attStructs, attStruct) + } + + attBytes, err := json.Marshal(attStructs) + if err != nil { + httputil.HandleError(w, fmt.Sprintf("Failed to marshal slashing: %v", err), http.StatusInternalServerError) + return } - slashings := structs.AttesterSlashingsFromConsensus(ss) - httputil.WriteJson(w, &structs.GetAttesterSlashingsResponse{Data: slashings}) + resp := &structs.GetAttesterSlashingsResponse{ + Version: version.String(v), + Data: attBytes, + } + w.Header().Set(api.VersionHeader, version.String(v)) + httputil.WriteJson(w, resp) } -// SubmitAttesterSlashing submits an attester slashing object to node's pool and +// SubmitAttesterSlashings submits an attester slashing object to node's pool and // if passes validation node MUST broadcast it to network. -func (s *Server) SubmitAttesterSlashing(w http.ResponseWriter, r *http.Request) { - ctx, span := trace.StartSpan(r.Context(), "beacon.SubmitAttesterSlashing") +func (s *Server) SubmitAttesterSlashings(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "beacon.SubmitAttesterSlashings") defer span.End() var req structs.AttesterSlashing @@ -504,16 +811,80 @@ func (s *Server) SubmitAttesterSlashing(w http.ResponseWriter, r *http.Request) httputil.HandleError(w, "Could not convert request slashing to consensus slashing: "+err.Error(), http.StatusBadRequest) return } + s.submitAttesterSlashing(w, ctx, slashing) +} + +// SubmitAttesterSlashingsV2 submits an attester slashing object to node's pool and +// if passes validation node MUST broadcast it to network. +func (s *Server) SubmitAttesterSlashingsV2(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "beacon.SubmitAttesterSlashingsV2") + defer span.End() + + versionHeader := r.Header.Get(api.VersionHeader) + if versionHeader == "" { + httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest) + } + v, err := version.FromString(versionHeader) + if err != nil { + httputil.HandleError(w, "Invalid version: "+err.Error(), http.StatusBadRequest) + return + } + + if v >= version.Electra { + var req structs.AttesterSlashingElectra + err := json.NewDecoder(r.Body).Decode(&req) + switch { + case errors.Is(err, io.EOF): + httputil.HandleError(w, "No data submitted", http.StatusBadRequest) + return + case err != nil: + httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest) + return + } + + slashing, err := req.ToConsensus() + if err != nil { + httputil.HandleError(w, "Could not convert request slashing to consensus slashing: "+err.Error(), http.StatusBadRequest) + return + } + s.submitAttesterSlashing(w, ctx, slashing) + } else { + var req structs.AttesterSlashing + err := json.NewDecoder(r.Body).Decode(&req) + switch { + case errors.Is(err, io.EOF): + httputil.HandleError(w, "No data submitted", http.StatusBadRequest) + return + case err != nil: + httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest) + return + } + + slashing, err := req.ToConsensus() + if err != nil { + httputil.HandleError(w, "Could not convert request slashing to consensus slashing: "+err.Error(), http.StatusBadRequest) + return + } + s.submitAttesterSlashing(w, ctx, slashing) + } +} + +func (s *Server) submitAttesterSlashing( + w http.ResponseWriter, + ctx context.Context, + slashing eth.AttSlashing, +) { headState, err := s.ChainInfoFetcher.HeadState(ctx) if err != nil { httputil.HandleError(w, "Could not get head state: "+err.Error(), http.StatusInternalServerError) return } - headState, err = transition.ProcessSlotsIfPossible(ctx, headState, slashing.Attestation_1.Data.Slot) + headState, err = transition.ProcessSlotsIfPossible(ctx, headState, slashing.FirstAttestation().GetData().Slot) if err != nil { httputil.HandleError(w, "Could not process slots: "+err.Error(), http.StatusInternalServerError) return } + err = blocks.VerifyAttesterSlashing(ctx, headState, slashing) if err != nil { httputil.HandleError(w, "Invalid attester slashing: "+err.Error(), http.StatusBadRequest) diff --git a/beacon-chain/rpc/eth/beacon/handlers_pool_test.go b/beacon-chain/rpc/eth/beacon/handlers_pool_test.go index d2ccfbfde25c..6bfe978ced4c 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_pool_test.go +++ b/beacon-chain/rpc/eth/beacon/handlers_pool_test.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server" "github.com/prysmaticlabs/prysm/v5/api/server/structs" blockchainmock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" @@ -37,6 +38,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/encoding/ssz" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpbv1alpha1 "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -112,77 +114,377 @@ func TestListAttestations(t *testing.T) { }, Signature: bytesutil.PadTo([]byte("signature4"), 96), } - s := &Server{ - AttestationsPool: attestations.NewPool(), - } - require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]ethpbv1alpha1.Att{att1, att2})) - require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]ethpbv1alpha1.Att{att3, att4})) - - t.Run("empty request", func(t *testing.T) { - url := "http://example.com" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.ListAttestations(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - resp := &structs.ListAttestationsResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.NotNil(t, resp) - require.NotNil(t, resp.Data) - assert.Equal(t, 4, len(resp.Data)) - }) - t.Run("slot request", func(t *testing.T) { - url := "http://example.com?slot=2" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + t.Run("V1", func(t *testing.T) { + bs, err := util.NewBeaconState() + require.NoError(t, err) - s.ListAttestations(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - resp := &structs.ListAttestationsResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.NotNil(t, resp) - require.NotNil(t, resp.Data) - assert.Equal(t, 2, len(resp.Data)) - for _, a := range resp.Data { - assert.Equal(t, "2", a.Data.Slot) + chainService := &blockchainmock.ChainService{State: bs} + s := &Server{ + ChainInfoFetcher: chainService, + TimeFetcher: chainService, + AttestationsPool: attestations.NewPool(), } - }) - t.Run("index request", func(t *testing.T) { - url := "http://example.com?committee_index=4" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - s.ListAttestations(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - resp := &structs.ListAttestationsResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.NotNil(t, resp) - require.NotNil(t, resp.Data) - assert.Equal(t, 2, len(resp.Data)) - for _, a := range resp.Data { - assert.Equal(t, "4", a.Data.CommitteeIndex) - } + require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]ethpbv1alpha1.Att{att1, att2})) + require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]ethpbv1alpha1.Att{att3, att4})) + + t.Run("empty request", func(t *testing.T) { + url := "http://example.com" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestations(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 4, len(atts)) + }) + t.Run("slot request", func(t *testing.T) { + url := "http://example.com?slot=2" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestations(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 2, len(atts)) + for _, a := range atts { + assert.Equal(t, "2", a.Data.Slot) + } + }) + t.Run("index request", func(t *testing.T) { + url := "http://example.com?committee_index=4" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestations(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 2, len(atts)) + for _, a := range atts { + assert.Equal(t, "4", a.Data.CommitteeIndex) + } + }) + t.Run("both slot + index request", func(t *testing.T) { + url := "http://example.com?slot=2&committee_index=4" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestations(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 1, len(atts)) + for _, a := range atts { + assert.Equal(t, "2", a.Data.Slot) + assert.Equal(t, "4", a.Data.CommitteeIndex) + } + }) }) - t.Run("both slot + index request", func(t *testing.T) { - url := "http://example.com?slot=2&committee_index=4" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.ListAttestations(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - resp := &structs.ListAttestationsResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.NotNil(t, resp) - require.NotNil(t, resp.Data) - assert.Equal(t, 1, len(resp.Data)) - for _, a := range resp.Data { - assert.Equal(t, "2", a.Data.Slot) - assert.Equal(t, "4", a.Data.CommitteeIndex) - } + t.Run("V2", func(t *testing.T) { + t.Run("Pre-Electra", func(t *testing.T) { + bs, err := util.NewBeaconState() + require.NoError(t, err) + + chainService := &blockchainmock.ChainService{State: bs} + s := &Server{ + ChainInfoFetcher: chainService, + TimeFetcher: chainService, + AttestationsPool: attestations.NewPool(), + } + + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.DenebForkEpoch = 0 + params.OverrideBeaconConfig(config) + + require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]ethpbv1alpha1.Att{att1, att2})) + require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]ethpbv1alpha1.Att{att3, att4})) + t.Run("empty request", func(t *testing.T) { + url := "http://example.com" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 4, len(atts)) + assert.Equal(t, "deneb", resp.Version) + }) + t.Run("slot request", func(t *testing.T) { + url := "http://example.com?slot=2" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 2, len(atts)) + assert.Equal(t, "deneb", resp.Version) + for _, a := range atts { + assert.Equal(t, "2", a.Data.Slot) + } + }) + t.Run("index request", func(t *testing.T) { + url := "http://example.com?committee_index=4" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 2, len(atts)) + assert.Equal(t, "deneb", resp.Version) + for _, a := range atts { + assert.Equal(t, "4", a.Data.CommitteeIndex) + } + }) + t.Run("both slot + index request", func(t *testing.T) { + url := "http://example.com?slot=2&committee_index=4" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 1, len(atts)) + assert.Equal(t, "deneb", resp.Version) + for _, a := range atts { + assert.Equal(t, "2", a.Data.Slot) + assert.Equal(t, "4", a.Data.CommitteeIndex) + } + }) + }) + t.Run("Post-Electra", func(t *testing.T) { + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(1, true) + attElectra1 := ðpbv1alpha1.AttestationElectra{ + AggregationBits: []byte{1, 10}, + Data: ðpbv1alpha1.AttestationData{ + Slot: 1, + CommitteeIndex: 1, + BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), + Source: ðpbv1alpha1.Checkpoint{ + Epoch: 1, + Root: bytesutil.PadTo([]byte("sourceroot1"), 32), + }, + Target: ðpbv1alpha1.Checkpoint{ + Epoch: 10, + Root: bytesutil.PadTo([]byte("targetroot1"), 32), + }, + }, + CommitteeBits: cb, + Signature: bytesutil.PadTo([]byte("signature1"), 96), + } + attElectra2 := ðpbv1alpha1.AttestationElectra{ + AggregationBits: []byte{1, 10}, + Data: ðpbv1alpha1.AttestationData{ + Slot: 1, + CommitteeIndex: 4, + BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), + Source: ðpbv1alpha1.Checkpoint{ + Epoch: 1, + Root: bytesutil.PadTo([]byte("sourceroot2"), 32), + }, + Target: ðpbv1alpha1.Checkpoint{ + Epoch: 10, + Root: bytesutil.PadTo([]byte("targetroot2"), 32), + }, + }, + CommitteeBits: cb, + Signature: bytesutil.PadTo([]byte("signature2"), 96), + } + attElectra3 := ðpbv1alpha1.AttestationElectra{ + AggregationBits: bitfield.NewBitlist(8), + Data: ðpbv1alpha1.AttestationData{ + Slot: 2, + CommitteeIndex: 2, + BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot3"), 32), + Source: ðpbv1alpha1.Checkpoint{ + Epoch: 1, + Root: bytesutil.PadTo([]byte("sourceroot3"), 32), + }, + Target: ðpbv1alpha1.Checkpoint{ + Epoch: 10, + Root: bytesutil.PadTo([]byte("targetroot3"), 32), + }, + }, + CommitteeBits: cb, + Signature: bytesutil.PadTo([]byte("signature3"), 96), + } + attElectra4 := ðpbv1alpha1.AttestationElectra{ + AggregationBits: bitfield.NewBitlist(8), + Data: ðpbv1alpha1.AttestationData{ + Slot: 2, + CommitteeIndex: 4, + BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot4"), 32), + Source: ðpbv1alpha1.Checkpoint{ + Epoch: 1, + Root: bytesutil.PadTo([]byte("sourceroot4"), 32), + }, + Target: ðpbv1alpha1.Checkpoint{ + Epoch: 10, + Root: bytesutil.PadTo([]byte("targetroot4"), 32), + }, + }, + CommitteeBits: cb, + Signature: bytesutil.PadTo([]byte("signature4"), 96), + } + bs, err := util.NewBeaconStateElectra() + require.NoError(t, err) + + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.ElectraForkEpoch = 0 + params.OverrideBeaconConfig(config) + + chainService := &blockchainmock.ChainService{State: bs} + s := &Server{ + AttestationsPool: attestations.NewPool(), + ChainInfoFetcher: chainService, + TimeFetcher: chainService, + } + // Added one pre electra attestation to ensure it is ignored. + require.NoError(t, s.AttestationsPool.SaveAggregatedAttestations([]ethpbv1alpha1.Att{attElectra1, attElectra2, att1})) + require.NoError(t, s.AttestationsPool.SaveUnaggregatedAttestations([]ethpbv1alpha1.Att{attElectra3, attElectra4, att3})) + + t.Run("empty request", func(t *testing.T) { + url := "http://example.com" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 4, len(atts)) + assert.Equal(t, "electra", resp.Version) + }) + t.Run("slot request", func(t *testing.T) { + url := "http://example.com?slot=2" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 2, len(atts)) + assert.Equal(t, "electra", resp.Version) + for _, a := range atts { + assert.Equal(t, "2", a.Data.Slot) + } + }) + t.Run("index request", func(t *testing.T) { + url := "http://example.com?committee_index=4" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 2, len(atts)) + assert.Equal(t, "electra", resp.Version) + for _, a := range atts { + assert.Equal(t, "4", a.Data.CommitteeIndex) + } + }) + t.Run("both slot + index request", func(t *testing.T) { + url := "http://example.com?slot=2&committee_index=4" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.ListAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.ListAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var atts []*structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &atts)) + assert.Equal(t, 1, len(atts)) + assert.Equal(t, "electra", resp.Version) + for _, a := range atts { + assert.Equal(t, "2", a.Data.Slot) + assert.Equal(t, "4", a.Data.CommitteeIndex) + } + }) + }) }) } @@ -196,13 +498,17 @@ func TestSubmitAttestations(t *testing.T) { c.SlotsPerEpoch = 1 params.OverrideBeaconConfig(c) - _, keys, err := util.DeterministicDepositsAndKeys(1) + _, keys, err := util.DeterministicDepositsAndKeys(2) require.NoError(t, err) validators := []*ethpbv1alpha1.Validator{ { PublicKey: keys[0].PublicKey().Marshal(), ExitEpoch: params.BeaconConfig().FarFutureEpoch, }, + { + PublicKey: keys[1].PublicKey().Marshal(), + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + }, } bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { state.Validators = validators @@ -219,99 +525,297 @@ func TestSubmitAttestations(t *testing.T) { chainService := &blockchainmock.ChainService{State: bs} s := &Server{ - HeadFetcher: chainService, - ChainInfoFetcher: chainService, - OperationNotifier: &blockchainmock.MockOperationNotifier{}, + HeadFetcher: chainService, + ChainInfoFetcher: chainService, + OperationNotifier: &blockchainmock.MockOperationNotifier{}, + AttestationStateFetcher: chainService, } - - t.Run("single", func(t *testing.T) { - broadcaster := &p2pMock.MockBroadcaster{} - s.Broadcaster = broadcaster - s.AttestationsPool = attestations.NewPool() - - var body bytes.Buffer - _, err := body.WriteString(singleAtt) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.SubmitAttestations(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) - assert.Equal(t, 1, broadcaster.NumAttestations()) - assert.Equal(t, "0x03", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetAggregationBits())) - assert.Equal(t, "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetSignature())) - assert.Equal(t, primitives.Slot(0), broadcaster.BroadcastAttestations[0].GetData().Slot) - assert.Equal(t, primitives.CommitteeIndex(0), broadcaster.BroadcastAttestations[0].GetData().CommitteeIndex) - assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().BeaconBlockRoot)) - assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Source.Root)) - assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Source.Epoch) - assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Target.Root)) - assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Target.Epoch) - assert.Equal(t, 1, s.AttestationsPool.UnaggregatedAttestationCount()) - }) - t.Run("multiple", func(t *testing.T) { - broadcaster := &p2pMock.MockBroadcaster{} - s.Broadcaster = broadcaster - s.AttestationsPool = attestations.NewPool() - - var body bytes.Buffer - _, err := body.WriteString(multipleAtts) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.SubmitAttestations(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) - assert.Equal(t, 2, broadcaster.NumAttestations()) - assert.Equal(t, 2, s.AttestationsPool.UnaggregatedAttestationCount()) - }) - t.Run("no body", func(t *testing.T) { - request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.SubmitAttestations(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + t.Run("V1", func(t *testing.T) { + t.Run("single", func(t *testing.T) { + broadcaster := &p2pMock.MockBroadcaster{} + s.Broadcaster = broadcaster + s.AttestationsPool = attestations.NewPool() + + var body bytes.Buffer + _, err := body.WriteString(singleAtt) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestations(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + assert.Equal(t, 1, broadcaster.NumAttestations()) + assert.Equal(t, "0x03", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetAggregationBits())) + assert.Equal(t, "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetSignature())) + assert.Equal(t, primitives.Slot(0), broadcaster.BroadcastAttestations[0].GetData().Slot) + assert.Equal(t, primitives.CommitteeIndex(0), broadcaster.BroadcastAttestations[0].GetData().CommitteeIndex) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().BeaconBlockRoot)) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Source.Root)) + assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Source.Epoch) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Target.Root)) + assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Target.Epoch) + assert.Equal(t, 1, s.AttestationsPool.UnaggregatedAttestationCount()) + }) + t.Run("multiple", func(t *testing.T) { + broadcaster := &p2pMock.MockBroadcaster{} + s.Broadcaster = broadcaster + s.AttestationsPool = attestations.NewPool() + + var body bytes.Buffer + _, err := body.WriteString(multipleAtts) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestations(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + assert.Equal(t, 2, broadcaster.NumAttestations()) + assert.Equal(t, 2, s.AttestationsPool.UnaggregatedAttestationCount()) + }) + t.Run("no body", func(t *testing.T) { + request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestations(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("empty", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString("[]") + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestations(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "no data submitted")) + }) + t.Run("invalid", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString(invalidAtt) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestations(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &server.IndexedVerificationFailureError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + require.Equal(t, 1, len(e.Failures)) + assert.Equal(t, true, strings.Contains(e.Failures[0].Message, "Incorrect attestation signature")) + }) }) - t.Run("empty", func(t *testing.T) { - var body bytes.Buffer - _, err := body.WriteString("[]") - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.SubmitAttestations(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + t.Run("V2", func(t *testing.T) { + t.Run("pre-electra", func(t *testing.T) { + t.Run("single", func(t *testing.T) { + broadcaster := &p2pMock.MockBroadcaster{} + s.Broadcaster = broadcaster + s.AttestationsPool = attestations.NewPool() + + var body bytes.Buffer + _, err := body.WriteString(singleAtt) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Phase0)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + assert.Equal(t, 1, broadcaster.NumAttestations()) + assert.Equal(t, "0x03", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetAggregationBits())) + assert.Equal(t, "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetSignature())) + assert.Equal(t, primitives.Slot(0), broadcaster.BroadcastAttestations[0].GetData().Slot) + assert.Equal(t, primitives.CommitteeIndex(0), broadcaster.BroadcastAttestations[0].GetData().CommitteeIndex) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().BeaconBlockRoot)) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Source.Root)) + assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Source.Epoch) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Target.Root)) + assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Target.Epoch) + assert.Equal(t, 1, s.AttestationsPool.UnaggregatedAttestationCount()) + }) + t.Run("multiple", func(t *testing.T) { + broadcaster := &p2pMock.MockBroadcaster{} + s.Broadcaster = broadcaster + s.AttestationsPool = attestations.NewPool() + + var body bytes.Buffer + _, err := body.WriteString(multipleAtts) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Phase0)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + assert.Equal(t, 2, broadcaster.NumAttestations()) + assert.Equal(t, 2, s.AttestationsPool.UnaggregatedAttestationCount()) + }) + t.Run("no body", func(t *testing.T) { + request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) + request.Header.Set(api.VersionHeader, version.String(version.Phase0)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("empty", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString("[]") + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Phase0)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "no data submitted")) + }) + t.Run("invalid", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString(invalidAtt) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Phase0)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &server.IndexedVerificationFailureError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + require.Equal(t, 1, len(e.Failures)) + assert.Equal(t, true, strings.Contains(e.Failures[0].Message, "Incorrect attestation signature")) + }) + }) + t.Run("post-electra", func(t *testing.T) { + t.Run("single", func(t *testing.T) { + broadcaster := &p2pMock.MockBroadcaster{} + s.Broadcaster = broadcaster + s.AttestationsPool = attestations.NewPool() + + var body bytes.Buffer + _, err := body.WriteString(singleAttElectra) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + assert.Equal(t, 1, broadcaster.NumAttestations()) + assert.Equal(t, primitives.ValidatorIndex(1), broadcaster.BroadcastAttestations[0].GetAttestingIndex()) + assert.Equal(t, "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetSignature())) + assert.Equal(t, primitives.Slot(0), broadcaster.BroadcastAttestations[0].GetData().Slot) + assert.Equal(t, primitives.CommitteeIndex(0), broadcaster.BroadcastAttestations[0].GetData().CommitteeIndex) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().BeaconBlockRoot)) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Source.Root)) + assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Source.Epoch) + assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Target.Root)) + assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Target.Epoch) + assert.Equal(t, 1, s.AttestationsPool.UnaggregatedAttestationCount()) + }) + t.Run("multiple", func(t *testing.T) { + broadcaster := &p2pMock.MockBroadcaster{} + s.Broadcaster = broadcaster + s.AttestationsPool = attestations.NewPool() + + var body bytes.Buffer + _, err := body.WriteString(multipleAttsElectra) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + assert.Equal(t, 2, broadcaster.NumAttestations()) + assert.Equal(t, 2, s.AttestationsPool.UnaggregatedAttestationCount()) + }) + t.Run("no body", func(t *testing.T) { + request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("empty", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString("[]") + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "no data submitted")) + }) + t.Run("invalid", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString(invalidAttElectra) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttestationsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &server.IndexedVerificationFailureError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + require.Equal(t, 1, len(e.Failures)) + assert.Equal(t, true, strings.Contains(e.Failures[0].Message, "Incorrect attestation signature")) + }) + }) }) - t.Run("invalid", func(t *testing.T) { - var body bytes.Buffer - _, err := body.WriteString(invalidAtt) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - s.SubmitAttestations(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &server.IndexedVerificationFailureError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - require.Equal(t, 1, len(e.Failures)) - assert.Equal(t, true, strings.Contains(e.Failures[0].Message, "Incorrect attestation signature")) - }) } func TestListVoluntaryExits(t *testing.T) { @@ -983,9 +1487,7 @@ func TestSubmitSignedBLSToExecutionChanges_Failures(t *testing.T) { } func TestGetAttesterSlashings(t *testing.T) { - bs, err := util.NewBeaconState() - require.NoError(t, err) - slashing1 := ðpbv1alpha1.AttesterSlashing{ + slashing1PreElectra := ðpbv1alpha1.AttesterSlashing{ Attestation_1: ðpbv1alpha1.IndexedAttestation{ AttestingIndices: []uint64{1, 10}, Data: ðpbv1alpha1.AttestationData{ @@ -1021,7 +1523,7 @@ func TestGetAttesterSlashings(t *testing.T) { Signature: bytesutil.PadTo([]byte("signature2"), 96), }, } - slashing2 := ðpbv1alpha1.AttesterSlashing{ + slashing2PreElectra := ðpbv1alpha1.AttesterSlashing{ Attestation_1: ðpbv1alpha1.IndexedAttestation{ AttestingIndices: []uint64{3, 30}, Data: ðpbv1alpha1.AttestationData{ @@ -1057,23 +1559,240 @@ func TestGetAttesterSlashings(t *testing.T) { Signature: bytesutil.PadTo([]byte("signature4"), 96), }, } - - s := &Server{ - ChainInfoFetcher: &blockchainmock.ChainService{State: bs}, - SlashingsPool: &slashingsmock.PoolMock{PendingAttSlashings: []ethpbv1alpha1.AttSlashing{slashing1, slashing2}}, + slashingPostElectra := ðpbv1alpha1.AttesterSlashingElectra{ + Attestation_1: ðpbv1alpha1.IndexedAttestationElectra{ + AttestingIndices: []uint64{1, 10}, + Data: ðpbv1alpha1.AttestationData{ + Slot: 1, + CommitteeIndex: 1, + BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), + Source: ðpbv1alpha1.Checkpoint{ + Epoch: 1, + Root: bytesutil.PadTo([]byte("sourceroot1"), 32), + }, + Target: ðpbv1alpha1.Checkpoint{ + Epoch: 10, + Root: bytesutil.PadTo([]byte("targetroot1"), 32), + }, + }, + Signature: bytesutil.PadTo([]byte("signature1"), 96), + }, + Attestation_2: ðpbv1alpha1.IndexedAttestationElectra{ + AttestingIndices: []uint64{2, 20}, + Data: ðpbv1alpha1.AttestationData{ + Slot: 2, + CommitteeIndex: 2, + BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), + Source: ðpbv1alpha1.Checkpoint{ + Epoch: 2, + Root: bytesutil.PadTo([]byte("sourceroot2"), 32), + }, + Target: ðpbv1alpha1.Checkpoint{ + Epoch: 20, + Root: bytesutil.PadTo([]byte("targetroot2"), 32), + }, + }, + Signature: bytesutil.PadTo([]byte("signature2"), 96), + }, } - request := httptest.NewRequest(http.MethodGet, "http://example.com/beacon/pool/attester_slashings", nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + t.Run("V1", func(t *testing.T) { + t.Run("ok", func(t *testing.T) { + bs, err := util.NewBeaconState() + require.NoError(t, err) - s.GetAttesterSlashings(writer, request) - require.Equal(t, http.StatusOK, writer.Code) - resp := &structs.GetAttesterSlashingsResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.NotNil(t, resp) - require.NotNil(t, resp.Data) - assert.Equal(t, 2, len(resp.Data)) + s := &Server{ + ChainInfoFetcher: &blockchainmock.ChainService{State: bs}, + SlashingsPool: &slashingsmock.PoolMock{PendingAttSlashings: []ethpbv1alpha1.AttSlashing{slashing1PreElectra, slashing2PreElectra}}, + } + + request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/pool/attester_slashings", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetAttesterSlashings(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetAttesterSlashingsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var slashings []*structs.AttesterSlashing + require.NoError(t, json.Unmarshal(resp.Data, &slashings)) + + ss, err := structs.AttesterSlashingsToConsensus(slashings) + require.NoError(t, err) + + require.DeepEqual(t, slashing1PreElectra, ss[0]) + require.DeepEqual(t, slashing2PreElectra, ss[1]) + }) + t.Run("no slashings", func(t *testing.T) { + bs, err := util.NewBeaconState() + require.NoError(t, err) + + s := &Server{ + ChainInfoFetcher: &blockchainmock.ChainService{State: bs}, + SlashingsPool: &slashingsmock.PoolMock{PendingAttSlashings: []ethpbv1alpha1.AttSlashing{}}, + } + + request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/pool/attester_slashings", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetAttesterSlashings(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetAttesterSlashingsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var slashings []*structs.AttesterSlashing + require.NoError(t, json.Unmarshal(resp.Data, &slashings)) + require.Equal(t, 0, len(slashings)) + }) + }) + t.Run("V2", func(t *testing.T) { + t.Run("post-electra-ok-1-pre-slashing", func(t *testing.T) { + bs, err := util.NewBeaconStateElectra() + require.NoError(t, err) + + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.ElectraForkEpoch = 100 + params.OverrideBeaconConfig(config) + + chainService := &blockchainmock.ChainService{State: bs} + + s := &Server{ + ChainInfoFetcher: chainService, + TimeFetcher: chainService, + SlashingsPool: &slashingsmock.PoolMock{PendingAttSlashings: []ethpbv1alpha1.AttSlashing{slashingPostElectra, slashing1PreElectra}}, + } + + request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/beacon/pool/attester_slashings", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetAttesterSlashingsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetAttesterSlashingsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + assert.Equal(t, "electra", resp.Version) + + // Unmarshal resp.Data into a slice of slashings + var slashings []*structs.AttesterSlashingElectra + require.NoError(t, json.Unmarshal(resp.Data, &slashings)) + + ss, err := structs.AttesterSlashingsElectraToConsensus(slashings) + require.NoError(t, err) + + require.DeepEqual(t, slashingPostElectra, ss[0]) + }) + t.Run("post-electra-ok", func(t *testing.T) { + bs, err := util.NewBeaconStateElectra() + require.NoError(t, err) + + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.ElectraForkEpoch = 100 + params.OverrideBeaconConfig(config) + + chainService := &blockchainmock.ChainService{State: bs} + + s := &Server{ + ChainInfoFetcher: chainService, + TimeFetcher: chainService, + SlashingsPool: &slashingsmock.PoolMock{PendingAttSlashings: []ethpbv1alpha1.AttSlashing{slashingPostElectra}}, + } + + request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/beacon/pool/attester_slashings", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetAttesterSlashingsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetAttesterSlashingsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + assert.Equal(t, "electra", resp.Version) + + // Unmarshal resp.Data into a slice of slashings + var slashings []*structs.AttesterSlashingElectra + require.NoError(t, json.Unmarshal(resp.Data, &slashings)) + + ss, err := structs.AttesterSlashingsElectraToConsensus(slashings) + require.NoError(t, err) + + require.DeepEqual(t, slashingPostElectra, ss[0]) + }) + t.Run("pre-electra-ok", func(t *testing.T) { + bs, err := util.NewBeaconState() + require.NoError(t, err) + chainService := &blockchainmock.ChainService{State: bs} + + s := &Server{ + ChainInfoFetcher: chainService, + TimeFetcher: chainService, + SlashingsPool: &slashingsmock.PoolMock{PendingAttSlashings: []ethpbv1alpha1.AttSlashing{slashing1PreElectra, slashing2PreElectra}}, + } + + request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/pool/attester_slashings", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetAttesterSlashingsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetAttesterSlashingsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + var slashings []*structs.AttesterSlashing + require.NoError(t, json.Unmarshal(resp.Data, &slashings)) + + ss, err := structs.AttesterSlashingsToConsensus(slashings) + require.NoError(t, err) + + require.DeepEqual(t, slashing1PreElectra, ss[0]) + require.DeepEqual(t, slashing2PreElectra, ss[1]) + }) + t.Run("no-slashings", func(t *testing.T) { + bs, err := util.NewBeaconStateElectra() + require.NoError(t, err) + + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.ElectraForkEpoch = 100 + params.OverrideBeaconConfig(config) + + chainService := &blockchainmock.ChainService{State: bs} + s := &Server{ + ChainInfoFetcher: chainService, + TimeFetcher: chainService, + SlashingsPool: &slashingsmock.PoolMock{PendingAttSlashings: []ethpbv1alpha1.AttSlashing{}}, + } + + request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/beacon/pool/attester_slashings", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetAttesterSlashingsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetAttesterSlashingsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + assert.Equal(t, "electra", resp.Version) + + // Unmarshal resp.Data into a slice of slashings + var slashings []*structs.AttesterSlashingElectra + require.NoError(t, json.Unmarshal(resp.Data, &slashings)) + require.Equal(t, 0, len(slashings)) + }) + }) } func TestGetProposerSlashings(t *testing.T) { @@ -1142,383 +1861,350 @@ func TestGetProposerSlashings(t *testing.T) { assert.Equal(t, 2, len(resp.Data)) } -func TestSubmitAttesterSlashing_Ok(t *testing.T) { +func TestSubmitAttesterSlashings(t *testing.T) { ctx := context.Background() transition.SkipSlotCache.Disable() defer transition.SkipSlotCache.Enable() - _, keys, err := util.DeterministicDepositsAndKeys(1) - require.NoError(t, err) - validator := ðpbv1alpha1.Validator{ - PublicKey: keys[0].PublicKey().Marshal(), + attestationData1 := ðpbv1alpha1.AttestationData{ + CommitteeIndex: 1, + BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), + Source: ðpbv1alpha1.Checkpoint{ + Epoch: 1, + Root: bytesutil.PadTo([]byte("sourceroot1"), 32), + }, + Target: ðpbv1alpha1.Checkpoint{ + Epoch: 10, + Root: bytesutil.PadTo([]byte("targetroot1"), 32), + }, + } + attestationData2 := ðpbv1alpha1.AttestationData{ + CommitteeIndex: 1, + BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), + Source: ðpbv1alpha1.Checkpoint{ + Epoch: 1, + Root: bytesutil.PadTo([]byte("sourceroot2"), 32), + }, + Target: ðpbv1alpha1.Checkpoint{ + Epoch: 10, + Root: bytesutil.PadTo([]byte("targetroot2"), 32), + }, } - bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { - state.Validators = []*ethpbv1alpha1.Validator{validator} - return nil - }) - require.NoError(t, err) - slashing := ðpbv1alpha1.AttesterSlashing{ - Attestation_1: ðpbv1alpha1.IndexedAttestation{ - AttestingIndices: []uint64{0}, - Data: ðpbv1alpha1.AttestationData{ - Slot: 1, - CommitteeIndex: 1, - BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), - Source: ðpbv1alpha1.Checkpoint{ - Epoch: 1, - Root: bytesutil.PadTo([]byte("sourceroot1"), 32), + t.Run("V1", func(t *testing.T) { + t.Run("ok", func(t *testing.T) { + attestationData1.Slot = 1 + attestationData2.Slot = 1 + slashing := ðpbv1alpha1.AttesterSlashing{ + Attestation_1: ðpbv1alpha1.IndexedAttestation{ + AttestingIndices: []uint64{0}, + Data: attestationData1, + Signature: make([]byte, 96), }, - Target: ðpbv1alpha1.Checkpoint{ - Epoch: 10, - Root: bytesutil.PadTo([]byte("targetroot1"), 32), + Attestation_2: ðpbv1alpha1.IndexedAttestation{ + AttestingIndices: []uint64{0}, + Data: attestationData2, + Signature: make([]byte, 96), }, - }, - Signature: make([]byte, 96), - }, - Attestation_2: ðpbv1alpha1.IndexedAttestation{ - AttestingIndices: []uint64{0}, - Data: ðpbv1alpha1.AttestationData{ - Slot: 1, - CommitteeIndex: 1, - BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), - Source: ðpbv1alpha1.Checkpoint{ - Epoch: 1, - Root: bytesutil.PadTo([]byte("sourceroot2"), 32), + } + + _, keys, err := util.DeterministicDepositsAndKeys(1) + require.NoError(t, err) + validator := ðpbv1alpha1.Validator{ + PublicKey: keys[0].PublicKey().Marshal(), + } + + bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { + state.Validators = []*ethpbv1alpha1.Validator{validator} + return nil + }) + require.NoError(t, err) + + for _, att := range []*ethpbv1alpha1.IndexedAttestation{slashing.Attestation_1, slashing.Attestation_2} { + sb, err := signing.ComputeDomainAndSign(bs, att.Data.Target.Epoch, att.Data, params.BeaconConfig().DomainBeaconAttester, keys[0]) + require.NoError(t, err) + sig, err := bls.SignatureFromBytes(sb) + require.NoError(t, err) + att.Signature = sig.Marshal() + } + + chainmock := &blockchainmock.ChainService{State: bs} + broadcaster := &p2pMock.MockBroadcaster{} + s := &Server{ + ChainInfoFetcher: chainmock, + SlashingsPool: &slashingsmock.PoolMock{}, + Broadcaster: broadcaster, + OperationNotifier: chainmock.OperationNotifier(), + } + + toSubmit := structs.AttesterSlashingsFromConsensus([]*ethpbv1alpha1.AttesterSlashing{slashing}) + b, err := json.Marshal(toSubmit[0]) + require.NoError(t, err) + var body bytes.Buffer + _, err = body.Write(b) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_slashings", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttesterSlashings(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + pendingSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, bs, true) + require.Equal(t, 1, len(pendingSlashings)) + assert.DeepEqual(t, slashing, pendingSlashings[0]) + require.Equal(t, 1, broadcaster.NumMessages()) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + _, ok := broadcaster.BroadcastMessages[0].(*ethpbv1alpha1.AttesterSlashing) + assert.Equal(t, true, ok) + }) + t.Run("across-fork", func(t *testing.T) { + attestationData1.Slot = params.BeaconConfig().SlotsPerEpoch + attestationData2.Slot = params.BeaconConfig().SlotsPerEpoch + slashing := ðpbv1alpha1.AttesterSlashing{ + Attestation_1: ðpbv1alpha1.IndexedAttestation{ + AttestingIndices: []uint64{0}, + Data: attestationData1, + Signature: make([]byte, 96), }, - Target: ðpbv1alpha1.Checkpoint{ - Epoch: 10, - Root: bytesutil.PadTo([]byte("targetroot2"), 32), + Attestation_2: ðpbv1alpha1.IndexedAttestation{ + AttestingIndices: []uint64{0}, + Data: attestationData2, + Signature: make([]byte, 96), }, - }, - Signature: make([]byte, 96), - }, - } - - for _, att := range []*ethpbv1alpha1.IndexedAttestation{slashing.Attestation_1, slashing.Attestation_2} { - sb, err := signing.ComputeDomainAndSign(bs, att.Data.Target.Epoch, att.Data, params.BeaconConfig().DomainBeaconAttester, keys[0]) - require.NoError(t, err) - sig, err := bls.SignatureFromBytes(sb) - require.NoError(t, err) - att.Signature = sig.Marshal() - } - - broadcaster := &p2pMock.MockBroadcaster{} - chainmock := &blockchainmock.ChainService{State: bs} - s := &Server{ - ChainInfoFetcher: chainmock, - SlashingsPool: &slashingsmock.PoolMock{}, - Broadcaster: broadcaster, - OperationNotifier: chainmock.OperationNotifier(), - } - - toSubmit := structs.AttesterSlashingsFromConsensus([]*ethpbv1alpha1.AttesterSlashing{slashing}) - b, err := json.Marshal(toSubmit[0]) - require.NoError(t, err) - var body bytes.Buffer - _, err = body.Write(b) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_slashings", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.SubmitAttesterSlashing(writer, request) - require.Equal(t, http.StatusOK, writer.Code) - pendingSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, bs, true) - require.Equal(t, 1, len(pendingSlashings)) - assert.DeepEqual(t, slashing, pendingSlashings[0]) - assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) - require.Equal(t, 1, broadcaster.NumMessages()) - _, ok := broadcaster.BroadcastMessages[0].(*ethpbv1alpha1.AttesterSlashing) - assert.Equal(t, true, ok) -} - -func TestSubmitAttesterSlashing_AcrossFork(t *testing.T) { - ctx := context.Background() - - transition.SkipSlotCache.Disable() - defer transition.SkipSlotCache.Enable() - - params.SetupTestConfigCleanup(t) - config := params.BeaconConfig() - config.AltairForkEpoch = 1 - params.OverrideBeaconConfig(config) - - bs, keys := util.DeterministicGenesisState(t, 1) - - slashing := ðpbv1alpha1.AttesterSlashing{ - Attestation_1: ðpbv1alpha1.IndexedAttestation{ - AttestingIndices: []uint64{0}, - Data: ðpbv1alpha1.AttestationData{ - Slot: params.BeaconConfig().SlotsPerEpoch, - CommitteeIndex: 1, - BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot1"), 32), - Source: ðpbv1alpha1.Checkpoint{ - Epoch: 1, - Root: bytesutil.PadTo([]byte("sourceroot1"), 32), + } + + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.AltairForkEpoch = 1 + params.OverrideBeaconConfig(config) + + bs, keys := util.DeterministicGenesisState(t, 1) + newBs := bs.Copy() + newBs, err := transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch) + require.NoError(t, err) + + for _, att := range []*ethpbv1alpha1.IndexedAttestation{slashing.Attestation_1, slashing.Attestation_2} { + sb, err := signing.ComputeDomainAndSign(newBs, att.Data.Target.Epoch, att.Data, params.BeaconConfig().DomainBeaconAttester, keys[0]) + require.NoError(t, err) + sig, err := bls.SignatureFromBytes(sb) + require.NoError(t, err) + att.Signature = sig.Marshal() + } + + broadcaster := &p2pMock.MockBroadcaster{} + chainmock := &blockchainmock.ChainService{State: bs} + s := &Server{ + ChainInfoFetcher: chainmock, + SlashingsPool: &slashingsmock.PoolMock{}, + Broadcaster: broadcaster, + OperationNotifier: chainmock.OperationNotifier(), + } + + toSubmit := structs.AttesterSlashingsFromConsensus([]*ethpbv1alpha1.AttesterSlashing{slashing}) + b, err := json.Marshal(toSubmit[0]) + require.NoError(t, err) + var body bytes.Buffer + _, err = body.Write(b) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_slashings", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttesterSlashings(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + pendingSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, bs, true) + require.Equal(t, 1, len(pendingSlashings)) + assert.DeepEqual(t, slashing, pendingSlashings[0]) + require.Equal(t, 1, broadcaster.NumMessages()) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + _, ok := broadcaster.BroadcastMessages[0].(*ethpbv1alpha1.AttesterSlashing) + assert.Equal(t, true, ok) + }) + t.Run("invalid-slashing", func(t *testing.T) { + bs, err := util.NewBeaconState() + require.NoError(t, err) + + broadcaster := &p2pMock.MockBroadcaster{} + s := &Server{ + ChainInfoFetcher: &blockchainmock.ChainService{State: bs}, + SlashingsPool: &slashingsmock.PoolMock{}, + Broadcaster: broadcaster, + } + + var body bytes.Buffer + _, err = body.WriteString(invalidAttesterSlashing) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_slashings", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttesterSlashings(writer, request) + require.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.StringContains(t, "Invalid attester slashing", e.Message) + }) + }) + t.Run("V2", func(t *testing.T) { + t.Run("ok", func(t *testing.T) { + attestationData1.Slot = 1 + attestationData2.Slot = 1 + electraSlashing := ðpbv1alpha1.AttesterSlashingElectra{ + Attestation_1: ðpbv1alpha1.IndexedAttestationElectra{ + AttestingIndices: []uint64{0}, + Data: attestationData1, + Signature: make([]byte, 96), }, - Target: ðpbv1alpha1.Checkpoint{ - Epoch: 10, - Root: bytesutil.PadTo([]byte("targetroot1"), 32), + Attestation_2: ðpbv1alpha1.IndexedAttestationElectra{ + AttestingIndices: []uint64{0}, + Data: attestationData2, + Signature: make([]byte, 96), }, - }, - Signature: make([]byte, 96), - }, - Attestation_2: ðpbv1alpha1.IndexedAttestation{ - AttestingIndices: []uint64{0}, - Data: ðpbv1alpha1.AttestationData{ - Slot: params.BeaconConfig().SlotsPerEpoch, - CommitteeIndex: 1, - BeaconBlockRoot: bytesutil.PadTo([]byte("blockroot2"), 32), - Source: ðpbv1alpha1.Checkpoint{ - Epoch: 1, - Root: bytesutil.PadTo([]byte("sourceroot2"), 32), + } + + _, keys, err := util.DeterministicDepositsAndKeys(1) + require.NoError(t, err) + validator := ðpbv1alpha1.Validator{ + PublicKey: keys[0].PublicKey().Marshal(), + } + + ebs, err := util.NewBeaconStateElectra(func(state *ethpbv1alpha1.BeaconStateElectra) error { + state.Validators = []*ethpbv1alpha1.Validator{validator} + return nil + }) + require.NoError(t, err) + + for _, att := range []*ethpbv1alpha1.IndexedAttestationElectra{electraSlashing.Attestation_1, electraSlashing.Attestation_2} { + sb, err := signing.ComputeDomainAndSign(ebs, att.Data.Target.Epoch, att.Data, params.BeaconConfig().DomainBeaconAttester, keys[0]) + require.NoError(t, err) + sig, err := bls.SignatureFromBytes(sb) + require.NoError(t, err) + att.Signature = sig.Marshal() + } + + chainmock := &blockchainmock.ChainService{State: ebs} + broadcaster := &p2pMock.MockBroadcaster{} + s := &Server{ + ChainInfoFetcher: chainmock, + SlashingsPool: &slashingsmock.PoolMock{}, + Broadcaster: broadcaster, + OperationNotifier: chainmock.OperationNotifier(), + } + + toSubmit := structs.AttesterSlashingsElectraFromConsensus([]*ethpbv1alpha1.AttesterSlashingElectra{electraSlashing}) + b, err := json.Marshal(toSubmit[0]) + require.NoError(t, err) + var body bytes.Buffer + _, err = body.Write(b) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_electras", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttesterSlashingsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + pendingSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, ebs, true) + require.Equal(t, 1, len(pendingSlashings)) + require.Equal(t, 1, broadcaster.NumMessages()) + assert.DeepEqual(t, electraSlashing, pendingSlashings[0]) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + _, ok := broadcaster.BroadcastMessages[0].(*ethpbv1alpha1.AttesterSlashingElectra) + assert.Equal(t, true, ok) + }) + t.Run("across-fork", func(t *testing.T) { + attestationData1.Slot = params.BeaconConfig().SlotsPerEpoch + attestationData2.Slot = params.BeaconConfig().SlotsPerEpoch + slashing := ðpbv1alpha1.AttesterSlashingElectra{ + Attestation_1: ðpbv1alpha1.IndexedAttestationElectra{ + AttestingIndices: []uint64{0}, + Data: attestationData1, + Signature: make([]byte, 96), }, - Target: ðpbv1alpha1.Checkpoint{ - Epoch: 10, - Root: bytesutil.PadTo([]byte("targetroot2"), 32), + Attestation_2: ðpbv1alpha1.IndexedAttestationElectra{ + AttestingIndices: []uint64{0}, + Data: attestationData2, + Signature: make([]byte, 96), }, - }, - Signature: make([]byte, 96), - }, - } - - newBs := bs.Copy() - newBs, err := transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch) - require.NoError(t, err) - - for _, att := range []*ethpbv1alpha1.IndexedAttestation{slashing.Attestation_1, slashing.Attestation_2} { - sb, err := signing.ComputeDomainAndSign(newBs, att.Data.Target.Epoch, att.Data, params.BeaconConfig().DomainBeaconAttester, keys[0]) - require.NoError(t, err) - sig, err := bls.SignatureFromBytes(sb) - require.NoError(t, err) - att.Signature = sig.Marshal() - } - - broadcaster := &p2pMock.MockBroadcaster{} - chainmock := &blockchainmock.ChainService{State: bs} - s := &Server{ - ChainInfoFetcher: chainmock, - SlashingsPool: &slashingsmock.PoolMock{}, - Broadcaster: broadcaster, - OperationNotifier: chainmock.OperationNotifier(), - } - - toSubmit := structs.AttesterSlashingsFromConsensus([]*ethpbv1alpha1.AttesterSlashing{slashing}) - b, err := json.Marshal(toSubmit[0]) - require.NoError(t, err) - var body bytes.Buffer - _, err = body.Write(b) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_slashings", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.SubmitAttesterSlashing(writer, request) - require.Equal(t, http.StatusOK, writer.Code) - pendingSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, bs, true) - require.Equal(t, 1, len(pendingSlashings)) - assert.DeepEqual(t, slashing, pendingSlashings[0]) - assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) - require.Equal(t, 1, broadcaster.NumMessages()) - _, ok := broadcaster.BroadcastMessages[0].(*ethpbv1alpha1.AttesterSlashing) - assert.Equal(t, true, ok) -} - -func TestSubmitAttesterSlashing_InvalidSlashing(t *testing.T) { - bs, err := util.NewBeaconState() - require.NoError(t, err) - - broadcaster := &p2pMock.MockBroadcaster{} - s := &Server{ - ChainInfoFetcher: &blockchainmock.ChainService{State: bs}, - SlashingsPool: &slashingsmock.PoolMock{}, - Broadcaster: broadcaster, - } - - var body bytes.Buffer - _, err = body.WriteString(invalidAttesterSlashing) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_slashings", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.SubmitAttesterSlashing(writer, request) - require.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.StringContains(t, "Invalid attester slashing", e.Message) -} - -func TestSubmitProposerSlashing_Ok(t *testing.T) { - ctx := context.Background() - - transition.SkipSlotCache.Disable() - defer transition.SkipSlotCache.Enable() - - _, keys, err := util.DeterministicDepositsAndKeys(1) - require.NoError(t, err) - validator := ðpbv1alpha1.Validator{ - PublicKey: keys[0].PublicKey().Marshal(), - WithdrawableEpoch: primitives.Epoch(1), - } - bs, err := util.NewBeaconState(func(state *ethpbv1alpha1.BeaconState) error { - state.Validators = []*ethpbv1alpha1.Validator{validator} - return nil + } + + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.AltairForkEpoch = 1 + params.OverrideBeaconConfig(config) + + bs, keys := util.DeterministicGenesisState(t, 1) + newBs := bs.Copy() + newBs, err := transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch) + require.NoError(t, err) + + for _, att := range []*ethpbv1alpha1.IndexedAttestationElectra{slashing.Attestation_1, slashing.Attestation_2} { + sb, err := signing.ComputeDomainAndSign(newBs, att.Data.Target.Epoch, att.Data, params.BeaconConfig().DomainBeaconAttester, keys[0]) + require.NoError(t, err) + sig, err := bls.SignatureFromBytes(sb) + require.NoError(t, err) + att.Signature = sig.Marshal() + } + + broadcaster := &p2pMock.MockBroadcaster{} + chainmock := &blockchainmock.ChainService{State: bs} + s := &Server{ + ChainInfoFetcher: chainmock, + SlashingsPool: &slashingsmock.PoolMock{}, + Broadcaster: broadcaster, + OperationNotifier: chainmock.OperationNotifier(), + } + + toSubmit := structs.AttesterSlashingsElectraFromConsensus([]*ethpbv1alpha1.AttesterSlashingElectra{slashing}) + b, err := json.Marshal(toSubmit[0]) + require.NoError(t, err) + var body bytes.Buffer + _, err = body.Write(b) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_slashings", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAttesterSlashingsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + pendingSlashings := s.SlashingsPool.PendingAttesterSlashings(ctx, bs, true) + require.Equal(t, 1, len(pendingSlashings)) + assert.DeepEqual(t, slashing, pendingSlashings[0]) + require.Equal(t, 1, broadcaster.NumMessages()) + assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) + _, ok := broadcaster.BroadcastMessages[0].(*ethpbv1alpha1.AttesterSlashingElectra) + assert.Equal(t, true, ok) + }) }) - require.NoError(t, err) - - slashing := ðpbv1alpha1.ProposerSlashing{ - Header_1: ðpbv1alpha1.SignedBeaconBlockHeader{ - Header: ðpbv1alpha1.BeaconBlockHeader{ - Slot: 1, - ProposerIndex: 0, - ParentRoot: bytesutil.PadTo([]byte("parentroot1"), 32), - StateRoot: bytesutil.PadTo([]byte("stateroot1"), 32), - BodyRoot: bytesutil.PadTo([]byte("bodyroot1"), 32), - }, - Signature: make([]byte, 96), - }, - Header_2: ðpbv1alpha1.SignedBeaconBlockHeader{ - Header: ðpbv1alpha1.BeaconBlockHeader{ - Slot: 1, - ProposerIndex: 0, - ParentRoot: bytesutil.PadTo([]byte("parentroot2"), 32), - StateRoot: bytesutil.PadTo([]byte("stateroot2"), 32), - BodyRoot: bytesutil.PadTo([]byte("bodyroot2"), 32), - }, - Signature: make([]byte, 96), - }, - } - - for _, h := range []*ethpbv1alpha1.SignedBeaconBlockHeader{slashing.Header_1, slashing.Header_2} { - sb, err := signing.ComputeDomainAndSign( - bs, - slots.ToEpoch(h.Header.Slot), - h.Header, - params.BeaconConfig().DomainBeaconProposer, - keys[0], - ) + t.Run("invalid-slashing", func(t *testing.T) { + bs, err := util.NewBeaconStateElectra() require.NoError(t, err) - sig, err := bls.SignatureFromBytes(sb) - require.NoError(t, err) - h.Signature = sig.Marshal() - } - - broadcaster := &p2pMock.MockBroadcaster{} - chainmock := &blockchainmock.ChainService{State: bs} - s := &Server{ - ChainInfoFetcher: chainmock, - SlashingsPool: &slashingsmock.PoolMock{}, - Broadcaster: broadcaster, - OperationNotifier: chainmock.OperationNotifier(), - } - - toSubmit := structs.ProposerSlashingsFromConsensus([]*ethpbv1alpha1.ProposerSlashing{slashing}) - b, err := json.Marshal(toSubmit[0]) - require.NoError(t, err) - var body bytes.Buffer - _, err = body.Write(b) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/proposer_slashings", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.SubmitProposerSlashing(writer, request) - require.Equal(t, http.StatusOK, writer.Code) - pendingSlashings := s.SlashingsPool.PendingProposerSlashings(ctx, bs, true) - require.Equal(t, 1, len(pendingSlashings)) - assert.DeepEqual(t, slashing, pendingSlashings[0]) - assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) - require.Equal(t, 1, broadcaster.NumMessages()) - _, ok := broadcaster.BroadcastMessages[0].(*ethpbv1alpha1.ProposerSlashing) - assert.Equal(t, true, ok) -} - -func TestSubmitProposerSlashing_AcrossFork(t *testing.T) { - ctx := context.Background() - transition.SkipSlotCache.Disable() - defer transition.SkipSlotCache.Enable() - - params.SetupTestConfigCleanup(t) - config := params.BeaconConfig() - config.AltairForkEpoch = 1 - params.OverrideBeaconConfig(config) - - bs, keys := util.DeterministicGenesisState(t, 1) - - slashing := ðpbv1alpha1.ProposerSlashing{ - Header_1: ðpbv1alpha1.SignedBeaconBlockHeader{ - Header: ðpbv1alpha1.BeaconBlockHeader{ - Slot: params.BeaconConfig().SlotsPerEpoch, - ProposerIndex: 0, - ParentRoot: bytesutil.PadTo([]byte("parentroot1"), 32), - StateRoot: bytesutil.PadTo([]byte("stateroot1"), 32), - BodyRoot: bytesutil.PadTo([]byte("bodyroot1"), 32), - }, - Signature: make([]byte, 96), - }, - Header_2: ðpbv1alpha1.SignedBeaconBlockHeader{ - Header: ðpbv1alpha1.BeaconBlockHeader{ - Slot: params.BeaconConfig().SlotsPerEpoch, - ProposerIndex: 0, - ParentRoot: bytesutil.PadTo([]byte("parentroot2"), 32), - StateRoot: bytesutil.PadTo([]byte("stateroot2"), 32), - BodyRoot: bytesutil.PadTo([]byte("bodyroot2"), 32), - }, - Signature: make([]byte, 96), - }, - } - - newBs := bs.Copy() - newBs, err := transition.ProcessSlots(ctx, newBs, params.BeaconConfig().SlotsPerEpoch) - require.NoError(t, err) + broadcaster := &p2pMock.MockBroadcaster{} + s := &Server{ + ChainInfoFetcher: &blockchainmock.ChainService{State: bs}, + SlashingsPool: &slashingsmock.PoolMock{}, + Broadcaster: broadcaster, + } - for _, h := range []*ethpbv1alpha1.SignedBeaconBlockHeader{slashing.Header_1, slashing.Header_2} { - sb, err := signing.ComputeDomainAndSign( - newBs, - slots.ToEpoch(h.Header.Slot), - h.Header, - params.BeaconConfig().DomainBeaconProposer, - keys[0], - ) - require.NoError(t, err) - sig, err := bls.SignatureFromBytes(sb) + var body bytes.Buffer + _, err = body.WriteString(invalidAttesterSlashing) require.NoError(t, err) - h.Signature = sig.Marshal() - } - - broadcaster := &p2pMock.MockBroadcaster{} - chainmock := &blockchainmock.ChainService{State: bs} - s := &Server{ - ChainInfoFetcher: chainmock, - SlashingsPool: &slashingsmock.PoolMock{}, - Broadcaster: broadcaster, - OperationNotifier: chainmock.OperationNotifier(), - } - - toSubmit := structs.ProposerSlashingsFromConsensus([]*ethpbv1alpha1.ProposerSlashing{slashing}) - b, err := json.Marshal(toSubmit[0]) - require.NoError(t, err) - var body bytes.Buffer - _, err = body.Write(b) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/proposer_slashings", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + request := httptest.NewRequest(http.MethodPost, "http://example.com/beacon/pool/attester_slashings", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} - s.SubmitProposerSlashing(writer, request) - require.Equal(t, http.StatusOK, writer.Code) - pendingSlashings := s.SlashingsPool.PendingProposerSlashings(ctx, bs, true) - require.Equal(t, 1, len(pendingSlashings)) - assert.DeepEqual(t, slashing, pendingSlashings[0]) - assert.Equal(t, true, broadcaster.BroadcastCalled.Load()) - require.Equal(t, 1, broadcaster.NumMessages()) - _, ok := broadcaster.BroadcastMessages[0].(*ethpbv1alpha1.ProposerSlashing) - assert.Equal(t, true, ok) + s.SubmitAttesterSlashingsV2(writer, request) + require.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.StringContains(t, "Invalid attester slashing", e.Message) + }) } func TestSubmitProposerSlashing_InvalidSlashing(t *testing.T) { @@ -1622,6 +2308,85 @@ var ( } } } +]` + singleAttElectra = `[ + { + "committee_index": "0", + "attester_index": "1", + "signature": "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", + "data": { + "slot": "0", + "index": "0", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "0", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "0", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + } +]` + multipleAttsElectra = `[ + { + "committee_index": "0", + "attester_index": "0", + "signature": "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", + "data": { + "slot": "0", + "index": "0", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "0", + "root": "0x736f75726365726f6f7431000000000000000000000000000000000000000000" + }, + "target": { + "epoch": "0", + "root": "0x746172676574726f6f7431000000000000000000000000000000000000000000" + } + } + }, + { + "committee_index": "0", + "attester_index": "1", + "signature": "0x8146f4397bfd8fd057ebbcd6a67327bdc7ed5fb650533edcb6377b650dea0b6da64c14ecd60846d5c0a0cd43893d6972092500f82c9d8a955e2b58c5ed3cbe885d84008ace6bd86ba9e23652f58e2ec207cec494c916063257abf285b9b15b15", + "data": { + "slot": "0", + "index": "0", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "0", + "root": "0x736f75726365726f6f7431000000000000000000000000000000000000000000" + }, + "target": { + "epoch": "0", + "root": "0x746172676574726f6f7432000000000000000000000000000000000000000000" + } + } + } +]` + // signature is invalid + invalidAttElectra = `[ + { + "committee_index": "0", + "attester_index": "0", + "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "data": { + "slot": "0", + "index": "0", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "0", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "0", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + } ]` exit1 = `{ "message": { diff --git a/beacon-chain/rpc/eth/beacon/handlers_state.go b/beacon-chain/rpc/eth/beacon/handlers_state.go index 6ada905f6dae..ad1d2abdd526 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_state.go +++ b/beacon-chain/rpc/eth/beacon/handlers_state.go @@ -8,7 +8,6 @@ import ( "strconv" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/helpers" @@ -18,10 +17,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpbalpha "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) type syncCommitteeStateRequest struct { @@ -34,7 +33,7 @@ func (s *Server) GetStateRoot(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetStateRoot") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return @@ -85,7 +84,7 @@ func (s *Server) GetRandao(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetRandao") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return @@ -151,7 +150,7 @@ func (s *Server) GetSyncCommittees(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetSyncCommittees") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return diff --git a/beacon-chain/rpc/eth/beacon/handlers_state_test.go b/beacon-chain/rpc/eth/beacon/handlers_state_test.go index 066ab839ee5b..b889576d5cc3 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_state_test.go +++ b/beacon-chain/rpc/eth/beacon/handlers_state_test.go @@ -12,7 +12,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" chainMock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" dbTest "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" @@ -56,7 +55,7 @@ func TestGetStateRoot(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/root", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -80,7 +79,7 @@ func TestGetStateRoot(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/root", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -111,7 +110,7 @@ func TestGetStateRoot(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/root", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -158,7 +157,7 @@ func TestGetRandao(t *testing.T) { t.Run("no epoch requested", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/randao", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -170,7 +169,7 @@ func TestGetRandao(t *testing.T) { }) t.Run("current epoch requested", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com//eth/v1/beacon/states/{state_id}/randao?epoch=%d", epochCurrent), nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -182,7 +181,7 @@ func TestGetRandao(t *testing.T) { }) t.Run("old epoch requested", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com//eth/v1/beacon/states/{state_id}/randao?epoch=%d", epochOld), nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -198,7 +197,7 @@ func TestGetRandao(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/randao", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -211,7 +210,7 @@ func TestGetRandao(t *testing.T) { t.Run("epoch too old", func(t *testing.T) { epochTooOld := primitives.Epoch(100000 - st.RandaoMixesLength()) request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com//eth/v1/beacon/states/{state_id}/randao?epoch=%d", epochTooOld), nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -225,7 +224,7 @@ func TestGetRandao(t *testing.T) { t.Run("epoch in the future", func(t *testing.T) { futureEpoch := primitives.Epoch(100000 + 1) request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com//eth/v1/beacon/states/{state_id}/randao?epoch=%d", futureEpoch), nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -257,7 +256,7 @@ func TestGetRandao(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/randao", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -294,7 +293,7 @@ func TestGetRandao(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/randao", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -453,7 +452,7 @@ func TestGetSyncCommittees(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/sync_committees", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": hexutil.Encode(stRoot[:])}) + request.SetPathValue("state_id", hexutil.Encode(stRoot[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -503,7 +502,7 @@ func TestGetSyncCommittees(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/sync_committees", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": hexutil.Encode(stRoot[:])}) + request.SetPathValue("state_id", hexutil.Encode(stRoot[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -547,7 +546,7 @@ func TestGetSyncCommittees(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com//eth/v1/beacon/states/{state_id}/sync_committees", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": hexutil.Encode(stRoot[:])}) + request.SetPathValue("state_id", hexutil.Encode(stRoot[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -613,7 +612,7 @@ func TestGetSyncCommittees_Future(t *testing.T) { epoch := 2 * params.BeaconConfig().EpochsPerSyncCommitteePeriod request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com//eth/v1/beacon/states/{state_id}/sync_committees?epoch=%d", epoch), nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} s.GetSyncCommittees(writer, request) @@ -625,7 +624,7 @@ func TestGetSyncCommittees_Future(t *testing.T) { epoch = 2*params.BeaconConfig().EpochsPerSyncCommitteePeriod - 1 request = httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com//eth/v1/beacon/states/{state_id}/sync_committees?epoch=%d", epoch), nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer = httptest.NewRecorder() writer.Body = &bytes.Buffer{} s.GetSyncCommittees(writer, request) diff --git a/beacon-chain/rpc/eth/beacon/handlers_test.go b/beacon-chain/rpc/eth/beacon/handlers_test.go index 67b571042268..c1bccc884c33 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_test.go +++ b/beacon-chain/rpc/eth/beacon/handlers_test.go @@ -12,8 +12,8 @@ import ( "testing" "time" + GoKZG "github.com/crate-crypto/go-kzg-4844" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/api" @@ -34,6 +34,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/network/httputil" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -96,7 +97,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "123552314"}) + request.SetPathValue("block_id", "123552314") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -118,7 +119,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -151,7 +152,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -185,7 +186,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -219,7 +220,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -253,7 +254,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -269,6 +270,70 @@ func TestGetBlockV2(t *testing.T) { require.NoError(t, err) assert.DeepEqual(t, blk, b) }) + t.Run("electra", func(t *testing.T) { + b := util.NewBeaconBlockElectra() + b.Block.Slot = 123 + sb, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + mockBlockFetcher := &testutil.MockBlocker{BlockToReturn: sb} + mockChainService := &chainMock.ChainService{ + FinalizedRoots: map[[32]byte]bool{}, + } + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: mockBlockFetcher, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, version.String(version.Electra), resp.Version) + sbb := &structs.SignedBeaconBlockElectra{Message: &structs.BeaconBlockElectra{}} + require.NoError(t, json.Unmarshal(resp.Data.Message, sbb.Message)) + sbb.Signature = resp.Data.Signature + blk, err := sbb.ToConsensus() + require.NoError(t, err) + assert.DeepEqual(t, blk, b) + }) + t.Run("fulu", func(t *testing.T) { + b := util.NewBeaconBlockFulu() + b.Block.Slot = 123 + sb, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + mockBlockFetcher := &testutil.MockBlocker{BlockToReturn: sb} + mockChainService := &chainMock.ChainService{ + FinalizedRoots: map[[32]byte]bool{}, + } + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: mockBlockFetcher, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, version.String(version.Fulu), resp.Version) + sbb := &structs.SignedBeaconBlockFulu{Message: &structs.BeaconBlockElectra{}} + require.NoError(t, json.Unmarshal(resp.Data.Message, sbb.Message)) + sbb.Signature = resp.Data.Signature + blk, err := sbb.ToConsensus() + require.NoError(t, err) + assert.DeepEqual(t, blk, b) + }) t.Run("execution optimistic", func(t *testing.T) { b := util.NewBeaconBlockBellatrix() sb, err := blocks.NewSignedBeaconBlock(b) @@ -287,7 +352,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -314,7 +379,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": hexutil.Encode(r[:])}) + request.SetPathValue("block_id", hexutil.Encode(r[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -333,7 +398,7 @@ func TestGetBlockV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": hexutil.Encode(r[:])}) + request.SetPathValue("block_id", hexutil.Encode(r[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -358,7 +423,7 @@ func TestGetBlockSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -381,7 +446,7 @@ func TestGetBlockSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -404,7 +469,7 @@ func TestGetBlockSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -427,7 +492,7 @@ func TestGetBlockSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -450,7 +515,7 @@ func TestGetBlockSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -462,142 +527,191 @@ func TestGetBlockSSZV2(t *testing.T) { require.NoError(t, err) assert.DeepEqual(t, sszExpected, writer.Body.Bytes()) }) - -} - -func TestGetBlockAttestations(t *testing.T) { - t.Run("ok", func(t *testing.T) { - b := util.NewBeaconBlock() - b.Block.Body.Attestations = []*eth.Attestation{ - { - AggregationBits: bitfield.Bitlist{0x00}, - Data: ð.AttestationData{ - Slot: 123, - CommitteeIndex: 123, - BeaconBlockRoot: bytesutil.PadTo([]byte("root1"), 32), - Source: ð.Checkpoint{ - Epoch: 123, - Root: bytesutil.PadTo([]byte("root1"), 32), - }, - Target: ð.Checkpoint{ - Epoch: 123, - Root: bytesutil.PadTo([]byte("root1"), 32), - }, - }, - Signature: bytesutil.PadTo([]byte("sig1"), 96), - }, - { - AggregationBits: bitfield.Bitlist{0x01}, - Data: ð.AttestationData{ - Slot: 456, - CommitteeIndex: 456, - BeaconBlockRoot: bytesutil.PadTo([]byte("root2"), 32), - Source: ð.Checkpoint{ - Epoch: 456, - Root: bytesutil.PadTo([]byte("root2"), 32), - }, - Target: ð.Checkpoint{ - Epoch: 456, - Root: bytesutil.PadTo([]byte("root2"), 32), - }, - }, - Signature: bytesutil.PadTo([]byte("sig2"), 96), - }, - } + t.Run("electra", func(t *testing.T) { + b := util.NewBeaconBlockElectra() + b.Block.Slot = 123 sb, err := blocks.NewSignedBeaconBlock(b) require.NoError(t, err) - mockBlockFetcher := &testutil.MockBlocker{BlockToReturn: sb} - mockChainService := &chainMock.ChainService{ - FinalizedRoots: map[[32]byte]bool{}, - } + s := &Server{ - OptimisticModeFetcher: mockChainService, - FinalizationFetcher: mockChainService, - Blocker: mockBlockFetcher, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, } - request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) + request.SetPathValue("block_id", "head") + request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - s.GetBlockAttestations(writer, request) + s.GetBlockV2(writer, request) require.Equal(t, http.StatusOK, writer.Code) - resp := &structs.GetBlockAttestationsResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.Equal(t, len(b.Block.Body.Attestations), len(resp.Data)) - atts := make([]*eth.Attestation, len(b.Block.Body.Attestations)) - for i, a := range resp.Data { - atts[i], err = a.ToConsensus() - require.NoError(t, err) - } - assert.DeepEqual(t, b.Block.Body.Attestations, atts) + assert.Equal(t, version.String(version.Electra), writer.Header().Get(api.VersionHeader)) + sszExpected, err := b.MarshalSSZ() + require.NoError(t, err) + assert.DeepEqual(t, sszExpected, writer.Body.Bytes()) }) - t.Run("execution optimistic", func(t *testing.T) { - b := util.NewBeaconBlockBellatrix() + t.Run("fulu", func(t *testing.T) { + b := util.NewBeaconBlockFulu() + b.Block.Slot = 123 sb, err := blocks.NewSignedBeaconBlock(b) require.NoError(t, err) - r, err := sb.Block().HashTreeRoot() - require.NoError(t, err) - mockBlockFetcher := &testutil.MockBlocker{BlockToReturn: sb} - mockChainService := &chainMock.ChainService{ - OptimisticRoots: map[[32]byte]bool{r: true}, - FinalizedRoots: map[[32]byte]bool{}, - } + s := &Server{ - OptimisticModeFetcher: mockChainService, - FinalizationFetcher: mockChainService, - Blocker: mockBlockFetcher, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, } - request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}", nil) + request.SetPathValue("block_id", "head") + request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - s.GetBlockAttestations(writer, request) + s.GetBlockV2(writer, request) require.Equal(t, http.StatusOK, writer.Code) - resp := &structs.GetBlockAttestationsResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - assert.Equal(t, true, resp.ExecutionOptimistic) - }) - t.Run("finalized", func(t *testing.T) { - b := util.NewBeaconBlock() - sb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - r, err := sb.Block().HashTreeRoot() + assert.Equal(t, version.String(version.Fulu), writer.Header().Get(api.VersionHeader)) + sszExpected, err := b.MarshalSSZ() require.NoError(t, err) - mockBlockFetcher := &testutil.MockBlocker{BlockToReturn: sb} + assert.DeepEqual(t, sszExpected, writer.Body.Bytes()) + }) +} + +func TestGetBlockAttestations(t *testing.T) { + preElectraAtts := []*eth.Attestation{ + { + AggregationBits: bitfield.Bitlist{0x00}, + Data: ð.AttestationData{ + Slot: 123, + CommitteeIndex: 123, + BeaconBlockRoot: bytesutil.PadTo([]byte("root1"), 32), + Source: ð.Checkpoint{ + Epoch: 123, + Root: bytesutil.PadTo([]byte("root1"), 32), + }, + Target: ð.Checkpoint{ + Epoch: 123, + Root: bytesutil.PadTo([]byte("root1"), 32), + }, + }, + Signature: bytesutil.PadTo([]byte("sig1"), 96), + }, + { + AggregationBits: bitfield.Bitlist{0x01}, + Data: ð.AttestationData{ + Slot: 456, + CommitteeIndex: 456, + BeaconBlockRoot: bytesutil.PadTo([]byte("root2"), 32), + Source: ð.Checkpoint{ + Epoch: 456, + Root: bytesutil.PadTo([]byte("root2"), 32), + }, + Target: ð.Checkpoint{ + Epoch: 456, + Root: bytesutil.PadTo([]byte("root2"), 32), + }, + }, + Signature: bytesutil.PadTo([]byte("sig2"), 96), + }, + } + electraAtts := []*eth.AttestationElectra{ + { + AggregationBits: bitfield.Bitlist{0x00}, + Data: ð.AttestationData{ + Slot: 123, + CommitteeIndex: 123, + BeaconBlockRoot: bytesutil.PadTo([]byte("root1"), 32), + Source: ð.Checkpoint{ + Epoch: 123, + Root: bytesutil.PadTo([]byte("root1"), 32), + }, + Target: ð.Checkpoint{ + Epoch: 123, + Root: bytesutil.PadTo([]byte("root1"), 32), + }, + }, + Signature: bytesutil.PadTo([]byte("sig1"), 96), + CommitteeBits: primitives.NewAttestationCommitteeBits(), + }, + { + AggregationBits: bitfield.Bitlist{0x01}, + Data: ð.AttestationData{ + Slot: 456, + CommitteeIndex: 456, + BeaconBlockRoot: bytesutil.PadTo([]byte("root2"), 32), + Source: ð.Checkpoint{ + Epoch: 456, + Root: bytesutil.PadTo([]byte("root2"), 32), + }, + Target: ð.Checkpoint{ + Epoch: 456, + Root: bytesutil.PadTo([]byte("root2"), 32), + }, + }, + Signature: bytesutil.PadTo([]byte("sig2"), 96), + CommitteeBits: primitives.NewAttestationCommitteeBits(), + }, + } + + b := util.NewBeaconBlock() + b.Block.Body.Attestations = preElectraAtts + sb, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + + bb := util.NewBeaconBlockBellatrix() + bb.Block.Body.Attestations = preElectraAtts + bsb, err := blocks.NewSignedBeaconBlock(bb) + require.NoError(t, err) + + eb := util.NewBeaconBlockElectra() + eb.Block.Body.Attestations = electraAtts + esb, err := blocks.NewSignedBeaconBlock(eb) + require.NoError(t, err) + + t.Run("v1", func(t *testing.T) { + t.Run("ok", func(t *testing.T) { + mockChainService := &chainMock.ChainService{ + FinalizedRoots: map[[32]byte]bool{}, + } - t.Run("true", func(t *testing.T) { - mockChainService := &chainMock.ChainService{FinalizedRoots: map[[32]byte]bool{r: true}} s := &Server{ OptimisticModeFetcher: mockChainService, FinalizationFetcher: mockChainService, - Blocker: mockBlockFetcher, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, } - request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} s.GetBlockAttestations(writer, request) require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockAttestationsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - assert.Equal(t, true, resp.Finalized) + require.Equal(t, len(b.Block.Body.Attestations), len(resp.Data)) + + atts := make([]*eth.Attestation, len(b.Block.Body.Attestations)) + for i, a := range resp.Data { + atts[i], err = a.ToConsensus() + require.NoError(t, err) + } + assert.DeepEqual(t, b.Block.Body.Attestations, atts) }) - t.Run("false", func(t *testing.T) { - mockChainService := &chainMock.ChainService{FinalizedRoots: map[[32]byte]bool{r: false}} + t.Run("execution-optimistic", func(t *testing.T) { + r, err := bsb.Block().HashTreeRoot() + require.NoError(t, err) + mockChainService := &chainMock.ChainService{ + OptimisticRoots: map[[32]byte]bool{r: true}, + FinalizedRoots: map[[32]byte]bool{}, + } s := &Server{ OptimisticModeFetcher: mockChainService, FinalizationFetcher: mockChainService, - Blocker: mockBlockFetcher, + Blocker: &testutil.MockBlocker{BlockToReturn: bsb}, } - request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -605,7 +719,194 @@ func TestGetBlockAttestations(t *testing.T) { require.Equal(t, http.StatusOK, writer.Code) resp := &structs.GetBlockAttestationsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - assert.Equal(t, false, resp.ExecutionOptimistic) + assert.Equal(t, true, resp.ExecutionOptimistic) + }) + t.Run("finalized", func(t *testing.T) { + r, err := sb.Block().HashTreeRoot() + require.NoError(t, err) + + t.Run("true", func(t *testing.T) { + mockChainService := &chainMock.ChainService{FinalizedRoots: map[[32]byte]bool{r: true}} + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockAttestations(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, true, resp.Finalized) + }) + t.Run("false", func(t *testing.T) { + mockChainService := &chainMock.ChainService{FinalizedRoots: map[[32]byte]bool{r: false}} + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockAttestations(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockAttestationsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, false, resp.ExecutionOptimistic) + }) + }) + }) + + t.Run("V2", func(t *testing.T) { + t.Run("ok-pre-electra", func(t *testing.T) { + mockChainService := &chainMock.ChainService{ + FinalizedRoots: map[[32]byte]bool{}, + } + + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockAttestationsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + + resp := &structs.GetBlockAttestationsV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + + var attStructs []structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &attStructs)) + + atts := make([]*eth.Attestation, len(attStructs)) + for i, attStruct := range attStructs { + atts[i], err = attStruct.ToConsensus() + require.NoError(t, err) + } + + assert.DeepEqual(t, b.Block.Body.Attestations, atts) + assert.Equal(t, "phase0", resp.Version) + }) + t.Run("ok-post-electra", func(t *testing.T) { + mockChainService := &chainMock.ChainService{ + FinalizedRoots: map[[32]byte]bool{}, + } + + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: esb}, + } + + mockBlockFetcher := &testutil.MockBlocker{BlockToReturn: esb} + s.Blocker = mockBlockFetcher + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockAttestationsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + + resp := &structs.GetBlockAttestationsV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + + var attStructs []structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &attStructs)) + + atts := make([]*eth.AttestationElectra, len(attStructs)) + for i, attStruct := range attStructs { + atts[i], err = attStruct.ToConsensus() + require.NoError(t, err) + } + + assert.DeepEqual(t, eb.Block.Body.Attestations, atts) + assert.Equal(t, "electra", resp.Version) + }) + t.Run("execution-optimistic", func(t *testing.T) { + r, err := bsb.Block().HashTreeRoot() + require.NoError(t, err) + mockChainService := &chainMock.ChainService{ + OptimisticRoots: map[[32]byte]bool{r: true}, + FinalizedRoots: map[[32]byte]bool{}, + } + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: bsb}, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockAttestationsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockAttestationsV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, true, resp.ExecutionOptimistic) + assert.Equal(t, "bellatrix", resp.Version) + }) + t.Run("finalized", func(t *testing.T) { + r, err := sb.Block().HashTreeRoot() + require.NoError(t, err) + + t.Run("true", func(t *testing.T) { + mockChainService := &chainMock.ChainService{FinalizedRoots: map[[32]byte]bool{r: true}} + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockAttestationsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockAttestationsV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, true, resp.Finalized) + assert.Equal(t, "phase0", resp.Version) + }) + t.Run("false", func(t *testing.T) { + mockChainService := &chainMock.ChainService{FinalizedRoots: map[[32]byte]bool{r: false}} + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v2/beacon/blocks/{block_id}/attestations", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlockAttestationsV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockAttestationsV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, false, resp.ExecutionOptimistic) + assert.Equal(t, "phase0", resp.Version) + }) }) }) } @@ -622,7 +923,7 @@ func TestGetBlindedBlock(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -651,7 +952,7 @@ func TestGetBlindedBlock(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -682,7 +983,7 @@ func TestGetBlindedBlock(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -713,7 +1014,7 @@ func TestGetBlindedBlock(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -744,7 +1045,7 @@ func TestGetBlindedBlock(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -760,6 +1061,64 @@ func TestGetBlindedBlock(t *testing.T) { require.NoError(t, err) assert.DeepEqual(t, blk, b) }) + t.Run("electra", func(t *testing.T) { + b := util.NewBlindedBeaconBlockElectra() + sb, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + + mockChainService := &chainMock.ChainService{} + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlindedBlock(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, version.String(version.Electra), resp.Version) + sbb := &structs.SignedBlindedBeaconBlockElectra{Message: &structs.BlindedBeaconBlockElectra{}} + require.NoError(t, json.Unmarshal(resp.Data.Message, sbb.Message)) + sbb.Signature = resp.Data.Signature + blk, err := sbb.ToConsensus() + require.NoError(t, err) + assert.DeepEqual(t, blk, b) + }) + t.Run("fulu", func(t *testing.T) { + b := util.NewBlindedBeaconBlockFulu() + sb, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + + mockChainService := &chainMock.ChainService{} + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + Blocker: &testutil.MockBlocker{BlockToReturn: sb}, + } + + request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) + request.SetPathValue("block_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBlindedBlock(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBlockV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, version.String(version.Fulu), resp.Version) + sbb := &structs.SignedBlindedBeaconBlockFulu{Message: &structs.BlindedBeaconBlockFulu{}} + require.NoError(t, json.Unmarshal(resp.Data.Message, sbb.Message)) + sbb.Signature = resp.Data.Signature + blk, err := sbb.ToConsensus() + require.NoError(t, err) + assert.DeepEqual(t, blk, b) + }) t.Run("execution optimistic", func(t *testing.T) { b := util.NewBlindedBeaconBlockBellatrix() sb, err := blocks.NewSignedBeaconBlock(b) @@ -777,7 +1136,7 @@ func TestGetBlindedBlock(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -803,7 +1162,7 @@ func TestGetBlindedBlock(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": hexutil.Encode(root[:])}) + request.SetPathValue("block_id", hexutil.Encode(root[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -829,7 +1188,7 @@ func TestGetBlindedBlock(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": hexutil.Encode(root[:])}) + request.SetPathValue("block_id", hexutil.Encode(root[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -852,7 +1211,7 @@ func TestGetBlindedBlockSSZ(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -874,7 +1233,7 @@ func TestGetBlindedBlockSSZ(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -896,7 +1255,7 @@ func TestGetBlindedBlockSSZ(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -918,7 +1277,7 @@ func TestGetBlindedBlockSSZ(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -940,7 +1299,7 @@ func TestGetBlindedBlockSSZ(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/blinded_blocks/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1017,45 +1376,168 @@ func TestPublishBlock(t *testing.T) { SyncChecker: &mockSync.Sync{IsSyncing: false}, } - request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BellatrixBlock))) - request.Header.Set(api.VersionHeader, version.String(version.Bellatrix)) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BellatrixBlock))) + request.Header.Set(api.VersionHeader, version.String(version.Bellatrix)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Capella", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Capella) + converted, err := structs.BeaconBlockCapellaFromConsensus(block.Capella.Block) + require.NoError(t, err) + var signedblock *structs.SignedBeaconBlockCapella + err = json.Unmarshal([]byte(rpctesting.CapellaBlock), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock.Message) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.CapellaBlock))) + request.Header.Set(api.VersionHeader, version.String(version.Capella)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Capella block without version header succeeds", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.CapellaForkEpoch = 4 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBeaconBlockCapella + require.NoError(t, json.Unmarshal([]byte(rpctesting.CapellaBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().CapellaForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Capella) + converted, err := structs.BeaconBlockCapellaFromConsensus(block.Capella.Block) + require.NoError(t, err) + var signedblock *structs.SignedBeaconBlockCapella + err = json.Unmarshal(newBlock, &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock.Message) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(newBlock)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Deneb", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Deneb) + converted, err := structs.SignedBeaconBlockContentsDenebFromConsensus(block.Deneb) + require.NoError(t, err) + var signedblock *structs.SignedBeaconBlockContentsDeneb + err = json.Unmarshal([]byte(rpctesting.DenebBlockContents), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.DenebBlockContents))) + request.Header.Set(api.VersionHeader, version.String(version.Deneb)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Electra", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra) + converted, err := structs.SignedBeaconBlockContentsElectraFromConsensus(block.Electra) + require.NoError(t, err) + var signedblock *structs.SignedBeaconBlockContentsElectra + err = json.Unmarshal([]byte(rpctesting.FuluBlockContents), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.ElectraBlockContents))) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Electra block without version header succeeds", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.ElectraForkEpoch = 6 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBeaconBlockContentsElectra + require.NoError(t, json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &signedblock)) + signedblock.SignedBlock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().ElectraForkEpoch)) + newContents, err := json.Marshal(signedblock) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra) + converted, err := structs.SignedBeaconBlockContentsElectraFromConsensus(block.Electra) + require.NoError(t, err) + var signedblock *structs.SignedBeaconBlockContentsElectra + err = json.Unmarshal(newContents, &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(newContents)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} server.PublishBlock(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) - t.Run("Capella", func(t *testing.T) { + t.Run("Electra block without version header on wrong fork", func(t *testing.T) { v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) - v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { - block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Capella) - converted, err := structs.BeaconBlockCapellaFromConsensus(block.Capella.Block) - require.NoError(t, err) - var signedblock *structs.SignedBeaconBlockCapella - err = json.Unmarshal([]byte(rpctesting.CapellaBlock), &signedblock) - require.NoError(t, err) - require.DeepEqual(t, converted, signedblock.Message) - return ok - })) server := &Server{ V1Alpha1ValidatorServer: v1alpha1Server, SyncChecker: &mockSync.Sync{IsSyncing: false}, } - - request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.CapellaBlock))) - request.Header.Set(api.VersionHeader, version.String(version.Capella)) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.ElectraBlockContents))) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} server.PublishBlock(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, http.StatusBadRequest, writer.Code) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Phase0)), writer.Body.String()) }) - t.Run("Deneb", func(t *testing.T) { + t.Run("Fulu", func(t *testing.T) { v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { - block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Deneb) - converted, err := structs.SignedBeaconBlockContentsDenebFromConsensus(block.Deneb) + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Fulu) + converted, err := structs.SignedBeaconBlockContentsFuluFromConsensus(block.Fulu) require.NoError(t, err) - var signedblock *structs.SignedBeaconBlockContentsDeneb - err = json.Unmarshal([]byte(rpctesting.DenebBlockContents), &signedblock) + var signedblock *structs.SignedBeaconBlockContentsFulu + err = json.Unmarshal([]byte(rpctesting.FuluBlockContents), &signedblock) require.NoError(t, err) require.DeepEqual(t, converted, signedblock) return ok @@ -1064,8 +1546,8 @@ func TestPublishBlock(t *testing.T) { V1Alpha1ValidatorServer: v1alpha1Server, SyncChecker: &mockSync.Sync{IsSyncing: false}, } - request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.DenebBlockContents))) - request.Header.Set(api.VersionHeader, version.String(version.Deneb)) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.FuluBlockContents))) + request.Header.Set(api.VersionHeader, version.String(version.Fulu)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} server.PublishBlock(writer, request) @@ -1082,7 +1564,7 @@ func TestPublishBlock(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlock(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) }) t.Run("wrong version header", func(t *testing.T) { server := &Server{ @@ -1095,7 +1577,7 @@ func TestPublishBlock(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlock(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) }) t.Run("syncing", func(t *testing.T) { chainService := &chainMock.ChainService{} @@ -1115,6 +1597,177 @@ func TestPublishBlock(t *testing.T) { }) } +func TestVersionHeaderFromRequest(t *testing.T) { + t.Run("Fulu block contents returns fulu header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.FuluForkEpoch = 7 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBeaconBlockContentsFulu + require.NoError(t, json.Unmarshal([]byte(rpctesting.FuluBlockContents), &signedblock)) + signedblock.SignedBlock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().FuluForkEpoch)) + newContents, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newContents) + require.NoError(t, err) + require.Equal(t, version.String(version.Fulu), versionHead) + }) + t.Run("Blinded Fulu block returns fulu header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.FuluForkEpoch = 7 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBlindedBeaconBlockFulu + require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().FuluForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Fulu), versionHead) + }) + t.Run("Electra block contents returns electra header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.ElectraForkEpoch = 6 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBeaconBlockContentsElectra + require.NoError(t, json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &signedblock)) + signedblock.SignedBlock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().ElectraForkEpoch)) + newContents, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newContents) + require.NoError(t, err) + require.Equal(t, version.String(version.Electra), versionHead) + }) + t.Run("Blinded Electra block returns electra header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.ElectraForkEpoch = 6 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBlindedBeaconBlockElectra + require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().ElectraForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Electra), versionHead) + }) + t.Run("Deneb block contents returns deneb header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.DenebForkEpoch = 5 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBeaconBlockContentsDeneb + require.NoError(t, json.Unmarshal([]byte(rpctesting.DenebBlockContents), &signedblock)) + signedblock.SignedBlock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().DenebForkEpoch)) + newContents, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newContents) + require.NoError(t, err) + require.Equal(t, version.String(version.Deneb), versionHead) + }) + t.Run("Blinded Deneb block returns Deneb header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.DenebForkEpoch = 5 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBlindedBeaconBlockDeneb + require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedDenebBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().DenebForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Deneb), versionHead) + }) + t.Run("Capella block returns Capella header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.CapellaForkEpoch = 4 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBeaconBlockCapella + require.NoError(t, json.Unmarshal([]byte(rpctesting.CapellaBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().CapellaForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Capella), versionHead) + }) + t.Run("Blinded Capella block returns Capella header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.CapellaForkEpoch = 4 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBlindedBeaconBlockCapella + require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedCapellaBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().CapellaForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Capella), versionHead) + }) + t.Run("Bellatrix block returns capella header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.BellatrixForkEpoch = 3 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBeaconBlockBellatrix + require.NoError(t, json.Unmarshal([]byte(rpctesting.BellatrixBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().BellatrixForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Bellatrix), versionHead) + }) + t.Run("Blinded Capella block returns Capella header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.BellatrixForkEpoch = 3 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBlindedBeaconBlockBellatrix + require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedBellatrixBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().BellatrixForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Bellatrix), versionHead) + }) + t.Run("Altair block returns capella header", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.AltairForkEpoch = 2 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBeaconBlockAltair + require.NoError(t, json.Unmarshal([]byte(rpctesting.AltairBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().AltairForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Altair), versionHead) + }) + t.Run("Phase0 block returns capella header", func(t *testing.T) { + var signedblock *structs.SignedBeaconBlock + require.NoError(t, json.Unmarshal([]byte(rpctesting.Phase0Block), &signedblock)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + versionHead, err := versionHeaderFromRequest(newBlock) + require.NoError(t, err) + require.Equal(t, version.String(version.Phase0), versionHead) + }) + t.Run("Malformed json returns error unable to peek slot from block contents", func(t *testing.T) { + malformedJSON := []byte(`{"age": 30,}`) + _, err := versionHeaderFromRequest(malformedJSON) + require.ErrorContains(t, "unable to peek slot", err) + }) +} + func TestPublishBlockSSZ(t *testing.T) { ctrl := gomock.NewController(t) t.Run("Phase 0", func(t *testing.T) { @@ -1254,6 +1907,58 @@ func TestPublishBlockSSZ(t *testing.T) { server.PublishBlock(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) + t.Run("Electra", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + var blk structs.SignedBeaconBlockContentsElectra + err := json.Unmarshal([]byte(rpctesting.FuluBlockContents), &blk) + require.NoError(t, err) + genericBlock, err := blk.ToGeneric() + require.NoError(t, err) + ssz, err := genericBlock.GetElectra().MarshalSSZ() + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) + request.Header.Set("Content-Type", api.OctetStreamMediaType) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Fulu", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Fulu) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + var blk structs.SignedBeaconBlockContentsFulu + err := json.Unmarshal([]byte(rpctesting.FuluBlockContents), &blk) + require.NoError(t, err) + genericBlock, err := blk.ToGeneric() + require.NoError(t, err) + ssz, err := genericBlock.GetFulu().MarshalSSZ() + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) + request.Header.Set("Content-Type", api.OctetStreamMediaType) + request.Header.Set(api.VersionHeader, version.String(version.Fulu)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) t.Run("invalid block", func(t *testing.T) { server := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, @@ -1273,7 +1978,7 @@ func TestPublishBlockSSZ(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlock(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) }) t.Run("wrong version header", func(t *testing.T) { server := &Server{ @@ -1294,7 +1999,7 @@ func TestPublishBlockSSZ(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlock(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) }) t.Run("syncing", func(t *testing.T) { chainService := &chainMock.ChainService{} @@ -1433,6 +2138,100 @@ func TestPublishBlindedBlock(t *testing.T) { server.PublishBlindedBlock(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) + t.Run("Blinded Electra", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra) + converted, err := structs.BlindedBeaconBlockElectraFromConsensus(block.BlindedElectra.Message) + require.NoError(t, err) + var signedblock *structs.SignedBlindedBeaconBlockElectra + err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock.Message) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BlindedElectraBlock))) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Blinded Electra block without version header succeeds", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.ElectraForkEpoch = 6 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + var signedblock *structs.SignedBlindedBeaconBlockElectra + require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock)) + signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().ElectraForkEpoch)) + newBlock, err := json.Marshal(signedblock) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra) + converted, err := structs.BlindedBeaconBlockElectraFromConsensus(block.BlindedElectra.Message) + require.NoError(t, err) + var signedblock *structs.SignedBlindedBeaconBlockElectra + err = json.Unmarshal(newBlock, &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock.Message) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(newBlock)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Blinded Electra block without version header on wrong fork", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BlindedElectraBlock))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlock(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + // block is sent with slot == 1 which means it's in the phase0 fork + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Phase0)), writer.Body.String()) + }) + t.Run("Blinded Fulu", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedFulu) + converted, err := structs.BlindedBeaconBlockFuluFromConsensus(block.BlindedFulu.Message) + require.NoError(t, err) + var signedblock *structs.SignedBlindedBeaconBlockFulu + err = json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock.Message) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BlindedFuluBlock))) + request.Header.Set(api.VersionHeader, version.String(version.Fulu)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) t.Run("invalid block", func(t *testing.T) { server := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, @@ -1444,7 +2243,7 @@ func TestPublishBlindedBlock(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlindedBlock(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) }) t.Run("wrong version header", func(t *testing.T) { server := &Server{ @@ -1457,7 +2256,7 @@ func TestPublishBlindedBlock(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlindedBlock(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) }) t.Run("syncing", func(t *testing.T) { chainService := &chainMock.ChainService{} @@ -1617,6 +2416,58 @@ func TestPublishBlindedBlockSSZ(t *testing.T) { server.PublishBlindedBlock(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) + t.Run("Electra", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + var blk structs.SignedBlindedBeaconBlockElectra + err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &blk) + require.NoError(t, err) + genericBlock, err := blk.ToGeneric() + require.NoError(t, err) + ssz, err := genericBlock.GetBlindedElectra().MarshalSSZ() + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) + request.Header.Set("Content-Type", api.OctetStreamMediaType) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Fulu", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedFulu) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + var blk structs.SignedBlindedBeaconBlockFulu + err := json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &blk) + require.NoError(t, err) + genericBlock, err := blk.ToGeneric() + require.NoError(t, err) + ssz, err := genericBlock.GetBlindedFulu().MarshalSSZ() + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) + request.Header.Set("Content-Type", api.OctetStreamMediaType) + request.Header.Set(api.VersionHeader, version.String(version.Fulu)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) t.Run("invalid block", func(t *testing.T) { server := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, @@ -1628,7 +2479,7 @@ func TestPublishBlindedBlockSSZ(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlindedBlock(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) }) t.Run("wrong version header", func(t *testing.T) { server := &Server{ @@ -1649,7 +2500,7 @@ func TestPublishBlindedBlockSSZ(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlindedBlock(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) }) t.Run("syncing", func(t *testing.T) { chainService := &chainMock.ChainService{} @@ -1788,6 +2639,54 @@ func TestPublishBlockV2(t *testing.T) { server.PublishBlockV2(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) + t.Run("Electra", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra) + converted, err := structs.SignedBeaconBlockContentsElectraFromConsensus(block.Electra) + require.NoError(t, err) + var signedblock *structs.SignedBeaconBlockContentsElectra + err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.ElectraBlockContents))) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlockV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Fulu", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_Fulu) + converted, err := structs.SignedBeaconBlockContentsFuluFromConsensus(block.Fulu) + require.NoError(t, err) + var signedblock *structs.SignedBeaconBlockContentsFulu + err = json.Unmarshal([]byte(rpctesting.FuluBlockContents), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.FuluBlockContents))) + request.Header.Set(api.VersionHeader, version.String(version.Fulu)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlockV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) t.Run("invalid block", func(t *testing.T) { server := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, @@ -1799,7 +2698,7 @@ func TestPublishBlockV2(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlockV2(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block:", version.String(version.Bellatrix)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block:", version.String(version.Bellatrix)), writer.Body.String()) }) t.Run("wrong version header", func(t *testing.T) { server := &Server{ @@ -1812,7 +2711,7 @@ func TestPublishBlockV2(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlockV2(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block:", version.String(version.Capella)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block:", version.String(version.Capella)), writer.Body.String()) }) t.Run("missing version header", func(t *testing.T) { server := &Server{ @@ -1901,41 +2800,93 @@ func TestPublishBlockV2SSZ(t *testing.T) { require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) request.Header.Set("Content-Type", api.OctetStreamMediaType) - request.Header.Set(api.VersionHeader, version.String(version.Altair)) + request.Header.Set(api.VersionHeader, version.String(version.Altair)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlockV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Bellatrix", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Bellatrix) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + var blk structs.SignedBeaconBlockBellatrix + err := json.Unmarshal([]byte(rpctesting.BellatrixBlock), &blk) + require.NoError(t, err) + genericBlock, err := blk.ToGeneric() + require.NoError(t, err) + ssz, err := genericBlock.GetBellatrix().MarshalSSZ() + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) + request.Header.Set("Content-Type", api.OctetStreamMediaType) + request.Header.Set(api.VersionHeader, version.String(version.Bellatrix)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlockV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Capella", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Capella) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + var blk structs.SignedBeaconBlockCapella + err := json.Unmarshal([]byte(rpctesting.CapellaBlock), &blk) + require.NoError(t, err) + genericBlock, err := blk.ToGeneric() + require.NoError(t, err) + ssz, err := genericBlock.GetCapella().MarshalSSZ() + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) + request.Header.Set("Content-Type", api.OctetStreamMediaType) + request.Header.Set(api.VersionHeader, version.String(version.Capella)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} server.PublishBlockV2(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) - t.Run("Bellatrix", func(t *testing.T) { + t.Run("Deneb", func(t *testing.T) { v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { - _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Bellatrix) + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Deneb) return ok })) server := &Server{ V1Alpha1ValidatorServer: v1alpha1Server, SyncChecker: &mockSync.Sync{IsSyncing: false}, } - var blk structs.SignedBeaconBlockBellatrix - err := json.Unmarshal([]byte(rpctesting.BellatrixBlock), &blk) + + var blk structs.SignedBeaconBlockContentsDeneb + err := json.Unmarshal([]byte(rpctesting.DenebBlockContents), &blk) require.NoError(t, err) genericBlock, err := blk.ToGeneric() require.NoError(t, err) - ssz, err := genericBlock.GetBellatrix().MarshalSSZ() + ssz, err := genericBlock.GetDeneb().MarshalSSZ() require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) request.Header.Set("Content-Type", api.OctetStreamMediaType) - request.Header.Set(api.VersionHeader, version.String(version.Bellatrix)) + request.Header.Set(api.VersionHeader, version.String(version.Deneb)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} server.PublishBlockV2(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) - t.Run("Capella", func(t *testing.T) { + t.Run("Electra", func(t *testing.T) { v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { - _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Capella) + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Electra) return ok })) server := &Server{ @@ -1943,25 +2894,25 @@ func TestPublishBlockV2SSZ(t *testing.T) { SyncChecker: &mockSync.Sync{IsSyncing: false}, } - var blk structs.SignedBeaconBlockCapella - err := json.Unmarshal([]byte(rpctesting.CapellaBlock), &blk) + var blk structs.SignedBeaconBlockContentsElectra + err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &blk) require.NoError(t, err) genericBlock, err := blk.ToGeneric() require.NoError(t, err) - ssz, err := genericBlock.GetCapella().MarshalSSZ() + ssz, err := genericBlock.GetElectra().MarshalSSZ() require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) request.Header.Set("Content-Type", api.OctetStreamMediaType) - request.Header.Set(api.VersionHeader, version.String(version.Capella)) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} server.PublishBlockV2(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) - t.Run("Deneb", func(t *testing.T) { + t.Run("Fulu", func(t *testing.T) { v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { - _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Deneb) + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_Fulu) return ok })) server := &Server{ @@ -1969,16 +2920,16 @@ func TestPublishBlockV2SSZ(t *testing.T) { SyncChecker: &mockSync.Sync{IsSyncing: false}, } - var blk structs.SignedBeaconBlockContentsDeneb - err := json.Unmarshal([]byte(rpctesting.DenebBlockContents), &blk) + var blk structs.SignedBeaconBlockContentsFulu + err := json.Unmarshal([]byte(rpctesting.FuluBlockContents), &blk) require.NoError(t, err) genericBlock, err := blk.ToGeneric() require.NoError(t, err) - ssz, err := genericBlock.GetDeneb().MarshalSSZ() + ssz, err := genericBlock.GetFulu().MarshalSSZ() require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) request.Header.Set("Content-Type", api.OctetStreamMediaType) - request.Header.Set(api.VersionHeader, version.String(version.Deneb)) + request.Header.Set(api.VersionHeader, version.String(version.Fulu)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} server.PublishBlockV2(writer, request) @@ -2003,7 +2954,7 @@ func TestPublishBlockV2SSZ(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlockV2(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) }) t.Run("wrong version header", func(t *testing.T) { server := &Server{ @@ -2024,7 +2975,7 @@ func TestPublishBlockV2SSZ(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlockV2(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) }) t.Run("missing version header", func(t *testing.T) { server := &Server{ @@ -2176,6 +3127,54 @@ func TestPublishBlindedBlockV2(t *testing.T) { server.PublishBlindedBlockV2(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) + t.Run("Blinded Electra", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra) + converted, err := structs.BlindedBeaconBlockElectraFromConsensus(block.BlindedElectra.Message) + require.NoError(t, err) + var signedblock *structs.SignedBlindedBeaconBlockElectra + err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock.Message) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BlindedElectraBlock))) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlockV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Blinded Fulu", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedFulu) + converted, err := structs.BlindedBeaconBlockFuluFromConsensus(block.BlindedFulu.Message) + require.NoError(t, err) + var signedblock *structs.SignedBlindedBeaconBlockFulu + err = json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &signedblock) + require.NoError(t, err) + require.DeepEqual(t, converted, signedblock.Message) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BlindedFuluBlock))) + request.Header.Set(api.VersionHeader, version.String(version.Fulu)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlockV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) t.Run("invalid block", func(t *testing.T) { server := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, @@ -2187,7 +3186,7 @@ func TestPublishBlindedBlockV2(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlindedBlockV2(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block:", version.String(version.Bellatrix)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block:", version.String(version.Bellatrix)), writer.Body.String()) }) t.Run("wrong version header", func(t *testing.T) { server := &Server{ @@ -2200,7 +3199,7 @@ func TestPublishBlindedBlockV2(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlindedBlockV2(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) }) t.Run("missing version header", func(t *testing.T) { server := &Server{ @@ -2372,6 +3371,58 @@ func TestPublishBlindedBlockV2SSZ(t *testing.T) { server.PublishBlindedBlock(writer, request) assert.Equal(t, http.StatusOK, writer.Code) }) + t.Run("Electra", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + var blk structs.SignedBlindedBeaconBlockElectra + err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &blk) + require.NoError(t, err) + genericBlock, err := blk.ToGeneric() + require.NoError(t, err) + ssz, err := genericBlock.GetBlindedElectra().MarshalSSZ() + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) + request.Header.Set("Content-Type", api.OctetStreamMediaType) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) + t.Run("Fulu", func(t *testing.T) { + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool { + _, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedFulu) + return ok + })) + server := &Server{ + V1Alpha1ValidatorServer: v1alpha1Server, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + var blk structs.SignedBlindedBeaconBlockFulu + err := json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &blk) + require.NoError(t, err) + genericBlock, err := blk.ToGeneric() + require.NoError(t, err) + ssz, err := genericBlock.GetBlindedFulu().MarshalSSZ() + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(ssz)) + request.Header.Set("Content-Type", api.OctetStreamMediaType) + request.Header.Set(api.VersionHeader, version.String(version.Fulu)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlindedBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + }) t.Run("invalid block", func(t *testing.T) { server := &Server{ SyncChecker: &mockSync.Sync{IsSyncing: false}, @@ -2383,7 +3434,7 @@ func TestPublishBlindedBlockV2SSZ(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlindedBlockV2(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String()) }) t.Run("wrong version header", func(t *testing.T) { server := &Server{ @@ -2404,7 +3455,7 @@ func TestPublishBlindedBlockV2SSZ(t *testing.T) { writer.Body = &bytes.Buffer{} server.PublishBlindedBlockV2(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) - assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) + assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String()) }) t.Run("missing version header", func(t *testing.T) { server := &Server{ @@ -2450,8 +3501,6 @@ func TestValidateConsensus(t *testing.T) { require.NoError(t, err) block, err := util.GenerateFullBlock(st, privs, util.DefaultBlockGenConfig(), st.Slot()) require.NoError(t, err) - sbb, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) parentRoot, err := parentSbb.Block().HashTreeRoot() require.NoError(t, err) server := &Server{ @@ -2459,7 +3508,11 @@ func TestValidateConsensus(t *testing.T) { Stater: &testutil.MockStater{StatesByRoot: map[[32]byte]state.BeaconState{bytesutil.ToBytes32(parentBlock.Block.StateRoot): parentState}}, } - require.NoError(t, server.validateConsensus(ctx, sbb)) + require.NoError(t, server.validateConsensus(ctx, ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Phase0{ + Phase0: block, + }, + })) } func TestValidateEquivocation(t *testing.T) { @@ -2467,13 +3520,15 @@ func TestValidateEquivocation(t *testing.T) { st, err := util.NewBeaconState() require.NoError(t, err) require.NoError(t, st.SetSlot(10)) + blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) + require.NoError(t, err) + roblock, err := blocks.NewROBlockWithRoot(blk, bytesutil.ToBytes32([]byte("root"))) + require.NoError(t, err) fc := doublylinkedtree.New() - require.NoError(t, fc.InsertNode(context.Background(), st, bytesutil.ToBytes32([]byte("root")))) + require.NoError(t, fc.InsertNode(context.Background(), st, roblock)) server := &Server{ ForkchoiceFetcher: &chainMock.ChainService{ForkChoiceStore: fc}, } - blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) - require.NoError(t, err) blk.SetSlot(st.Slot() + 1) require.NoError(t, server.validateEquivocation(blk.Block())) @@ -2482,15 +3537,17 @@ func TestValidateEquivocation(t *testing.T) { st, err := util.NewBeaconState() require.NoError(t, err) require.NoError(t, st.SetSlot(10)) - fc := doublylinkedtree.New() - require.NoError(t, fc.InsertNode(context.Background(), st, bytesutil.ToBytes32([]byte("root")))) - server := &Server{ - ForkchoiceFetcher: &chainMock.ChainService{ForkChoiceStore: fc}, - } blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) require.NoError(t, err) blk.SetSlot(st.Slot()) + roblock, err := blocks.NewROBlockWithRoot(blk, bytesutil.ToBytes32([]byte("root"))) + require.NoError(t, err) + fc := doublylinkedtree.New() + require.NoError(t, fc.InsertNode(context.Background(), st, roblock)) + server := &Server{ + ForkchoiceFetcher: &chainMock.ChainService{ForkChoiceStore: fc}, + } err = server.validateEquivocation(blk.Block()) assert.ErrorContains(t, "already exists", err) require.ErrorIs(t, err, errEquivocatedBlock) @@ -2604,8 +3661,9 @@ func TestServer_GetBlockRoot(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + blockID := tt.blockID request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, tt.blockID) + request.SetPathValue("block_id", blockID["block_id"]) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2648,7 +3706,7 @@ func TestServer_GetBlockRoot(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2683,7 +3741,7 @@ func TestServer_GetBlockRoot(t *testing.T) { } t.Run("true", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "32"}) + request.SetPathValue("block_id", "32") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2695,7 +3753,7 @@ func TestServer_GetBlockRoot(t *testing.T) { }) t.Run("false", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "64"}) + request.SetPathValue("block_id", "64") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2711,7 +3769,7 @@ func TestServer_GetBlockRoot(t *testing.T) { func TestGetStateFork(t *testing.T) { ctx := context.Background() request := httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/states/{state_id}/fork", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") request.Header.Set("Accept", "application/octet-stream") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2750,7 +3808,7 @@ func TestGetStateFork(t *testing.T) { assert.DeepEqual(t, hexutil.Encode(expectedFork.PreviousVersion), stateForkReponse.Data.PreviousVersion) t.Run("execution optimistic", func(t *testing.T) { request = httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/states/{state_id}/fork", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") request.Header.Set("Accept", "application/octet-stream") writer = httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2781,7 +3839,7 @@ func TestGetStateFork(t *testing.T) { t.Run("finalized", func(t *testing.T) { request = httptest.NewRequest(http.MethodGet, "http://foo.example/eth/v1/beacon/states/{state_id}/fork", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") request.Header.Set("Accept", "application/octet-stream") writer = httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2839,7 +3897,7 @@ func TestGetCommittees(t *testing.T) { t.Run("Head all committees", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2860,7 +3918,7 @@ func TestGetCommittees(t *testing.T) { t.Run("Head all committees of epoch 10", func(t *testing.T) { query := url + "?epoch=10" request := httptest.NewRequest(http.MethodGet, query, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2877,7 +3935,7 @@ func TestGetCommittees(t *testing.T) { t.Run("Head all committees of slot 4", func(t *testing.T) { query := url + "?slot=4" request := httptest.NewRequest(http.MethodGet, query, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2903,7 +3961,7 @@ func TestGetCommittees(t *testing.T) { t.Run("Head all committees of index 1", func(t *testing.T) { query := url + "?index=1" request := httptest.NewRequest(http.MethodGet, query, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2929,7 +3987,7 @@ func TestGetCommittees(t *testing.T) { t.Run("Head all committees of slot 2, index 1", func(t *testing.T) { query := url + "?slot=2&index=1" request := httptest.NewRequest(http.MethodGet, query, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2972,7 +4030,7 @@ func TestGetCommittees(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3009,7 +4067,7 @@ func TestGetCommittees(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3282,7 +4340,7 @@ func TestServer_GetBlockHeader(t *testing.T) { t.Run("ok", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/headers/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3326,7 +4384,7 @@ func TestServer_GetBlockHeader(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/headers/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": "head"}) + request.SetPathValue("block_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3350,7 +4408,7 @@ func TestServer_GetBlockHeader(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/headers/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": hexutil.Encode(r[:])}) + request.SetPathValue("block_id", hexutil.Encode(r[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3370,7 +4428,7 @@ func TestServer_GetBlockHeader(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/headers/{block_id}", nil) - request = mux.SetURLVars(request, map[string]string{"block_id": hexutil.Encode(r[:])}) + request.SetPathValue("block_id", hexutil.Encode(r[:])) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3422,7 +4480,7 @@ func TestGetFinalityCheckpoints(t *testing.T) { t.Run("ok", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "/eth/v1/beacon/states/{state_id}/finality_checkpoints", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3452,7 +4510,7 @@ func TestGetFinalityCheckpoints(t *testing.T) { }) t.Run("state not found", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "/eth/v1/beacon/states/{state_id}/finality_checkpoints", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "foobar"}) + request.SetPathValue("state_id", "foobar") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3475,7 +4533,7 @@ func TestGetFinalityCheckpoints(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "/eth/v1/beacon/states/{state_id}/finality_checkpoints", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3503,7 +4561,7 @@ func TestGetFinalityCheckpoints(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "/eth/v1/beacon/states/{state_id}/finality_checkpoints", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -3675,3 +4733,407 @@ func TestServer_broadcastBlobSidecars(t *testing.T) { require.NoError(t, server.broadcastSeenBlockSidecars(context.Background(), blk, b.GetDeneb().Blobs, b.GetDeneb().KzgProofs)) require.LogsContain(t, hook, "Broadcasted blob sidecar for already seen block") } + +func Test_validateBlobSidecars(t *testing.T) { + blob := util.GetRandBlob(123) + commitment := GoKZG.KZGCommitment{180, 218, 156, 194, 59, 20, 10, 189, 186, 254, 132, 93, 7, 127, 104, 172, 238, 240, 237, 70, 83, 89, 1, 152, 99, 0, 165, 65, 143, 62, 20, 215, 230, 14, 205, 95, 28, 245, 54, 25, 160, 16, 178, 31, 232, 207, 38, 85} + proof := GoKZG.KZGProof{128, 110, 116, 170, 56, 111, 126, 87, 229, 234, 211, 42, 110, 150, 129, 206, 73, 142, 167, 243, 90, 149, 240, 240, 236, 204, 143, 182, 229, 249, 81, 27, 153, 171, 83, 70, 144, 250, 42, 1, 188, 215, 71, 235, 30, 7, 175, 86} + blk := util.NewBeaconBlockDeneb() + blk.Block.Body.BlobKzgCommitments = [][]byte{commitment[:]} + b, err := blocks.NewSignedBeaconBlock(blk) + require.NoError(t, err) + s := &Server{} + require.NoError(t, s.validateBlobSidecars(b, [][]byte{blob[:]}, [][]byte{proof[:]})) + + require.ErrorContains(t, "number of blobs, proofs, and commitments do not match", s.validateBlobSidecars(b, [][]byte{blob[:]}, [][]byte{})) + + sk, err := bls.RandKey() + require.NoError(t, err) + blk.Block.Body.BlobKzgCommitments = [][]byte{sk.PublicKey().Marshal()} + b, err = blocks.NewSignedBeaconBlock(blk) + require.NoError(t, err) + require.ErrorContains(t, "could not verify blob proof: can't verify opening proof", s.validateBlobSidecars(b, [][]byte{blob[:]}, [][]byte{proof[:]})) +} + +func TestGetPendingDeposits(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, 10) + + validators := st.Validators() + dummySig := make([]byte, 96) + for j := 0; j < 96; j++ { + dummySig[j] = byte(j) + } + deps := make([]*eth.PendingDeposit, 10) + for i := 0; i < len(deps); i += 1 { + deps[i] = ð.PendingDeposit{ + PublicKey: validators[i].PublicKey, + WithdrawalCredentials: validators[i].WithdrawalCredentials, + Amount: 100, + Slot: 0, + Signature: dummySig, + } + } + require.NoError(t, st.SetPendingDeposits(deps)) + + chainService := &chainMock.ChainService{ + Optimistic: false, + FinalizedRoots: map[[32]byte]bool{}, + } + server := &Server{ + Stater: &testutil.MockStater{ + BeaconState: st, + }, + OptimisticModeFetcher: chainService, + FinalizationFetcher: chainService, + } + + t.Run("json response", func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_deposits", nil) + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + server.GetPendingDeposits(rec, req) + require.Equal(t, http.StatusOK, rec.Code) + require.Equal(t, "electra", rec.Header().Get(api.VersionHeader)) + + var resp structs.GetPendingDepositsResponse + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + + expectedVersion := version.String(st.Version()) + require.Equal(t, expectedVersion, resp.Version) + + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) + + expectedDeposits := structs.PendingDepositsFromConsensus(deps) + require.DeepEqual(t, expectedDeposits, resp.Data) + }) + t.Run("ssz response", func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_deposits", nil) + req.Header.Set("Accept", "application/octet-stream") + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + server.GetPendingDeposits(rec, req) + require.Equal(t, http.StatusOK, rec.Code) + require.Equal(t, "electra", rec.Header().Get(api.VersionHeader)) + + responseBytes := rec.Body.Bytes() + var recoveredDeposits []*eth.PendingDeposit + + // Verify total size matches expected number of deposits + depositSize := (ð.PendingDeposit{}).SizeSSZ() + require.Equal(t, len(responseBytes), depositSize*len(deps)) + + for i := 0; i < len(deps); i++ { + start := i * depositSize + end := start + depositSize + + var deposit eth.PendingDeposit + require.NoError(t, deposit.UnmarshalSSZ(responseBytes[start:end])) + recoveredDeposits = append(recoveredDeposits, &deposit) + } + require.DeepEqual(t, deps, recoveredDeposits) + }) + t.Run("pre electra state", func(t *testing.T) { + preElectraSt, _ := util.DeterministicGenesisStateDeneb(t, 1) + preElectraServer := &Server{ + Stater: &testutil.MockStater{ + BeaconState: preElectraSt, + }, + OptimisticModeFetcher: chainService, + FinalizationFetcher: chainService, + } + + // Test JSON request + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_deposits", nil) + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + preElectraServer.GetPendingDeposits(rec, req) + require.Equal(t, http.StatusBadRequest, rec.Code) + + var errResp struct { + Code int `json:"code"` + Message string `json:"message"` + } + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.Equal(t, "state_id is prior to electra", errResp.Message) + + // Test SSZ request + sszReq := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_deposits", nil) + sszReq.Header.Set("Accept", "application/octet-stream") + sszReq.SetPathValue("state_id", "head") + sszRec := httptest.NewRecorder() + sszRec.Body = new(bytes.Buffer) + + preElectraServer.GetPendingDeposits(sszRec, sszReq) + require.Equal(t, http.StatusBadRequest, sszRec.Code) + + var sszErrResp struct { + Code int `json:"code"` + Message string `json:"message"` + } + require.NoError(t, json.Unmarshal(sszRec.Body.Bytes(), &sszErrResp)) + require.Equal(t, "state_id is prior to electra", sszErrResp.Message) + }) + t.Run("missing state_id parameter", func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_deposits", nil) + // Intentionally not setting state_id + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + server.GetPendingDeposits(rec, req) + require.Equal(t, http.StatusBadRequest, rec.Code) + + var errResp struct { + Code int `json:"code"` + Message string `json:"message"` + } + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.Equal(t, "state_id is required in URL params", errResp.Message) + }) + t.Run("optimistic node", func(t *testing.T) { + optimisticChainService := &chainMock.ChainService{ + Optimistic: true, + FinalizedRoots: map[[32]byte]bool{}, + } + optimisticServer := &Server{ + Stater: server.Stater, + OptimisticModeFetcher: optimisticChainService, + FinalizationFetcher: optimisticChainService, + } + + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_deposits", nil) + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + optimisticServer.GetPendingDeposits(rec, req) + require.Equal(t, http.StatusOK, rec.Code) + + var resp structs.GetPendingDepositsResponse + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.Equal(t, true, resp.ExecutionOptimistic) + }) + + t.Run("finalized node", func(t *testing.T) { + blockRoot, err := st.LatestBlockHeader().HashTreeRoot() + require.NoError(t, err) + + finalizedChainService := &chainMock.ChainService{ + Optimistic: false, + FinalizedRoots: map[[32]byte]bool{blockRoot: true}, + } + finalizedServer := &Server{ + Stater: server.Stater, + OptimisticModeFetcher: finalizedChainService, + FinalizationFetcher: finalizedChainService, + } + + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_deposits", nil) + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + finalizedServer.GetPendingDeposits(rec, req) + require.Equal(t, http.StatusOK, rec.Code) + + var resp structs.GetPendingDepositsResponse + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.Equal(t, true, resp.Finalized) + }) +} + +func TestGetPendingPartialWithdrawals(t *testing.T) { + st, _ := util.DeterministicGenesisStateElectra(t, 10) + for i := 0; i < 10; i += 1 { + err := st.AppendPendingPartialWithdrawal( + ð.PendingPartialWithdrawal{ + Index: primitives.ValidatorIndex(i), + Amount: 100, + WithdrawableEpoch: primitives.Epoch(0), + }) + require.NoError(t, err) + } + withdrawals, err := st.PendingPartialWithdrawals() + require.NoError(t, err) + + chainService := &chainMock.ChainService{ + Optimistic: false, + FinalizedRoots: map[[32]byte]bool{}, + } + server := &Server{ + Stater: &testutil.MockStater{ + BeaconState: st, + }, + OptimisticModeFetcher: chainService, + FinalizationFetcher: chainService, + } + + t.Run("json response", func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals", nil) + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + server.GetPendingPartialWithdrawals(rec, req) + require.Equal(t, http.StatusOK, rec.Code) + require.Equal(t, "electra", rec.Header().Get(api.VersionHeader)) + + var resp structs.GetPendingPartialWithdrawalsResponse + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + + expectedVersion := version.String(st.Version()) + require.Equal(t, expectedVersion, resp.Version) + + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) + + expectedWithdrawals := structs.PendingPartialWithdrawalsFromConsensus(withdrawals) + require.DeepEqual(t, expectedWithdrawals, resp.Data) + }) + + t.Run("ssz response", func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals", nil) + req.Header.Set("Accept", "application/octet-stream") + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + server.GetPendingPartialWithdrawals(rec, req) + require.Equal(t, http.StatusOK, rec.Code) + require.Equal(t, "electra", rec.Header().Get(api.VersionHeader)) + + responseBytes := rec.Body.Bytes() + var recoveredWithdrawals []*eth.PendingPartialWithdrawal + + withdrawalSize := (ð.PendingPartialWithdrawal{}).SizeSSZ() + require.Equal(t, len(responseBytes), withdrawalSize*len(withdrawals)) + + for i := 0; i < len(withdrawals); i++ { + start := i * withdrawalSize + end := start + withdrawalSize + + var withdrawal eth.PendingPartialWithdrawal + require.NoError(t, withdrawal.UnmarshalSSZ(responseBytes[start:end])) + recoveredWithdrawals = append(recoveredWithdrawals, &withdrawal) + } + require.DeepEqual(t, withdrawals, recoveredWithdrawals) + }) + + t.Run("pre electra state", func(t *testing.T) { + preElectraSt, _ := util.DeterministicGenesisStateDeneb(t, 1) + preElectraServer := &Server{ + Stater: &testutil.MockStater{ + BeaconState: preElectraSt, + }, + OptimisticModeFetcher: chainService, + FinalizationFetcher: chainService, + } + + // Test JSON request + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals", nil) + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + preElectraServer.GetPendingPartialWithdrawals(rec, req) + require.Equal(t, http.StatusBadRequest, rec.Code) + + var errResp struct { + Code int `json:"code"` + Message string `json:"message"` + } + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.Equal(t, "state_id is prior to electra", errResp.Message) + + // Test SSZ request + sszReq := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals", nil) + sszReq.Header.Set("Accept", "application/octet-stream") + sszReq.SetPathValue("state_id", "head") + sszRec := httptest.NewRecorder() + sszRec.Body = new(bytes.Buffer) + + preElectraServer.GetPendingPartialWithdrawals(sszRec, sszReq) + require.Equal(t, http.StatusBadRequest, sszRec.Code) + + var sszErrResp struct { + Code int `json:"code"` + Message string `json:"message"` + } + require.NoError(t, json.Unmarshal(sszRec.Body.Bytes(), &sszErrResp)) + require.Equal(t, "state_id is prior to electra", sszErrResp.Message) + }) + + t.Run("missing state_id parameter", func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals", nil) + // Intentionally not setting state_id + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + server.GetPendingPartialWithdrawals(rec, req) + require.Equal(t, http.StatusBadRequest, rec.Code) + + var errResp struct { + Code int `json:"code"` + Message string `json:"message"` + } + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.Equal(t, "state_id is required in URL params", errResp.Message) + }) + + t.Run("optimistic node", func(t *testing.T) { + optimisticChainService := &chainMock.ChainService{ + Optimistic: true, + FinalizedRoots: map[[32]byte]bool{}, + } + optimisticServer := &Server{ + Stater: server.Stater, + OptimisticModeFetcher: optimisticChainService, + FinalizationFetcher: optimisticChainService, + } + + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals", nil) + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + optimisticServer.GetPendingPartialWithdrawals(rec, req) + require.Equal(t, http.StatusOK, rec.Code) + + var resp structs.GetPendingPartialWithdrawalsResponse + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.Equal(t, true, resp.ExecutionOptimistic) + }) + + t.Run("finalized node", func(t *testing.T) { + blockRoot, err := st.LatestBlockHeader().HashTreeRoot() + require.NoError(t, err) + + finalizedChainService := &chainMock.ChainService{ + Optimistic: false, + FinalizedRoots: map[[32]byte]bool{blockRoot: true}, + } + finalizedServer := &Server{ + Stater: server.Stater, + OptimisticModeFetcher: finalizedChainService, + FinalizationFetcher: finalizedChainService, + } + + req := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/pending_partial_withdrawals", nil) + req.SetPathValue("state_id", "head") + rec := httptest.NewRecorder() + rec.Body = new(bytes.Buffer) + + finalizedServer.GetPendingPartialWithdrawals(rec, req) + require.Equal(t, http.StatusOK, rec.Code) + + var resp structs.GetPendingPartialWithdrawalsResponse + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.Equal(t, true, resp.Finalized) + }) +} diff --git a/beacon-chain/rpc/eth/beacon/handlers_validator.go b/beacon-chain/rpc/eth/beacon/handlers_validator.go index d14fd6bf87ea..77bc703bddc2 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_validator.go +++ b/beacon-chain/rpc/eth/beacon/handlers_validator.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/helpers" @@ -20,9 +19,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // GetValidators returns filterable list of validators with their balance, status and index. @@ -30,7 +29,7 @@ func (s *Server) GetValidators(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetValidators") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return @@ -179,12 +178,12 @@ func (s *Server) GetValidator(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetValidator") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return } - valId := mux.Vars(r)["validator_id"] + valId := r.PathValue("validator_id") if valId == "" { httputil.HandleError(w, "validator_id is required in URL params", http.StatusBadRequest) return @@ -244,7 +243,7 @@ func (s *Server) GetValidatorBalances(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetValidatorBalances") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return diff --git a/beacon-chain/rpc/eth/beacon/handlers_validators_test.go b/beacon-chain/rpc/eth/beacon/handlers_validators_test.go index 10f562f4d8ee..d6051a48a963 100644 --- a/beacon-chain/rpc/eth/beacon/handlers_validators_test.go +++ b/beacon-chain/rpc/eth/beacon/handlers_validators_test.go @@ -11,7 +11,6 @@ import ( "testing" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" chainMock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup" @@ -47,7 +46,7 @@ func TestGetValidators(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -86,7 +85,7 @@ func TestGetValidators(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validators?id=0&id=1", nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -118,7 +117,7 @@ func TestGetValidators(t *testing.T) { fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validators?id=%s&id=%s", hexPubkey1, hexPubkey2), nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -148,7 +147,7 @@ func TestGetValidators(t *testing.T) { fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validators?id=%s&id=1", hexPubkey), nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -197,7 +196,7 @@ func TestGetValidators(t *testing.T) { fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validators?id=%s&id=%s", hexPubkey, hexutil.Encode([]byte(strings.Repeat("x", fieldparams.BLSPubkeyLength)))), nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -220,7 +219,7 @@ func TestGetValidators(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators?id=1&id=99999", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -243,7 +242,7 @@ func TestGetValidators(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -271,7 +270,7 @@ func TestGetValidators(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -306,7 +305,7 @@ func TestGetValidators(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validators", &body, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -342,7 +341,7 @@ func TestGetValidators(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validators", &body, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -368,7 +367,7 @@ func TestGetValidators(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validators", nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -398,7 +397,7 @@ func TestGetValidators(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validators", &body, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -492,7 +491,7 @@ func TestGetValidators_FilterByStatus(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators?status=active", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -523,7 +522,7 @@ func TestGetValidators_FilterByStatus(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators?status=active_ongoing", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -553,7 +552,7 @@ func TestGetValidators_FilterByStatus(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators?status=exited", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -586,7 +585,7 @@ func TestGetValidators_FilterByStatus(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validators?status=pending_initialized&status=exited_unslashed", nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -619,7 +618,7 @@ func TestGetValidators_FilterByStatus(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validators?status=pending&status=exited_slashed", nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -654,7 +653,8 @@ func TestGetValidator(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "0"}) + request.SetPathValue("state_id", "head") + request.SetPathValue("validator_id", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -689,7 +689,8 @@ func TestGetValidator(t *testing.T) { pubKey := st.PubkeyAtIndex(primitives.ValidatorIndex(0)) hexPubkey := hexutil.Encode(pubKey[:]) request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": hexPubkey}) + request.SetPathValue("state_id", "head") + request.SetPathValue("validator_id", hexPubkey) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -708,7 +709,7 @@ func TestGetValidator(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil) - request = mux.SetURLVars(request, map[string]string{"validator_id": "1"}) + request.SetPathValue("validator_id", "1") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -728,7 +729,7 @@ func TestGetValidator(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -748,7 +749,8 @@ func TestGetValidator(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "99999"}) + request.SetPathValue("state_id", "head") + request.SetPathValue("validator_id", "99999") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -768,7 +770,8 @@ func TestGetValidator(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": hexutil.Encode([]byte(strings.Repeat("x", fieldparams.BLSPubkeyLength)))}) + request.SetPathValue("state_id", "head") + request.SetPathValue("validator_id", hexutil.Encode([]byte(strings.Repeat("x", fieldparams.BLSPubkeyLength)))) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -791,7 +794,8 @@ func TestGetValidator(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "0"}) + request.SetPathValue("state_id", "head") + request.SetPathValue("validator_id", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -819,7 +823,8 @@ func TestGetValidator(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validators/{validator_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head", "validator_id": "0"}) + request.SetPathValue("state_id", "head") + request.SetPathValue("validator_id", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -853,7 +858,7 @@ func TestGetValidatorBalances(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validator_balances", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -882,7 +887,7 @@ func TestGetValidatorBalances(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=0&id=1", nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -914,7 +919,7 @@ func TestGetValidatorBalances(t *testing.T) { fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=%s&id=%s", hexPubkey1, hexPubkey2), nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -944,7 +949,7 @@ func TestGetValidatorBalances(t *testing.T) { fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validators?id=%s&id=1", hexPubkey), nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -974,7 +979,7 @@ func TestGetValidatorBalances(t *testing.T) { fmt.Sprintf("http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=%s&id=%s", hexPubkey, hexutil.Encode([]byte(strings.Repeat("x", fieldparams.BLSPubkeyLength)))), nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -997,7 +1002,7 @@ func TestGetValidatorBalances(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=1&id=99999", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1043,7 +1048,7 @@ func TestGetValidatorBalances(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=0", nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1075,7 +1080,7 @@ func TestGetValidatorBalances(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validator_balances?id=0", nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1108,7 +1113,7 @@ func TestGetValidatorBalances(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validator_balances", &body, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1136,7 +1141,7 @@ func TestGetValidatorBalances(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validator_balances", nil, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1166,7 +1171,7 @@ func TestGetValidatorBalances(t *testing.T) { "http://example.com/eth/v1/beacon/states/{state_id}/validator_balances", &body, ) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} diff --git a/beacon-chain/rpc/eth/beacon/server.go b/beacon-chain/rpc/eth/beacon/server.go index e7eef22493f5..4ac573288705 100644 --- a/beacon-chain/rpc/eth/beacon/server.go +++ b/beacon-chain/rpc/eth/beacon/server.go @@ -5,6 +5,7 @@ package beacon import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" blockfeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/block" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" @@ -24,28 +25,30 @@ import ( // Server defines a server implementation of the gRPC Beacon Chain service, // providing RPC endpoints to access data relevant to the Ethereum Beacon Chain. type Server struct { - BeaconDB db.ReadOnlyDatabase - ChainInfoFetcher blockchain.ChainInfoFetcher - GenesisTimeFetcher blockchain.TimeFetcher - BlockReceiver blockchain.BlockReceiver - BlockNotifier blockfeed.Notifier - OperationNotifier operation.Notifier - Broadcaster p2p.Broadcaster - AttestationsPool attestations.Pool - SlashingsPool slashings.PoolManager - VoluntaryExitsPool voluntaryexits.PoolManager - StateGenService stategen.StateManager - Stater lookup.Stater - Blocker lookup.Blocker - HeadFetcher blockchain.HeadFetcher - TimeFetcher blockchain.TimeFetcher - OptimisticModeFetcher blockchain.OptimisticModeFetcher - V1Alpha1ValidatorServer eth.BeaconNodeValidatorServer - SyncChecker sync.Checker - CanonicalHistory *stategen.CanonicalHistory - ExecutionPayloadReconstructor execution.PayloadReconstructor - FinalizationFetcher blockchain.FinalizationFetcher - BLSChangesPool blstoexec.PoolManager - ForkchoiceFetcher blockchain.ForkchoiceFetcher - CoreService *core.Service + BeaconDB db.ReadOnlyDatabase + ChainInfoFetcher blockchain.ChainInfoFetcher + GenesisTimeFetcher blockchain.TimeFetcher + BlockReceiver blockchain.BlockReceiver + BlockNotifier blockfeed.Notifier + OperationNotifier operation.Notifier + Broadcaster p2p.Broadcaster + AttestationCache *cache.AttestationCache + AttestationsPool attestations.Pool + SlashingsPool slashings.PoolManager + VoluntaryExitsPool voluntaryexits.PoolManager + StateGenService stategen.StateManager + Stater lookup.Stater + Blocker lookup.Blocker + HeadFetcher blockchain.HeadFetcher + TimeFetcher blockchain.TimeFetcher + OptimisticModeFetcher blockchain.OptimisticModeFetcher + V1Alpha1ValidatorServer eth.BeaconNodeValidatorServer + SyncChecker sync.Checker + CanonicalHistory *stategen.CanonicalHistory + ExecutionReconstructor execution.Reconstructor + FinalizationFetcher blockchain.FinalizationFetcher + BLSChangesPool blstoexec.PoolManager + ForkchoiceFetcher blockchain.ForkchoiceFetcher + CoreService *core.Service + AttestationStateFetcher blockchain.AttestationStateFetcher } diff --git a/beacon-chain/rpc/eth/blob/BUILD.bazel b/beacon-chain/rpc/eth/blob/BUILD.bazel index 438f8313daf7..f21386e7bded 100644 --- a/beacon-chain/rpc/eth/blob/BUILD.bazel +++ b/beacon-chain/rpc/eth/blob/BUILD.bazel @@ -9,14 +9,20 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/blob", visibility = ["//visibility:public"], deps = [ + "//api:go_default_library", "//api/server/structs:go_default_library", + "//beacon-chain/blockchain:go_default_library", "//beacon-chain/rpc/core:go_default_library", "//beacon-chain/rpc/lookup:go_default_library", "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/primitives:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@com_github_pkg_errors//:go_default_library", ], ) @@ -25,6 +31,7 @@ go_test( srcs = ["handlers_test.go"], embed = [":go_default_library"], deps = [ + "//api:go_default_library", "//api/server/structs:go_default_library", "//beacon-chain/blockchain/testing:go_default_library", "//beacon-chain/db/filesystem:go_default_library", @@ -32,9 +39,11 @@ go_test( "//beacon-chain/rpc/lookup:go_default_library", "//beacon-chain/rpc/testutil:go_default_library", "//beacon-chain/verification:go_default_library", + "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", diff --git a/beacon-chain/rpc/eth/blob/handlers.go b/beacon-chain/rpc/eth/blob/handlers.go index dd40c4620135..8dc57a056f01 100644 --- a/beacon-chain/rpc/eth/blob/handlers.go +++ b/beacon-chain/rpc/eth/blob/handlers.go @@ -8,21 +8,25 @@ import ( "strings" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core" field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" - eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/runtime/version" ) // Blobs is an HTTP handler for Beacon API getBlobs. func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.Blobs") defer span.End() - var sidecars []*eth.BlobSidecar - indices, err := parseIndices(r.URL) + indices, err := parseIndices(r.URL, s.TimeFetcher.CurrentSlot()) if err != nil { httputil.HandleError(w, err.Error(), http.StatusBadRequest) return @@ -48,29 +52,54 @@ func (s *Server) Blobs(w http.ResponseWriter, r *http.Request) { return } } - for i := range verifiedBlobs { - sidecars = append(sidecars, verifiedBlobs[i].BlobSidecar) + + blk, err := s.Blocker.Block(ctx, []byte(blockId)) + if err != nil { + httputil.HandleError(w, "Could not fetch block: "+err.Error(), http.StatusInternalServerError) + return + } + if blk == nil { + httputil.HandleError(w, "Block not found", http.StatusNotFound) + return } + if httputil.RespondWithSsz(r) { - sidecarResp := ð.BlobSidecars{ - Sidecars: sidecars, - } - sszResp, err := sidecarResp.MarshalSSZ() + sszResp, err := buildSidecarsSSZResponse(verifiedBlobs) if err != nil { httputil.HandleError(w, err.Error(), http.StatusInternalServerError) return } + w.Header().Set(api.VersionHeader, version.String(blk.Version())) httputil.WriteSsz(w, sszResp, "blob_sidecars.ssz") return } - httputil.WriteJson(w, buildSidecarsResponse(sidecars)) + blkRoot, err := blk.Block().HashTreeRoot() + if err != nil { + httputil.HandleError(w, "Could not hash block: "+err.Error(), http.StatusInternalServerError) + return + } + isOptimistic, err := s.OptimisticModeFetcher.IsOptimisticForRoot(ctx, blkRoot) + if err != nil { + httputil.HandleError(w, "Could not check if block is optimistic: "+err.Error(), http.StatusInternalServerError) + return + } + + data := buildSidecarsJsonResponse(verifiedBlobs) + resp := &structs.SidecarsResponse{ + Version: version.String(blk.Version()), + Data: data, + ExecutionOptimistic: isOptimistic, + Finalized: s.FinalizationFetcher.IsFinalized(ctx, blkRoot), + } + w.Header().Set(api.VersionHeader, version.String(blk.Version())) + httputil.WriteJson(w, resp) } // parseIndices filters out invalid and duplicate blob indices -func parseIndices(url *url.URL) ([]uint64, error) { +func parseIndices(url *url.URL, s primitives.Slot) ([]uint64, error) { rawIndices := url.Query()["indices"] - indices := make([]uint64, 0, field_params.MaxBlobsPerBlock) + indices := make([]uint64, 0, params.BeaconConfig().MaxBlobsPerBlock(s)) invalidIndices := make([]string, 0) loop: for _, raw := range rawIndices { @@ -79,7 +108,7 @@ loop: invalidIndices = append(invalidIndices, raw) continue } - if ix >= field_params.MaxBlobsPerBlock { + if ix >= uint64(params.BeaconConfig().MaxBlobsPerBlock(s)) { invalidIndices = append(invalidIndices, raw) continue } @@ -97,14 +126,14 @@ loop: return indices, nil } -func buildSidecarsResponse(sidecars []*eth.BlobSidecar) *structs.SidecarsResponse { - resp := &structs.SidecarsResponse{Data: make([]*structs.Sidecar, len(sidecars))} - for i, sc := range sidecars { +func buildSidecarsJsonResponse(verifiedBlobs []*blocks.VerifiedROBlob) []*structs.Sidecar { + sidecars := make([]*structs.Sidecar, len(verifiedBlobs)) + for i, sc := range verifiedBlobs { proofs := make([]string, len(sc.CommitmentInclusionProof)) for j := range sc.CommitmentInclusionProof { proofs[j] = hexutil.Encode(sc.CommitmentInclusionProof[j]) } - resp.Data[i] = &structs.Sidecar{ + sidecars[i] = &structs.Sidecar{ Index: strconv.FormatUint(sc.Index, 10), Blob: hexutil.Encode(sc.Blob), KzgCommitment: hexutil.Encode(sc.KzgCommitment), @@ -113,5 +142,17 @@ func buildSidecarsResponse(sidecars []*eth.BlobSidecar) *structs.SidecarsRespons CommitmentInclusionProof: proofs, } } - return resp + return sidecars +} + +func buildSidecarsSSZResponse(verifiedBlobs []*blocks.VerifiedROBlob) ([]byte, error) { + ssz := make([]byte, field_params.BlobSidecarSize*len(verifiedBlobs)) + for i, sidecar := range verifiedBlobs { + sszrep, err := sidecar.MarshalSSZ() + if err != nil { + return nil, errors.Wrap(err, "failed to marshal sidecar ssz") + } + copy(ssz[i*field_params.BlobSidecarSize:(i+1)*field_params.BlobSidecarSize], sszrep) + } + return ssz, nil } diff --git a/beacon-chain/rpc/eth/blob/handlers_test.go b/beacon-chain/rpc/eth/blob/handlers_test.go index 707cc567dd9f..431045fa41f7 100644 --- a/beacon-chain/rpc/eth/blob/handlers_test.go +++ b/beacon-chain/rpc/eth/blob/handlers_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "fmt" "net/http" "net/http/httptest" "net/url" @@ -13,6 +14,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" mockChain "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" @@ -20,9 +22,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/testutil" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/network/httputil" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -38,23 +42,27 @@ func TestBlobs(t *testing.T) { denebBlock, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 123, 4) require.NoError(t, db.SaveBlock(context.Background(), denebBlock)) bs := filesystem.NewEphemeralBlobStorage(t) - testSidecars, err := verification.BlobSidecarSliceNoop(blobs) - require.NoError(t, err) + testSidecars := verification.FakeVerifySliceForTest(t, blobs) for i := range testSidecars { require.NoError(t, bs.Save(testSidecars[i])) } blockRoot := blobs[0].BlockRoot() + mockChainService := &mockChain.ChainService{ + FinalizedRoots: map[[32]byte]bool{}, + } + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + TimeFetcher: mockChainService, + } + t.Run("genesis", func(t *testing.T) { u := "http://foo.example/genesis" request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{} - s := &Server{ - Blocker: blocker, - } - + s.Blocker = &lookup.BeaconDbBlocker{} s.Blobs(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) @@ -68,18 +76,14 @@ func TestBlobs(t *testing.T) { request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ - ChainInfoFetcher: &mockChain.ChainService{Root: blockRoot[:]}, + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{Root: blockRoot[:], Block: denebBlock}, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), }, BeaconDB: db, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, - } - s.Blobs(writer, request) assert.Equal(t, http.StatusOK, writer.Code) @@ -110,120 +114,116 @@ func TestBlobs(t *testing.T) { assert.Equal(t, hexutil.Encode(blobs[3].Blob), sidecar.Blob) assert.Equal(t, hexutil.Encode(blobs[3].KzgCommitment), sidecar.KzgCommitment) assert.Equal(t, hexutil.Encode(blobs[3].KzgProof), sidecar.KzgProof) + + require.Equal(t, "deneb", resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) }) t.Run("finalized", func(t *testing.T) { u := "http://foo.example/finalized" request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ - ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}}, + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}, Block: denebBlock}, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), }, BeaconDB: db, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, - } - s.Blobs(writer, request) assert.Equal(t, http.StatusOK, writer.Code) resp := &structs.SidecarsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) require.Equal(t, 4, len(resp.Data)) + + require.Equal(t, "deneb", resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) }) - t.Run("justified", func(t *testing.T) { - u := "http://foo.example/justified" + t.Run("root", func(t *testing.T) { + u := "http://foo.example/" + hexutil.Encode(blockRoot[:]) request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ - ChainInfoFetcher: &mockChain.ChainService{CurrentJustifiedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}}, + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{Block: denebBlock}, + BeaconDB: db, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), }, - BeaconDB: db, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, - } - s.Blobs(writer, request) assert.Equal(t, http.StatusOK, writer.Code) resp := &structs.SidecarsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) require.Equal(t, 4, len(resp.Data)) + + require.Equal(t, "deneb", resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) }) - t.Run("root", func(t *testing.T) { - u := "http://foo.example/" + hexutil.Encode(blockRoot[:]) + t.Run("slot", func(t *testing.T) { + u := "http://foo.example/123" request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ - BeaconDB: db, + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{Block: denebBlock}, + BeaconDB: db, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), }, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, - } - s.Blobs(writer, request) assert.Equal(t, http.StatusOK, writer.Code) resp := &structs.SidecarsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) require.Equal(t, 4, len(resp.Data)) + + require.Equal(t, "deneb", resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) }) - t.Run("slot", func(t *testing.T) { - u := "http://foo.example/123" + t.Run("slot not found", func(t *testing.T) { + u := "http://foo.example/122" request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ - BeaconDB: db, + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{Block: denebBlock}, + BeaconDB: db, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), }, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, - } - s.Blobs(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - resp := &structs.SidecarsResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.Equal(t, 4, len(resp.Data)) + assert.Equal(t, http.StatusNotFound, writer.Code) }) t.Run("one blob only", func(t *testing.T) { u := "http://foo.example/123?indices=2" request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ - ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}}, + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}, Block: denebBlock}, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), }, BeaconDB: db, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, - } - s.Blobs(writer, request) + assert.Equal(t, version.String(version.Deneb), writer.Header().Get(api.VersionHeader)) assert.Equal(t, http.StatusOK, writer.Code) resp := &structs.SidecarsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) @@ -234,45 +234,62 @@ func TestBlobs(t *testing.T) { assert.Equal(t, hexutil.Encode(blobs[2].Blob), sidecar.Blob) assert.Equal(t, hexutil.Encode(blobs[2].KzgCommitment), sidecar.KzgCommitment) assert.Equal(t, hexutil.Encode(blobs[2].KzgProof), sidecar.KzgProof) + + require.Equal(t, "deneb", resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) }) t.Run("no blobs returns an empty array", func(t *testing.T) { u := "http://foo.example/123" request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ - ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}}, + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}, Block: denebBlock}, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), }, BeaconDB: db, BlobStorage: filesystem.NewEphemeralBlobStorage(t), // new ephemeral storage } - s := &Server{ - Blocker: blocker, - } s.Blobs(writer, request) assert.Equal(t, http.StatusOK, writer.Code) resp := &structs.SidecarsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) require.Equal(t, len(resp.Data), 0) + + require.Equal(t, "deneb", resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) + }) + t.Run("blob index over max", func(t *testing.T) { + overLimit := params.BeaconConfig().MaxBlobsPerBlockByVersion(version.Deneb) + u := fmt.Sprintf("http://foo.example/123?indices=%d", overLimit) + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s.Blocker = &lookup.BeaconDbBlocker{} + s.Blobs(writer, request) + + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, fmt.Sprintf("requested blob indices [%d] are invalid", overLimit))) }) t.Run("outside retention period returns 200 w/ empty list ", func(t *testing.T) { u := "http://foo.example/123" request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - moc := &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}} - blocker := &lookup.BeaconDbBlocker{ + moc := &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}, Block: denebBlock} + s.Blocker = &lookup.BeaconDbBlocker{ ChainInfoFetcher: moc, GenesisTimeFetcher: moc, // genesis time is set to 0 here, so it results in current epoch being extremely large BeaconDB: db, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, - } s.Blobs(writer, request) @@ -280,6 +297,10 @@ func TestBlobs(t *testing.T) { resp := &structs.SidecarsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) require.Equal(t, 0, len(resp.Data)) + + require.Equal(t, "deneb", resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) }) t.Run("block without commitments returns 200 w/empty list ", func(t *testing.T) { denebBlock, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 333, 0) @@ -292,17 +313,14 @@ func TestBlobs(t *testing.T) { request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ - ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}}, + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}, Block: denebBlock}, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), }, BeaconDB: db, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, - } s.Blobs(writer, request) @@ -310,16 +328,17 @@ func TestBlobs(t *testing.T) { resp := &structs.SidecarsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) require.Equal(t, 0, len(resp.Data)) + + require.Equal(t, "deneb", resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) }) t.Run("slot before Deneb fork", func(t *testing.T) { u := "http://foo.example/31" request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{} - s := &Server{ - Blocker: blocker, - } + s.Blocker = &lookup.BeaconDbBlocker{} s.Blobs(writer, request) @@ -334,11 +353,7 @@ func TestBlobs(t *testing.T) { request := httptest.NewRequest("GET", u, nil) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{} - s := &Server{ - Blocker: blocker, - } - + s.Blocker = &lookup.BeaconDbBlocker{} s.Blobs(writer, request) assert.Equal(t, http.StatusBadRequest, writer.Code) @@ -353,7 +368,30 @@ func TestBlobs(t *testing.T) { request.Header.Add("Accept", "application/octet-stream") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} - blocker := &lookup.BeaconDbBlocker{ + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}}, + GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ + Genesis: time.Now(), + }, + BeaconDB: db, + BlobStorage: bs, + } + s.Blobs(writer, request) + assert.Equal(t, version.String(version.Deneb), writer.Header().Get(api.VersionHeader)) + assert.Equal(t, http.StatusOK, writer.Code) + require.Equal(t, len(writer.Body.Bytes()), fieldparams.BlobSidecarSize) // size of each sidecar + // can directly unmarshal to sidecar since there's only 1 + var sidecar eth.BlobSidecar + require.NoError(t, sidecar.UnmarshalSSZ(writer.Body.Bytes())) + require.NotNil(t, sidecar.Blob) + }) + t.Run("ssz multiple blobs", func(t *testing.T) { + u := "http://foo.example/finalized" + request := httptest.NewRequest("GET", u, nil) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s.Blocker = &lookup.BeaconDbBlocker{ ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}}, GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ Genesis: time.Now(), @@ -361,12 +399,115 @@ func TestBlobs(t *testing.T) { BeaconDB: db, BlobStorage: bs, } - s := &Server{ - Blocker: blocker, + s.Blobs(writer, request) + + assert.Equal(t, http.StatusOK, writer.Code) + require.Equal(t, len(writer.Body.Bytes()), fieldparams.BlobSidecarSize*4) // size of each sidecar + }) +} + +func TestBlobs_Electra(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.DenebForkEpoch = 0 + cfg.ElectraForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + + db := testDB.SetupDB(t) + electraBlock, blobs := util.GenerateTestElectraBlockWithSidecar(t, [32]byte{}, 123, params.BeaconConfig().MaxBlobsPerBlockByVersion(version.Electra)) + require.NoError(t, db.SaveBlock(context.Background(), electraBlock)) + bs := filesystem.NewEphemeralBlobStorage(t) + testSidecars := verification.FakeVerifySliceForTest(t, blobs) + for i := range testSidecars { + require.NoError(t, bs.Save(testSidecars[i])) + } + blockRoot := blobs[0].BlockRoot() + + mockChainService := &mockChain.ChainService{ + FinalizedRoots: map[[32]byte]bool{}, + } + s := &Server{ + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + TimeFetcher: mockChainService, + } + t.Run("max blobs for electra", func(t *testing.T) { + u := "http://foo.example/123" + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}, Block: electraBlock}, + GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ + Genesis: time.Now(), + }, + BeaconDB: db, + BlobStorage: bs, + } + s.Blobs(writer, request) + + assert.Equal(t, version.String(version.Electra), writer.Header().Get(api.VersionHeader)) + assert.Equal(t, http.StatusOK, writer.Code) + resp := &structs.SidecarsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.Equal(t, params.BeaconConfig().MaxBlobsPerBlockByVersion(version.Electra), len(resp.Data)) + sidecar := resp.Data[0] + require.NotNil(t, sidecar) + assert.Equal(t, "0", sidecar.Index) + assert.Equal(t, hexutil.Encode(blobs[0].Blob), sidecar.Blob) + assert.Equal(t, hexutil.Encode(blobs[0].KzgCommitment), sidecar.KzgCommitment) + assert.Equal(t, hexutil.Encode(blobs[0].KzgProof), sidecar.KzgProof) + + require.Equal(t, version.String(version.Electra), resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) + }) + t.Run("requested blob index at max", func(t *testing.T) { + limit := params.BeaconConfig().MaxBlobsPerBlockByVersion(version.Electra) - 1 + u := fmt.Sprintf("http://foo.example/123?indices=%d", limit) + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s.Blocker = &lookup.BeaconDbBlocker{ + ChainInfoFetcher: &mockChain.ChainService{FinalizedCheckPoint: ð.Checkpoint{Root: blockRoot[:]}, Block: electraBlock}, + GenesisTimeFetcher: &testutil.MockGenesisTimeFetcher{ + Genesis: time.Now(), + }, + BeaconDB: db, + BlobStorage: bs, } s.Blobs(writer, request) + + assert.Equal(t, version.String(version.Electra), writer.Header().Get(api.VersionHeader)) assert.Equal(t, http.StatusOK, writer.Code) - require.Equal(t, len(writer.Body.Bytes()), 131932) + resp := &structs.SidecarsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + require.Equal(t, 1, len(resp.Data)) + sidecar := resp.Data[0] + require.NotNil(t, sidecar) + assert.Equal(t, fmt.Sprintf("%d", limit), sidecar.Index) + assert.Equal(t, hexutil.Encode(blobs[limit].Blob), sidecar.Blob) + assert.Equal(t, hexutil.Encode(blobs[limit].KzgCommitment), sidecar.KzgCommitment) + assert.Equal(t, hexutil.Encode(blobs[limit].KzgProof), sidecar.KzgProof) + + require.Equal(t, version.String(version.Electra), resp.Version) + require.Equal(t, false, resp.ExecutionOptimistic) + require.Equal(t, false, resp.Finalized) + }) + t.Run("blob index over max", func(t *testing.T) { + overLimit := params.BeaconConfig().MaxBlobsPerBlockByVersion(version.Electra) + u := fmt.Sprintf("http://foo.example/123?indices=%d", overLimit) + request := httptest.NewRequest("GET", u, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + s.Blocker = &lookup.BeaconDbBlocker{} + s.Blobs(writer, request) + + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, fmt.Sprintf("requested blob indices [%d] are invalid", overLimit))) }) } @@ -400,7 +541,7 @@ func Test_parseIndices(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := parseIndices(&url.URL{RawQuery: tt.query}) + got, err := parseIndices(&url.URL{RawQuery: tt.query}, 0) if err != nil && tt.wantErr != "" { require.StringContains(t, tt.wantErr, err.Error()) return diff --git a/beacon-chain/rpc/eth/blob/server.go b/beacon-chain/rpc/eth/blob/server.go index 821c53741016..84080982a09e 100644 --- a/beacon-chain/rpc/eth/blob/server.go +++ b/beacon-chain/rpc/eth/blob/server.go @@ -1,9 +1,13 @@ package blob import ( + "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup" ) type Server struct { - Blocker lookup.Blocker + Blocker lookup.Blocker + OptimisticModeFetcher blockchain.OptimisticModeFetcher + FinalizationFetcher blockchain.FinalizationFetcher + TimeFetcher blockchain.TimeFetcher } diff --git a/beacon-chain/rpc/eth/builder/BUILD.bazel b/beacon-chain/rpc/eth/builder/BUILD.bazel index 8d8f8d43f80c..dd0663e2dda0 100644 --- a/beacon-chain/rpc/eth/builder/BUILD.bazel +++ b/beacon-chain/rpc/eth/builder/BUILD.bazel @@ -20,7 +20,6 @@ go_library( "//proto/engine/v1:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", ], ) @@ -44,6 +43,5 @@ go_test( "//testing/util:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", ], ) diff --git a/beacon-chain/rpc/eth/builder/handlers.go b/beacon-chain/rpc/eth/builder/handlers.go index d175d798522b..f6dd1cce0f1a 100644 --- a/beacon-chain/rpc/eth/builder/handlers.go +++ b/beacon-chain/rpc/eth/builder/handlers.go @@ -6,7 +6,6 @@ import ( "strconv" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" @@ -18,10 +17,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/time/slots" ) +// Deprecated: use SSE from events for `payload attributes` instead // ExpectedWithdrawals get the withdrawals computed from the specified state, that will be included in the block that gets built on the specified state. func (s *Server) ExpectedWithdrawals(w http.ResponseWriter, r *http.Request) { // Retrieve beacon state - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.WriteError(w, &httputil.DefaultJsonError{ Message: "state_id is required in URL params", @@ -126,7 +126,7 @@ func buildExpectedWithdrawalsData(withdrawals []*enginev1.Withdrawal) []*structs func handleWrapError(err error, message string, code int) *httputil.DefaultJsonError { return &httputil.DefaultJsonError{ - Message: errors.Wrapf(err, message).Error(), + Message: errors.Wrap(err, message).Error(), Code: code, } } diff --git a/beacon-chain/rpc/eth/builder/handlers_test.go b/beacon-chain/rpc/eth/builder/handlers_test.go index 120a3d3eab05..1a26384f5baa 100644 --- a/beacon-chain/rpc/eth/builder/handlers_test.go +++ b/beacon-chain/rpc/eth/builder/handlers_test.go @@ -9,7 +9,6 @@ import ( "testing" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" mock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/testutil" @@ -91,7 +90,7 @@ func TestExpectedWithdrawals_BadRequest(t *testing.T) { Stater: &testutil.MockStater{BeaconState: testCase.state}, } request := httptest.NewRequest("GET", testCase.path, nil) - request = mux.SetURLVars(request, testCase.urlParams) + request.SetPathValue("state_id", testCase.urlParams["state_id"]) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -172,7 +171,7 @@ func TestExpectedWithdrawals(t *testing.T) { request := httptest.NewRequest( "GET", "/eth/v1/builder/states/{state_id}/expected_withdrawals?proposal_slot="+ strconv.FormatUint(uint64(currentSlot+params.BeaconConfig().SlotsPerEpoch), 10), nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} diff --git a/beacon-chain/rpc/eth/config/BUILD.bazel b/beacon-chain/rpc/eth/config/BUILD.bazel index 92d73dcb8def..cbd920b5dec1 100644 --- a/beacon-chain/rpc/eth/config/BUILD.bazel +++ b/beacon-chain/rpc/eth/config/BUILD.bazel @@ -8,10 +8,10 @@ go_library( deps = [ "//api/server/structs:go_default_library", "//config/params:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/forks:go_default_library", "//network/httputil:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/rpc/eth/config/handlers.go b/beacon-chain/rpc/eth/config/handlers.go index c0a9f769d1d4..b5f103c90222 100644 --- a/beacon-chain/rpc/eth/config/handlers.go +++ b/beacon-chain/rpc/eth/config/handlers.go @@ -10,9 +10,9 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/forks" "github.com/prysmaticlabs/prysm/v5/network/httputil" - "go.opencensus.io/trace" ) // GetDepositContract retrieves deposit contract address and genesis fork version. diff --git a/beacon-chain/rpc/eth/config/handlers_test.go b/beacon-chain/rpc/eth/config/handlers_test.go index 080082e35e6f..6d8e1b826bb9 100644 --- a/beacon-chain/rpc/eth/config/handlers_test.go +++ b/beacon-chain/rpc/eth/config/handlers_test.go @@ -79,6 +79,8 @@ func TestGetSpec(t *testing.T) { config.DenebForkEpoch = 105 config.ElectraForkVersion = []byte("ElectraForkVersion") config.ElectraForkEpoch = 107 + config.FuluForkVersion = []byte("FuluForkVersion") + config.FuluForkEpoch = 109 config.BLSWithdrawalPrefixByte = byte('b') config.ETH1AddressWithdrawalPrefixByte = byte('c') config.GenesisDelay = 24 @@ -138,7 +140,7 @@ func TestGetSpec(t *testing.T) { config.WhistleBlowerRewardQuotientElectra = 79 config.PendingPartialWithdrawalsLimit = 80 config.MinActivationBalance = 81 - config.PendingBalanceDepositLimit = 82 + config.PendingDepositsLimit = 82 config.MaxPendingPartialsPerWithdrawalsSweep = 83 config.PendingConsolidationsLimit = 84 config.MaxPartialWithdrawalsPerPayload = 85 @@ -150,6 +152,14 @@ func TestGetSpec(t *testing.T) { config.MaxCellsInExtendedMatrix = 91 config.UnsetDepositRequestsStartIndex = 92 config.MaxDepositRequestsPerPayload = 93 + config.MaxPendingDepositsPerEpoch = 94 + config.MaxBlobCommitmentsPerBlock = 95 + config.MaxBytesPerTransaction = 96 + config.MaxExtraDataBytes = 97 + config.BytesPerLogsBloom = 98 + config.MaxTransactionsPerPayload = 99 + config.FieldElementsPerBlob = 100 + config.KzgCommitmentInclusionProofDepth = 101 var dbp [4]byte copy(dbp[:], []byte{'0', '0', '0', '1'}) @@ -175,10 +185,6 @@ func TestGetSpec(t *testing.T) { var dam [4]byte copy(dam[:], []byte{'1', '0', '0', '0'}) config.DomainApplicationMask = dam - var dc [4]byte - copy(dc[:], []byte{'1', '1', '0', '0'}) - config.DomainConsolidation = dc - params.OverrideBeaconConfig(config) request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/config/spec", nil) @@ -192,7 +198,7 @@ func TestGetSpec(t *testing.T) { data, ok := resp.Data.(map[string]interface{}) require.Equal(t, true, ok) - assert.Equal(t, 155, len(data)) + assert.Equal(t, 168, len(data)) for k, v := range data { t.Run(k, func(t *testing.T) { switch k { @@ -270,6 +276,10 @@ func TestGetSpec(t *testing.T) { assert.Equal(t, "0x"+hex.EncodeToString([]byte("ElectraForkVersion")), v) case "ELECTRA_FORK_EPOCH": assert.Equal(t, "107", v) + case "FULU_FORK_VERSION": + assert.Equal(t, "0x"+hex.EncodeToString([]byte("FuluForkVersion")), v) + case "FULU_FORK_EPOCH": + assert.Equal(t, "109", v) case "MIN_ANCHOR_POW_BLOCK_DIFFICULTY": assert.Equal(t, "1000", v) case "BLS_WITHDRAWAL_PREFIX": @@ -335,7 +345,7 @@ func TestGetSpec(t *testing.T) { case "MAX_VOLUNTARY_EXITS": assert.Equal(t, "52", v) case "MAX_BLOBS_PER_BLOCK": - assert.Equal(t, "4", v) + assert.Equal(t, "6", v) case "TIMELY_HEAD_FLAG_INDEX": assert.Equal(t, "0x35", v) case "TIMELY_SOURCE_FLAG_INDEX": @@ -434,7 +444,7 @@ func TestGetSpec(t *testing.T) { assert.Equal(t, "76", v) case "REORG_MAX_EPOCHS_SINCE_FINALIZATION": assert.Equal(t, "2", v) - case "REORG_WEIGHT_THRESHOLD": + case "REORG_HEAD_WEIGHT_THRESHOLD": assert.Equal(t, "20", v) case "REORG_PARENT_WEIGHT_THRESHOLD": assert.Equal(t, "160", v) @@ -488,7 +498,7 @@ func TestGetSpec(t *testing.T) { case "MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT": assert.Equal(t, "256000000000", v) case "DATA_COLUMN_SIDECAR_SUBNET_COUNT": - assert.Equal(t, "32", v) + assert.Equal(t, "128", v) case "MAX_REQUEST_DATA_COLUMN_SIDECARS": assert.Equal(t, "16384", v) case "MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA": @@ -503,7 +513,7 @@ func TestGetSpec(t *testing.T) { assert.Equal(t, "80", v) case "MIN_ACTIVATION_BALANCE": assert.Equal(t, "81", v) - case "PENDING_BALANCE_DEPOSITS_LIMIT": + case "PENDING_DEPOSITS_LIMIT": assert.Equal(t, "82", v) case "MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP": assert.Equal(t, "83", v) @@ -515,8 +525,6 @@ func TestGetSpec(t *testing.T) { assert.Equal(t, "86", v) case "MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD": assert.Equal(t, "87", v) - case "DOMAIN_CONSOLIDATION": - assert.Equal(t, "0x31313030", v) case "MAX_ATTESTER_SLASHINGS_ELECTRA": assert.Equal(t, "88", v) case "MAX_ATTESTATIONS_ELECTRA": @@ -529,6 +537,28 @@ func TestGetSpec(t *testing.T) { assert.Equal(t, "92", v) case "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD": assert.Equal(t, "93", v) + case "MAX_PENDING_DEPOSITS_PER_EPOCH": + assert.Equal(t, "94", v) + case "TARGET_BLOBS_PER_BLOCK_ELECTRA": + assert.Equal(t, "6", v) + case "MAX_BLOBS_PER_BLOCK_ELECTRA": + assert.Equal(t, "9", v) + case "MAX_REQUEST_BLOB_SIDECARS_ELECTRA": + assert.Equal(t, "1152", v) + case "MAX_BLOB_COMMITMENTS_PER_BLOCK": + assert.Equal(t, "95", v) + case "MAX_BYTES_PER_TRANSACTION": + assert.Equal(t, "96", v) + case "MAX_EXTRA_DATA_BYTES": + assert.Equal(t, "97", v) + case "BYTES_PER_LOGS_BLOOM": + assert.Equal(t, "98", v) + case "MAX_TRANSACTIONS_PER_PAYLOAD": + assert.Equal(t, "99", v) + case "FIELD_ELEMENTS_PER_BLOB": + assert.Equal(t, "100", v) + case "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH": + assert.Equal(t, "101", v) default: t.Errorf("Incorrect key: %s", k) } diff --git a/beacon-chain/rpc/eth/debug/BUILD.bazel b/beacon-chain/rpc/eth/debug/BUILD.bazel index 4ec4ce801693..87b922c9bd29 100644 --- a/beacon-chain/rpc/eth/debug/BUILD.bazel +++ b/beacon-chain/rpc/eth/debug/BUILD.bazel @@ -16,11 +16,10 @@ go_library( "//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/eth/shared:go_default_library", "//beacon-chain/rpc/lookup:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//runtime/version:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -42,6 +41,5 @@ go_test( "//testing/require:go_default_library", "//testing/util:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", ], ) diff --git a/beacon-chain/rpc/eth/debug/handlers.go b/beacon-chain/rpc/eth/debug/handlers.go index 49741eb67439..f50acec64106 100644 --- a/beacon-chain/rpc/eth/debug/handlers.go +++ b/beacon-chain/rpc/eth/debug/handlers.go @@ -7,14 +7,13 @@ import ( "net/http" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" ) const errMsgStateFromConsensus = "Could not convert consensus state to response" @@ -24,7 +23,7 @@ func (s *Server) GetBeaconStateV2(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "debug.GetBeaconStateV2") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return @@ -89,6 +88,18 @@ func (s *Server) getBeaconStateV2(ctx context.Context, w http.ResponseWriter, id httputil.HandleError(w, errMsgStateFromConsensus+": "+err.Error(), http.StatusInternalServerError) return } + case version.Electra: + respSt, err = structs.BeaconStateElectraFromConsensus(st) + if err != nil { + httputil.HandleError(w, errMsgStateFromConsensus+": "+err.Error(), http.StatusInternalServerError) + return + } + case version.Fulu: + respSt, err = structs.BeaconStateFuluFromConsensus(st) + if err != nil { + httputil.HandleError(w, errMsgStateFromConsensus+": "+err.Error(), http.StatusInternalServerError) + return + } default: httputil.HandleError(w, "Unsupported state version", http.StatusInternalServerError) return diff --git a/beacon-chain/rpc/eth/debug/handlers_test.go b/beacon-chain/rpc/eth/debug/handlers_test.go index eee70e3e9994..e501247f8f6f 100644 --- a/beacon-chain/rpc/eth/debug/handlers_test.go +++ b/beacon-chain/rpc/eth/debug/handlers_test.go @@ -9,7 +9,6 @@ import ( "testing" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" blockchainmock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" @@ -43,7 +42,7 @@ func TestGetBeaconStateV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -71,7 +70,7 @@ func TestGetBeaconStateV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -99,7 +98,7 @@ func TestGetBeaconStateV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -127,7 +126,7 @@ func TestGetBeaconStateV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -155,7 +154,7 @@ func TestGetBeaconStateV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -168,6 +167,62 @@ func TestGetBeaconStateV2(t *testing.T) { require.NoError(t, json.Unmarshal(resp.Data, st)) assert.Equal(t, "123", st.Slot) }) + t.Run("Electra", func(t *testing.T) { + fakeState, err := util.NewBeaconStateElectra() + require.NoError(t, err) + require.NoError(t, fakeState.SetSlot(123)) + chainService := &blockchainmock.ChainService{} + s := &Server{ + Stater: &testutil.MockStater{ + BeaconState: fakeState, + }, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + FinalizationFetcher: chainService, + } + + request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) + request.SetPathValue("state_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBeaconStateV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBeaconStateV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, version.String(version.Electra), resp.Version) + st := &structs.BeaconStateElectra{} + require.NoError(t, json.Unmarshal(resp.Data, st)) + assert.Equal(t, "123", st.Slot) + }) + t.Run("Fulu", func(t *testing.T) { + fakeState, err := util.NewBeaconStateFulu() + require.NoError(t, err) + require.NoError(t, fakeState.SetSlot(123)) + chainService := &blockchainmock.ChainService{} + s := &Server{ + Stater: &testutil.MockStater{ + BeaconState: fakeState, + }, + HeadFetcher: chainService, + OptimisticModeFetcher: chainService, + FinalizationFetcher: chainService, + } + + request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) + request.SetPathValue("state_id", "head") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetBeaconStateV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.GetBeaconStateV2Response{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, version.String(version.Fulu), resp.Version) + st := &structs.BeaconStateElectra{} + require.NoError(t, json.Unmarshal(resp.Data, st)) + assert.Equal(t, "123", st.Slot) + }) t.Run("execution optimistic", func(t *testing.T) { parentRoot := [32]byte{'a'} blk := util.NewBeaconBlock() @@ -191,7 +246,7 @@ func TestGetBeaconStateV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -230,7 +285,7 @@ func TestGetBeaconStateV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -255,7 +310,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -279,7 +334,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -303,7 +358,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -327,7 +382,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -351,7 +406,7 @@ func TestGetBeaconStateSSZV2(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v2/debug/beacon/states/{state_id}", nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} diff --git a/beacon-chain/rpc/eth/events/BUILD.bazel b/beacon-chain/rpc/eth/events/BUILD.bazel index 37d627b50820..9bbea34e1c06 100644 --- a/beacon-chain/rpc/eth/events/BUILD.bazel +++ b/beacon-chain/rpc/eth/events/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "events.go", + "log.go", "server.go", ], importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/events", @@ -18,23 +19,31 @@ go_library( "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/time:go_default_library", - "//beacon-chain/core/transition:go_default_library", "//config/params:go_default_library", + "//consensus-types/interfaces:go_default_library", + "//consensus-types/payload-attribute:go_default_library", + "//consensus-types/primitives:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", + "//proto/engine/v1:go_default_library", "//proto/eth/v1:go_default_library", - "//proto/eth/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@com_github_prometheus_client_golang//prometheus:go_default_library", + "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", ], ) go_test( name = "go_default_test", - srcs = ["events_test.go"], + srcs = [ + "events_test.go", + "http_test.go", + ], embed = [":go_default_library"], deps = [ "//beacon-chain/blockchain/testing:go_default_library", @@ -44,14 +53,17 @@ go_test( "//beacon-chain/core/feed/state:go_default_library", "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", + "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", + "//consensus-types/payload-attribute:go_default_library", "//consensus-types/primitives:go_default_library", "//proto/eth/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", + "@com_github_r3labs_sse_v2//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", ], ) diff --git a/beacon-chain/rpc/eth/events/events.go b/beacon-chain/rpc/eth/events/events.go index c4782f8c14b3..b1ba8e2f1702 100644 --- a/beacon-chain/rpc/eth/events/events.go +++ b/beacon-chain/rpc/eth/events/events.go @@ -1,40 +1,52 @@ package events import ( + "bytes" "context" "encoding/json" "fmt" + "io" "net/http" - time2 "time" + "strconv" + "time" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" + chaintime "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" + engine "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) +const DefaultEventFeedDepth = 1000 +const payloadAttributeTimeout = 2 * time.Second + const ( + InvalidTopic = "__invalid__" // HeadTopic represents a new chain head event topic. HeadTopic = "head" // BlockTopic represents a new produced block event topic. BlockTopic = "block" // AttestationTopic represents a new submitted attestation event topic. AttestationTopic = "attestation" + // SingleAttestationTopic represents a new submitted single attestation event topic. + SingleAttestationTopic = "single_attestation" // VoluntaryExitTopic represents a new performed voluntary exit event topic. VoluntaryExitTopic = "voluntary_exit" // FinalizedCheckpointTopic represents a new finalized checkpoint event topic. @@ -59,25 +71,86 @@ const ( LightClientOptimisticUpdateTopic = "light_client_optimistic_update" ) -const topicDataMismatch = "Event data type %T does not correspond to event topic %s" - -const chanBuffer = 1000 - -var casesHandled = map[string]bool{ - HeadTopic: true, - BlockTopic: true, - AttestationTopic: true, - VoluntaryExitTopic: true, - FinalizedCheckpointTopic: true, - ChainReorgTopic: true, - SyncCommitteeContributionTopic: true, - BLSToExecutionChangeTopic: true, - PayloadAttributesTopic: true, - BlobSidecarTopic: true, - ProposerSlashingTopic: true, - AttesterSlashingTopic: true, - LightClientFinalityUpdateTopic: true, - LightClientOptimisticUpdateTopic: true, +var ( + errInvalidTopicName = errors.New("invalid topic name") + errNoValidTopics = errors.New("no valid topics specified") + errSlowReader = errors.New("client failed to read fast enough to keep outgoing buffer below threshold") + errNotRequested = errors.New("event not requested by client") + errUnhandledEventData = errors.New("unable to represent event data in the event stream") + errWriterUnusable = errors.New("http response writer is unusable") +) + +var httpSSEErrorCount = promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "http_sse_error_count", + Help: "Total HTTP errors for server sent events endpoint", + }, + []string{"endpoint", "error"}, +) + +// The eventStreamer uses lazyReaders to defer serialization until the moment the value is ready to be written to the client. +type lazyReader func() io.Reader + +var opsFeedEventTopics = map[feed.EventType]string{ + operation.AggregatedAttReceived: AttestationTopic, + operation.UnaggregatedAttReceived: AttestationTopic, + operation.SingleAttReceived: SingleAttestationTopic, + operation.ExitReceived: VoluntaryExitTopic, + operation.SyncCommitteeContributionReceived: SyncCommitteeContributionTopic, + operation.BLSToExecutionChangeReceived: BLSToExecutionChangeTopic, + operation.BlobSidecarReceived: BlobSidecarTopic, + operation.AttesterSlashingReceived: AttesterSlashingTopic, + operation.ProposerSlashingReceived: ProposerSlashingTopic, +} + +var stateFeedEventTopics = map[feed.EventType]string{ + statefeed.NewHead: HeadTopic, + statefeed.FinalizedCheckpoint: FinalizedCheckpointTopic, + statefeed.LightClientFinalityUpdate: LightClientFinalityUpdateTopic, + statefeed.LightClientOptimisticUpdate: LightClientOptimisticUpdateTopic, + statefeed.Reorg: ChainReorgTopic, + statefeed.BlockProcessed: BlockTopic, + statefeed.PayloadAttributes: PayloadAttributesTopic, +} + +var topicsForStateFeed = topicsForFeed(stateFeedEventTopics) +var topicsForOpsFeed = topicsForFeed(opsFeedEventTopics) + +func topicsForFeed(em map[feed.EventType]string) map[string]bool { + topics := make(map[string]bool, len(em)) + for _, topic := range em { + topics[topic] = true + } + return topics +} + +type topicRequest struct { + topics map[string]bool + needStateFeed bool + needOpsFeed bool +} + +func (req *topicRequest) requested(topic string) bool { + return req.topics[topic] +} + +func newTopicRequest(topics []string) (*topicRequest, error) { + req := &topicRequest{topics: make(map[string]bool)} + for _, name := range topics { + if topicsForStateFeed[name] { + req.needStateFeed = true + } else if topicsForOpsFeed[name] { + req.needOpsFeed = true + } else { + return nil, errors.Wrap(errInvalidTopicName, name) + } + req.topics[name] = true + } + if len(req.topics) == 0 || (!req.needStateFeed && !req.needOpsFeed) { + return nil, errNoValidTopics + } + + return req, nil } // StreamEvents provides an endpoint to subscribe to the beacon node Server-Sent-Events stream. @@ -85,443 +158,686 @@ var casesHandled = map[string]bool{ // Servers may send SSE comments beginning with ':' for any purpose, // including to keep the event stream connection alive in the presence of proxy servers. func (s *Server) StreamEvents(w http.ResponseWriter, r *http.Request) { + var err error + defer func() { + if err != nil { + httpSSEErrorCount.WithLabelValues(r.URL.Path, err.Error()).Inc() + } + }() + + log.Debug("Starting StreamEvents handler") ctx, span := trace.StartSpan(r.Context(), "events.StreamEvents") defer span.End() - flusher, ok := w.(http.Flusher) - if !ok { - httputil.HandleError(w, "Streaming unsupported!", http.StatusInternalServerError) + topics, err := newTopicRequest(r.URL.Query()["topics"]) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusBadRequest) return } - topics := r.URL.Query()["topics"] - if len(topics) == 0 { - httputil.HandleError(w, "No topics specified to subscribe to", http.StatusBadRequest) - return + timeout := s.EventWriteTimeout + if timeout == 0 { + timeout = time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second } - topicsMap := make(map[string]bool) - for _, topic := range topics { - if _, ok := casesHandled[topic]; !ok { - httputil.HandleError(w, fmt.Sprintf("Invalid topic: %s", topic), http.StatusBadRequest) - return + ka := s.KeepAliveInterval + if ka == 0 { + ka = timeout + } + buffSize := s.EventFeedDepth + if buffSize == 0 { + buffSize = DefaultEventFeedDepth + } + + api.SetSSEHeaders(w) + sw := newStreamingResponseController(w, timeout) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + es := newEventStreamer(buffSize, ka) + + go es.outboxWriteLoop(ctx, cancel, sw, r.URL.Path) + if err := es.recvEventLoop(ctx, cancel, topics, s); err != nil { + log.WithError(err).Debug("Shutting down StreamEvents handler.") + } + cleanupStart := time.Now() + es.waitForExit() + log.WithField("cleanup_wait", time.Since(cleanupStart)).Debug("streamEvents shutdown complete") +} + +func newEventStreamer(buffSize int, ka time.Duration) *eventStreamer { + return &eventStreamer{ + outbox: make(chan lazyReader, buffSize), + keepAlive: ka, + openUntilExit: make(chan struct{}), + } +} + +type eventStreamer struct { + outbox chan lazyReader + keepAlive time.Duration + openUntilExit chan struct{} +} + +func (es *eventStreamer) recvEventLoop(ctx context.Context, cancel context.CancelFunc, req *topicRequest, s *Server) error { + defer close(es.outbox) + defer cancel() + eventsChan := make(chan *feed.Event, len(es.outbox)) + if req.needOpsFeed { + opsSub := s.OperationNotifier.OperationFeed().Subscribe(eventsChan) + defer opsSub.Unsubscribe() + } + if req.needStateFeed { + stateSub := s.StateNotifier.StateFeed().Subscribe(eventsChan) + defer stateSub.Unsubscribe() + } + for { + select { + case <-ctx.Done(): + return ctx.Err() + case event := <-eventsChan: + lr, err := s.lazyReaderForEvent(ctx, event, req) + if err != nil { + if !errors.Is(err, errNotRequested) { + log.WithField("event_type", fmt.Sprintf("%v", event.Data)).WithError(err).Error("StreamEvents API endpoint received an event it was unable to handle.") + } + continue + } + // If the client can't keep up, the outbox will eventually completely fill, at which + // safeWrite will error, and we'll hit the below return statement, at which point the deferred + // Unsuscribe calls will be made and the event feed will stop writing to this channel. + // Since the outbox and event stream channels are separately buffered, the event subscription + // channel should stay relatively empty, which gives this loop time to unsubscribe + // and cleanup before the event stream channel fills and disrupts other readers. + if err := es.safeWrite(ctx, lr); err != nil { + // note: we could hijack the connection and close it here. Does that cause issues? What are the benefits? + // A benefit of hijack and close is that it may force an error on the remote end, however just closing the context of the + // http handler may be sufficient to cause the remote http response reader to close. + if errors.Is(err, errSlowReader) { + log.WithError(err).Warn("Client is unable to keep up with event stream, shutting down.") + } + return err + } } - topicsMap[topic] = true - } - - // Subscribe to event feeds from information received in the beacon node runtime. - opsChan := make(chan *feed.Event, chanBuffer) - opsSub := s.OperationNotifier.OperationFeed().Subscribe(opsChan) - stateChan := make(chan *feed.Event, chanBuffer) - stateSub := s.StateNotifier.StateFeed().Subscribe(stateChan) - defer opsSub.Unsubscribe() - defer stateSub.Unsubscribe() - - // Set up SSE response headers - w.Header().Set("Content-Type", api.EventStreamMediaType) - w.Header().Set("Connection", api.KeepAlive) - - // Handle each event received and context cancellation. - // We send a keepalive dummy message immediately to prevent clients - // stalling while waiting for the first response chunk. - // After that we send a keepalive dummy message every SECONDS_PER_SLOT - // to prevent anyone (e.g. proxy servers) from closing connections. - if err := sendKeepalive(w, flusher); err != nil { - httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + } +} + +func (es *eventStreamer) safeWrite(ctx context.Context, rf func() io.Reader) error { + if rf == nil { + return nil + } + select { + case <-ctx.Done(): + return ctx.Err() + case es.outbox <- rf: + return nil + default: + // If this is the case, the select case to write to the outbox could not proceed, meaning the outbox is full. + // If a reader can't keep up with the stream, we shut them down. + return errSlowReader + } +} + +// newlineReader is used to write keep-alives to the client. +// keep-alives in the sse protocol are a single ':' colon followed by 2 newlines. +func newlineReader() io.Reader { + return bytes.NewBufferString(":\n\n") +} + +// outboxWriteLoop runs in a separate goroutine. Its job is to write the values in the outbox to +// the client as fast as the client can read them. +func (es *eventStreamer) outboxWriteLoop(ctx context.Context, cancel context.CancelFunc, w *streamingResponseWriterController, endpoint string) { + var err error + defer func() { + if err != nil { + log.WithError(err).Debug("Event streamer shutting down due to error.") + httpSSEErrorCount.WithLabelValues(endpoint, err.Error()).Inc() + } + es.exit() + }() + defer cancel() + // Write a keepalive at the start to test the connection and simplify test setup. + if err = es.writeOutbox(ctx, w, nil); err != nil { return } - keepaliveTicker := time2.NewTicker(time2.Duration(params.BeaconConfig().SecondsPerSlot) * time2.Second) + kaT := time.NewTimer(es.keepAlive) + // Ensure the keepalive timer is stopped and drained if it has fired. + defer func() { + if !kaT.Stop() { + <-kaT.C + } + }() for { select { - case event := <-opsChan: - if err := handleBlockOperationEvents(w, flusher, topicsMap, event); err != nil { - httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + case <-ctx.Done(): + err = ctx.Err() + return + case <-kaT.C: + if err = es.writeOutbox(ctx, w, nil); err != nil { return } - case event := <-stateChan: - if err := s.handleStateEvents(ctx, w, flusher, topicsMap, event); err != nil { - httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + // In this case the timer doesn't need to be Stopped before the Reset call after the select statement, + // because the timer has already fired. + case lr := <-es.outbox: + if err = es.writeOutbox(ctx, w, lr); err != nil { return } - case <-keepaliveTicker.C: - if err := sendKeepalive(w, flusher); err != nil { - httputil.HandleError(w, err.Error(), http.StatusInternalServerError) - return + // We don't know if the timer fired concurrently to this case being ready, so we need to check the return + // of Stop and drain the timer channel if it fired. We won't need to do this in go 1.23. + if !kaT.Stop() { + <-kaT.C } - case <-ctx.Done(): - return } + kaT.Reset(es.keepAlive) } } -func handleBlockOperationEvents(w http.ResponseWriter, flusher http.Flusher, requestedTopics map[string]bool, event *feed.Event) error { - switch event.Type { - case operation.AggregatedAttReceived: - if _, ok := requestedTopics[AttestationTopic]; !ok { - return nil - } - attData, ok := event.Data.(*operation.AggregatedAttReceivedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, AttestationTopic) - } - att := structs.AttFromConsensus(attData.Attestation.Aggregate) - return send(w, flusher, AttestationTopic, att) - case operation.UnaggregatedAttReceived: - if _, ok := requestedTopics[AttestationTopic]; !ok { - return nil - } - attData, ok := event.Data.(*operation.UnAggregatedAttReceivedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, AttestationTopic) - } - a, ok := attData.Attestation.(*eth.Attestation) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, AttestationTopic) - } - att := structs.AttFromConsensus(a) - return send(w, flusher, AttestationTopic, att) - case operation.ExitReceived: - if _, ok := requestedTopics[VoluntaryExitTopic]; !ok { - return nil - } - exitData, ok := event.Data.(*operation.ExitReceivedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, VoluntaryExitTopic) - } - exit := structs.SignedExitFromConsensus(exitData.Exit) - return send(w, flusher, VoluntaryExitTopic, exit) - case operation.SyncCommitteeContributionReceived: - if _, ok := requestedTopics[SyncCommitteeContributionTopic]; !ok { - return nil - } - contributionData, ok := event.Data.(*operation.SyncCommitteeContributionReceivedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, SyncCommitteeContributionTopic) - } - contribution := structs.SignedContributionAndProofFromConsensus(contributionData.Contribution) - return send(w, flusher, SyncCommitteeContributionTopic, contribution) - case operation.BLSToExecutionChangeReceived: - if _, ok := requestedTopics[BLSToExecutionChangeTopic]; !ok { - return nil - } - changeData, ok := event.Data.(*operation.BLSToExecutionChangeReceivedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, BLSToExecutionChangeTopic) - } - return send(w, flusher, BLSToExecutionChangeTopic, structs.SignedBLSChangeFromConsensus(changeData.Change)) - case operation.BlobSidecarReceived: - if _, ok := requestedTopics[BlobSidecarTopic]; !ok { - return nil - } - blobData, ok := event.Data.(*operation.BlobSidecarReceivedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, BlobSidecarTopic) - } - versionedHash := blockchain.ConvertKzgCommitmentToVersionedHash(blobData.Blob.KzgCommitment) - blobEvent := &structs.BlobSidecarEvent{ - BlockRoot: hexutil.Encode(blobData.Blob.BlockRootSlice()), - Index: fmt.Sprintf("%d", blobData.Blob.Index), - Slot: fmt.Sprintf("%d", blobData.Blob.Slot()), - VersionedHash: versionedHash.String(), - KzgCommitment: hexutil.Encode(blobData.Blob.KzgCommitment), - } - return send(w, flusher, BlobSidecarTopic, blobEvent) - case operation.AttesterSlashingReceived: - if _, ok := requestedTopics[AttesterSlashingTopic]; !ok { - return nil - } - attesterSlashingData, ok := event.Data.(*operation.AttesterSlashingReceivedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, AttesterSlashingTopic) - } - slashing, ok := attesterSlashingData.AttesterSlashing.(*eth.AttesterSlashing) - if ok { - return send(w, flusher, AttesterSlashingTopic, structs.AttesterSlashingFromConsensus(slashing)) - } - // TODO: extend to Electra - case operation.ProposerSlashingReceived: - if _, ok := requestedTopics[ProposerSlashingTopic]; !ok { - return nil - } - proposerSlashingData, ok := event.Data.(*operation.ProposerSlashingReceivedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, ProposerSlashingTopic) - } - return send(w, flusher, ProposerSlashingTopic, structs.ProposerSlashingFromConsensus(proposerSlashingData.ProposerSlashing)) +func (es *eventStreamer) exit() { + drained := 0 + for range es.outbox { + drained += 1 + } + log.WithField("undelivered_events", drained).Debug("Event stream outbox drained.") + close(es.openUntilExit) +} + +// waitForExit blocks until the outboxWriteLoop has exited. +// While this function blocks, it is not yet safe to exit the http handler, +// because the outboxWriteLoop may still be writing to the http ResponseWriter. +func (es *eventStreamer) waitForExit() { + <-es.openUntilExit +} + +func writeLazyReaderWithRecover(w *streamingResponseWriterController, lr lazyReader) (err error) { + defer func() { + if r := recover(); r != nil { + log.WithField("panic", r).Error("Recovered from panic while writing event to client.") + err = errWriterUnusable + } + }() + r := lr() + out, err := io.ReadAll(r) + if err != nil { + return err } - return nil + _, err = w.Write(out) + return err } -func (s *Server) handleStateEvents(ctx context.Context, w http.ResponseWriter, flusher http.Flusher, requestedTopics map[string]bool, event *feed.Event) error { - switch event.Type { - case statefeed.NewHead: - if _, ok := requestedTopics[HeadTopic]; ok { - headData, ok := event.Data.(*ethpb.EventHead) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, HeadTopic) +func (es *eventStreamer) writeOutbox(ctx context.Context, w *streamingResponseWriterController, first lazyReader) error { + // The outboxWriteLoop is responsible for managing the keep-alive timer and toggling between reading from the outbox + // when it is ready, only allowing the keep-alive to fire when there hasn't been a write in the keep-alive interval. + // Since outboxWriteLoop will get either the first event or the keep-alive, we let it pass in the first event to write, + // either the event's lazyReader, or nil for a keep-alive. + needKeepAlive := true + if first != nil { + if err := writeLazyReaderWithRecover(w, first); err != nil { + return err + } + needKeepAlive = false + } + // While the first event was being read by the client, further events may be queued in the outbox. + // We can drain them right away rather than go back out to the outer select statement, where the keepAlive timer + // may have fired, triggering an unnecessary extra keep-alive write and flush. + for { + select { + case <-ctx.Done(): + return ctx.Err() + case rf := <-es.outbox: + // We don't want to call Flush until we've exhausted all the writes - it's always preferable to + // just keep draining the outbox and rely on the underlying Write code to flush+block when it + // needs to based on buffering. Whenever we fill the buffer with a string of writes, the underlying + // code will flush on its own, so it's better to explicitly flush only once, after we've totally + // drained the outbox, to catch any dangling bytes stuck in a buffer. + if err := writeLazyReaderWithRecover(w, rf); err != nil { + return err } - head := &structs.HeadEvent{ - Slot: fmt.Sprintf("%d", headData.Slot), - Block: hexutil.Encode(headData.Block), - State: hexutil.Encode(headData.State), - EpochTransition: headData.EpochTransition, - ExecutionOptimistic: headData.ExecutionOptimistic, - PreviousDutyDependentRoot: hexutil.Encode(headData.PreviousDutyDependentRoot), - CurrentDutyDependentRoot: hexutil.Encode(headData.CurrentDutyDependentRoot), + needKeepAlive = false + default: + if needKeepAlive { + if err := writeLazyReaderWithRecover(w, newlineReader); err != nil { + return err + } } - return send(w, flusher, HeadTopic, head) - } - if _, ok := requestedTopics[PayloadAttributesTopic]; ok { - return s.sendPayloadAttributes(ctx, w, flusher) - } - case statefeed.MissedSlot: - if _, ok := requestedTopics[PayloadAttributesTopic]; ok { - return s.sendPayloadAttributes(ctx, w, flusher) - } - case statefeed.FinalizedCheckpoint: - if _, ok := requestedTopics[FinalizedCheckpointTopic]; !ok { - return nil - } - checkpointData, ok := event.Data.(*ethpb.EventFinalizedCheckpoint) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, FinalizedCheckpointTopic) - } - checkpoint := &structs.FinalizedCheckpointEvent{ - Block: hexutil.Encode(checkpointData.Block), - State: hexutil.Encode(checkpointData.State), - Epoch: fmt.Sprintf("%d", checkpointData.Epoch), - ExecutionOptimistic: checkpointData.ExecutionOptimistic, - } - return send(w, flusher, FinalizedCheckpointTopic, checkpoint) - case statefeed.LightClientFinalityUpdate: - if _, ok := requestedTopics[LightClientFinalityUpdateTopic]; !ok { - return nil - } - updateData, ok := event.Data.(*ethpbv2.LightClientFinalityUpdateWithVersion) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, LightClientFinalityUpdateTopic) + return w.Flush() } + } +} - var finalityBranch []string - for _, b := range updateData.Data.FinalityBranch { - finalityBranch = append(finalityBranch, hexutil.Encode(b)) - } - update := &structs.LightClientFinalityUpdateEvent{ - Version: version.String(int(updateData.Version)), - Data: &structs.LightClientFinalityUpdate{ - AttestedHeader: &structs.BeaconBlockHeader{ - Slot: fmt.Sprintf("%d", updateData.Data.AttestedHeader.Slot), - ProposerIndex: fmt.Sprintf("%d", updateData.Data.AttestedHeader.ProposerIndex), - ParentRoot: hexutil.Encode(updateData.Data.AttestedHeader.ParentRoot), - StateRoot: hexutil.Encode(updateData.Data.AttestedHeader.StateRoot), - BodyRoot: hexutil.Encode(updateData.Data.AttestedHeader.BodyRoot), - }, - FinalizedHeader: &structs.BeaconBlockHeader{ - Slot: fmt.Sprintf("%d", updateData.Data.FinalizedHeader.Slot), - ProposerIndex: fmt.Sprintf("%d", updateData.Data.FinalizedHeader.ProposerIndex), - ParentRoot: hexutil.Encode(updateData.Data.FinalizedHeader.ParentRoot), - StateRoot: hexutil.Encode(updateData.Data.FinalizedHeader.StateRoot), - }, - FinalityBranch: finalityBranch, - SyncAggregate: &structs.SyncAggregate{ - SyncCommitteeBits: hexutil.Encode(updateData.Data.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: hexutil.Encode(updateData.Data.SyncAggregate.SyncCommitteeSignature), - }, - SignatureSlot: fmt.Sprintf("%d", updateData.Data.SignatureSlot), - }, - } - return send(w, flusher, LightClientFinalityUpdateTopic, update) - case statefeed.LightClientOptimisticUpdate: - if _, ok := requestedTopics[LightClientOptimisticUpdateTopic]; !ok { - return nil - } - updateData, ok := event.Data.(*ethpbv2.LightClientOptimisticUpdateWithVersion) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, LightClientOptimisticUpdateTopic) - } - update := &structs.LightClientOptimisticUpdateEvent{ - Version: version.String(int(updateData.Version)), - Data: &structs.LightClientOptimisticUpdate{ - AttestedHeader: &structs.BeaconBlockHeader{ - Slot: fmt.Sprintf("%d", updateData.Data.AttestedHeader.Slot), - ProposerIndex: fmt.Sprintf("%d", updateData.Data.AttestedHeader.ProposerIndex), - ParentRoot: hexutil.Encode(updateData.Data.AttestedHeader.ParentRoot), - StateRoot: hexutil.Encode(updateData.Data.AttestedHeader.StateRoot), - BodyRoot: hexutil.Encode(updateData.Data.AttestedHeader.BodyRoot), - }, - SyncAggregate: &structs.SyncAggregate{ - SyncCommitteeBits: hexutil.Encode(updateData.Data.SyncAggregate.SyncCommitteeBits), - SyncCommitteeSignature: hexutil.Encode(updateData.Data.SyncAggregate.SyncCommitteeSignature), - }, - SignatureSlot: fmt.Sprintf("%d", updateData.Data.SignatureSlot), - }, - } - return send(w, flusher, LightClientOptimisticUpdateTopic, update) - case statefeed.Reorg: - if _, ok := requestedTopics[ChainReorgTopic]; !ok { - return nil - } - reorgData, ok := event.Data.(*ethpb.EventChainReorg) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, ChainReorgTopic) - } - reorg := &structs.ChainReorgEvent{ - Slot: fmt.Sprintf("%d", reorgData.Slot), - Depth: fmt.Sprintf("%d", reorgData.Depth), - OldHeadBlock: hexutil.Encode(reorgData.OldHeadBlock), - NewHeadBlock: hexutil.Encode(reorgData.NewHeadBlock), - OldHeadState: hexutil.Encode(reorgData.OldHeadState), - NewHeadState: hexutil.Encode(reorgData.NewHeadState), - Epoch: fmt.Sprintf("%d", reorgData.Epoch), - ExecutionOptimistic: reorgData.ExecutionOptimistic, - } - return send(w, flusher, ChainReorgTopic, reorg) - case statefeed.BlockProcessed: - if _, ok := requestedTopics[BlockTopic]; !ok { - return nil +func jsonMarshalReader(name string, v any) io.Reader { + d, err := json.Marshal(v) + if err != nil { + log.WithError(err).WithField("type_name", fmt.Sprintf("%T", v)).Error("Could not marshal event data") + return nil + } + return bytes.NewBufferString("event: " + name + "\ndata: " + string(d) + "\n\n") +} + +func topicForEvent(event *feed.Event) string { + switch event.Data.(type) { + case *operation.AggregatedAttReceivedData: + return AttestationTopic + case *operation.UnAggregatedAttReceivedData: + return AttestationTopic + case *operation.SingleAttReceivedData: + return SingleAttestationTopic + case *operation.ExitReceivedData: + return VoluntaryExitTopic + case *operation.SyncCommitteeContributionReceivedData: + return SyncCommitteeContributionTopic + case *operation.BLSToExecutionChangeReceivedData: + return BLSToExecutionChangeTopic + case *operation.BlobSidecarReceivedData: + return BlobSidecarTopic + case *operation.AttesterSlashingReceivedData: + return AttesterSlashingTopic + case *operation.ProposerSlashingReceivedData: + return ProposerSlashingTopic + case *ethpb.EventHead: + return HeadTopic + case *ethpb.EventFinalizedCheckpoint: + return FinalizedCheckpointTopic + case interfaces.LightClientFinalityUpdate: + return LightClientFinalityUpdateTopic + case interfaces.LightClientOptimisticUpdate: + return LightClientOptimisticUpdateTopic + case *ethpb.EventChainReorg: + return ChainReorgTopic + case *statefeed.BlockProcessedData: + return BlockTopic + case payloadattribute.EventData: + return PayloadAttributesTopic + default: + return InvalidTopic + } +} + +func (s *Server) lazyReaderForEvent(ctx context.Context, event *feed.Event, topics *topicRequest) (lazyReader, error) { + eventName := topicForEvent(event) + if !topics.requested(eventName) { + return nil, errNotRequested + } + if event == nil || event.Data == nil { + return nil, errors.New("event or event data is nil") + } + switch v := event.Data.(type) { + case payloadattribute.EventData: + return s.payloadAttributesReader(ctx, v) + case *ethpb.EventHead: + // The head event is a special case because, if the client requested the payload attributes topic, + // we send two event messages in reaction; the head event and the payload attributes. + return func() io.Reader { + return jsonMarshalReader(eventName, structs.HeadEventFromV1(v)) + }, nil + case *operation.AggregatedAttReceivedData: + switch att := v.Attestation.AggregateVal().(type) { + case *eth.Attestation: + return func() io.Reader { + att := structs.AttFromConsensus(att) + return jsonMarshalReader(eventName, att) + }, nil + case *eth.AttestationElectra: + return func() io.Reader { + att := structs.AttElectraFromConsensus(att) + return jsonMarshalReader(eventName, att) + }, nil + default: + return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .Attestation field of AggregatedAttReceivedData", v.Attestation) + } + case *operation.UnAggregatedAttReceivedData: + switch att := v.Attestation.(type) { + case *eth.Attestation: + return func() io.Reader { + att := structs.AttFromConsensus(att) + return jsonMarshalReader(eventName, att) + }, nil + case *eth.AttestationElectra: + return func() io.Reader { + att := structs.AttElectraFromConsensus(att) + return jsonMarshalReader(eventName, att) + }, nil + default: + return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .Attestation field of UnAggregatedAttReceivedData", v.Attestation) + } + case *operation.SingleAttReceivedData: + switch att := v.Attestation.(type) { + case *eth.SingleAttestation: + return func() io.Reader { + att := structs.SingleAttFromConsensus(att) + return jsonMarshalReader(eventName, att) + }, nil + default: + return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .Attestation field of SingleAttReceivedData", v.Attestation) + } + case *operation.ExitReceivedData: + return func() io.Reader { + return jsonMarshalReader(eventName, structs.SignedExitFromConsensus(v.Exit)) + }, nil + case *operation.SyncCommitteeContributionReceivedData: + return func() io.Reader { + return jsonMarshalReader(eventName, structs.SignedContributionAndProofFromConsensus(v.Contribution)) + }, nil + case *operation.BLSToExecutionChangeReceivedData: + return func() io.Reader { + return jsonMarshalReader(eventName, structs.SignedBLSChangeFromConsensus(v.Change)) + }, nil + case *operation.BlobSidecarReceivedData: + return func() io.Reader { + versionedHash := primitives.ConvertKzgCommitmentToVersionedHash(v.Blob.KzgCommitment) + return jsonMarshalReader(eventName, &structs.BlobSidecarEvent{ + BlockRoot: hexutil.Encode(v.Blob.BlockRootSlice()), + Index: fmt.Sprintf("%d", v.Blob.Index), + Slot: fmt.Sprintf("%d", v.Blob.Slot()), + VersionedHash: versionedHash.String(), + KzgCommitment: hexutil.Encode(v.Blob.KzgCommitment), + }) + }, nil + case *operation.AttesterSlashingReceivedData: + switch slashing := v.AttesterSlashing.(type) { + case *eth.AttesterSlashing: + return func() io.Reader { + return jsonMarshalReader(eventName, structs.AttesterSlashingFromConsensus(slashing)) + }, nil + case *eth.AttesterSlashingElectra: + return func() io.Reader { + return jsonMarshalReader(eventName, structs.AttesterSlashingElectraFromConsensus(slashing)) + }, nil + default: + return nil, errors.Wrapf(errUnhandledEventData, "Unexpected type %T for the .AttesterSlashing field of AttesterSlashingReceivedData", v.AttesterSlashing) + } + case *operation.ProposerSlashingReceivedData: + return func() io.Reader { + return jsonMarshalReader(eventName, structs.ProposerSlashingFromConsensus(v.ProposerSlashing)) + }, nil + case *ethpb.EventFinalizedCheckpoint: + return func() io.Reader { + return jsonMarshalReader(eventName, structs.FinalizedCheckpointEventFromV1(v)) + }, nil + case interfaces.LightClientFinalityUpdate: + cv, err := structs.LightClientFinalityUpdateFromConsensus(v) + if err != nil { + return nil, errors.Wrap(err, "LightClientFinalityUpdate conversion failure") } - blkData, ok := event.Data.(*statefeed.BlockProcessedData) - if !ok { - return write(w, flusher, topicDataMismatch, event.Data, BlockTopic) + ev := &structs.LightClientFinalityUpdateEvent{ + Version: version.String(v.Version()), + Data: cv, } - blockRoot, err := blkData.SignedBlock.Block().HashTreeRoot() + return func() io.Reader { + return jsonMarshalReader(eventName, ev) + }, nil + case interfaces.LightClientOptimisticUpdate: + cv, err := structs.LightClientOptimisticUpdateFromConsensus(v) if err != nil { - return write(w, flusher, "Could not get block root: "+err.Error()) - } - blk := &structs.BlockEvent{ - Slot: fmt.Sprintf("%d", blkData.Slot), - Block: hexutil.Encode(blockRoot[:]), - ExecutionOptimistic: blkData.Optimistic, + return nil, errors.Wrap(err, "LightClientOptimisticUpdate conversion failure") + } + ev := &structs.LightClientOptimisticUpdateEvent{ + Version: version.String(v.Version()), + Data: cv, + } + return func() io.Reader { + return jsonMarshalReader(eventName, ev) + }, nil + case *ethpb.EventChainReorg: + return func() io.Reader { + return jsonMarshalReader(eventName, structs.EventChainReorgFromV1(v)) + }, nil + case *statefeed.BlockProcessedData: + blockRoot, err := v.SignedBlock.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not compute block root for BlockProcessedData state feed event") } - return send(w, flusher, BlockTopic, blk) + return func() io.Reader { + blk := &structs.BlockEvent{ + Slot: fmt.Sprintf("%d", v.Slot), + Block: hexutil.Encode(blockRoot[:]), + ExecutionOptimistic: v.Optimistic, + } + return jsonMarshalReader(eventName, blk) + }, nil + default: + return nil, errors.Wrapf(errUnhandledEventData, "event data type %T unsupported", v) } - return nil } -// This event stream is intended to be used by builders and relays. -// Parent fields are based on state at N_{current_slot}, while the rest of fields are based on state of N_{current_slot + 1} -func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWriter, flusher http.Flusher) error { - headRoot, err := s.HeadFetcher.HeadRoot(ctx) - if err != nil { - return write(w, flusher, "Could not get head root: "+err.Error()) +var errUnsupportedPayloadAttribute = errors.New("cannot compute payload attributes pre-Bellatrix") + +func (s *Server) computePayloadAttributes(ctx context.Context, ev payloadattribute.EventData) (payloadattribute.Attributer, error) { + v := ev.HeadState.Version() + if v < version.Bellatrix { + return nil, errors.Wrapf(errUnsupportedPayloadAttribute, "%s is not supported", version.String(v)) } - st, err := s.HeadFetcher.HeadState(ctx) + + t, err := slots.ToTime(ev.HeadState.GenesisTime(), ev.HeadState.Slot()) if err != nil { - return write(w, flusher, "Could not get head state: "+err.Error()) + return nil, errors.Wrap(err, "could not get head state slot time") } - // advance the head state - headState, err := transition.ProcessSlotsIfPossible(ctx, st, s.ChainInfoFetcher.CurrentSlot()+1) + timestamp := uint64(t.Unix()) + prevRando, err := helpers.RandaoMix(ev.HeadState, chaintime.CurrentEpoch(ev.HeadState)) if err != nil { - return write(w, flusher, "Could not advance head state: "+err.Error()) + return nil, errors.Wrap(err, "could not get head state randao mix") } - - headBlock, err := s.HeadFetcher.HeadBlock(ctx) + proposerIndex, err := helpers.BeaconProposerIndex(ctx, ev.HeadState) if err != nil { - return write(w, flusher, "Could not get head block: "+err.Error()) + return nil, errors.Wrap(err, "could not get head state proposer index") } - - headPayload, err := headBlock.Block().Body().Execution() - if err != nil { - return write(w, flusher, "Could not get execution payload: "+err.Error()) + feeRecpt := params.BeaconConfig().DefaultFeeRecipient.Bytes() + tValidator, exists := s.TrackedValidatorsCache.Validator(proposerIndex) + if exists { + feeRecpt = tValidator.FeeRecipient[:] } - t, err := slots.ToTime(headState.GenesisTime(), headState.Slot()) - if err != nil { - return write(w, flusher, "Could not get head state slot time: "+err.Error()) + if v == version.Bellatrix { + return payloadattribute.New(&engine.PayloadAttributes{ + Timestamp: timestamp, + PrevRandao: prevRando, + SuggestedFeeRecipient: feeRecpt, + }) } - prevRando, err := helpers.RandaoMix(headState, time.CurrentEpoch(headState)) + w, _, err := ev.HeadState.ExpectedWithdrawals() if err != nil { - return write(w, flusher, "Could not get head state randao mix: "+err.Error()) + return nil, errors.Wrap(err, "could not get withdrawals from head state") + } + if v == version.Capella { + return payloadattribute.New(&engine.PayloadAttributesV2{ + Timestamp: timestamp, + PrevRandao: prevRando, + SuggestedFeeRecipient: feeRecpt, + Withdrawals: w, + }) } - proposerIndex, err := helpers.BeaconProposerIndex(ctx, headState) + pr, err := ev.HeadBlock.Block().HashTreeRoot() if err != nil { - return write(w, flusher, "Could not get head state proposer index: "+err.Error()) + return nil, errors.Wrap(err, "could not compute head block root") } - feeRecipient := params.BeaconConfig().DefaultFeeRecipient.Bytes() - tValidator, exists := s.TrackedValidatorsCache.Validator(proposerIndex) - if exists { - feeRecipient = tValidator.FeeRecipient[:] - } - var attributes interface{} - switch headState.Version() { - case version.Bellatrix: - attributes = &structs.PayloadAttributesV1{ - Timestamp: fmt.Sprintf("%d", t.Unix()), - PrevRandao: hexutil.Encode(prevRando), - SuggestedFeeRecipient: hexutil.Encode(feeRecipient), + return payloadattribute.New(&engine.PayloadAttributesV3{ + Timestamp: timestamp, + PrevRandao: prevRando, + SuggestedFeeRecipient: feeRecpt, + Withdrawals: w, + ParentBeaconBlockRoot: pr[:], + }) +} + +type asyncPayloadAttrData struct { + data json.RawMessage + version string + err error +} + +func (s *Server) fillEventData(ctx context.Context, ev payloadattribute.EventData) (payloadattribute.EventData, error) { + if ev.HeadBlock == nil || ev.HeadBlock.IsNil() { + hb, err := s.HeadFetcher.HeadBlock(ctx) + if err != nil { + return ev, errors.Wrap(err, "Could not look up head block") } - case version.Capella: - withdrawals, _, err := headState.ExpectedWithdrawals() + root, err := hb.Block().HashTreeRoot() if err != nil { - return write(w, flusher, "Could not get head state expected withdrawals: "+err.Error()) + return ev, errors.Wrap(err, "Could not compute head block root") } - attributes = &structs.PayloadAttributesV2{ - Timestamp: fmt.Sprintf("%d", t.Unix()), - PrevRandao: hexutil.Encode(prevRando), - SuggestedFeeRecipient: hexutil.Encode(feeRecipient), - Withdrawals: structs.WithdrawalsFromConsensus(withdrawals), + if ev.HeadRoot != root { + return ev, errors.Wrap(err, "head root changed before payload attribute event handler execution") } - case version.Deneb, version.Electra: - withdrawals, _, err := headState.ExpectedWithdrawals() + ev.HeadBlock = hb + payload, err := hb.Block().Body().Execution() if err != nil { - return write(w, flusher, "Could not get head state expected withdrawals: "+err.Error()) + return ev, errors.Wrap(err, "Could not get execution payload for head block") } - parentRoot, err := headBlock.Block().HashTreeRoot() + ev.ParentBlockHash = payload.BlockHash() + ev.ParentBlockNumber = payload.BlockNumber() + } + + attr := ev.Attributer + if attr == nil || attr.IsEmpty() { + attr, err := s.computePayloadAttributes(ctx, ev) if err != nil { - return write(w, flusher, "Could not get head block root: "+err.Error()) + return ev, errors.Wrap(err, "Could not compute payload attributes") } - attributes = &structs.PayloadAttributesV3{ - Timestamp: fmt.Sprintf("%d", t.Unix()), - PrevRandao: hexutil.Encode(prevRando), - SuggestedFeeRecipient: hexutil.Encode(feeRecipient), - Withdrawals: structs.WithdrawalsFromConsensus(withdrawals), - ParentBeaconBlockRoot: hexutil.Encode(parentRoot[:]), + ev.Attributer = attr + } + return ev, nil +} + +// This event stream is intended to be used by builders and relays. +// Parent fields are based on state at N_{current_slot}, while the rest of fields are based on state of N_{current_slot + 1} +func (s *Server) payloadAttributesReader(ctx context.Context, ev payloadattribute.EventData) (lazyReader, error) { + ctx, cancel := context.WithTimeout(ctx, payloadAttributeTimeout) + edc := make(chan asyncPayloadAttrData) + go func() { + d := asyncPayloadAttrData{ + version: version.String(ev.HeadState.Version()), } - default: - return write(w, flusher, "Payload version %s is not supported", version.String(headState.Version())) + + defer func() { + edc <- d + }() + ev, err := s.fillEventData(ctx, ev) + if err != nil { + d.err = errors.Wrap(err, "Could not fill event data") + return + } + attributesBytes, err := marshalAttributes(ev.Attributer) + if err != nil { + d.err = errors.Wrap(err, "errors marshaling payload attributes to json") + return + } + d.data, d.err = json.Marshal(structs.PayloadAttributesEventData{ + ProposerIndex: strconv.FormatUint(uint64(ev.ProposerIndex), 10), + ProposalSlot: strconv.FormatUint(uint64(ev.ProposalSlot), 10), + ParentBlockNumber: strconv.FormatUint(ev.ParentBlockNumber, 10), + ParentBlockRoot: hexutil.Encode(ev.ParentBlockRoot), + ParentBlockHash: hexutil.Encode(ev.ParentBlockHash), + PayloadAttributes: attributesBytes, + }) + if d.err != nil { + d.err = errors.Wrap(d.err, "errors marshaling payload attributes event data to json") + } + }() + return func() io.Reader { + defer cancel() + select { + case <-ctx.Done(): + log.WithError(ctx.Err()).Warn("Context canceled while waiting for payload attributes event data") + return nil + case ed := <-edc: + if ed.err != nil { + log.WithError(ed.err).Warn("Error while marshaling payload attributes event data") + return nil + } + return jsonMarshalReader(PayloadAttributesTopic, &structs.PayloadAttributesEvent{ + Version: ed.version, + Data: ed.data, + }) + } + }, nil +} + +func marshalAttributes(attr payloadattribute.Attributer) ([]byte, error) { + v := attr.Version() + if v < version.Bellatrix { + return nil, errors.Wrapf(errUnsupportedPayloadAttribute, "Payload version %s is not supported", version.String(v)) } - attributesBytes, err := json.Marshal(attributes) + timestamp := strconv.FormatUint(attr.Timestamp(), 10) + prevRandao := hexutil.Encode(attr.PrevRandao()) + feeRecpt := hexutil.Encode(attr.SuggestedFeeRecipient()) + if v == version.Bellatrix { + return json.Marshal(&structs.PayloadAttributesV1{ + Timestamp: timestamp, + PrevRandao: prevRandao, + SuggestedFeeRecipient: feeRecpt, + }) + } + w, err := attr.Withdrawals() if err != nil { - return write(w, flusher, err.Error()) + return nil, errors.Wrap(err, "could not get withdrawals from payload attributes event") } - eventData := structs.PayloadAttributesEventData{ - ProposerIndex: fmt.Sprintf("%d", proposerIndex), - ProposalSlot: fmt.Sprintf("%d", headState.Slot()), - ParentBlockNumber: fmt.Sprintf("%d", headPayload.BlockNumber()), - ParentBlockRoot: hexutil.Encode(headRoot), - ParentBlockHash: hexutil.Encode(headPayload.BlockHash()), - PayloadAttributes: attributesBytes, + withdrawals := structs.WithdrawalsFromConsensus(w) + if v == version.Capella { + return json.Marshal(&structs.PayloadAttributesV2{ + Timestamp: timestamp, + PrevRandao: prevRandao, + SuggestedFeeRecipient: feeRecpt, + Withdrawals: withdrawals, + }) } - eventDataBytes, err := json.Marshal(eventData) + parentRoot, err := attr.ParentBeaconBlockRoot() if err != nil { - return write(w, flusher, err.Error()) + return nil, errors.Wrap(err, "could not get parent beacon block root from payload attributes event") } - return send(w, flusher, PayloadAttributesTopic, &structs.PayloadAttributesEvent{ - Version: version.String(headState.Version()), - Data: eventDataBytes, + return json.Marshal(&structs.PayloadAttributesV3{ + Timestamp: timestamp, + PrevRandao: prevRandao, + SuggestedFeeRecipient: feeRecpt, + Withdrawals: withdrawals, + ParentBeaconBlockRoot: hexutil.Encode(parentRoot), }) } -func send(w http.ResponseWriter, flusher http.Flusher, name string, data interface{}) error { - j, err := json.Marshal(data) - if err != nil { - return write(w, flusher, "Could not marshal event to JSON: "+err.Error()) +func newStreamingResponseController(rw http.ResponseWriter, timeout time.Duration) *streamingResponseWriterController { + rc := http.NewResponseController(rw) + return &streamingResponseWriterController{ + timeout: timeout, + rw: rw, + rc: rc, } - return write(w, flusher, "event: %s\ndata: %s\n\n", name, string(j)) } -func sendKeepalive(w http.ResponseWriter, flusher http.Flusher) error { - return write(w, flusher, ":\n\n") +// streamingResponseWriterController provides an interface similar to an http.ResponseWriter, +// wrapping an http.ResponseWriter and an http.ResponseController, using the ResponseController +// to set and clear deadlines for Write and Flush methods, and delegating to the underlying +// types to Write and Flush. +type streamingResponseWriterController struct { + timeout time.Duration + rw http.ResponseWriter + rc *http.ResponseController } -func write(w http.ResponseWriter, flusher http.Flusher, format string, a ...any) error { - _, err := fmt.Fprintf(w, format, a...) +func (c *streamingResponseWriterController) Write(b []byte) (int, error) { + if err := c.setDeadline(); err != nil { + return 0, err + } + out, err := c.rw.Write(b) if err != nil { - return errors.Wrap(err, "could not write to response writer") + return out, err + } + return out, c.clearDeadline() +} + +func (c *streamingResponseWriterController) setDeadline() error { + return c.rc.SetWriteDeadline(time.Now().Add(c.timeout)) +} + +func (c *streamingResponseWriterController) clearDeadline() error { + return c.rc.SetWriteDeadline(time.Time{}) +} + +func (c *streamingResponseWriterController) Flush() error { + if err := c.setDeadline(); err != nil { + return err + } + if err := c.rc.Flush(); err != nil { + return err } - flusher.Flush() - return nil + return c.clearDeadline() } diff --git a/beacon-chain/rpc/eth/events/events_test.go b/beacon-chain/rpc/eth/events/events_test.go index d44ca7e04938..82c970839449 100644 --- a/beacon-chain/rpc/eth/events/events_test.go +++ b/beacon-chain/rpc/eth/events/events_test.go @@ -1,6 +1,7 @@ package events import ( + "context" "fmt" "io" "math" @@ -18,61 +19,118 @@ import ( statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" + sse "github.com/r3labs/sse/v2" + "github.com/sirupsen/logrus" ) -type flushableResponseRecorder struct { - *httptest.ResponseRecorder - flushed bool -} +var testEventWriteTimeout = 100 * time.Millisecond -func (f *flushableResponseRecorder) Flush() { - f.flushed = true -} +func requireAllEventsReceived(t *testing.T, stn, opn *mockChain.EventFeedWrapper, events []*feed.Event, req *topicRequest, s *Server, w *StreamingResponseWriterRecorder, logs chan *logrus.Entry) { + // maxBufferSize param copied from sse lib client code + sseR := sse.NewEventStreamReader(w.Body(), 1<<24) + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() -func TestStreamEvents_OperationsEvents(t *testing.T) { - t.Run("operations", func(t *testing.T) { - s := &Server{ - StateNotifier: &mockChain.MockStateNotifier{}, - OperationNotifier: &mockChain.MockOperationNotifier{}, - } + expected := make(map[string]bool) + for i := range events { + ev := events[i] + // serialize the event the same way the server will so that we can compare expectation to results. + top := topicForEvent(ev) + eb, err := s.lazyReaderForEvent(context.Background(), ev, req) + require.NoError(t, err) + exb, err := io.ReadAll(eb()) + require.NoError(t, err) + exs := string(exb[0 : len(exb)-2]) // remove trailing double newline - topics := []string{ - AttestationTopic, - VoluntaryExitTopic, - SyncCommitteeContributionTopic, - BLSToExecutionChangeTopic, - BlobSidecarTopic, - AttesterSlashingTopic, - ProposerSlashingTopic, + if topicsForOpsFeed[top] { + if err := opn.WaitForSubscription(ctx); err != nil { + t.Fatal(err) + } + // Send the event on the feed. + s.OperationNotifier.OperationFeed().Send(ev) + } else { + if err := stn.WaitForSubscription(ctx); err != nil { + t.Fatal(err) + } + // Send the event on the feed. + s.StateNotifier.StateFeed().Send(ev) } - for i, topic := range topics { - topics[i] = "topics=" + topic + expected[exs] = true + } + done := make(chan struct{}) + go func() { + defer close(done) + for { + ev, err := sseR.ReadEvent() + if err == io.EOF { + return + } + require.NoError(t, err) + str := string(ev) + delete(expected, str) + if len(expected) == 0 { + return + } } - request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/events?%s", strings.Join(topics, "&")), nil) - w := &flushableResponseRecorder{ - ResponseRecorder: httptest.NewRecorder(), + }() + for { + select { + case entry := <-logs: + errAttr, ok := entry.Data[logrus.ErrorKey] + if ok { + t.Errorf("unexpected error in logs: %v", errAttr) + } + case <-done: + require.Equal(t, 0, len(expected), "expected events not seen") + return + case <-ctx.Done(): + t.Fatalf("context canceled / timed out waiting for events, err=%v", ctx.Err()) } + } +} - go func() { - s.StreamEvents(w, request) - }() - // wait for initiation of StreamEvents - time.Sleep(100 * time.Millisecond) - s.OperationNotifier.OperationFeed().Send(&feed.Event{ +func (tr *topicRequest) testHttpRequest(ctx context.Context, _ *testing.T) *http.Request { + tq := make([]string, 0, len(tr.topics)) + for topic := range tr.topics { + tq = append(tq, "topics="+topic) + } + req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/events?%s", strings.Join(tq, "&")), nil) + return req.WithContext(ctx) +} + +func operationEventsFixtures(t *testing.T) (*topicRequest, []*feed.Event) { + topics, err := newTopicRequest([]string{ + AttestationTopic, + SingleAttestationTopic, + VoluntaryExitTopic, + SyncCommitteeContributionTopic, + BLSToExecutionChangeTopic, + BlobSidecarTopic, + AttesterSlashingTopic, + ProposerSlashingTopic, + }) + require.NoError(t, err) + ro, err := blocks.NewROBlob(util.HydrateBlobSidecar(ð.BlobSidecar{})) + require.NoError(t, err) + vblob := blocks.NewVerifiedROBlob(ro) + + return topics, []*feed.Event{ + { Type: operation.UnaggregatedAttReceived, Data: &operation.UnAggregatedAttReceivedData{ Attestation: util.HydrateAttestation(ð.Attestation{}), }, - }) - s.OperationNotifier.OperationFeed().Send(&feed.Event{ + }, + { Type: operation.AggregatedAttReceived, Data: &operation.AggregatedAttReceivedData{ Attestation: ð.AggregateAttestationAndProof{ @@ -81,8 +139,14 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { SelectionProof: make([]byte, 96), }, }, - }) - s.OperationNotifier.OperationFeed().Send(&feed.Event{ + }, + { + Type: operation.SingleAttReceived, + Data: &operation.SingleAttReceivedData{ + Attestation: util.HydrateSingleAttestation(ð.SingleAttestation{}), + }, + }, + { Type: operation.ExitReceived, Data: &operation.ExitReceivedData{ Exit: ð.SignedVoluntaryExit{ @@ -93,8 +157,8 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { Signature: make([]byte, 96), }, }, - }) - s.OperationNotifier.OperationFeed().Send(&feed.Event{ + }, + { Type: operation.SyncCommitteeContributionReceived, Data: &operation.SyncCommitteeContributionReceivedData{ Contribution: ð.SignedContributionAndProof{ @@ -112,8 +176,8 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { Signature: make([]byte, 96), }, }, - }) - s.OperationNotifier.OperationFeed().Send(&feed.Event{ + }, + { Type: operation.BLSToExecutionChangeReceived, Data: &operation.BLSToExecutionChangeReceivedData{ Change: ð.SignedBLSToExecutionChange{ @@ -125,18 +189,14 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { Signature: make([]byte, 96), }, }, - }) - ro, err := blocks.NewROBlob(util.HydrateBlobSidecar(ð.BlobSidecar{})) - require.NoError(t, err) - vblob := blocks.NewVerifiedROBlob(ro) - s.OperationNotifier.OperationFeed().Send(&feed.Event{ + }, + { Type: operation.BlobSidecarReceived, Data: &operation.BlobSidecarReceivedData{ Blob: &vblob, }, - }) - - s.OperationNotifier.OperationFeed().Send(&feed.Event{ + }, + { Type: operation.AttesterSlashingReceived, Data: &operation.AttesterSlashingReceivedData{ AttesterSlashing: ð.AttesterSlashing{ @@ -168,9 +228,41 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { }, }, }, - }) - - s.OperationNotifier.OperationFeed().Send(&feed.Event{ + }, + { + Type: operation.AttesterSlashingReceived, + Data: &operation.AttesterSlashingReceivedData{ + AttesterSlashing: ð.AttesterSlashingElectra{ + Attestation_1: ð.IndexedAttestationElectra{ + AttestingIndices: []uint64{0, 1}, + Data: ð.AttestationData{ + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ð.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + Target: ð.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + }, + Signature: make([]byte, fieldparams.BLSSignatureLength), + }, + Attestation_2: ð.IndexedAttestationElectra{ + AttestingIndices: []uint64{0, 1}, + Data: ð.AttestationData{ + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ð.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + Target: ð.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + }, + Signature: make([]byte, fieldparams.BLSSignatureLength), + }, + }, + }, + }, + { Type: operation.ProposerSlashingReceived, Data: &operation.ProposerSlashingReceivedData{ ProposerSlashing: ð.ProposerSlashing{ @@ -192,100 +284,154 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { }, }, }, - }) + }, + } +} - time.Sleep(1 * time.Second) - request.Context().Done() +type streamTestSync struct { + done chan struct{} + cancel func() + undo func() + logs chan *logrus.Entry + ctx context.Context + t *testing.T +} - resp := w.Result() - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.NotNil(t, body) - assert.Equal(t, operationsResult, string(body)) - }) - t.Run("state", func(t *testing.T) { +func (s *streamTestSync) cleanup() { + s.cancel() + select { + case <-s.done: + case <-time.After(10 * time.Millisecond): + s.t.Fatal("timed out waiting for handler to finish") + } + s.undo() +} + +func (s *streamTestSync) markDone() { + close(s.done) +} + +func newStreamTestSync(t *testing.T) *streamTestSync { + logChan := make(chan *logrus.Entry, 100) + cew := util.NewChannelEntryWriter(logChan) + undo := util.RegisterHookWithUndo(logger, cew) + ctx, cancel := context.WithCancel(context.Background()) + return &streamTestSync{ + t: t, + ctx: ctx, + cancel: cancel, + logs: logChan, + undo: undo, + done: make(chan struct{}), + } +} + +func TestStreamEvents_OperationsEvents(t *testing.T) { + t.Run("operations", func(t *testing.T) { + testSync := newStreamTestSync(t) + defer testSync.cleanup() + stn := mockChain.NewEventFeedWrapper() + opn := mockChain.NewEventFeedWrapper() s := &Server{ - StateNotifier: &mockChain.MockStateNotifier{}, - OperationNotifier: &mockChain.MockOperationNotifier{}, + StateNotifier: &mockChain.SimpleNotifier{Feed: stn}, + OperationNotifier: &mockChain.SimpleNotifier{Feed: opn}, + EventWriteTimeout: testEventWriteTimeout, } - topics := []string{HeadTopic, FinalizedCheckpointTopic, ChainReorgTopic, BlockTopic} - for i, topic := range topics { - topics[i] = "topics=" + topic - } - request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/events?%s", strings.Join(topics, "&")), nil) - w := &flushableResponseRecorder{ - ResponseRecorder: httptest.NewRecorder(), - } + topics, events := operationEventsFixtures(t) + request := topics.testHttpRequest(testSync.ctx, t) + w := NewStreamingResponseWriterRecorder(testSync.ctx) go func() { s.StreamEvents(w, request) + testSync.markDone() }() - // wait for initiation of StreamEvents - time.Sleep(100 * time.Millisecond) - s.StateNotifier.StateFeed().Send(&feed.Event{ - Type: statefeed.NewHead, - Data: ðpb.EventHead{ - Slot: 0, - Block: make([]byte, 32), - State: make([]byte, 32), - EpochTransition: true, - PreviousDutyDependentRoot: make([]byte, 32), - CurrentDutyDependentRoot: make([]byte, 32), - ExecutionOptimistic: false, - }, - }) - s.StateNotifier.StateFeed().Send(&feed.Event{ - Type: statefeed.FinalizedCheckpoint, - Data: ðpb.EventFinalizedCheckpoint{ - Block: make([]byte, 32), - State: make([]byte, 32), - Epoch: 0, - ExecutionOptimistic: false, - }, - }) - s.StateNotifier.StateFeed().Send(&feed.Event{ - Type: statefeed.Reorg, - Data: ðpb.EventChainReorg{ - Slot: 0, - Depth: 0, - OldHeadBlock: make([]byte, 32), - NewHeadBlock: make([]byte, 32), - OldHeadState: make([]byte, 32), - NewHeadState: make([]byte, 32), - Epoch: 0, - ExecutionOptimistic: false, - }, + + requireAllEventsReceived(t, stn, opn, events, topics, s, w, testSync.logs) + }) + t.Run("state", func(t *testing.T) { + testSync := newStreamTestSync(t) + defer testSync.cleanup() + + stn := mockChain.NewEventFeedWrapper() + opn := mockChain.NewEventFeedWrapper() + s := &Server{ + StateNotifier: &mockChain.SimpleNotifier{Feed: stn}, + OperationNotifier: &mockChain.SimpleNotifier{Feed: opn}, + EventWriteTimeout: testEventWriteTimeout, + } + + topics, err := newTopicRequest([]string{ + HeadTopic, + FinalizedCheckpointTopic, + ChainReorgTopic, + BlockTopic, }) + require.NoError(t, err) + request := topics.testHttpRequest(testSync.ctx, t) + w := NewStreamingResponseWriterRecorder(testSync.ctx) + b, err := blocks.NewSignedBeaconBlock(util.HydrateSignedBeaconBlock(ð.SignedBeaconBlock{})) require.NoError(t, err) - s.StateNotifier.StateFeed().Send(&feed.Event{ - Type: statefeed.BlockProcessed, - Data: &statefeed.BlockProcessedData{ - Slot: 0, - BlockRoot: [32]byte{}, - SignedBlock: b, - Verified: true, - Optimistic: false, + events := []*feed.Event{ + { + Type: statefeed.BlockProcessed, + Data: &statefeed.BlockProcessedData{ + Slot: 0, + BlockRoot: [32]byte{}, + SignedBlock: b, + Verified: true, + Optimistic: false, + }, }, - }) + { + Type: statefeed.NewHead, + Data: ðpb.EventHead{ + Slot: 0, + Block: make([]byte, 32), + State: make([]byte, 32), + EpochTransition: true, + PreviousDutyDependentRoot: make([]byte, 32), + CurrentDutyDependentRoot: make([]byte, 32), + ExecutionOptimistic: false, + }, + }, + { + Type: statefeed.Reorg, + Data: ðpb.EventChainReorg{ + Slot: 0, + Depth: 0, + OldHeadBlock: make([]byte, 32), + NewHeadBlock: make([]byte, 32), + OldHeadState: make([]byte, 32), + NewHeadState: make([]byte, 32), + Epoch: 0, + ExecutionOptimistic: false, + }, + }, + { + Type: statefeed.FinalizedCheckpoint, + Data: ðpb.EventFinalizedCheckpoint{ + Block: make([]byte, 32), + State: make([]byte, 32), + Epoch: 0, + ExecutionOptimistic: false, + }, + }, + } - // wait for feed - time.Sleep(1 * time.Second) - request.Context().Done() + go func() { + s.StreamEvents(w, request) + testSync.markDone() + }() - resp := w.Result() - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.NotNil(t, body) - assert.Equal(t, stateResult, string(body)) + requireAllEventsReceived(t, stn, opn, events, topics, s, w, testSync.logs) }) t.Run("payload attributes", func(t *testing.T) { type testCase struct { name string getState func() state.BeaconState getBlock func() interfaces.SignedBeaconBlock - expected string SetTrackedValidatorsCache func(*cache.TrackedValidatorsCache) } testCases := []testCase{ @@ -301,7 +447,6 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { require.NoError(t, err) return b }, - expected: payloadAttributesBellatrixResult, }, { name: "capella", @@ -315,7 +460,6 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { require.NoError(t, err) return b }, - expected: payloadAttributesCapellaResult, }, { name: "deneb", @@ -329,7 +473,6 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { require.NoError(t, err) return b }, - expected: payloadAttributesDenebResult, }, { name: "electra", @@ -343,7 +486,6 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { require.NoError(t, err) return b }, - expected: payloadAttributesElectraResultWithTVC, SetTrackedValidatorsCache: func(c *cache.TrackedValidatorsCache) { c.Set(cache.TrackedValidator{ Active: true, @@ -354,124 +496,150 @@ func TestStreamEvents_OperationsEvents(t *testing.T) { }, } for _, tc := range testCases { - st := tc.getState() - v := ð.Validator{ExitEpoch: math.MaxUint64} - require.NoError(t, st.SetValidators([]*eth.Validator{v})) - currentSlot := primitives.Slot(0) - // to avoid slot processing - require.NoError(t, st.SetSlot(currentSlot+1)) - b := tc.getBlock() - mockChainService := &mockChain.ChainService{ - Root: make([]byte, 32), - State: st, - Block: b, - Slot: ¤tSlot, - } - - s := &Server{ - StateNotifier: &mockChain.MockStateNotifier{}, - OperationNotifier: &mockChain.MockOperationNotifier{}, - HeadFetcher: mockChainService, - ChainInfoFetcher: mockChainService, - TrackedValidatorsCache: cache.NewTrackedValidatorsCache(), - } - if tc.SetTrackedValidatorsCache != nil { - tc.SetTrackedValidatorsCache(s.TrackedValidatorsCache) - } - - request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://example.com/eth/v1/events?topics=%s", PayloadAttributesTopic), nil) - w := &flushableResponseRecorder{ - ResponseRecorder: httptest.NewRecorder(), - } - - go func() { - s.StreamEvents(w, request) - }() - // wait for initiation of StreamEvents - time.Sleep(100 * time.Millisecond) - s.StateNotifier.StateFeed().Send(&feed.Event{Type: statefeed.MissedSlot}) - - // wait for feed - time.Sleep(1 * time.Second) - request.Context().Done() - - resp := w.Result() - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.NotNil(t, body) - assert.Equal(t, tc.expected, string(body), "wrong result for "+tc.name) + t.Run(tc.name, func(t *testing.T) { + testSync := newStreamTestSync(t) + defer testSync.cleanup() + + st := tc.getState() + v := ð.Validator{ExitEpoch: math.MaxUint64, EffectiveBalance: params.BeaconConfig().MinActivationBalance, WithdrawalCredentials: make([]byte, 32)} + require.NoError(t, st.SetValidators([]*eth.Validator{v})) + currentSlot := primitives.Slot(0) + // to avoid slot processing + require.NoError(t, st.SetSlot(currentSlot+1)) + b := tc.getBlock() + mockChainService := &mockChain.ChainService{ + Root: make([]byte, 32), + State: st, + Block: b, + Slot: ¤tSlot, + } + + stn := mockChain.NewEventFeedWrapper() + opn := mockChain.NewEventFeedWrapper() + s := &Server{ + StateNotifier: &mockChain.SimpleNotifier{Feed: stn}, + OperationNotifier: &mockChain.SimpleNotifier{Feed: opn}, + HeadFetcher: mockChainService, + ChainInfoFetcher: mockChainService, + TrackedValidatorsCache: cache.NewTrackedValidatorsCache(), + EventWriteTimeout: testEventWriteTimeout, + } + if tc.SetTrackedValidatorsCache != nil { + tc.SetTrackedValidatorsCache(s.TrackedValidatorsCache) + } + topics, err := newTopicRequest([]string{PayloadAttributesTopic}) + require.NoError(t, err) + request := topics.testHttpRequest(testSync.ctx, t) + w := NewStreamingResponseWriterRecorder(testSync.ctx) + events := []*feed.Event{ + { + Type: statefeed.PayloadAttributes, + Data: payloadattribute.EventData{ + ProposerIndex: 0, + ProposalSlot: 0, + ParentBlockNumber: 0, + ParentBlockRoot: make([]byte, 32), + ParentBlockHash: make([]byte, 32), + HeadState: st, + HeadBlock: b, + HeadRoot: [fieldparams.RootLength]byte{}, + }, + }, + } + + go func() { + s.StreamEvents(w, request) + testSync.markDone() + }() + requireAllEventsReceived(t, stn, opn, events, topics, s, w, testSync.logs) + }) } }) } -const operationsResult = `: - -event: attestation -data: {"aggregation_bits":"0x00","data":{"slot":"0","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"target":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} - -event: attestation -data: {"aggregation_bits":"0x00","data":{"slot":"0","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"target":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} - -event: voluntary_exit -data: {"message":{"epoch":"0","validator_index":"0"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} - -event: contribution_and_proof -data: {"message":{"aggregator_index":"0","contribution":{"slot":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","subcommittee_index":"0","aggregation_bits":"0x00000000000000000000000000000000","signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"selection_proof":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} - -event: bls_to_execution_change -data: {"message":{"validator_index":"0","from_bls_pubkey":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","to_execution_address":"0x0000000000000000000000000000000000000000"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} - -event: blob_sidecar -data: {"block_root":"0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c","index":"0","slot":"0","kzg_commitment":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","versioned_hash":"0x01b0761f87b081d5cf10757ccc89f12be355c70e2e29df288b65b30710dcbcd1"} - -event: attester_slashing -data: {"attestation_1":{"attesting_indices":["0","1"],"data":{"slot":"0","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"target":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"attestation_2":{"attesting_indices":["0","1"],"data":{"slot":"0","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"target":{"epoch":"0","root":"0x0000000000000000000000000000000000000000000000000000000000000000"}},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}} - -event: proposer_slashing -data: {"signed_header_1":{"message":{"slot":"0","proposer_index":"0","parent_root":"0x0000000000000000000000000000000000000000000000000000000000000000","state_root":"0x0000000000000000000000000000000000000000000000000000000000000000","body_root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"signed_header_2":{"message":{"slot":"0","proposer_index":"0","parent_root":"0x0000000000000000000000000000000000000000000000000000000000000000","state_root":"0x0000000000000000000000000000000000000000000000000000000000000000","body_root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}} - -` - -const stateResult = `: - -event: head -data: {"slot":"0","block":"0x0000000000000000000000000000000000000000000000000000000000000000","state":"0x0000000000000000000000000000000000000000000000000000000000000000","epoch_transition":true,"execution_optimistic":false,"previous_duty_dependent_root":"0x0000000000000000000000000000000000000000000000000000000000000000","current_duty_dependent_root":"0x0000000000000000000000000000000000000000000000000000000000000000"} - -event: finalized_checkpoint -data: {"block":"0x0000000000000000000000000000000000000000000000000000000000000000","state":"0x0000000000000000000000000000000000000000000000000000000000000000","epoch":"0","execution_optimistic":false} - -event: chain_reorg -data: {"slot":"0","depth":"0","old_head_block":"0x0000000000000000000000000000000000000000000000000000000000000000","old_head_state":"0x0000000000000000000000000000000000000000000000000000000000000000","new_head_block":"0x0000000000000000000000000000000000000000000000000000000000000000","new_head_state":"0x0000000000000000000000000000000000000000000000000000000000000000","epoch":"0","execution_optimistic":false} - -event: block -data: {"slot":"0","block":"0xeade62f0457b2fdf48e7d3fc4b60736688286be7c7a3ac4c9a16a5e0600bd9e4","execution_optimistic":false} - -` - -const payloadAttributesBellatrixResult = `: - -event: payload_attributes -data: {"version":"bellatrix","data":{"proposer_index":"0","proposal_slot":"1","parent_block_number":"0","parent_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","parent_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","payload_attributes":{"timestamp":"12","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","suggested_fee_recipient":"0x0000000000000000000000000000000000000000"}}} - -` - -const payloadAttributesCapellaResult = `: - -event: payload_attributes -data: {"version":"capella","data":{"proposer_index":"0","proposal_slot":"1","parent_block_number":"0","parent_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","parent_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","payload_attributes":{"timestamp":"12","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","suggested_fee_recipient":"0x0000000000000000000000000000000000000000","withdrawals":[]}}} - -` - -const payloadAttributesDenebResult = `: - -event: payload_attributes -data: {"version":"deneb","data":{"proposer_index":"0","proposal_slot":"1","parent_block_number":"0","parent_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","parent_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","payload_attributes":{"timestamp":"12","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","suggested_fee_recipient":"0x0000000000000000000000000000000000000000","withdrawals":[],"parent_beacon_block_root":"0xbef96cb938fd48b2403d3e662664325abb0102ed12737cbb80d717520e50cf4a"}}} - -` - -const payloadAttributesElectraResultWithTVC = `: - -event: payload_attributes -data: {"version":"electra","data":{"proposer_index":"0","proposal_slot":"1","parent_block_number":"0","parent_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","parent_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","payload_attributes":{"timestamp":"12","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","suggested_fee_recipient":"0xd2dbd02e4efe087d7d195de828b9dd25f19a89c9","withdrawals":[],"parent_beacon_block_root":"0x66d641f7eae038f2dd28081b09d2ba279462cc47655c7b7e1fd1159a50c8eb32"}}} +func TestStuckReaderScenarios(t *testing.T) { + cases := []struct { + name string + queueDepth func([]*feed.Event) int + }{ + { + name: "slow reader - queue overflows", + queueDepth: func(events []*feed.Event) int { + return len(events) - 1 + }, + }, + { + name: "slow reader - all queued, but writer is stuck, write timeout", + queueDepth: func(events []*feed.Event) int { + return len(events) + 1 + }, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + wedgedWriterTestCase(t, c.queueDepth) + }) + } +} -` +func wedgedWriterTestCase(t *testing.T, queueDepth func([]*feed.Event) int) { + topics, events := operationEventsFixtures(t) + require.Equal(t, 10, len(events)) + + // set eventFeedDepth to a number lower than the events we intend to send to force the server to drop the reader. + stn := mockChain.NewEventFeedWrapper() + opn := mockChain.NewEventFeedWrapper() + s := &Server{ + EventWriteTimeout: 10 * time.Millisecond, + StateNotifier: &mockChain.SimpleNotifier{Feed: stn}, + OperationNotifier: &mockChain.SimpleNotifier{Feed: opn}, + EventFeedDepth: queueDepth(events), + } + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + eventsWritten := make(chan struct{}) + go func() { + for i := range events { + ev := events[i] + top := topicForEvent(ev) + if topicsForOpsFeed[top] { + err := opn.WaitForSubscription(ctx) + require.NoError(t, err) + s.OperationNotifier.OperationFeed().Send(ev) + } else { + err := stn.WaitForSubscription(ctx) + require.NoError(t, err) + s.StateNotifier.StateFeed().Send(ev) + } + } + close(eventsWritten) + }() + + request := topics.testHttpRequest(ctx, t) + w := NewStreamingResponseWriterRecorder(ctx) + + handlerFinished := make(chan struct{}) + go func() { + s.StreamEvents(w, request) + close(handlerFinished) + }() + + // Make sure that the stream writer shut down when the reader failed to clear the write buffer. + select { + case <-handlerFinished: + // We expect the stream handler to max out the queue buffer and exit gracefully. + return + case <-ctx.Done(): + t.Fatalf("context canceled / timed out waiting for handler completion, err=%v", ctx.Err()) + } + + // Also make sure all the events were written. + select { + case <-eventsWritten: + // We expect the stream handler to max out the queue buffer and exit gracefully. + return + case <-ctx.Done(): + t.Fatalf("context canceled / timed out waiting to write all events, err=%v", ctx.Err()) + } +} diff --git a/beacon-chain/rpc/eth/events/http_test.go b/beacon-chain/rpc/eth/events/http_test.go new file mode 100644 index 000000000000..afff92518a32 --- /dev/null +++ b/beacon-chain/rpc/eth/events/http_test.go @@ -0,0 +1,117 @@ +package events + +import ( + "context" + "io" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +type StreamingResponseWriterRecorder struct { + http.ResponseWriter + r io.Reader + w io.Writer + statusWritten *int + status chan int + bodyRecording []byte + flushed bool + writeDeadline time.Time + ctx context.Context +} + +func (w *StreamingResponseWriterRecorder) StatusChan() chan int { + return w.status +} + +func NewStreamingResponseWriterRecorder(ctx context.Context) *StreamingResponseWriterRecorder { + r, w := io.Pipe() + return &StreamingResponseWriterRecorder{ + ResponseWriter: httptest.NewRecorder(), + r: r, + w: w, + status: make(chan int, 1), + ctx: ctx, + } +} + +// Write implements http.ResponseWriter. +func (w *StreamingResponseWriterRecorder) Write(data []byte) (int, error) { + w.WriteHeader(http.StatusOK) + written, err := writeWithDeadline(w.ctx, w.w, data, w.writeDeadline) + if err != nil { + return written, err + } + // The test response writer is non-blocking. + return w.ResponseWriter.Write(data) +} + +var zeroTimeValue = time.Time{} + +func writeWithDeadline(ctx context.Context, w io.Writer, data []byte, deadline time.Time) (int, error) { + result := struct { + written int + err error + }{} + done := make(chan struct{}) + go func() { + defer close(done) + result.written, result.err = w.Write(data) + }() + if deadline == zeroTimeValue { + select { + case <-ctx.Done(): + return 0, ctx.Err() + case <-done: + return result.written, result.err + } + } + select { + case <-time.After(time.Until(deadline)): + return 0, http.ErrHandlerTimeout + case <-done: + return result.written, result.err + case <-ctx.Done(): + return 0, ctx.Err() + } +} + +// WriteHeader implements http.ResponseWriter. +func (w *StreamingResponseWriterRecorder) WriteHeader(statusCode int) { + if w.statusWritten != nil { + return + } + w.statusWritten = &statusCode + w.status <- statusCode + w.ResponseWriter.WriteHeader(statusCode) +} + +func (w *StreamingResponseWriterRecorder) Body() io.Reader { + return w.r +} + +func (w *StreamingResponseWriterRecorder) RequireStatus(t *testing.T, status int) { + if w.statusWritten == nil { + t.Fatal("WriteHeader was not called") + } + require.Equal(t, status, *w.statusWritten) +} + +func (w *StreamingResponseWriterRecorder) Flush() { + w.WriteHeader(200) + fw, ok := w.ResponseWriter.(http.Flusher) + if ok { + fw.Flush() + } + w.flushed = true +} + +func (w *StreamingResponseWriterRecorder) SetWriteDeadline(d time.Time) error { + w.writeDeadline = d + return nil +} + +var _ http.ResponseWriter = &StreamingResponseWriterRecorder{} diff --git a/beacon-chain/rpc/eth/events/log.go b/beacon-chain/rpc/eth/events/log.go new file mode 100644 index 000000000000..6d218a4f034a --- /dev/null +++ b/beacon-chain/rpc/eth/events/log.go @@ -0,0 +1,6 @@ +package events + +import "github.com/sirupsen/logrus" + +var logger = logrus.StandardLogger() +var log = logger.WithField("prefix", "events") diff --git a/beacon-chain/rpc/eth/events/server.go b/beacon-chain/rpc/eth/events/server.go index 58cd671e9c4b..07649c786f97 100644 --- a/beacon-chain/rpc/eth/events/server.go +++ b/beacon-chain/rpc/eth/events/server.go @@ -4,13 +4,15 @@ package events import ( + "time" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" opfeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" ) -// Server defines a server implementation of the gRPC events service, +// Server defines a server implementation of the http events service, // providing RPC endpoints to subscribe to events from the beacon node. type Server struct { StateNotifier statefeed.Notifier @@ -18,4 +20,7 @@ type Server struct { HeadFetcher blockchain.HeadFetcher ChainInfoFetcher blockchain.ChainInfoFetcher TrackedValidatorsCache *cache.TrackedValidatorsCache + KeepAliveInterval time.Duration + EventFeedDepth int + EventWriteTimeout time.Duration } diff --git a/beacon-chain/rpc/eth/helpers/BUILD.bazel b/beacon-chain/rpc/eth/helpers/BUILD.bazel index 29abaf29b165..c9e1b5ff4b4d 100644 --- a/beacon-chain/rpc/eth/helpers/BUILD.bazel +++ b/beacon-chain/rpc/eth/helpers/BUILD.bazel @@ -10,14 +10,11 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/helpers", visibility = ["//visibility:public"], deps = [ - "//api/grpc:go_default_library", - "//api/server/structs:go_default_library", "//beacon-chain/blockchain:go_default_library", "//beacon-chain/db:go_default_library", "//beacon-chain/rpc/lookup:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/stategen:go_default_library", - "//beacon-chain/sync:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", @@ -40,14 +37,12 @@ go_test( ], embed = [":go_default_library"], deps = [ - "//api/grpc:go_default_library", "//beacon-chain/blockchain/testing:go_default_library", "//beacon-chain/db/testing:go_default_library", "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", "//beacon-chain/rpc/testutil:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", - "//beacon-chain/sync/initial-sync/testing:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", @@ -62,7 +57,5 @@ go_test( "//testing/require:go_default_library", "//testing/util:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", - "@org_golang_google_grpc//:go_default_library", ], ) diff --git a/beacon-chain/rpc/eth/helpers/sync.go b/beacon-chain/rpc/eth/helpers/sync.go index 856f1c0aced8..0f1d4509306a 100644 --- a/beacon-chain/rpc/eth/helpers/sync.go +++ b/beacon-chain/rpc/eth/helpers/sync.go @@ -8,58 +8,15 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/api/grpc" - "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/time/slots" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) -// ValidateSyncGRPC checks whether the node is currently syncing and returns an error if it is. -// It also appends syncing info to gRPC headers. -func ValidateSyncGRPC( - ctx context.Context, - syncChecker sync.Checker, - headFetcher blockchain.HeadFetcher, - timeFetcher blockchain.TimeFetcher, - optimisticModeFetcher blockchain.OptimisticModeFetcher, -) error { - if !syncChecker.Syncing() { - return nil - } - headSlot := headFetcher.HeadSlot() - isOptimistic, err := optimisticModeFetcher.IsOptimistic(ctx) - if err != nil { - return status.Errorf(codes.Internal, "Could not check optimistic status: %v", err) - } - - syncDetailsContainer := &structs.SyncDetailsContainer{ - Data: &structs.SyncDetails{ - HeadSlot: strconv.FormatUint(uint64(headSlot), 10), - SyncDistance: strconv.FormatUint(uint64(timeFetcher.CurrentSlot()-headSlot), 10), - IsSyncing: true, - IsOptimistic: isOptimistic, - }, - } - - err = grpc.AppendCustomErrorHeader(ctx, syncDetailsContainer) - if err != nil { - return status.Errorf( - codes.Internal, - "Syncing to latest head, not ready to respond. Could not prepare sync details: %v", - err, - ) - } - return status.Error(codes.Unavailable, "Syncing to latest head, not ready to respond") -} - // IsOptimistic checks whether the beacon state's block is optimistic. func IsOptimistic( ctx context.Context, diff --git a/beacon-chain/rpc/eth/helpers/sync_test.go b/beacon-chain/rpc/eth/helpers/sync_test.go index 014e61888a5f..2823a80cbc91 100644 --- a/beacon-chain/rpc/eth/helpers/sync_test.go +++ b/beacon-chain/rpc/eth/helpers/sync_test.go @@ -3,19 +3,15 @@ package helpers import ( "context" "strconv" - "strings" "testing" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - grpcutil "github.com/prysmaticlabs/prysm/v5/api/grpc" chainmock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" dbtest "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/testutil" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - syncmock "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/initial-sync/testing" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" @@ -26,53 +22,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/grpc" ) -func TestValidateSync(t *testing.T) { - ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) - t.Run("syncing", func(t *testing.T) { - syncChecker := &syncmock.Sync{ - IsSyncing: true, - } - headSlot := primitives.Slot(100) - st, err := util.NewBeaconState() - require.NoError(t, err) - require.NoError(t, st.SetSlot(50)) - chainService := &chainmock.ChainService{ - Slot: &headSlot, - State: st, - } - err = ValidateSyncGRPC(ctx, syncChecker, chainService, chainService, chainService) - require.NotNil(t, err) - sts, ok := grpc.ServerTransportStreamFromContext(ctx).(*runtime.ServerTransportStream) - require.Equal(t, true, ok, "type assertion failed") - md := sts.Header() - v, ok := md[strings.ToLower(grpcutil.CustomErrorMetadataKey)] - require.Equal(t, true, ok, "could not retrieve custom error metadata value") - assert.DeepEqual( - t, - []string{`{"data":{"head_slot":"50","sync_distance":"50","is_syncing":true,"is_optimistic":false,"el_offline":false}}`}, - v, - ) - }) - t.Run("not syncing", func(t *testing.T) { - syncChecker := &syncmock.Sync{ - IsSyncing: false, - } - headSlot := primitives.Slot(100) - st, err := util.NewBeaconState() - require.NoError(t, err) - require.NoError(t, st.SetSlot(50)) - chainService := &chainmock.ChainService{ - Slot: &headSlot, - State: st, - } - err = ValidateSyncGRPC(ctx, syncChecker, nil, nil, chainService) - require.NoError(t, err) - }) -} - func TestIsOptimistic(t *testing.T) { ctx := context.Background() @@ -378,7 +329,7 @@ func prepareForkchoiceState( payloadHash [32]byte, justified *eth.Checkpoint, finalized *eth.Checkpoint, -) (state.BeaconState, [32]byte, error) { +) (state.BeaconState, blocks.ROBlock, error) { blockHeader := ð.BeaconBlockHeader{ ParentRoot: parentRoot[:], } @@ -399,5 +350,24 @@ func prepareForkchoiceState( base.BlockRoots[0] = append(base.BlockRoots[0], blockRoot[:]...) st, err := state_native.InitializeFromProtoBellatrix(base) - return st, blockRoot, err + if err != nil { + return nil, blocks.ROBlock{}, err + } + blk := ð.SignedBeaconBlockBellatrix{ + Block: ð.BeaconBlockBellatrix{ + Slot: slot, + ParentRoot: parentRoot[:], + Body: ð.BeaconBlockBodyBellatrix{ + ExecutionPayload: &enginev1.ExecutionPayload{ + BlockHash: payloadHash[:], + }, + }, + }, + } + signed, err := blocks.NewSignedBeaconBlock(blk) + if err != nil { + return nil, blocks.ROBlock{}, err + } + roblock, err := blocks.NewROBlockWithRoot(signed, blockRoot) + return st, roblock, err } diff --git a/beacon-chain/rpc/eth/light-client/BUILD.bazel b/beacon-chain/rpc/eth/light-client/BUILD.bazel index db4370fd4ede..be1c31a0e3d0 100644 --- a/beacon-chain/rpc/eth/light-client/BUILD.bazel +++ b/beacon-chain/rpc/eth/light-client/BUILD.bazel @@ -10,25 +10,24 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/light-client", visibility = ["//beacon-chain:__subpackages__"], deps = [ + "//api:go_default_library", "//api/server/structs:go_default_library", "//beacon-chain/blockchain:go_default_library", + "//beacon-chain/core/light-client:go_default_library", + "//beacon-chain/db:go_default_library", "//beacon-chain/rpc/eth/shared:go_default_library", "//beacon-chain/rpc/lookup:go_default_library", "//beacon-chain/state:go_default_library", - "//config/fieldparams:go_default_library", + "//config/features:go_default_library", "//config/params:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", - "//proto/eth/v1:go_default_library", - "//proto/eth/v2:go_default_library", - "//proto/migration:go_default_library", "//runtime/version:go_default_library", - "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", + "@com_github_pkg_errors//:go_default_library", "@com_github_wealdtech_go_bytesutil//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -41,24 +40,24 @@ go_test( embed = [":go_default_library"], deps = [ "//api/server/structs:go_default_library", - "//beacon-chain/blockchain:go_default_library", "//beacon-chain/blockchain/testing:go_default_library", "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/core/light-client:go_default_library", + "//beacon-chain/db/testing:go_default_library", "//beacon-chain/rpc/testutil:go_default_library", "//beacon-chain/state:go_default_library", + "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", + "//consensus-types/light-client:go_default_library", "//consensus-types/primitives:go_default_library", - "//encoding/bytesutil:go_default_library", - "//proto/eth/v1:go_default_library", - "//proto/eth/v2:go_default_library", + "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//testing/assert:go_default_library", + "//runtime/version:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", ], ) diff --git a/beacon-chain/rpc/eth/light-client/handlers.go b/beacon-chain/rpc/eth/light-client/handlers.go index 74296f192e85..84db74dc067b 100644 --- a/beacon-chain/rpc/eth/light-client/handlers.go +++ b/beacon-chain/rpc/eth/light-client/handlers.go @@ -7,81 +7,88 @@ import ( "net/http" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" - types "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/wealdtech/go-bytesutil" - "go.opencensus.io/trace" ) // GetLightClientBootstrap - implements https://github.com/ethereum/beacon-APIs/blob/263f4ed6c263c967f13279c7a9f5629b51c5fc55/apis/beacon/light_client/bootstrap.yaml func (s *Server) GetLightClientBootstrap(w http.ResponseWriter, req *http.Request) { + if !features.Get().EnableLightClient { + httputil.HandleError(w, "Light client feature flag is not enabled", http.StatusNotFound) + return + } + // Prepare ctx, span := trace.StartSpan(req.Context(), "beacon.GetLightClientBootstrap") defer span.End() // Get the block - blockRootParam, err := hexutil.Decode(mux.Vars(req)["block_root"]) + blockRootParam, err := hexutil.Decode(req.PathValue("block_root")) if err != nil { - httputil.HandleError(w, "invalid block root: "+err.Error(), http.StatusBadRequest) + httputil.HandleError(w, "Invalid block root: "+err.Error(), http.StatusBadRequest) return } blockRoot := bytesutil.ToBytes32(blockRootParam) - blk, err := s.Blocker.Block(ctx, blockRoot[:]) - if !shared.WriteBlockFetchError(w, blk, err) { - return - } - - // Get the state - state, err := s.Stater.StateBySlot(ctx, blk.Block().Slot()) + bootstrap, err := s.BeaconDB.LightClientBootstrap(ctx, blockRoot[:]) if err != nil { - httputil.HandleError(w, "could not get state: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not get light client bootstrap: "+err.Error(), http.StatusInternalServerError) return } - - bootstrap, err := createLightClientBootstrap(ctx, state) - if err != nil { - httputil.HandleError(w, "could not get light client bootstrap: "+err.Error(), http.StatusInternalServerError) + if bootstrap == nil { + httputil.HandleError(w, "Light client bootstrap not found", http.StatusNotFound) return } - response := &structs.LightClientBootstrapResponse{ - Version: version.String(blk.Version()), - Data: bootstrap, - } + w.Header().Set(api.VersionHeader, version.String(bootstrap.Version())) - httputil.WriteJson(w, response) + if httputil.RespondWithSsz(req) { + ssz, err := bootstrap.MarshalSSZ() + if err != nil { + httputil.HandleError(w, "Could not marshal bootstrap to SSZ: "+err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteSsz(w, ssz, "light_client_bootstrap.ssz") + } else { + data, err := structs.LightClientBootstrapFromConsensus(bootstrap) + if err != nil { + httputil.HandleError(w, "Could not marshal bootstrap to JSON: "+err.Error(), http.StatusInternalServerError) + return + } + response := &structs.LightClientBootstrapResponse{ + Version: version.String(bootstrap.Version()), + Data: data, + } + httputil.WriteJson(w, response) + } } // GetLightClientUpdatesByRange - implements https://github.com/ethereum/beacon-APIs/blob/263f4ed6c263c967f13279c7a9f5629b51c5fc55/apis/beacon/light_client/updates.yaml func (s *Server) GetLightClientUpdatesByRange(w http.ResponseWriter, req *http.Request) { - // Prepare + if !features.Get().EnableLightClient { + httputil.HandleError(w, "Light client feature flag is not enabled", http.StatusNotFound) + return + } + ctx, span := trace.StartSpan(req.Context(), "beacon.GetLightClientUpdatesByRange") defer span.End() - // Determine slots per period config := params.BeaconConfig() - slotsPerPeriod := uint64(config.EpochsPerSyncCommitteePeriod) * uint64(config.SlotsPerEpoch) - // Adjust count based on configuration _, count, gotCount := shared.UintFromQuery(w, req, "count", true) if !gotCount { return } else if count == 0 { - httputil.HandleError(w, fmt.Sprintf("got invalid 'count' query variable '%d': count must be greater than 0", count), http.StatusInternalServerError) - return - } - - // Determine the start and end periods - _, startPeriod, gotStartPeriod := shared.UintFromQuery(w, req, "start_period", true) - if !gotStartPeriod { + httputil.HandleError(w, fmt.Sprintf("Got invalid 'count' query variable '%d': count must be greater than 0", count), http.StatusBadRequest) return } @@ -89,142 +96,50 @@ func (s *Server) GetLightClientUpdatesByRange(w http.ResponseWriter, req *http.R count = config.MaxRequestLightClientUpdates } - // max possible slot is current head - headState, err := s.HeadFetcher.HeadState(ctx) - if err != nil { - httputil.HandleError(w, "could not get head state: "+err.Error(), http.StatusInternalServerError) + _, startPeriod, gotStartPeriod := shared.UintFromQuery(w, req, "start_period", true) + if !gotStartPeriod { return } - maxSlot := uint64(headState.Slot()) - - // min possible slot is Altair fork period - minSlot := uint64(config.AltairForkEpoch) * uint64(config.SlotsPerEpoch) + endPeriod := startPeriod + count - 1 - // Adjust startPeriod, the end of start period must be later than Altair fork epoch, otherwise, can not get the sync committee votes - startPeriodEndSlot := (startPeriod+1)*slotsPerPeriod - 1 - if startPeriodEndSlot < minSlot { - startPeriod = minSlot / slotsPerPeriod + // get updates + updatesMap, err := s.BeaconDB.LightClientUpdates(ctx, startPeriod, endPeriod) + if err != nil { + httputil.HandleError(w, "Could not get light client updates from DB: "+err.Error(), http.StatusInternalServerError) + return } - // Get the initial endPeriod, then we will adjust - endPeriod := startPeriod + count - 1 - - // Adjust endPeriod, the end of end period must be earlier than current head slot - endPeriodEndSlot := (endPeriod+1)*slotsPerPeriod - 1 - if endPeriodEndSlot > maxSlot { - endPeriod = maxSlot / slotsPerPeriod - } - - // Populate updates - var updates []*structs.LightClientUpdateWithVersion - for period := startPeriod; period <= endPeriod; period++ { - // Get the last known state of the period, - // 1. We wish the block has a parent in the same period if possible - // 2. We wish the block has a state in the same period - lastSlotInPeriod := period*slotsPerPeriod + slotsPerPeriod - 1 - if lastSlotInPeriod > maxSlot { - lastSlotInPeriod = maxSlot - } - firstSlotInPeriod := period * slotsPerPeriod - - // Let's not use the first slot in the period, otherwise the attested header will be in previous period - firstSlotInPeriod++ - - var state state.BeaconState - var block interfaces.ReadOnlySignedBeaconBlock - for slot := lastSlotInPeriod; slot >= firstSlotInPeriod; slot-- { - state, err = s.Stater.StateBySlot(ctx, types.Slot(slot)) - if err != nil { - continue - } - - // Get the block - latestBlockHeader := state.LatestBlockHeader() - latestStateRoot, err := state.HashTreeRoot(ctx) - if err != nil { - continue - } - latestBlockHeader.StateRoot = latestStateRoot[:] - blockRoot, err := latestBlockHeader.HashTreeRoot() - if err != nil { - continue - } - - block, err = s.Blocker.Block(ctx, blockRoot[:]) - if err != nil || block == nil { - continue - } - - syncAggregate, err := block.Block().Body().SyncAggregate() - if err != nil || syncAggregate == nil { - continue - } - - if syncAggregate.SyncCommitteeBits.Count()*3 < config.SyncCommitteeSize*2 { - // Not enough votes - continue - } + updates := make([]*structs.LightClientUpdateResponse, 0, len(updatesMap)) + for i := startPeriod; i <= endPeriod; i++ { + update, ok := updatesMap[i] + if !ok { + // Only return the first contiguous range of updates break } - if block == nil { - // No valid block found for the period - continue - } - - // Get attested state - attestedRoot := block.Block().ParentRoot() - attestedBlock, err := s.Blocker.Block(ctx, attestedRoot[:]) - if err != nil || attestedBlock == nil { - continue - } - - attestedSlot := attestedBlock.Block().Slot() - attestedState, err := s.Stater.StateBySlot(ctx, attestedSlot) + updateJson, err := structs.LightClientUpdateFromConsensus(update) if err != nil { - continue + httputil.HandleError(w, "Could not convert light client update: "+err.Error(), http.StatusInternalServerError) + return } - - // Get finalized block - var finalizedBlock interfaces.ReadOnlySignedBeaconBlock - finalizedCheckPoint := attestedState.FinalizedCheckpoint() - if finalizedCheckPoint != nil { - finalizedRoot := bytesutil.ToBytes32(finalizedCheckPoint.Root) - finalizedBlock, err = s.Blocker.Block(ctx, finalizedRoot[:]) - if err != nil { - finalizedBlock = nil - } + updateResponse := &structs.LightClientUpdateResponse{ + Version: version.String(update.Version()), + Data: updateJson, } - - update, err := createLightClientUpdate( - ctx, - state, - block, - attestedState, - finalizedBlock, - ) - - if err == nil { - updates = append(updates, &structs.LightClientUpdateWithVersion{ - Version: version.String(attestedState.Version()), - Data: update, - }) - } - } - - if len(updates) == 0 { - httputil.HandleError(w, "no updates found", http.StatusNotFound) - return + updates = append(updates, updateResponse) } - httputil.WriteJson(w, updates) } // GetLightClientFinalityUpdate - implements https://github.com/ethereum/beacon-APIs/blob/263f4ed6c263c967f13279c7a9f5629b51c5fc55/apis/beacon/light_client/finality_update.yaml func (s *Server) GetLightClientFinalityUpdate(w http.ResponseWriter, req *http.Request) { - // Prepare + if !features.Get().EnableLightClient { + httputil.HandleError(w, "Light client feature flag is not enabled", http.StatusNotFound) + return + } + ctx, span := trace.StartSpan(req.Context(), "beacon.GetLightClientFinalityUpdate") defer span.End() @@ -232,56 +147,48 @@ func (s *Server) GetLightClientFinalityUpdate(w http.ResponseWriter, req *http.R minSyncCommitteeParticipants := float64(params.BeaconConfig().MinSyncCommitteeParticipants) minSignatures := uint64(math.Ceil(minSyncCommitteeParticipants * 2 / 3)) - block, err := s.getLightClientEventBlock(ctx, minSignatures) + block, err := s.suitableBlock(ctx, minSignatures) if !shared.WriteBlockFetchError(w, block, err) { return } - state, err := s.Stater.StateBySlot(ctx, block.Block().Slot()) + st, err := s.Stater.StateBySlot(ctx, block.Block().Slot()) if err != nil { - httputil.HandleError(w, "could not get state: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not get state: "+err.Error(), http.StatusInternalServerError) return } - // Get attested state attestedRoot := block.Block().ParentRoot() attestedBlock, err := s.Blocker.Block(ctx, attestedRoot[:]) - if err != nil || attestedBlock == nil { - httputil.HandleError(w, "could not get attested block: "+err.Error(), http.StatusInternalServerError) + if !shared.WriteBlockFetchError(w, block, errors.Wrap(err, "could not get attested block")) { return } - attestedSlot := attestedBlock.Block().Slot() attestedState, err := s.Stater.StateBySlot(ctx, attestedSlot) if err != nil { - httputil.HandleError(w, "could not get attested state: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not get attested state: "+err.Error(), http.StatusInternalServerError) return } - // Get finalized block var finalizedBlock interfaces.ReadOnlySignedBeaconBlock - finalizedCheckPoint := attestedState.FinalizedCheckpoint() - if finalizedCheckPoint != nil { - finalizedRoot := bytesutil.ToBytes32(finalizedCheckPoint.Root) - finalizedBlock, err = s.Blocker.Block(ctx, finalizedRoot[:]) - if err != nil { - finalizedBlock = nil - } + finalizedCheckpoint := attestedState.FinalizedCheckpoint() + if finalizedCheckpoint == nil { + httputil.HandleError(w, "Attested state does not have a finalized checkpoint", http.StatusInternalServerError) + return + } + finalizedRoot := bytesutil.ToBytes32(finalizedCheckpoint.Root) + finalizedBlock, err = s.Blocker.Block(ctx, finalizedRoot[:]) + if !shared.WriteBlockFetchError(w, block, errors.Wrap(err, "could not get finalized block")) { + return } - update, err := newLightClientFinalityUpdateFromBeaconState( - ctx, - state, - block, - attestedState, - finalizedBlock, - ) + update, err := newLightClientFinalityUpdateFromBeaconState(ctx, s.ChainInfoFetcher.CurrentSlot(), st, block, attestedState, attestedBlock, finalizedBlock) if err != nil { - httputil.HandleError(w, "could not get light client finality update: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not get light client finality update: "+err.Error(), http.StatusInternalServerError) return } - response := &structs.LightClientUpdateWithVersion{ + response := &structs.LightClientFinalityUpdateResponse{ Version: version.String(attestedState.Version()), Data: update, } @@ -291,54 +198,47 @@ func (s *Server) GetLightClientFinalityUpdate(w http.ResponseWriter, req *http.R // GetLightClientOptimisticUpdate - implements https://github.com/ethereum/beacon-APIs/blob/263f4ed6c263c967f13279c7a9f5629b51c5fc55/apis/beacon/light_client/optimistic_update.yaml func (s *Server) GetLightClientOptimisticUpdate(w http.ResponseWriter, req *http.Request) { - // Prepare + if !features.Get().EnableLightClient { + httputil.HandleError(w, "Light client feature flag is not enabled", http.StatusNotFound) + return + } + ctx, span := trace.StartSpan(req.Context(), "beacon.GetLightClientOptimisticUpdate") defer span.End() - minSignatures := params.BeaconConfig().MinSyncCommitteeParticipants - - block, err := s.getLightClientEventBlock(ctx, minSignatures) + block, err := s.suitableBlock(ctx, params.BeaconConfig().MinSyncCommitteeParticipants) if !shared.WriteBlockFetchError(w, block, err) { return } - - state, err := s.Stater.StateBySlot(ctx, block.Block().Slot()) + st, err := s.Stater.StateBySlot(ctx, block.Block().Slot()) if err != nil { httputil.HandleError(w, "could not get state: "+err.Error(), http.StatusInternalServerError) return } - - // Get attested state attestedRoot := block.Block().ParentRoot() attestedBlock, err := s.Blocker.Block(ctx, attestedRoot[:]) if err != nil { - httputil.HandleError(w, "could not get attested block: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not get attested block: "+err.Error(), http.StatusInternalServerError) return } if attestedBlock == nil { - httputil.HandleError(w, "attested block is nil", http.StatusInternalServerError) + httputil.HandleError(w, "Attested block is nil", http.StatusInternalServerError) return } - attestedSlot := attestedBlock.Block().Slot() attestedState, err := s.Stater.StateBySlot(ctx, attestedSlot) if err != nil { - httputil.HandleError(w, "could not get attested state: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not get attested state: "+err.Error(), http.StatusInternalServerError) return } - update, err := newLightClientOptimisticUpdateFromBeaconState( - ctx, - state, - block, - attestedState, - ) + update, err := newLightClientOptimisticUpdateFromBeaconState(ctx, s.ChainInfoFetcher.CurrentSlot(), st, block, attestedState, attestedBlock) if err != nil { - httputil.HandleError(w, "could not get light client optimistic update: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not get light client optimistic update: "+err.Error(), http.StatusInternalServerError) return } - response := &structs.LightClientUpdateWithVersion{ + response := &structs.LightClientOptimisticUpdateResponse{ Version: version.String(attestedState.Version()), Data: update, } @@ -346,37 +246,35 @@ func (s *Server) GetLightClientOptimisticUpdate(w http.ResponseWriter, req *http httputil.WriteJson(w, response) } -// getLightClientEventBlock - returns the block that should be used for light client events, which satisfies the minimum number of signatures from sync committee -func (s *Server) getLightClientEventBlock(ctx context.Context, minSignaturesRequired uint64) (interfaces.ReadOnlySignedBeaconBlock, error) { - // Get the current state - state, err := s.HeadFetcher.HeadState(ctx) +// suitableBlock returns the latest block that satisfies all criteria required for creating a new update +func (s *Server) suitableBlock(ctx context.Context, minSignaturesRequired uint64) (interfaces.ReadOnlySignedBeaconBlock, error) { + st, err := s.HeadFetcher.HeadState(ctx) if err != nil { - return nil, fmt.Errorf("could not get head state %w", err) + return nil, errors.Wrap(err, "could not get head state") } - // Get the block - latestBlockHeader := *state.LatestBlockHeader() - stateRoot, err := state.HashTreeRoot(ctx) + latestBlockHeader := st.LatestBlockHeader() + stateRoot, err := st.HashTreeRoot(ctx) if err != nil { - return nil, fmt.Errorf("could not get state root %w", err) + return nil, errors.Wrap(err, "could not get state root") } latestBlockHeader.StateRoot = stateRoot[:] latestBlockHeaderRoot, err := latestBlockHeader.HashTreeRoot() if err != nil { - return nil, fmt.Errorf("could not get latest block header root %w", err) + return nil, errors.Wrap(err, "could not get latest block header root") } block, err := s.Blocker.Block(ctx, latestBlockHeaderRoot[:]) if err != nil { - return nil, fmt.Errorf("could not get latest block %w", err) + return nil, errors.Wrap(err, "could not get latest block") } if block == nil { - return nil, fmt.Errorf("latest block is nil") + return nil, errors.New("latest block is nil") } // Loop through the blocks until we find a block that satisfies minSignaturesRequired requirement var numOfSyncCommitteeSignatures uint64 - if syncAggregate, err := block.Block().Body().SyncAggregate(); err == nil && syncAggregate != nil { + if syncAggregate, err := block.Block().Body().SyncAggregate(); err == nil { numOfSyncCommitteeSignatures = syncAggregate.SyncCommitteeBits.Count() } @@ -385,15 +283,15 @@ func (s *Server) getLightClientEventBlock(ctx context.Context, minSignaturesRequ parentRoot := block.Block().ParentRoot() block, err = s.Blocker.Block(ctx, parentRoot[:]) if err != nil { - return nil, fmt.Errorf("could not get parent block %w", err) + return nil, errors.Wrap(err, "could not get parent block") } if block == nil { - return nil, fmt.Errorf("parent block is nil") + return nil, errors.New("parent block is nil") } // Get the number of sync committee signatures numOfSyncCommitteeSignatures = 0 - if syncAggregate, err := block.Block().Body().SyncAggregate(); err == nil && syncAggregate != nil { + if syncAggregate, err := block.Block().Body().SyncAggregate(); err == nil { numOfSyncCommitteeSignatures = syncAggregate.SyncCommitteeBits.Count() } } diff --git a/beacon-chain/rpc/eth/light-client/handlers_test.go b/beacon-chain/rpc/eth/light-client/handlers_test.go index aff9643128cc..422dfcba9d40 100644 --- a/beacon-chain/rpc/eth/light-client/handlers_test.go +++ b/beacon-chain/rpc/eth/light-client/handlers_test.go @@ -5,815 +5,1123 @@ import ( "context" "encoding/json" "fmt" + "math/rand" "net/http" "net/http/httptest" + "strconv" "testing" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" mock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client" + dbtesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/testutil" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/features" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" ) func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) { - helpers.ClearCache() - slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) - - b := util.NewBeaconBlockCapella() - b.Block.StateRoot = bytesutil.PadTo([]byte("foo"), 32) - b.Block.Slot = slot - - signedBlock, err := blocks.NewSignedBeaconBlock(b) - - require.NoError(t, err) - header, err := signedBlock.Header() - require.NoError(t, err) - - r, err := b.Block.HashTreeRoot() - require.NoError(t, err) - - bs, err := util.NewBeaconStateCapella(func(state *ethpb.BeaconStateCapella) error { - state.BlockRoots[0] = r[:] - return nil - }) - require.NoError(t, err) - - require.NoError(t, bs.SetSlot(slot)) - require.NoError(t, bs.SetLatestBlockHeader(header.Header)) - - mockBlocker := &testutil.MockBlocker{BlockToReturn: signedBlock} - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot: bs, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - muxVars := make(map[string]string) - muxVars["block_root"] = hexutil.Encode(r[:]) - request := httptest.NewRequest("GET", "http://foo.com/", nil) - request = mux.SetURLVars(request, muxVars) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.GetLightClientBootstrap(writer, request) - require.Equal(t, http.StatusOK, writer.Code) - resp := &structs.LightClientBootstrapResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.Equal(t, "capella", resp.Version) - require.Equal(t, hexutil.Encode(header.Header.BodyRoot), resp.Data.Header.BodyRoot) - require.NotNil(t, resp.Data) -} - -func TestLightClientHandler_GetLightClientUpdatesByRange(t *testing.T) { - helpers.ClearCache() - ctx := context.Background() - config := params.BeaconConfig() - slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = attestedState.SetSlot(slot.Sub(1)) - require.NoError(t, err) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot.Sub(1) - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - parentHeader, err := signedParent.Header() - require.NoError(t, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - st, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = st.SetSlot(slot) - require.NoError(t, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(t, err) - - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < config.SyncCommitteeSize; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - h, err := signedBlock.Header() - require.NoError(t, err) - - err = st.SetLatestBlockHeader(h.Header) - require.NoError(t, err) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - root, err := block.Block.HashTreeRoot() - require.NoError(t, err) - - mockBlocker := &testutil.MockBlocker{ - RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ - parentRoot: signedParent, - root: signedBlock, - }, - SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ - slot.Sub(1): signedParent, - slot: signedBlock, - }, - } - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot.Sub(1): attestedState, - slot: st, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - startPeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) - url := fmt.Sprintf("http://foo.com/?count=1&start_period=%d", startPeriod) - request := httptest.NewRequest("GET", url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.GetLightClientUpdatesByRange(writer, request) - - require.Equal(t, http.StatusOK, writer.Code) - var resp []structs.LightClientUpdateWithVersion - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) - require.Equal(t, 1, len(resp)) - require.Equal(t, "capella", resp[0].Version) - require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), resp[0].Data.AttestedHeader.BodyRoot) - require.NotNil(t, resp) -} - -func TestLightClientHandler_GetLightClientUpdatesByRange_TooBigInputCount(t *testing.T) { - helpers.ClearCache() - ctx := context.Background() - config := params.BeaconConfig() - slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = attestedState.SetSlot(slot.Sub(1)) - require.NoError(t, err) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot.Sub(1) - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - parentHeader, err := signedParent.Header() - require.NoError(t, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - st, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = st.SetSlot(slot) - require.NoError(t, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(t, err) - - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < config.SyncCommitteeSize; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - h, err := signedBlock.Header() - require.NoError(t, err) - - err = st.SetLatestBlockHeader(h.Header) - require.NoError(t, err) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - root, err := block.Block.HashTreeRoot() - require.NoError(t, err) - - mockBlocker := &testutil.MockBlocker{ - RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ - parentRoot: signedParent, - root: signedBlock, - }, - SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ - slot.Sub(1): signedParent, - slot: signedBlock, - }, - } - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot.Sub(1): attestedState, - slot: st, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - startPeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) - count := 129 // config.MaxRequestLightClientUpdates is 128 - url := fmt.Sprintf("http://foo.com/?count=%d&start_period=%d", count, startPeriod) - request := httptest.NewRequest("GET", url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.GetLightClientUpdatesByRange(writer, request) - - require.Equal(t, http.StatusOK, writer.Code) - var resp []structs.LightClientUpdateWithVersion - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) - require.Equal(t, 1, len(resp)) // Even with big count input, the response is still the max available period, which is 1 in test case. - require.Equal(t, "capella", resp[0].Version) - require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), resp[0].Data.AttestedHeader.BodyRoot) - require.NotNil(t, resp) -} - -func TestLightClientHandler_GetLightClientUpdatesByRange_TooEarlyPeriod(t *testing.T) { - helpers.ClearCache() - ctx := context.Background() - config := params.BeaconConfig() - slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = attestedState.SetSlot(slot.Sub(1)) - require.NoError(t, err) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot.Sub(1) - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - parentHeader, err := signedParent.Header() - require.NoError(t, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - st, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = st.SetSlot(slot) - require.NoError(t, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(t, err) - - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < config.SyncCommitteeSize; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - h, err := signedBlock.Header() - require.NoError(t, err) - - err = st.SetLatestBlockHeader(h.Header) - require.NoError(t, err) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - root, err := block.Block.HashTreeRoot() - require.NoError(t, err) - - mockBlocker := &testutil.MockBlocker{ - RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ - parentRoot: signedParent, - root: signedBlock, - }, - SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ - slot.Sub(1): signedParent, - slot: signedBlock, - }, - } - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot.Sub(1): attestedState, - slot: st, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - startPeriod := 1 // very early period before Altair fork - count := 1 - url := fmt.Sprintf("http://foo.com/?count=%d&start_period=%d", count, startPeriod) - request := httptest.NewRequest("GET", url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.GetLightClientUpdatesByRange(writer, request) - - require.Equal(t, http.StatusOK, writer.Code) - var resp []structs.LightClientUpdateWithVersion - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) - require.Equal(t, 1, len(resp)) - require.Equal(t, "capella", resp[0].Version) - require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), resp[0].Data.AttestedHeader.BodyRoot) - require.NotNil(t, resp) -} - -func TestLightClientHandler_GetLightClientUpdatesByRange_TooBigCount(t *testing.T) { - helpers.ClearCache() - ctx := context.Background() - config := params.BeaconConfig() - slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = attestedState.SetSlot(slot.Sub(1)) - require.NoError(t, err) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot.Sub(1) - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - parentHeader, err := signedParent.Header() - require.NoError(t, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - st, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = st.SetSlot(slot) - require.NoError(t, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(t, err) - - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < config.SyncCommitteeSize; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - h, err := signedBlock.Header() - require.NoError(t, err) - - err = st.SetLatestBlockHeader(h.Header) - require.NoError(t, err) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - root, err := block.Block.HashTreeRoot() - require.NoError(t, err) - - mockBlocker := &testutil.MockBlocker{ - RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ - parentRoot: signedParent, - root: signedBlock, - }, - SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ - slot.Sub(1): signedParent, - slot: signedBlock, - }, - } - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot.Sub(1): attestedState, - slot: st, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - startPeriod := 1 // very early period before Altair fork - count := 10 // This is big count as we only have one period in test case. - url := fmt.Sprintf("http://foo.com/?count=%d&start_period=%d", count, startPeriod) - request := httptest.NewRequest("GET", url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.GetLightClientUpdatesByRange(writer, request) - - require.Equal(t, http.StatusOK, writer.Code) - var resp []structs.LightClientUpdateWithVersion - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) - require.Equal(t, 1, len(resp)) - require.Equal(t, "capella", resp[0].Version) - require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), resp[0].Data.AttestedHeader.BodyRoot) - require.NotNil(t, resp) -} - -func TestLightClientHandler_GetLightClientUpdatesByRange_BeforeAltair(t *testing.T) { - helpers.ClearCache() - ctx := context.Background() - config := params.BeaconConfig() - slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Sub(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = attestedState.SetSlot(slot.Sub(1)) - require.NoError(t, err) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot.Sub(1) - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - parentHeader, err := signedParent.Header() - require.NoError(t, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - st, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = st.SetSlot(slot) - require.NoError(t, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(t, err) - - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < config.SyncCommitteeSize; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - h, err := signedBlock.Header() - require.NoError(t, err) - - err = st.SetLatestBlockHeader(h.Header) - require.NoError(t, err) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - root, err := block.Block.HashTreeRoot() - require.NoError(t, err) - - mockBlocker := &testutil.MockBlocker{ - RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ - parentRoot: signedParent, - root: signedBlock, - }, - SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ - slot.Sub(1): signedParent, - slot: signedBlock, - }, - } - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot.Sub(1): attestedState, - slot: st, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - startPeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) - count := 1 - url := fmt.Sprintf("http://foo.com/?count=%d&start_period=%d", count, startPeriod) - request := httptest.NewRequest("GET", url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.GetLightClientUpdatesByRange(writer, request) - - require.Equal(t, http.StatusNotFound, writer.Code) -} - -func TestLightClientHandler_GetLightClientFinalityUpdate(t *testing.T) { - helpers.ClearCache() - ctx := context.Background() - config := params.BeaconConfig() - slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = attestedState.SetSlot(slot.Sub(1)) - require.NoError(t, err) - - require.NoError(t, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: config.AltairForkEpoch - 10, - Root: make([]byte, 32), - })) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot.Sub(1) - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - parentHeader, err := signedParent.Header() - require.NoError(t, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - st, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = st.SetSlot(slot) - require.NoError(t, err) - - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(t, err) - - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] - - for i := uint64(0); i < config.SyncCommitteeSize; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - h, err := signedBlock.Header() - require.NoError(t, err) + resetFn := features.InitWithReset(&features.Flags{ + EnableLightClient: true, + }) + defer resetFn() + + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + cfg.AltairForkEpoch = 0 + cfg.BellatrixForkEpoch = 1 + cfg.CapellaForkEpoch = 2 + cfg.DenebForkEpoch = 3 + cfg.ElectraForkEpoch = 4 + cfg.FuluForkEpoch = 5 + params.OverrideBeaconConfig(cfg) + + t.Run("altair", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + + var resp structs.LightClientBootstrapResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) + require.NoError(t, err) + var respHeader structs.LightClientHeader + err = json.Unmarshal(resp.Data.Header, &respHeader) + require.NoError(t, err) + require.Equal(t, "altair", resp.Version) + + blockHeader, err := l.Block.Header() + require.NoError(t, err) + require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot) + require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot) + + require.NotNil(t, resp.Data.CurrentSyncCommittee) + require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) + }) + t.Run("altairSSZ", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() + + slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + + var resp pb.LightClientBootstrapAltair + err = resp.UnmarshalSSZ(writer.Body.Bytes()) + require.NoError(t, err) + require.DeepEqual(t, resp.Header, bootstrap.Header().Proto()) + require.DeepEqual(t, resp.CurrentSyncCommittee, bootstrap.CurrentSyncCommittee()) + require.NotNil(t, resp.CurrentSyncCommitteeBranch) + }) + t.Run("altair - no bootstrap found", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestAltair() - err = st.SetLatestBlockHeader(h.Header) - require.NoError(t, err) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) + slot := primitives.Slot(params.BeaconConfig().AltairForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) - root, err := block.Block.HashTreeRoot() - require.NoError(t, err) + db := dbtesting.SetupDB(t) - mockBlocker := &testutil.MockBlocker{ - RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ - parentRoot: signedParent, - root: signedBlock, - }, - SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ - slot.Sub(1): signedParent, - slot: signedBlock, - }, - } - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ - root: true, - }} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot.Sub(1): attestedState, - slot: st, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - request := httptest.NewRequest("GET", "http://foo.com", nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[1:], bootstrap) + require.NoError(t, err) - s.GetLightClientFinalityUpdate(writer, request) + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} - require.Equal(t, http.StatusOK, writer.Code) - resp := &structs.LightClientUpdateWithVersion{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.Equal(t, "capella", resp.Version) - require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), resp.Data.AttestedHeader.BodyRoot) - require.NotNil(t, resp.Data) + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusNotFound, writer.Code) + }) + t.Run("bellatrix", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestBellatrix() + + slot := primitives.Slot(params.BeaconConfig().BellatrixForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientBootstrapResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) + require.NoError(t, err) + var respHeader structs.LightClientHeader + err = json.Unmarshal(resp.Data.Header, &respHeader) + require.NoError(t, err) + require.Equal(t, "altair", resp.Version) + + blockHeader, err := l.Block.Header() + require.NoError(t, err) + require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot) + require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot) + + require.NotNil(t, resp.Data.CurrentSyncCommittee) + require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) + }) + t.Run("bellatrixSSZ", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestBellatrix() + + slot := primitives.Slot(params.BeaconConfig().BellatrixForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + + var resp pb.LightClientBootstrapAltair + err = resp.UnmarshalSSZ(writer.Body.Bytes()) + require.NoError(t, err) + require.DeepEqual(t, resp.Header, bootstrap.Header().Proto()) + require.DeepEqual(t, resp.CurrentSyncCommittee, bootstrap.CurrentSyncCommittee()) + require.NotNil(t, resp.CurrentSyncCommitteeBranch) + }) + t.Run("capella", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) // result is same for true and false + + slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientBootstrapResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) + require.NoError(t, err) + var respHeader structs.LightClientHeader + err = json.Unmarshal(resp.Data.Header, &respHeader) + require.NoError(t, err) + require.Equal(t, "capella", resp.Version) + + blockHeader, err := l.Block.Header() + require.NoError(t, err) + require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot) + require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot) + + require.NotNil(t, resp.Data.CurrentSyncCommittee) + require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) + }) + t.Run("capellaSSZ", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestCapella(false) // result is same for true and false + + slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + + var resp pb.LightClientBootstrapCapella + err = resp.UnmarshalSSZ(writer.Body.Bytes()) + require.NoError(t, err) + require.DeepEqual(t, resp.Header, bootstrap.Header().Proto()) + require.DeepEqual(t, resp.CurrentSyncCommittee, bootstrap.CurrentSyncCommittee()) + require.NotNil(t, resp.CurrentSyncCommitteeBranch) + }) + t.Run("deneb", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) // result is same for true and false + + slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientBootstrapResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) + require.NoError(t, err) + var respHeader structs.LightClientHeader + err = json.Unmarshal(resp.Data.Header, &respHeader) + require.NoError(t, err) + require.Equal(t, "deneb", resp.Version) + + blockHeader, err := l.Block.Header() + require.NoError(t, err) + require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot) + require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot) + + require.NotNil(t, resp.Data.CurrentSyncCommittee) + require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) + }) + t.Run("denebSSZ", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestDeneb(false) // result is same for true and false + + slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + + var resp pb.LightClientBootstrapDeneb + err = resp.UnmarshalSSZ(writer.Body.Bytes()) + require.NoError(t, err) + require.DeepEqual(t, resp.Header, bootstrap.Header().Proto()) + require.DeepEqual(t, resp.CurrentSyncCommittee, bootstrap.CurrentSyncCommittee()) + require.NotNil(t, resp.CurrentSyncCommitteeBranch) + }) + t.Run("electra", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestElectra(false) // result is same for true and false + + slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientBootstrapResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) + require.NoError(t, err) + var respHeader structs.LightClientHeader + err = json.Unmarshal(resp.Data.Header, &respHeader) + require.NoError(t, err) + require.Equal(t, "electra", resp.Version) + + blockHeader, err := l.Block.Header() + require.NoError(t, err) + require.Equal(t, hexutil.Encode(blockHeader.Header.BodyRoot), respHeader.Beacon.BodyRoot) + require.Equal(t, strconv.FormatUint(uint64(blockHeader.Header.Slot), 10), respHeader.Beacon.Slot) + + require.NotNil(t, resp.Data.CurrentSyncCommittee) + require.NotNil(t, resp.Data.CurrentSyncCommitteeBranch) + }) + t.Run("electraSSZ", func(t *testing.T) { + l := util.NewTestLightClient(t).SetupTestElectra(false) // result is same for true and false + + slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + blockRoot, err := l.Block.Block().HashTreeRoot() + require.NoError(t, err) + + bootstrap, err := lightclient.NewLightClientBootstrapFromBeaconState(l.Ctx, slot, l.State, l.Block) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + err = db.SaveLightClientBootstrap(l.Ctx, blockRoot[:], bootstrap) + require.NoError(t, err) + + s := &Server{ + BeaconDB: db, + } + request := httptest.NewRequest("GET", "http://foo.com/", nil) + request.SetPathValue("block_root", hexutil.Encode(blockRoot[:])) + request.Header.Add("Accept", "application/octet-stream") + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientBootstrap(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + + var resp pb.LightClientBootstrapElectra + err = resp.UnmarshalSSZ(writer.Body.Bytes()) + require.NoError(t, err) + require.DeepEqual(t, resp.Header, bootstrap.Header().Proto()) + require.DeepEqual(t, resp.CurrentSyncCommittee, bootstrap.CurrentSyncCommittee()) + require.NotNil(t, resp.CurrentSyncCommitteeBranch) + }) } -func TestLightClientHandler_GetLightClientOptimisticUpdate(t *testing.T) { +func TestLightClientHandler_GetLightClientByRange(t *testing.T) { + resetFn := features.InitWithReset(&features.Flags{ + EnableLightClient: true, + }) + defer resetFn() + helpers.ClearCache() ctx := context.Background() - config := params.BeaconConfig() - slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = attestedState.SetSlot(slot.Sub(1)) - require.NoError(t, err) - - require.NoError(t, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: config.AltairForkEpoch - 10, - Root: make([]byte, 32), - })) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot.Sub(1) - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - - parentHeader, err := signedParent.Header() - require.NoError(t, err) - attestedHeader := parentHeader.Header - - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(t, err) - - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - st, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = st.SetSlot(slot) - require.NoError(t, err) + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.EpochsPerSyncCommitteePeriod = 1 + config.AltairForkEpoch = 0 + config.CapellaForkEpoch = 1 + config.DenebForkEpoch = 2 + params.OverrideBeaconConfig(config) + + t.Run("altair", func(t *testing.T) { + slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updatePeriod := uint64(slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch))) + + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + err = db.SaveLightClientUpdate(ctx, updatePeriod, update) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=1&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 1, len(resp.Updates)) + require.Equal(t, "altair", resp.Updates[0].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[0].Data) + }) - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(t, err) + t.Run("capella", func(t *testing.T) { + slot := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateCapella() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updatePeriod := uint64(slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch))) + + update, err := createUpdate(t, version.Capella) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, updatePeriod, update) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=1&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 1, len(resp.Updates)) + require.Equal(t, "capella", resp.Updates[0].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[0].Data) + }) - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] + t.Run("deneb", func(t *testing.T) { + slot := primitives.Slot(config.DenebForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateDeneb() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updatePeriod := uint64(slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch))) + + update, err := createUpdate(t, version.Deneb) + require.NoError(t, err) + err = db.SaveLightClientUpdate(ctx, updatePeriod, update) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=1&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 1, len(resp.Updates)) + require.Equal(t, "deneb", resp.Updates[0].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[0].Data) + }) - for i := uint64(0); i < config.SyncCommitteeSize; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } + t.Run("altair Multiple", func(t *testing.T) { + slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + headSlot := slot.Add(2 * uint64(config.SlotsPerEpoch) * uint64(config.EpochsPerSyncCommitteePeriod)) // 2 periods + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updatePeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates := make([]interfaces.LightClientUpdate, 0) + for i := 1; i <= 2; i++ { + update, err := createUpdate(t, version.Altair) + require.NoError(t, err) + updates = append(updates, update) + } + + for _, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(updatePeriod), update) + require.NoError(t, err) + updatePeriod++ + } + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slot.Sub(1).Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Updates)) + for i, update := range updates { + require.Equal(t, "altair", resp.Updates[i].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[i].Data) + } + }) - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) + t.Run("capella Multiple", func(t *testing.T) { + slot := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + headSlot := slot.Add(2 * uint64(config.SlotsPerEpoch) * uint64(config.EpochsPerSyncCommitteePeriod)) // 2 periods + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updatePeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates := make([]interfaces.LightClientUpdate, 0) + for i := 0; i < 2; i++ { + update, err := createUpdate(t, version.Capella) + require.NoError(t, err) + updates = append(updates, update) + } + + for _, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(updatePeriod), update) + require.NoError(t, err) + updatePeriod++ + } + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slot.Sub(1).Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Updates)) + for i, update := range updates { + require.Equal(t, "capella", resp.Updates[i].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[i].Data) + } + }) - h, err := signedBlock.Header() - require.NoError(t, err) + t.Run("deneb Multiple", func(t *testing.T) { + slot := primitives.Slot(config.DenebForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + headSlot := slot.Add(2 * uint64(config.SlotsPerEpoch) * uint64(config.EpochsPerSyncCommitteePeriod)) + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updatePeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates := make([]interfaces.LightClientUpdate, 0) + for i := 0; i < 2; i++ { + update, err := createUpdate(t, version.Deneb) + require.NoError(t, err) + updates = append(updates, update) + } + + for _, update := range updates { + err := db.SaveLightClientUpdate(ctx, uint64(updatePeriod), update) + require.NoError(t, err) + updatePeriod++ + } + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := slot.Sub(1).Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Updates)) + for i, update := range updates { + require.Equal(t, "deneb", resp.Updates[i].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[i].Data) + } + }) - err = st.SetLatestBlockHeader(h.Header) - require.NoError(t, err) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) + t.Run("multiple forks - altair, capella", func(t *testing.T) { + slotCapella := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + slotAltair := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + headSlot := slotCapella.Add(1) + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updates := make([]interfaces.LightClientUpdate, 2) + + updatePeriod := slotAltair.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates[0], err = createUpdate(t, version.Altair) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[0]) + require.NoError(t, err) + + updatePeriod = slotCapella.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates[1], err = createUpdate(t, version.Capella) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[1]) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := 0 + url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Updates)) + for i, update := range updates { + if i < 1 { + require.Equal(t, "altair", resp.Updates[i].Version) + } else { + require.Equal(t, "capella", resp.Updates[i].Version) + } + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[i].Data) + } + }) - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) + t.Run("multiple forks - capella, deneb", func(t *testing.T) { + slotDeneb := primitives.Slot(config.DenebForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + slotCapella := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + headSlot := slotDeneb.Add(1) + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updates := make([]interfaces.LightClientUpdate, 2) + + updatePeriod := slotCapella.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates[0], err = createUpdate(t, version.Capella) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[0]) + require.NoError(t, err) + + updatePeriod = slotDeneb.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + updates[1], err = createUpdate(t, version.Deneb) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[1]) + require.NoError(t, err) + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := 1 + url := fmt.Sprintf("http://foo.com/?count=100&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Updates)) + for i, update := range updates { + if i < 1 { + require.Equal(t, "capella", resp.Updates[i].Version) + } else { + require.Equal(t, "deneb", resp.Updates[i].Version) + } + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[i].Data) + } + }) - root, err := block.Block.HashTreeRoot() - require.NoError(t, err) + t.Run("count bigger than limit", func(t *testing.T) { + config.MaxRequestLightClientUpdates = 2 + params.OverrideBeaconConfig(config) + slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + headSlot := slot.Add(4 * uint64(config.SlotsPerEpoch) * uint64(config.EpochsPerSyncCommitteePeriod)) // 4 periods + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updates := make([]interfaces.LightClientUpdate, 3) + + updatePeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + for i := 0; i < 3; i++ { + + updates[i], err = createUpdate(t, version.Altair) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[i]) + require.NoError(t, err) + + updatePeriod++ + } + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := 0 + url := fmt.Sprintf("http://foo.com/?count=4&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Updates)) + for i, update := range updates { + if i < 2 { + require.Equal(t, "altair", resp.Updates[i].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[i].Data) + } + } + }) - mockBlocker := &testutil.MockBlocker{ - RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ - parentRoot: signedParent, - root: signedBlock, - }, - SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ - slot.Sub(1): signedParent, - slot: signedBlock, - }, - } - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ - root: true, - }} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot.Sub(1): attestedState, - slot: st, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - request := httptest.NewRequest("GET", "http://foo.com", nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + t.Run("count bigger than max", func(t *testing.T) { + config.MaxRequestLightClientUpdates = 2 + params.OverrideBeaconConfig(config) + slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + headSlot := slot.Add(4 * uint64(config.SlotsPerEpoch) * uint64(config.EpochsPerSyncCommitteePeriod)) // 4 periods + err = st.SetSlot(headSlot) + require.NoError(t, err) + + db := dbtesting.SetupDB(t) + + updates := make([]interfaces.LightClientUpdate, 3) + + updatePeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + for i := 0; i < 3; i++ { + updates[i], err = createUpdate(t, version.Altair) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[i]) + require.NoError(t, err) + + updatePeriod++ + } + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := 0 + url := fmt.Sprintf("http://foo.com/?count=10&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 2, len(resp.Updates)) + for i, update := range updates { + if i < 2 { + require.Equal(t, "altair", resp.Updates[i].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(update) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[i].Data) + } + } + }) - s.GetLightClientOptimisticUpdate(writer, request) + t.Run("start period before altair", func(t *testing.T) { + db := dbtesting.SetupDB(t) + + s := &Server{ + BeaconDB: db, + } + startPeriod := 0 + url := fmt.Sprintf("http://foo.com/?count=128&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err := json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 0, len(resp.Updates)) + }) - require.Equal(t, http.StatusOK, writer.Code) - resp := &structs.LightClientUpdateWithVersion{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.Equal(t, "capella", resp.Version) - require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), resp.Data.AttestedHeader.BodyRoot) - require.NotNil(t, resp.Data) + t.Run("missing updates", func(t *testing.T) { + slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + headSlot := slot.Add(4 * uint64(config.SlotsPerEpoch) * uint64(config.EpochsPerSyncCommitteePeriod)) // 4 periods + err = st.SetSlot(headSlot) + require.NoError(t, err) + + t.Run("missing update in the middle", func(t *testing.T) { + db := dbtesting.SetupDB(t) + + updates := make([]interfaces.LightClientUpdate, 3) + + updatePeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + for i := 0; i < 3; i++ { + if i == 1 { // skip this update + updatePeriod++ + continue + } + + updates[i], err = createUpdate(t, version.Altair) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[i]) + require.NoError(t, err) + + updatePeriod++ + } + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := 0 + url := fmt.Sprintf("http://foo.com/?count=10&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 1, len(resp.Updates)) + require.Equal(t, "altair", resp.Updates[0].Version) + updateJson, err := structs.LightClientUpdateFromConsensus(updates[0]) + require.NoError(t, err) + require.DeepEqual(t, updateJson, resp.Updates[0].Data) + }) + + t.Run("missing update at the beginning", func(t *testing.T) { + db := dbtesting.SetupDB(t) + + updates := make([]interfaces.LightClientUpdate, 3) + + updatePeriod := slot.Div(uint64(config.EpochsPerSyncCommitteePeriod)).Div(uint64(config.SlotsPerEpoch)) + + for i := 0; i < 3; i++ { + if i == 0 { // skip this update + updatePeriod++ + continue + } + + updates[i], err = createUpdate(t, version.Altair) + require.NoError(t, err) + + err = db.SaveLightClientUpdate(ctx, uint64(updatePeriod), updates[i]) + require.NoError(t, err) + + updatePeriod++ + } + + mockChainService := &mock.ChainService{State: st} + s := &Server{ + HeadFetcher: mockChainService, + BeaconDB: db, + } + startPeriod := 0 + url := fmt.Sprintf("http://foo.com/?count=10&start_period=%d", startPeriod) + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientUpdatesByRange(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp structs.LightClientUpdatesByRangeResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp.Updates) + require.NoError(t, err) + require.Equal(t, 0, len(resp.Updates)) + }) + }) } -func TestLightClientHandler_GetLightClientEventBlock(t *testing.T) { +func TestLightClientHandler_GetLightClientFinalityUpdate(t *testing.T) { + resetFn := features.InitWithReset(&features.Flags{ + EnableLightClient: true, + }) + defer resetFn() + helpers.ClearCache() ctx := context.Background() config := params.BeaconConfig() slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - attestedState, err := util.NewBeaconStateCapella() + attestedState, err := util.NewBeaconStateAltair() require.NoError(t, err) err = attestedState.SetSlot(slot.Sub(1)) require.NoError(t, err) - require.NoError(t, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + require.NoError(t, attestedState.SetFinalizedCheckpoint(&pb.Checkpoint{ Epoch: config.AltairForkEpoch - 10, Root: make([]byte, 32), })) - parent := util.NewBeaconBlockCapella() + parent := util.NewBeaconBlockAltair() parent.Block.Slot = slot.Sub(1) signedParent, err := blocks.NewSignedBeaconBlock(parent) @@ -833,7 +1141,7 @@ func TestLightClientHandler_GetLightClientEventBlock(t *testing.T) { signedParent, err = blocks.NewSignedBeaconBlock(parent) require.NoError(t, err) - st, err := util.NewBeaconStateCapella() + st, err := util.NewBeaconStateAltair() require.NoError(t, err) err = st.SetSlot(slot) require.NoError(t, err) @@ -841,7 +1149,7 @@ func TestLightClientHandler_GetLightClientEventBlock(t *testing.T) { parentRoot, err := signedParent.Block().HashTreeRoot() require.NoError(t, err) - block := util.NewBeaconBlockCapella() + block := util.NewBeaconBlockAltair() block.Block.Slot = slot block.Block.ParentRoot = parentRoot[:] @@ -881,129 +1189,752 @@ func TestLightClientHandler_GetLightClientEventBlock(t *testing.T) { mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ root: true, }} + mockChainInfoFetcher := &mock.ChainService{Slot: &slot} s := &Server{ Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ slot.Sub(1): attestedState, slot: st, }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, + Blocker: mockBlocker, + HeadFetcher: mockChainService, + ChainInfoFetcher: mockChainInfoFetcher, } + request := httptest.NewRequest("GET", "http://foo.com", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} - minSignaturesRequired := uint64(100) - eventBlock, err := s.getLightClientEventBlock(ctx, minSignaturesRequired) + s.GetLightClientFinalityUpdate(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + var resp *structs.LightClientUpdateResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) require.NoError(t, err) - require.NotNil(t, eventBlock) - require.Equal(t, slot, eventBlock.Block().Slot()) - syncAggregate, err := eventBlock.Block().Body().SyncAggregate() + var respHeader structs.LightClientHeader + err = json.Unmarshal(resp.Data.AttestedHeader, &respHeader) require.NoError(t, err) - require.Equal(t, true, syncAggregate.SyncCommitteeBits.Count() >= minSignaturesRequired) + require.Equal(t, "altair", resp.Version) + require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), respHeader.Beacon.BodyRoot) + require.NotNil(t, resp.Data) } -func TestLightClientHandler_GetLightClientEventBlock_NeedFetchParent(t *testing.T) { +func TestLightClientHandler_GetLightClientOptimisticUpdate(t *testing.T) { + resetFn := features.InitWithReset(&features.Flags{ + EnableLightClient: true, + }) + defer resetFn() helpers.ClearCache() - ctx := context.Background() config := params.BeaconConfig() - slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) - - attestedState, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = attestedState.SetSlot(slot.Sub(1)) - require.NoError(t, err) - - require.NoError(t, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ - Epoch: config.AltairForkEpoch - 10, - Root: make([]byte, 32), - })) - - parent := util.NewBeaconBlockCapella() - parent.Block.Slot = slot.Sub(1) - for i := uint64(0); i < config.SyncCommitteeSize; i++ { - parent.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) - } - - signedParent, err := blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) - parentHeader, err := signedParent.Header() - require.NoError(t, err) - attestedHeader := parentHeader.Header + t.Run("altair", func(t *testing.T) { + ctx := context.Background() + slot := primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + attestedState, err := util.NewBeaconStateAltair() + require.NoError(t, err) + err = attestedState.SetSlot(slot.Sub(1)) + require.NoError(t, err) + + require.NoError(t, attestedState.SetFinalizedCheckpoint(&pb.Checkpoint{ + Epoch: config.AltairForkEpoch - 10, + Root: make([]byte, 32), + })) + + parent := util.NewBeaconBlockAltair() + parent.Block.Slot = slot.Sub(1) + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + parentHeader, err := signedParent.Header() + require.NoError(t, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(t, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + st, err := util.NewBeaconStateAltair() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(t, err) + + block := util.NewBeaconBlockAltair() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < config.SyncCommitteeSize; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + h, err := signedBlock.Header() + require.NoError(t, err) + + err = st.SetLatestBlockHeader(h.Header) + require.NoError(t, err) + stateRoot, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + root, err := block.Block.HashTreeRoot() + require.NoError(t, err) + + mockBlocker := &testutil.MockBlocker{ + RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ + parentRoot: signedParent, + root: signedBlock, + }, + SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ + slot.Sub(1): signedParent, + slot: signedBlock, + }, + } + mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ + root: true, + }} + mockChainInfoFetcher := &mock.ChainService{Slot: &slot} + s := &Server{ + Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ + slot.Sub(1): attestedState, + slot: st, + }}, + Blocker: mockBlocker, + HeadFetcher: mockChainService, + ChainInfoFetcher: mockChainInfoFetcher, + } + request := httptest.NewRequest("GET", "http://foo.com", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientOptimisticUpdate(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp *structs.LightClientUpdateResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) + require.NoError(t, err) + var respHeader structs.LightClientHeader + err = json.Unmarshal(resp.Data.AttestedHeader, &respHeader) + require.NoError(t, err) + require.Equal(t, "altair", resp.Version) + require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), respHeader.Beacon.BodyRoot) + require.NotNil(t, resp.Data) + }) - err = attestedState.SetLatestBlockHeader(attestedHeader) - require.NoError(t, err) - attestedStateRoot, err := attestedState.HashTreeRoot(ctx) - require.NoError(t, err) + t.Run("capella", func(t *testing.T) { + ctx := context.Background() + slot := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + attestedState, err := util.NewBeaconStateCapella() + require.NoError(t, err) + err = attestedState.SetSlot(slot.Sub(1)) + require.NoError(t, err) + + require.NoError(t, attestedState.SetFinalizedCheckpoint(&pb.Checkpoint{ + Epoch: config.AltairForkEpoch - 10, + Root: make([]byte, 32), + })) + + parent := util.NewBeaconBlockCapella() + parent.Block.Slot = slot.Sub(1) + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + parentHeader, err := signedParent.Header() + require.NoError(t, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(t, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + st, err := util.NewBeaconStateCapella() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(t, err) + + block := util.NewBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < config.SyncCommitteeSize; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + h, err := signedBlock.Header() + require.NoError(t, err) + + err = st.SetLatestBlockHeader(h.Header) + require.NoError(t, err) + stateRoot, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + root, err := block.Block.HashTreeRoot() + require.NoError(t, err) + + mockBlocker := &testutil.MockBlocker{ + RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ + parentRoot: signedParent, + root: signedBlock, + }, + SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ + slot.Sub(1): signedParent, + slot: signedBlock, + }, + } + mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ + root: true, + }} + mockChainInfoFetcher := &mock.ChainService{Slot: &slot} + s := &Server{ + Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ + slot.Sub(1): attestedState, + slot: st, + }}, + Blocker: mockBlocker, + HeadFetcher: mockChainService, + ChainInfoFetcher: mockChainInfoFetcher, + } + request := httptest.NewRequest("GET", "http://foo.com", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientOptimisticUpdate(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp *structs.LightClientUpdateResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) + require.NoError(t, err) + var respHeader structs.LightClientHeaderCapella + err = json.Unmarshal(resp.Data.AttestedHeader, &respHeader) + require.NoError(t, err) + require.Equal(t, "capella", resp.Version) + require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), respHeader.Beacon.BodyRoot) + require.NotNil(t, resp.Data) + }) - // get a new signed block so the root is updated with the new state root - parent.Block.StateRoot = attestedStateRoot[:] - signedParent, err = blocks.NewSignedBeaconBlock(parent) - require.NoError(t, err) + t.Run("deneb", func(t *testing.T) { + ctx := context.Background() + slot := primitives.Slot(config.DenebForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + attestedState, err := util.NewBeaconStateDeneb() + require.NoError(t, err) + err = attestedState.SetSlot(slot.Sub(1)) + require.NoError(t, err) + + require.NoError(t, attestedState.SetFinalizedCheckpoint(&pb.Checkpoint{ + Epoch: config.AltairForkEpoch - 10, + Root: make([]byte, 32), + })) + + parent := util.NewBeaconBlockDeneb() + parent.Block.Slot = slot.Sub(1) + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + parentHeader, err := signedParent.Header() + require.NoError(t, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(t, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + st, err := util.NewBeaconStateDeneb() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(t, err) + + block := util.NewBeaconBlockDeneb() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < config.SyncCommitteeSize; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + h, err := signedBlock.Header() + require.NoError(t, err) + + err = st.SetLatestBlockHeader(h.Header) + require.NoError(t, err) + stateRoot, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + root, err := block.Block.HashTreeRoot() + require.NoError(t, err) + + mockBlocker := &testutil.MockBlocker{ + RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ + parentRoot: signedParent, + root: signedBlock, + }, + SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ + slot.Sub(1): signedParent, + slot: signedBlock, + }, + } + mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ + root: true, + }} + mockChainInfoFetcher := &mock.ChainService{Slot: &slot} + s := &Server{ + Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ + slot.Sub(1): attestedState, + slot: st, + }}, + Blocker: mockBlocker, + HeadFetcher: mockChainService, + ChainInfoFetcher: mockChainInfoFetcher, + } + request := httptest.NewRequest("GET", "http://foo.com", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.GetLightClientOptimisticUpdate(writer, request) + + require.Equal(t, http.StatusOK, writer.Code) + var resp *structs.LightClientUpdateResponse + err = json.Unmarshal(writer.Body.Bytes(), &resp) + require.NoError(t, err) + var respHeader structs.LightClientHeaderDeneb + err = json.Unmarshal(resp.Data.AttestedHeader, &respHeader) + require.NoError(t, err) + require.Equal(t, "deneb", resp.Version) + require.Equal(t, hexutil.Encode(attestedHeader.BodyRoot), respHeader.Beacon.BodyRoot) + require.NotNil(t, resp.Data) + }) +} - st, err := util.NewBeaconStateCapella() - require.NoError(t, err) - err = st.SetSlot(slot) - require.NoError(t, err) +func TestLightClientHandler_GetLightClientEventBlock(t *testing.T) { + helpers.ClearCache() + config := params.BeaconConfig() - parentRoot, err := signedParent.Block().HashTreeRoot() - require.NoError(t, err) + t.Run("head suitable", func(t *testing.T) { + ctx := context.Background() + slot := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + attestedState, err := util.NewBeaconStateCapella() + require.NoError(t, err) + err = attestedState.SetSlot(slot.Sub(1)) + require.NoError(t, err) + + require.NoError(t, attestedState.SetFinalizedCheckpoint(&pb.Checkpoint{ + Epoch: config.AltairForkEpoch - 10, + Root: make([]byte, 32), + })) + + parent := util.NewBeaconBlockCapella() + parent.Block.Slot = slot.Sub(1) + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + parentHeader, err := signedParent.Header() + require.NoError(t, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(t, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + st, err := util.NewBeaconStateCapella() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(t, err) + + block := util.NewBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < config.SyncCommitteeSize; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + h, err := signedBlock.Header() + require.NoError(t, err) + + err = st.SetLatestBlockHeader(h.Header) + require.NoError(t, err) + stateRoot, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + root, err := block.Block.HashTreeRoot() + require.NoError(t, err) + + mockBlocker := &testutil.MockBlocker{ + RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ + parentRoot: signedParent, + root: signedBlock, + }, + SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ + slot.Sub(1): signedParent, + slot: signedBlock, + }, + } + mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ + root: true, + }} + mockChainInfoFetcher := &mock.ChainService{Slot: &slot} + s := &Server{ + Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ + slot.Sub(1): attestedState, + slot: st, + }}, + Blocker: mockBlocker, + HeadFetcher: mockChainService, + ChainInfoFetcher: mockChainInfoFetcher, + } + + minSignaturesRequired := uint64(100) + eventBlock, err := s.suitableBlock(ctx, minSignaturesRequired) + + require.NoError(t, err) + require.NotNil(t, eventBlock) + require.Equal(t, slot, eventBlock.Block().Slot()) + syncAggregate, err := eventBlock.Block().Body().SyncAggregate() + require.NoError(t, err) + require.Equal(t, true, syncAggregate.SyncCommitteeBits.Count() >= minSignaturesRequired) + }) - block := util.NewBeaconBlockCapella() - block.Block.Slot = slot - block.Block.ParentRoot = parentRoot[:] + t.Run("head not suitable, parent suitable", func(t *testing.T) { + ctx := context.Background() + slot := primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + + attestedState, err := util.NewBeaconStateCapella() + require.NoError(t, err) + err = attestedState.SetSlot(slot.Sub(1)) + require.NoError(t, err) + + require.NoError(t, attestedState.SetFinalizedCheckpoint(&pb.Checkpoint{ + Epoch: config.AltairForkEpoch - 10, + Root: make([]byte, 32), + })) + + parent := util.NewBeaconBlockCapella() + parent.Block.Slot = slot.Sub(1) + for i := uint64(0); i < config.SyncCommitteeSize; i++ { + parent.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + parentHeader, err := signedParent.Header() + require.NoError(t, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(t, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(t, err) + + st, err := util.NewBeaconStateCapella() + require.NoError(t, err) + err = st.SetSlot(slot) + require.NoError(t, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(t, err) + + block := util.NewBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < 10; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + h, err := signedBlock.Header() + require.NoError(t, err) + + err = st.SetLatestBlockHeader(h.Header) + require.NoError(t, err) + stateRoot, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(t, err) + + root, err := block.Block.HashTreeRoot() + require.NoError(t, err) + + mockBlocker := &testutil.MockBlocker{ + RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ + parentRoot: signedParent, + root: signedBlock, + }, + SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ + slot.Sub(1): signedParent, + slot: signedBlock, + }, + } + mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ + root: true, + }} + mockChainInfoFetcher := &mock.ChainService{Slot: &slot} + s := &Server{ + Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ + slot.Sub(1): attestedState, + slot: st, + }}, + Blocker: mockBlocker, + HeadFetcher: mockChainService, + ChainInfoFetcher: mockChainInfoFetcher, + } + + minSignaturesRequired := uint64(100) + eventBlock, err := s.suitableBlock(ctx, minSignaturesRequired) + + require.NoError(t, err) + require.NotNil(t, eventBlock) + syncAggregate, err := eventBlock.Block().Body().SyncAggregate() + require.NoError(t, err) + require.Equal(t, true, syncAggregate.SyncCommitteeBits.Count() >= minSignaturesRequired) + require.Equal(t, slot-1, eventBlock.Block().Slot()) + }) +} - for i := uint64(0); i < 10; i++ { - block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) +func createUpdate(t *testing.T, v int) (interfaces.LightClientUpdate, error) { + config := params.BeaconConfig() + var slot primitives.Slot + var header interfaces.LightClientHeader + var st state.BeaconState + var err error + + sampleRoot := make([]byte, 32) + for i := 0; i < 32; i++ { + sampleRoot[i] = byte(i) } - signedBlock, err := blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) - - h, err := signedBlock.Header() - require.NoError(t, err) - - err = st.SetLatestBlockHeader(h.Header) - require.NoError(t, err) - stateRoot, err := st.HashTreeRoot(ctx) - require.NoError(t, err) + sampleExecutionBranch := make([][]byte, fieldparams.ExecutionBranchDepth) + for i := 0; i < 4; i++ { + sampleExecutionBranch[i] = make([]byte, 32) + for j := 0; j < 32; j++ { + sampleExecutionBranch[i][j] = byte(i + j) + } + } - // get a new signed block so the root is updated with the new state root - block.Block.StateRoot = stateRoot[:] - signedBlock, err = blocks.NewSignedBeaconBlock(block) - require.NoError(t, err) + switch v { + case version.Altair: + slot = primitives.Slot(config.AltairForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateAltair() + require.NoError(t, err) + case version.Capella: + slot = primitives.Slot(config.CapellaForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderCapella{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + Execution: &enginev1.ExecutionPayloadHeaderCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: sampleExecutionBranch, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateCapella() + require.NoError(t, err) + case version.Deneb: + slot = primitives.Slot(config.DenebForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: sampleExecutionBranch, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateDeneb() + require.NoError(t, err) + case version.Electra: + slot = primitives.Slot(config.ElectraForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: sampleExecutionBranch, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateElectra() + require.NoError(t, err) + case version.Fulu: + slot = primitives.Slot(config.FuluForkEpoch * primitives.Epoch(config.SlotsPerEpoch)).Add(1) + header, err = light_client.NewWrappedHeader(&pb.LightClientHeaderDeneb{ + Beacon: &pb.BeaconBlockHeader{ + Slot: 1, + ProposerIndex: primitives.ValidatorIndex(rand.Int()), + ParentRoot: sampleRoot, + StateRoot: sampleRoot, + BodyRoot: sampleRoot, + }, + Execution: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), + }, + ExecutionBranch: sampleExecutionBranch, + }) + require.NoError(t, err) + st, err = util.NewBeaconStateFulu() + require.NoError(t, err) + default: + return nil, fmt.Errorf("unsupported version %s", version.String(v)) + } - root, err := block.Block.HashTreeRoot() + update, err := lightclient.CreateDefaultLightClientUpdate(slot, st) require.NoError(t, err) + update.SetSignatureSlot(slot - 1) + syncCommitteeBits := make([]byte, 64) + syncCommitteeSignature := make([]byte, 96) + update.SetSyncAggregate(&pb.SyncAggregate{ + SyncCommitteeBits: syncCommitteeBits, + SyncCommitteeSignature: syncCommitteeSignature, + }) - mockBlocker := &testutil.MockBlocker{ - RootBlockMap: map[[32]byte]interfaces.ReadOnlySignedBeaconBlock{ - parentRoot: signedParent, - root: signedBlock, - }, - SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ - slot.Sub(1): signedParent, - slot: signedBlock, - }, - } - mockChainService := &mock.ChainService{Optimistic: true, Slot: &slot, State: st, FinalizedRoots: map[[32]byte]bool{ - root: true, - }} - s := &Server{ - Stater: &testutil.MockStater{StatesBySlot: map[primitives.Slot]state.BeaconState{ - slot.Sub(1): attestedState, - slot: st, - }}, - Blocker: mockBlocker, - HeadFetcher: mockChainService, - } - - minSignaturesRequired := uint64(100) - eventBlock, err := s.getLightClientEventBlock(ctx, minSignaturesRequired) + require.NoError(t, update.SetAttestedHeader(header)) + require.NoError(t, update.SetFinalizedHeader(header)) - require.NoError(t, err) - require.NotNil(t, eventBlock) - syncAggregate, err := eventBlock.Block().Body().SyncAggregate() - require.NoError(t, err) - require.Equal(t, true, syncAggregate.SyncCommitteeBits.Count() >= minSignaturesRequired) - require.Equal(t, slot-1, eventBlock.Block().Slot()) + return update, nil } diff --git a/beacon-chain/rpc/eth/light-client/helpers.go b/beacon-chain/rpc/eth/light-client/helpers.go index d6fe7a22f9dd..779bbd447dbd 100644 --- a/beacon-chain/rpc/eth/light-client/helpers.go +++ b/beacon-chain/rpc/eth/light-client/helpers.go @@ -2,374 +2,44 @@ package lightclient import ( "context" - "fmt" - "reflect" - "strconv" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/api/server/structs" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" + lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" - v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - v2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" - "github.com/prysmaticlabs/prysm/v5/proto/migration" - "github.com/prysmaticlabs/prysm/v5/time/slots" ) -// createLightClientBootstrap - implements https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_bootstrap -// def create_light_client_bootstrap(state: BeaconState) -> LightClientBootstrap: -// -// assert compute_epoch_at_slot(state.slot) >= ALTAIR_FORK_EPOCH -// assert state.slot == state.latest_block_header.slot -// -// return LightClientBootstrap( -// header=BeaconBlockHeader( -// slot=state.latest_block_header.slot, -// proposer_index=state.latest_block_header.proposer_index, -// parent_root=state.latest_block_header.parent_root, -// state_root=hash_tree_root(state), -// body_root=state.latest_block_header.body_root, -// ), -// current_sync_committee=state.current_sync_committee, -// current_sync_committee_branch=compute_merkle_proof_for_state(state, CURRENT_SYNC_COMMITTEE_INDEX) -// ) -func createLightClientBootstrap(ctx context.Context, state state.BeaconState) (*structs.LightClientBootstrap, error) { - // assert compute_epoch_at_slot(state.slot) >= ALTAIR_FORK_EPOCH - if slots.ToEpoch(state.Slot()) < params.BeaconConfig().AltairForkEpoch { - return nil, fmt.Errorf("light client bootstrap is not supported before Altair, invalid slot %d", state.Slot()) - } - - // assert state.slot == state.latest_block_header.slot - latestBlockHeader := state.LatestBlockHeader() - if state.Slot() != latestBlockHeader.Slot { - return nil, fmt.Errorf("state slot %d not equal to latest block header slot %d", state.Slot(), latestBlockHeader.Slot) - } - - // Prepare data - currentSyncCommittee, err := state.CurrentSyncCommittee() - if err != nil { - return nil, fmt.Errorf("could not get current sync committee: %s", err.Error()) - } - - committee := structs.SyncCommitteeFromConsensus(currentSyncCommittee) - - currentSyncCommitteeProof, err := state.CurrentSyncCommitteeProof(ctx) - if err != nil { - return nil, fmt.Errorf("could not get current sync committee proof: %s", err.Error()) - } - - branch := make([]string, fieldparams.NextSyncCommitteeBranchDepth) - for i, proof := range currentSyncCommitteeProof { - branch[i] = hexutil.Encode(proof) - } - - header := structs.BeaconBlockHeaderFromConsensus(latestBlockHeader) - if header == nil { - return nil, fmt.Errorf("could not get beacon block header") - } - - // Above shared util function won't calculate state root, so we need to do it manually - stateRoot, err := state.HashTreeRoot(ctx) - if err != nil { - return nil, fmt.Errorf("could not get state root: %s", err.Error()) - } - header.StateRoot = hexutil.Encode(stateRoot[:]) - - // Return result - result := &structs.LightClientBootstrap{ - Header: header, - CurrentSyncCommittee: committee, - CurrentSyncCommitteeBranch: branch, - } - - return result, nil -} - -// createLightClientUpdate - implements https://github. -// com/ethereum/consensus-specs/blob/d70dcd9926a4bbe987f1b4e65c3e05bd029fcfb8/specs/altair/light-client/full-node.md#create_light_client_update -// def create_light_client_update(state: BeaconState, -// -// block: SignedBeaconBlock, -// attested_state: BeaconState, -// finalized_block: Optional[SignedBeaconBlock]) -> LightClientUpdate: -// assert compute_epoch_at_slot(attested_state.slot) >= ALTAIR_FORK_EPOCH -// assert sum(block.message.body.sync_aggregate.sync_committee_bits) >= MIN_SYNC_COMMITTEE_PARTICIPANTS -// -// assert state.slot == state.latest_block_header.slot -// header = state.latest_block_header.copy() -// header.state_root = hash_tree_root(state) -// assert hash_tree_root(header) == hash_tree_root(block.message) -// update_signature_period = compute_sync_committee_period(compute_epoch_at_slot(block.message.slot)) -// -// assert attested_state.slot == attested_state.latest_block_header.slot -// attested_header = attested_state.latest_block_header.copy() -// attested_header.state_root = hash_tree_root(attested_state) -// assert hash_tree_root(attested_header) == block.message.parent_root -// update_attested_period = compute_sync_committee_period(compute_epoch_at_slot(attested_header.slot)) -// -// # `next_sync_committee` is only useful if the message is signed by the current sync committee -// if update_attested_period == update_signature_period: -// next_sync_committee = attested_state.next_sync_committee -// next_sync_committee_branch = compute_merkle_proof_for_state(attested_state, NEXT_SYNC_COMMITTEE_INDEX) -// else: -// next_sync_committee = SyncCommittee() -// next_sync_committee_branch = [Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))] -// -// # Indicate finality whenever possible -// if finalized_block is not None: -// if finalized_block.message.slot != GENESIS_SLOT: -// finalized_header = BeaconBlockHeader( -// slot=finalized_block.message.slot, -// proposer_index=finalized_block.message.proposer_index, -// parent_root=finalized_block.message.parent_root, -// state_root=finalized_block.message.state_root, -// body_root=hash_tree_root(finalized_block.message.body), -// ) -// assert hash_tree_root(finalized_header) == attested_state.finalized_checkpoint.root -// else: -// assert attested_state.finalized_checkpoint.root == Bytes32() -// finalized_header = BeaconBlockHeader() -// finality_branch = compute_merkle_proof_for_state(attested_state, FINALIZED_ROOT_INDEX) -// else: -// finalized_header = BeaconBlockHeader() -// finality_branch = [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))] -// -// return LightClientUpdate( -// attested_header=attested_header, -// next_sync_committee=next_sync_committee, -// next_sync_committee_branch=next_sync_committee_branch, -// finalized_header=finalized_header, -// finality_branch=finality_branch, -// sync_aggregate=block.message.body.sync_aggregate, -// signature_slot=block.message.slot, -// ) -func createLightClientUpdate( - ctx context.Context, - state state.BeaconState, - block interfaces.ReadOnlySignedBeaconBlock, - attestedState state.BeaconState, - finalizedBlock interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientUpdate, error) { - result, err := blockchain.NewLightClientFinalityUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock) - if err != nil { - return nil, err - } - - // Generate next sync committee and proof - var nextSyncCommittee *v2.SyncCommittee - var nextSyncCommitteeBranch [][]byte - - // update_signature_period = compute_sync_committee_period(compute_epoch_at_slot(block.message.slot)) - updateSignaturePeriod := slots.ToEpoch(block.Block().Slot()) - - // update_attested_period = compute_sync_committee_period(compute_epoch_at_slot(attested_header.slot)) - updateAttestedPeriod := slots.ToEpoch(result.AttestedHeader.Slot) - - if updateAttestedPeriod == updateSignaturePeriod { - tempNextSyncCommittee, err := attestedState.NextSyncCommittee() - if err != nil { - return nil, fmt.Errorf("could not get next sync committee: %s", err.Error()) - } - - nextSyncCommittee = &v2.SyncCommittee{ - Pubkeys: tempNextSyncCommittee.Pubkeys, - AggregatePubkey: tempNextSyncCommittee.AggregatePubkey, - } - - nextSyncCommitteeBranch, err = attestedState.NextSyncCommitteeProof(ctx) - if err != nil { - return nil, fmt.Errorf("could not get next sync committee proof: %s", err.Error()) - } - } else { - syncCommitteeSize := params.BeaconConfig().SyncCommitteeSize - pubKeys := make([][]byte, syncCommitteeSize) - for i := uint64(0); i < syncCommitteeSize; i++ { - pubKeys[i] = make([]byte, fieldparams.BLSPubkeyLength) - } - nextSyncCommittee = &v2.SyncCommittee{ - Pubkeys: pubKeys, - AggregatePubkey: make([]byte, fieldparams.BLSPubkeyLength), - } - - nextSyncCommitteeBranch = make([][]byte, fieldparams.NextSyncCommitteeBranchDepth) - for i := 0; i < fieldparams.NextSyncCommitteeBranchDepth; i++ { - nextSyncCommitteeBranch[i] = make([]byte, fieldparams.RootLength) - } - } - - result.NextSyncCommittee = nextSyncCommittee - result.NextSyncCommitteeBranch = nextSyncCommitteeBranch - return newLightClientUpdateToJSON(result), nil -} - func newLightClientFinalityUpdateFromBeaconState( ctx context.Context, + currentSlot primitives.Slot, state state.BeaconState, block interfaces.ReadOnlySignedBeaconBlock, attestedState state.BeaconState, - finalizedBlock interfaces.ReadOnlySignedBeaconBlock) (*structs.LightClientUpdate, error) { - result, err := blockchain.NewLightClientFinalityUpdateFromBeaconState(ctx, state, block, attestedState, finalizedBlock) + attestedBlock interfaces.ReadOnlySignedBeaconBlock, + finalizedBlock interfaces.ReadOnlySignedBeaconBlock, +) (*structs.LightClientFinalityUpdate, error) { + result, err := lightclient.NewLightClientFinalityUpdateFromBeaconState(ctx, currentSlot, state, block, attestedState, attestedBlock, finalizedBlock) if err != nil { return nil, err } - return newLightClientUpdateToJSON(result), nil + return structs.LightClientFinalityUpdateFromConsensus(result) } func newLightClientOptimisticUpdateFromBeaconState( ctx context.Context, + currentSlot primitives.Slot, state state.BeaconState, block interfaces.ReadOnlySignedBeaconBlock, - attestedState state.BeaconState) (*structs.LightClientUpdate, error) { - result, err := blockchain.NewLightClientOptimisticUpdateFromBeaconState(ctx, state, block, attestedState) - if err != nil { - return nil, err - } - - return newLightClientUpdateToJSON(result), nil -} - -func NewLightClientBootstrapFromJSON(bootstrapJSON *structs.LightClientBootstrap) (*v2.LightClientBootstrap, error) { - bootstrap := &v2.LightClientBootstrap{} - - var err error - - v1Alpha1Header, err := bootstrapJSON.Header.ToConsensus() - if err != nil { - return nil, err - } - bootstrap.Header = migration.V1Alpha1HeaderToV1(v1Alpha1Header) - - currentSyncCommittee, err := bootstrapJSON.CurrentSyncCommittee.ToConsensus() + attestedState state.BeaconState, + attestedBlock interfaces.ReadOnlySignedBeaconBlock, +) (*structs.LightClientOptimisticUpdate, error) { + result, err := lightclient.NewLightClientOptimisticUpdateFromBeaconState(ctx, currentSlot, state, block, attestedState, attestedBlock) if err != nil { return nil, err } - bootstrap.CurrentSyncCommittee = migration.V1Alpha1SyncCommitteeToV2(currentSyncCommittee) - - if bootstrap.CurrentSyncCommitteeBranch, err = branchFromJSON(bootstrapJSON.CurrentSyncCommitteeBranch); err != nil { - return nil, err - } - return bootstrap, nil -} - -func branchFromJSON(branch []string) ([][]byte, error) { - var branchBytes [][]byte - for _, root := range branch { - branch, err := hexutil.Decode(root) - if err != nil { - return nil, err - } - branchBytes = append(branchBytes, branch) - } - return branchBytes, nil -} - -func branchToJSON(branchBytes [][]byte) []string { - if branchBytes == nil { - return nil - } - branch := make([]string, len(branchBytes)) - for i, root := range branchBytes { - branch[i] = hexutil.Encode(root) - } - return branch -} - -func syncAggregateToJSON(input *v1.SyncAggregate) *structs.SyncAggregate { - if input == nil { - return nil - } - return &structs.SyncAggregate{ - SyncCommitteeBits: hexutil.Encode(input.SyncCommitteeBits), - SyncCommitteeSignature: hexutil.Encode(input.SyncCommitteeSignature), - } -} - -func newLightClientUpdateToJSON(input *v2.LightClientUpdate) *structs.LightClientUpdate { - if input == nil { - return nil - } - - var nextSyncCommittee *structs.SyncCommittee - if input.NextSyncCommittee != nil { - nextSyncCommittee = structs.SyncCommitteeFromConsensus(migration.V2SyncCommitteeToV1Alpha1(input.NextSyncCommittee)) - } - var finalizedHeader *structs.BeaconBlockHeader - if input.FinalizedHeader != nil { - finalizedHeader = structs.BeaconBlockHeaderFromConsensus(migration.V1HeaderToV1Alpha1(input.FinalizedHeader)) - } - - return &structs.LightClientUpdate{ - AttestedHeader: structs.BeaconBlockHeaderFromConsensus(migration.V1HeaderToV1Alpha1(input.AttestedHeader)), - NextSyncCommittee: nextSyncCommittee, - NextSyncCommitteeBranch: branchToJSON(input.NextSyncCommitteeBranch), - FinalizedHeader: finalizedHeader, - FinalityBranch: branchToJSON(input.FinalityBranch), - SyncAggregate: syncAggregateToJSON(input.SyncAggregate), - SignatureSlot: strconv.FormatUint(uint64(input.SignatureSlot), 10), - } -} - -func IsSyncCommitteeUpdate(update *v2.LightClientUpdate) bool { - nextSyncCommitteeBranch := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth) - return !reflect.DeepEqual(update.NextSyncCommitteeBranch, nextSyncCommitteeBranch) -} - -func IsFinalityUpdate(update *v2.LightClientUpdate) bool { - finalityBranch := make([][]byte, blockchain.FinalityBranchNumOfLeaves) - return !reflect.DeepEqual(update.FinalityBranch, finalityBranch) -} - -func IsBetterUpdate(newUpdate, oldUpdate *v2.LightClientUpdate) bool { - maxActiveParticipants := newUpdate.SyncAggregate.SyncCommitteeBits.Len() - newNumActiveParticipants := newUpdate.SyncAggregate.SyncCommitteeBits.Count() - oldNumActiveParticipants := oldUpdate.SyncAggregate.SyncCommitteeBits.Count() - newHasSupermajority := newNumActiveParticipants*3 >= maxActiveParticipants*2 - oldHasSupermajority := oldNumActiveParticipants*3 >= maxActiveParticipants*2 - - if newHasSupermajority != oldHasSupermajority { - return newHasSupermajority - } - if !newHasSupermajority && newNumActiveParticipants != oldNumActiveParticipants { - return newNumActiveParticipants > oldNumActiveParticipants - } - - // Compare presence of relevant sync committee - newHasRelevantSyncCommittee := IsSyncCommitteeUpdate(newUpdate) && (slots.SyncCommitteePeriod(slots.ToEpoch(newUpdate.AttestedHeader.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(newUpdate.SignatureSlot))) - oldHasRelevantSyncCommittee := IsSyncCommitteeUpdate(oldUpdate) && (slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdate.AttestedHeader.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdate.SignatureSlot))) - - if newHasRelevantSyncCommittee != oldHasRelevantSyncCommittee { - return newHasRelevantSyncCommittee - } - - // Compare indication of any finality - newHasFinality := IsFinalityUpdate(newUpdate) - oldHasFinality := IsFinalityUpdate(oldUpdate) - if newHasFinality != oldHasFinality { - return newHasFinality - } - - // Compare sync committee finality - if newHasFinality { - newHasSyncCommitteeFinality := slots.SyncCommitteePeriod(slots.ToEpoch(newUpdate.FinalizedHeader.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(newUpdate.AttestedHeader.Slot)) - oldHasSyncCommitteeFinality := slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdate.FinalizedHeader.Slot)) == slots.SyncCommitteePeriod(slots.ToEpoch(oldUpdate.AttestedHeader.Slot)) - - if newHasSyncCommitteeFinality != oldHasSyncCommitteeFinality { - return newHasSyncCommitteeFinality - } - } - - // Tiebreaker 1: Sync committee participation beyond supermajority - if newNumActiveParticipants != oldNumActiveParticipants { - return newNumActiveParticipants > oldNumActiveParticipants - } - - // Tiebreaker 2: Prefer older data (fewer changes to best) - if newUpdate.AttestedHeader.Slot != oldUpdate.AttestedHeader.Slot { - return newUpdate.AttestedHeader.Slot < oldUpdate.AttestedHeader.Slot - } - return newUpdate.SignatureSlot < oldUpdate.SignatureSlot + return structs.LightClientOptimisticUpdateFromConsensus(result) } diff --git a/beacon-chain/rpc/eth/light-client/helpers_test.go b/beacon-chain/rpc/eth/light-client/helpers_test.go index 97a817717c29..51b23585a906 100644 --- a/beacon-chain/rpc/eth/light-client/helpers_test.go +++ b/beacon-chain/rpc/eth/light-client/helpers_test.go @@ -1,453 +1 @@ package lightclient - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" - "github.com/prysmaticlabs/prysm/v5/testing/assert" -) - -// When the update has relevant sync committee -func createNonEmptySyncCommitteeBranch() [][]byte { - res := make([][]byte, fieldparams.NextSyncCommitteeBranchDepth) - res[0] = []byte("xyz") - return res -} - -// When the update has finality -func createNonEmptyFinalityBranch() [][]byte { - res := make([][]byte, blockchain.FinalityBranchNumOfLeaves) - res[0] = []byte("xyz") - return res -} - -func TestIsBetterUpdate(t *testing.T) { - testCases := []struct { - name string - oldUpdate *ethpbv2.LightClientUpdate - newUpdate *ethpbv2.LightClientUpdate - expectedResult bool - }{ - { - name: "new has supermajority but old doesn't", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1] - }, - }, - expectedResult: true, - }, - { - name: "old has supermajority but new doesn't", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1] - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] - }, - }, - expectedResult: false, - }, - { - name: "new doesn't have supermajority and newNumActiveParticipants is greater than oldNumActiveParticipants", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] - }, - }, - expectedResult: true, - }, - { - name: "new doesn't have supermajority and newNumActiveParticipants is lesser than oldNumActiveParticipants", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0] - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - }, - expectedResult: false, - }, - { - name: "new has relevant sync committee but old doesn't", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: make([][]byte, fieldparams.NextSyncCommitteeBranchDepth), - SignatureSlot: 9999, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000001, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 1000000, - }, - expectedResult: true, - }, - { - name: "old has relevant sync committee but new doesn't", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000001, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 1000000, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: make([][]byte, fieldparams.NextSyncCommitteeBranchDepth), - SignatureSlot: 9999, - }, - expectedResult: false, - }, - { - name: "new has finality but old doesn't", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: make([][]byte, blockchain.FinalityBranchNumOfLeaves), - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - }, - expectedResult: true, - }, - { - name: "old has finality but new doesn't", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: make([][]byte, blockchain.FinalityBranchNumOfLeaves), - }, - expectedResult: false, - }, - { - name: "new has finality and sync committee finality both but old doesn't have sync committee finality", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 999999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 999999, - }, - }, - expectedResult: true, - }, - { - name: "new has finality but doesn't have sync committee finality and old has sync committee finality", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 999999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 999999, - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - expectedResult: false, - }, - { - name: "new has more active participants than old", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - expectedResult: true, - }, - { - name: "new has less active participants than old", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - expectedResult: false, - }, - { - name: "new's attested header's slot is lesser than old's attested header's slot", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 999999, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - expectedResult: true, - }, - { - name: "new's attested header's slot is greater than old's attested header's slot", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 999999, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - expectedResult: false, - }, - { - name: "none of the above conditions are met and new signature's slot is lesser than old signature's slot", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9998, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - expectedResult: true, - }, - { - name: "none of the above conditions are met and new signature's slot is greater than old signature's slot", - oldUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9998, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - newUpdate: ðpbv2.LightClientUpdate{ - SyncAggregate: ðpbv1.SyncAggregate{ - SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0] - }, - AttestedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 1000000, - }, - NextSyncCommitteeBranch: createNonEmptySyncCommitteeBranch(), - SignatureSlot: 9999, - FinalityBranch: createNonEmptyFinalityBranch(), - FinalizedHeader: ðpbv1.BeaconBlockHeader{ - Slot: 9999, - }, - }, - expectedResult: false, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - assert.Equal(t, testCase.expectedResult, IsBetterUpdate(testCase.newUpdate, testCase.oldUpdate)) - }) - } -} diff --git a/beacon-chain/rpc/eth/light-client/server.go b/beacon-chain/rpc/eth/light-client/server.go index f01100a259fa..84b061379fc1 100644 --- a/beacon-chain/rpc/eth/light-client/server.go +++ b/beacon-chain/rpc/eth/light-client/server.go @@ -2,11 +2,14 @@ package lightclient import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup" ) type Server struct { - Blocker lookup.Blocker - Stater lookup.Stater - HeadFetcher blockchain.HeadFetcher + Blocker lookup.Blocker + Stater lookup.Stater + HeadFetcher blockchain.HeadFetcher + ChainInfoFetcher blockchain.ChainInfoFetcher + BeaconDB db.HeadAccessDatabase } diff --git a/beacon-chain/rpc/eth/node/BUILD.bazel b/beacon-chain/rpc/eth/node/BUILD.bazel index e0ee146f73c5..5b35395a1b34 100644 --- a/beacon-chain/rpc/eth/node/BUILD.bazel +++ b/beacon-chain/rpc/eth/node/BUILD.bazel @@ -19,16 +19,15 @@ go_library( "//beacon-chain/p2p/peers/peerdata:go_default_library", "//beacon-chain/rpc/eth/shared:go_default_library", "//beacon-chain/sync:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//proto/eth/v1:go_default_library", "//proto/migration:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_libp2p_go_libp2p//core/peer:go_default_library", "@com_github_pkg_errors//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//:go_default_library", ], ) @@ -58,7 +57,6 @@ go_test( "//testing/util:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enode:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enr:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_libp2p_go_libp2p//core/network:go_default_library", "@com_github_libp2p_go_libp2p//core/peer:go_default_library", "@com_github_libp2p_go_libp2p//p2p/host/peerstore/test:go_default_library", diff --git a/beacon-chain/rpc/eth/node/handlers.go b/beacon-chain/rpc/eth/node/handlers.go index 7ccae43ed4ad..63c795316f5e 100644 --- a/beacon-chain/rpc/eth/node/handlers.go +++ b/beacon-chain/rpc/eth/node/handlers.go @@ -10,10 +10,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" ) var ( diff --git a/beacon-chain/rpc/eth/node/handlers_peers.go b/beacon-chain/rpc/eth/node/handlers_peers.go index 571a4c934000..039b247bed8a 100644 --- a/beacon-chain/rpc/eth/node/handlers_peers.go +++ b/beacon-chain/rpc/eth/node/handlers_peers.go @@ -5,17 +5,16 @@ import ( "strconv" "strings" - "github.com/gorilla/mux" "github.com/libp2p/go-libp2p/core/peer" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/peerdata" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/proto/migration" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // GetPeer retrieves data about the given peer. @@ -23,7 +22,7 @@ func (s *Server) GetPeer(w http.ResponseWriter, r *http.Request) { _, span := trace.StartSpan(r.Context(), "node.GetPeer") defer span.End() - rawId := mux.Vars(r)["peer_id"] + rawId := r.PathValue("peer_id") if rawId == "" { httputil.HandleError(w, "peer_id is required in URL params", http.StatusBadRequest) return diff --git a/beacon-chain/rpc/eth/node/handlers_peers_test.go b/beacon-chain/rpc/eth/node/handlers_peers_test.go index 753c1e5b3158..b910321cd7e0 100644 --- a/beacon-chain/rpc/eth/node/handlers_peers_test.go +++ b/beacon-chain/rpc/eth/node/handlers_peers_test.go @@ -10,7 +10,6 @@ import ( "testing" "github.com/ethereum/go-ethereum/p2p/enr" - "github.com/gorilla/mux" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" libp2ptest "github.com/libp2p/go-libp2p/p2p/host/peerstore/test" @@ -43,7 +42,7 @@ func TestGetPeer(t *testing.T) { t.Run("OK", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/node/peers/{peer_id}", nil) - request = mux.SetURLVars(request, map[string]string{"peer_id": rawId}) + request.SetPathValue("peer_id", rawId) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -60,7 +59,7 @@ func TestGetPeer(t *testing.T) { t.Run("Invalid ID", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/node/peers/{peer_id}", nil) - request = mux.SetURLVars(request, map[string]string{"peer_id": "foo"}) + request.SetPathValue("peer_id", "foo") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -74,7 +73,7 @@ func TestGetPeer(t *testing.T) { t.Run("Peer not found", func(t *testing.T) { request := httptest.NewRequest(http.MethodGet, "http://example.com/eth/v1/node/peers/{peer_id}", nil) - request = mux.SetURLVars(request, map[string]string{"peer_id": "16Uiu2HAmQqFdEcHbSmQTQuLoAhnMUrgoWoraKK4cUJT6FuuqHqTU"}) + request.SetPathValue("peer_id", "16Uiu2HAmQqFdEcHbSmQTQuLoAhnMUrgoWoraKK4cUJT6FuuqHqTU") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -118,13 +117,13 @@ func TestGetPeers(t *testing.T) { switch i { case 0, 1: - peerStatus.SetConnectionState(id, peers.PeerConnecting) + peerStatus.SetConnectionState(id, peers.Connecting) case 2, 3: - peerStatus.SetConnectionState(id, peers.PeerConnected) + peerStatus.SetConnectionState(id, peers.Connected) case 4, 5: - peerStatus.SetConnectionState(id, peers.PeerDisconnecting) + peerStatus.SetConnectionState(id, peers.Disconnecting) case 6, 7: - peerStatus.SetConnectionState(id, peers.PeerDisconnected) + peerStatus.SetConnectionState(id, peers.Disconnected) default: t.Fatalf("Failed to set connection state for peer") } @@ -240,7 +239,7 @@ func TestGetPeers(t *testing.T) { } } if !found { - t.Errorf("Expected ID '" + expectedId + "' not found") + t.Error("Expected ID '" + expectedId + "' not found") } } }) @@ -290,13 +289,13 @@ func TestGetPeerCount(t *testing.T) { switch i { case 0: - peerStatus.SetConnectionState(id, peers.PeerConnecting) + peerStatus.SetConnectionState(id, peers.Connecting) case 1, 2: - peerStatus.SetConnectionState(id, peers.PeerConnected) + peerStatus.SetConnectionState(id, peers.Connected) case 3, 4, 5: - peerStatus.SetConnectionState(id, peers.PeerDisconnecting) + peerStatus.SetConnectionState(id, peers.Disconnecting) case 6, 7, 8, 9: - peerStatus.SetConnectionState(id, peers.PeerDisconnected) + peerStatus.SetConnectionState(id, peers.Disconnected) default: t.Fatalf("Failed to set connection state for peer") } diff --git a/beacon-chain/rpc/eth/rewards/BUILD.bazel b/beacon-chain/rpc/eth/rewards/BUILD.bazel index a41bb4e7d562..67196cd720dd 100644 --- a/beacon-chain/rpc/eth/rewards/BUILD.bazel +++ b/beacon-chain/rpc/eth/rewards/BUILD.bazel @@ -27,11 +27,11 @@ go_library( "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_wealdtech_go_bytesutil//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -63,6 +63,7 @@ go_test( "//encoding/bytesutil:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", diff --git a/beacon-chain/rpc/eth/rewards/handlers.go b/beacon-chain/rpc/eth/rewards/handlers.go index 762a119bdac4..8c6520d62c30 100644 --- a/beacon-chain/rpc/eth/rewards/handlers.go +++ b/beacon-chain/rpc/eth/rewards/handlers.go @@ -16,11 +16,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/wealdtech/go-bytesutil" - "go.opencensus.io/trace" ) // BlockRewards is an HTTP handler for Beacon API getBlockRewards. diff --git a/beacon-chain/rpc/eth/rewards/handlers_test.go b/beacon-chain/rpc/eth/rewards/handlers_test.go index d95020348502..39f14948b5e1 100644 --- a/beacon-chain/rpc/eth/rewards/handlers_test.go +++ b/beacon-chain/rpc/eth/rewards/handlers_test.go @@ -32,45 +32,52 @@ import ( "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/network/httputil" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func BlockRewardTestSetup(t *testing.T, forkName string) (state.BeaconState, interfaces.SignedBeaconBlock, error) { +func BlockRewardTestSetup(t *testing.T, ver int) (state.BeaconState, interfaces.SignedBeaconBlock, error) { helpers.ClearCache() var sbb interfaces.SignedBeaconBlock var st state.BeaconState var err error - switch forkName { - case "phase0": + switch ver { + case version.Phase0: return nil, nil, errors.New("phase0 not supported") - case "altair": + case version.Altair: st, err = util.NewBeaconStateAltair() require.NoError(t, err) b := util.HydrateSignedBeaconBlockAltair(util.NewBeaconBlockAltair()) sbb, err = blocks.NewSignedBeaconBlock(b) require.NoError(t, err) - case "bellatrix": + case version.Bellatrix: st, err = util.NewBeaconStateBellatrix() require.NoError(t, err) b := util.HydrateSignedBeaconBlockBellatrix(util.NewBeaconBlockBellatrix()) sbb, err = blocks.NewSignedBeaconBlock(b) require.NoError(t, err) - case "capella": + case version.Capella: st, err = util.NewBeaconStateCapella() require.NoError(t, err) b := util.HydrateSignedBeaconBlockCapella(util.NewBeaconBlockCapella()) sbb, err = blocks.NewSignedBeaconBlock(b) require.NoError(t, err) - case "deneb": + case version.Deneb: st, err = util.NewBeaconStateDeneb() require.NoError(t, err) b := util.HydrateSignedBeaconBlockDeneb(util.NewBeaconBlockDeneb()) sbb, err = blocks.NewSignedBeaconBlock(b) require.NoError(t, err) + case version.Electra: + st, err = util.NewBeaconStateElectra() + require.NoError(t, err) + b := util.HydrateSignedBeaconBlockElectra(util.NewBeaconBlockElectra()) + sbb, err = blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) default: - return nil, nil, errors.New("fork is not supported") + return nil, nil, fmt.Errorf("fork %s is not supported", version.String(ver)) } valCount := 64 require.NoError(t, st.SetSlot(1)) @@ -102,20 +109,47 @@ func BlockRewardTestSetup(t *testing.T, forkName string) (state.BeaconState, int require.NoError(t, st.SetBlockRoots(bRoots)) sbb.SetSlot(2) + // we have to set the proposer index to the value that will be randomly chosen (fortunately it's deterministic) - sbb.SetProposerIndex(12) - require.NoError(t, sbb.SetAttestations([]eth.Att{ - ð.Attestation{ - AggregationBits: bitfield.Bitlist{0b00000111}, - Data: util.HydrateAttestationData(ð.AttestationData{}), - Signature: make([]byte, fieldparams.BLSSignatureLength), - }, - ð.Attestation{ - AggregationBits: bitfield.Bitlist{0b00000111}, - Data: util.HydrateAttestationData(ð.AttestationData{}), - Signature: make([]byte, fieldparams.BLSSignatureLength), - }, - })) + if ver >= version.Electra { + sbb.SetProposerIndex(4) + } else { + sbb.SetProposerIndex(12) + } + + var atts []eth.Att + if ver >= version.Electra { + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(0, true) + atts = []eth.Att{ + ð.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b00000111}, + Data: util.HydrateAttestationData(ð.AttestationData{}), + Signature: make([]byte, fieldparams.BLSSignatureLength), + CommitteeBits: cb, + }, + ð.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b00000111}, + Data: util.HydrateAttestationData(ð.AttestationData{}), + Signature: make([]byte, fieldparams.BLSSignatureLength), + CommitteeBits: cb, + }, + } + } else { + atts = []eth.Att{ + ð.Attestation{ + AggregationBits: bitfield.Bitlist{0b00000111}, + Data: util.HydrateAttestationData(ð.AttestationData{}), + Signature: make([]byte, fieldparams.BLSSignatureLength), + }, + ð.Attestation{ + AggregationBits: bitfield.Bitlist{0b00000111}, + Data: util.HydrateAttestationData(ð.AttestationData{}), + Signature: make([]byte, fieldparams.BLSSignatureLength), + }, + } + } + require.NoError(t, sbb.SetAttestations(atts)) attData1 := util.HydrateAttestationData(ð.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte("root1"), 32)}) attData2 := util.HydrateAttestationData(ð.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte("root2"), 32)}) @@ -125,8 +159,23 @@ func BlockRewardTestSetup(t *testing.T, forkName string) (state.BeaconState, int require.NoError(t, err) sigRoot2, err := signing.ComputeSigningRoot(attData2, domain) require.NoError(t, err) - require.NoError(t, sbb.SetAttesterSlashings([]eth.AttSlashing{ - ð.AttesterSlashing{ + + var attSlashing eth.AttSlashing + if ver >= version.Electra { + attSlashing = ð.AttesterSlashingElectra{ + Attestation_1: ð.IndexedAttestationElectra{ + AttestingIndices: []uint64{0}, + Data: attData1, + Signature: secretKeys[0].Sign(sigRoot1[:]).Marshal(), + }, + Attestation_2: ð.IndexedAttestationElectra{ + AttestingIndices: []uint64{0}, + Data: attData2, + Signature: secretKeys[0].Sign(sigRoot2[:]).Marshal(), + }, + } + } else { + attSlashing = ð.AttesterSlashing{ Attestation_1: ð.IndexedAttestation{ AttestingIndices: []uint64{0}, Data: attData1, @@ -137,8 +186,10 @@ func BlockRewardTestSetup(t *testing.T, forkName string) (state.BeaconState, int Data: attData2, Signature: secretKeys[0].Sign(sigRoot2[:]).Marshal(), }, - }, - })) + } + } + require.NoError(t, sbb.SetAttesterSlashings([]eth.AttSlashing{attSlashing})) + header1 := ð.BeaconBlockHeader{ Slot: 0, ProposerIndex: 1, @@ -179,11 +230,21 @@ func BlockRewardTestSetup(t *testing.T, forkName string) (state.BeaconState, int sszBytes := primitives.SSZBytes(slot0bRoot) r, err := signing.ComputeSigningRoot(&sszBytes, domain) require.NoError(t, err) + // Bits set in sync committee bits determine which validators will be treated as participating in sync committee. // These validators have to sign the message. - sig1, err := blst.SignatureFromBytes(secretKeys[47].Sign(r[:]).Marshal()) + var scValIdx1 int + var scValIdx2 int + if ver >= version.Electra { + scValIdx1 = 14 + scValIdx2 = 27 + } else { + scValIdx1 = 47 + scValIdx2 = 19 + } + sig1, err := blst.SignatureFromBytes(secretKeys[scValIdx1].Sign(r[:]).Marshal()) require.NoError(t, err) - sig2, err := blst.SignatureFromBytes(secretKeys[19].Sign(r[:]).Marshal()) + sig2, err := blst.SignatureFromBytes(secretKeys[scValIdx2].Sign(r[:]).Marshal()) require.NoError(t, err) aggSig := bls.AggregateSignatures([]bls.Signature{sig1, sig2}).Marshal() err = sbb.SetSyncAggregate(ð.SyncAggregate{SyncCommitteeBits: scBits, SyncCommitteeSignature: aggSig}) @@ -211,14 +272,14 @@ func TestBlockRewards(t *testing.T) { writer.Body = &bytes.Buffer{} s.BlockRewards(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) + require.Equal(t, http.StatusBadRequest, writer.Code) e := &httputil.DefaultJsonError{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) + require.Equal(t, http.StatusBadRequest, e.Code) assert.Equal(t, "Block rewards are not supported for Phase 0 blocks", e.Message) }) t.Run("altair", func(t *testing.T) { - st, sbb, err := BlockRewardTestSetup(t, "altair") + st, sbb, err := BlockRewardTestSetup(t, version.Altair) require.NoError(t, err) mockChainService := &mock.ChainService{Optimistic: true} @@ -241,7 +302,7 @@ func TestBlockRewards(t *testing.T) { writer.Body = &bytes.Buffer{} s.BlockRewards(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) + require.Equal(t, http.StatusOK, writer.Code) resp := &structs.BlockRewardsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) assert.Equal(t, "12", resp.Data.ProposerIndex) @@ -254,7 +315,7 @@ func TestBlockRewards(t *testing.T) { assert.Equal(t, false, resp.Finalized) }) t.Run("bellatrix", func(t *testing.T) { - st, sbb, err := BlockRewardTestSetup(t, "bellatrix") + st, sbb, err := BlockRewardTestSetup(t, version.Bellatrix) require.NoError(t, err) mockChainService := &mock.ChainService{Optimistic: true} @@ -277,7 +338,7 @@ func TestBlockRewards(t *testing.T) { writer.Body = &bytes.Buffer{} s.BlockRewards(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) + require.Equal(t, http.StatusOK, writer.Code) resp := &structs.BlockRewardsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) assert.Equal(t, "12", resp.Data.ProposerIndex) @@ -290,7 +351,7 @@ func TestBlockRewards(t *testing.T) { assert.Equal(t, false, resp.Finalized) }) t.Run("capella", func(t *testing.T) { - st, sbb, err := BlockRewardTestSetup(t, "capella") + st, sbb, err := BlockRewardTestSetup(t, version.Capella) require.NoError(t, err) mockChainService := &mock.ChainService{Optimistic: true} @@ -313,7 +374,7 @@ func TestBlockRewards(t *testing.T) { writer.Body = &bytes.Buffer{} s.BlockRewards(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) + require.Equal(t, http.StatusOK, writer.Code) resp := &structs.BlockRewardsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) assert.Equal(t, "12", resp.Data.ProposerIndex) @@ -326,7 +387,7 @@ func TestBlockRewards(t *testing.T) { assert.Equal(t, false, resp.Finalized) }) t.Run("deneb", func(t *testing.T) { - st, sbb, err := BlockRewardTestSetup(t, "deneb") + st, sbb, err := BlockRewardTestSetup(t, version.Deneb) require.NoError(t, err) mockChainService := &mock.ChainService{Optimistic: true} @@ -349,7 +410,7 @@ func TestBlockRewards(t *testing.T) { writer.Body = &bytes.Buffer{} s.BlockRewards(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) + require.Equal(t, http.StatusOK, writer.Code) resp := &structs.BlockRewardsResponse{} require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) assert.Equal(t, "12", resp.Data.ProposerIndex) @@ -361,6 +422,42 @@ func TestBlockRewards(t *testing.T) { assert.Equal(t, true, resp.ExecutionOptimistic) assert.Equal(t, false, resp.Finalized) }) + t.Run("electra", func(t *testing.T) { + st, sbb, err := BlockRewardTestSetup(t, version.Electra) + require.NoError(t, err) + + mockChainService := &mock.ChainService{Optimistic: true} + s := &Server{ + Blocker: &testutil.MockBlocker{SlotBlockMap: map[primitives.Slot]interfaces.ReadOnlySignedBeaconBlock{ + 0: phase0block, + 2: sbb, + }}, + OptimisticModeFetcher: mockChainService, + FinalizationFetcher: mockChainService, + BlockRewardFetcher: &BlockRewardService{ + Replayer: mockstategen.NewReplayerBuilder(mockstategen.WithMockState(st)), + DB: db, + }, + } + + url := "http://only.the.slot.number.at.the.end.is.important/2" + request := httptest.NewRequest("GET", url, nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.BlockRewards(writer, request) + require.Equal(t, http.StatusOK, writer.Code) + resp := &structs.BlockRewardsResponse{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) + assert.Equal(t, "4", resp.Data.ProposerIndex) + assert.Equal(t, "15714490", resp.Data.Total) + assert.Equal(t, "89442", resp.Data.Attestations) + assert.Equal(t, "48", resp.Data.SyncAggregate) + assert.Equal(t, "7812500", resp.Data.AttesterSlashings) + assert.Equal(t, "7812500", resp.Data.ProposerSlashings) + assert.Equal(t, true, resp.ExecutionOptimistic) + assert.Equal(t, false, resp.Finalized) + }) } func TestAttestationRewards(t *testing.T) { diff --git a/beacon-chain/rpc/eth/shared/BUILD.bazel b/beacon-chain/rpc/eth/shared/BUILD.bazel index 78c012169402..1fbfb4754f29 100644 --- a/beacon-chain/rpc/eth/shared/BUILD.bazel +++ b/beacon-chain/rpc/eth/shared/BUILD.bazel @@ -17,7 +17,6 @@ go_library( "//consensus-types/interfaces:go_default_library", "//network/httputil:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", ], ) diff --git a/beacon-chain/rpc/eth/shared/request.go b/beacon-chain/rpc/eth/shared/request.go index ad781fa7134a..1609c0d8f597 100644 --- a/beacon-chain/rpc/eth/shared/request.go +++ b/beacon-chain/rpc/eth/shared/request.go @@ -9,7 +9,6 @@ import ( "strings" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync" @@ -29,7 +28,7 @@ func UintFromQuery(w http.ResponseWriter, r *http.Request, name string, required } func UintFromRoute(w http.ResponseWriter, r *http.Request, name string) (string, uint64, bool) { - raw := mux.Vars(r)[name] + raw := r.PathValue(name) v, valid := ValidateUint(w, name, raw) if !valid { return "", 0, false @@ -50,7 +49,7 @@ func HexFromQuery(w http.ResponseWriter, r *http.Request, name string, length in } func HexFromRoute(w http.ResponseWriter, r *http.Request, name string, length int) (string, []byte, bool) { - raw := mux.Vars(r)[name] + raw := r.PathValue(name) v, valid := ValidateHex(w, name, raw, length) if !valid { return "", nil, false diff --git a/beacon-chain/rpc/eth/shared/testing/BUILD.bazel b/beacon-chain/rpc/eth/shared/testing/BUILD.bazel index 0ef68bda6595..d9a33634e8c4 100644 --- a/beacon-chain/rpc/eth/shared/testing/BUILD.bazel +++ b/beacon-chain/rpc/eth/shared/testing/BUILD.bazel @@ -3,7 +3,11 @@ load("@prysm//tools/go:def.bzl", "go_library") go_library( name = "go_default_library", testonly = True, - srcs = ["json.go"], + srcs = [ + "json.go", + "json_mainnet.go", + "json_minimal.go", # keep + ], importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared/testing", visibility = ["//visibility:public"], ) diff --git a/beacon-chain/rpc/eth/shared/testing/json.go b/beacon-chain/rpc/eth/shared/testing/json.go index 16aa30ce10d5..5b70080f53a4 100644 --- a/beacon-chain/rpc/eth/shared/testing/json.go +++ b/beacon-chain/rpc/eth/shared/testing/json.go @@ -1639,6 +1639,227 @@ const ( }` ) +var BlindedElectraBlock = fmt.Sprintf(`{ + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body": { + "randao_reveal": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "eth1_data": { + "deposit_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "deposit_count": "1", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "graffiti": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "signed_header_2": { + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indices": [ + "1" + ], + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + }, + "attestation_2": { + "attesting_indices": [ + "1" + ], + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + } + } + ], + "attestations": [ + { + "aggregation_bits": "0xffffffffffffffffffffffffffffffffff3f", + "committee_bits": "%s", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "0", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + } + ], + "deposits": [ + { + "proof": [ + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + ], + "data": { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "amount": "1", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + } + ], + "voluntary_exits": [ + { + "message": { + "epoch": "1", + "validator_index": "1" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0x6451e9f951ebf05edc01de67e593484b672877054f055903ff0df1a1a945cf30ca26bb4d4b154f94a1bc776bcf5d0efb3603e1f9b8ee2499ccdcfe2a18cef458", + "sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "execution_payload_header": { + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_number": "1", + "gas_limit": "1", + "gas_used": "1", + "timestamp": "1", + "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "base_fee_per_gas": "14074904626401341155369551180448584754667373453244490859944217516317499064576", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "blob_gas_used": "1", + "excess_blob_gas": "2", + "transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "withdrawals_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "bls_to_execution_changes": [ + { + "message": { + "validator_index": "1", + "from_bls_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "to_execution_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + ], + "blob_kzg_commitments":["0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8000"], + "execution_requests": { + "deposits": [ + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "amount": "123", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "index": "123" + } + ], + "withdrawals": [ + { + "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "validator_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "amount": "123" + } + ], + "consolidations": [ + { + "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "source_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "target_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" + } + ] + } + + } + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" +}`, attestationCommitteeBits) + +var BlindedFuluBlock = BlindedElectraBlock + var DenebBlockContents = fmt.Sprintf(`{ "signed_block":{ "message": { @@ -1844,4 +2065,237 @@ var DenebBlockContents = fmt.Sprintf(`{ "blobs":["%s"] }`, Blob) +var ElectraBlockContents = fmt.Sprintf(`{ + "signed_block":{ + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body": { + "randao_reveal": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "eth1_data": { + "deposit_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "deposit_count": "1", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "graffiti": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "signed_header_2": { + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indices": [ + "1" + ], + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + }, + "attestation_2": { + "attesting_indices": [ + "1" + ], + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + } + } + ], + "attestations": [ + { + "aggregation_bits": "0x01", + "committee_bits": "%s", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + } + ], + "deposits": [ + { + "proof": [ + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + ], + "data": { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "amount": "1", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + } + ], + "voluntary_exits": [ + { + "message": { + "epoch": "1", + "validator_index": "1" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "execution_payload": { + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_number": "1", + "gas_limit": "1", + "gas_used": "1", + "timestamp": "1", + "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "base_fee_per_gas": "1", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "blob_gas_used": "1", + "excess_blob_gas": "2", + "transactions": [ + "0x02f878831469668303f51d843b9ac9f9843b9aca0082520894c93269b73096998db66be0441e836d873535cb9c8894a19041886f000080c001a031cc29234036afbf9a1fb9476b463367cb1f957ac0b919b69bbc798436e604aaa018c4e9c3914eb27aadd0b91e10b18655739fcf8c1fc398763a9f1beecb8ddc86" + ], + "withdrawals": [ + { + "index": "1", + "validator_index": "1", + "address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "amount": "1" + } + ] + }, + "bls_to_execution_changes": [ + { + "message": { + "validator_index": "1", + "from_bls_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "to_execution_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + ], + "blob_kzg_commitments":["0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8000"], + "execution_requests": { + "deposits": [ + { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "amount": "123", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "index": "123" + } + ], + "withdrawals": [ + { + "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "validator_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "amount": "123" + } + ], + "consolidations": [ + { + "source_address": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "source_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "target_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" + } + ] + } + } + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "kzg_proofs":["0xaa0ef7404c3a164741856c78cc844072448886291e3c5b29514001d1bd8c5ccc9c342a1caa58c3b45734195ef4b4122a"], + "blobs":["%s"] +}`, attestationCommitteeBits, Blob) + var Blob = `0xe3078ecee8c4625a862b8abab2e220be24d7bcbb6b72dbcf0a2afa6b6b5ea77afb84bfa2ec47e6fbce8f3d4fa8a46b70a1db8adaec6cb2bdd1c36cda64ecfc9128aecf2d1b73c7ffe75dbac4efb9e49a5f05bda1df6f7caad2ebcea7fe9919de9afefc6581f2b7bfeac8bcdbfbaec107fdcdaf3cbe765898c01ada724ebca0aaf356ba584aec7a9f2e44d07ae60ed29347dbe0930ee05ada11b861d24a7f1e5afbcca9eaea56e714eca0a54194e6da9e2a34dfa3d2cebe6c1c9eeed7fde1ce8af8ed66d9a63273df5240d20e0e2b3cdffcf6ae8aa1698fb2204adcdd1e79afc4a4fecc7e096edee38c9bb9980dfac02518ff88dc44b20a664dcbb34661da4df5af8f97ac41dfb7cdaec2acc91cb3bb7acceabb1db6f0cbe71fe2580ed83d056d7ebaf87e4a1dac19143d6b889782ae0c7aa65e4af3feb4c7da479a1a3b6f102cf7c1dfd26b6ee2baafc281297be1fcf5e032dbde78a67123a920bf5b6bfefdb8dd94a86b6eefde5e7f9d683acf6a0c3b1ea013a5dfdf54be6a6cb3ae262fecffeee90bff4f556bfc4e9dddffdd4756611f8facb8666637aa3dcefcf1bfca29dda307c349b0cef9f0ec40bfeb1cfd4aaa8a85570487c4f834ab12ecbbfe1bdf932abd1d484b7d9e7efdba6215d34c6201da6ed9f907a50197b5067f7cd7d01ba94b1af82efbc8e9ef5d781ff1efecececfff36fafb16957bbffad95fbafb14ccfe2a2bf570bf90a6f98fc660d80c712f13d0d630d4710eefcd27603bfb3cb1b2c1e3d6c7bcdc537d80f7eb31ed785de8b47a4119415c83b352cef30d23dad7f3c701162aa37db213da385785aacc79faa5f5f6ec4bff4cbf51e82f56ad33870ae74fdc7dd2dbd8d76ff92a8446f723a8e42c79bdfde1c6b61bdafa97a9cc25ae83a3d9b1e493f5fc5e5999fbfebe1c0879dbf4d64d14e0ca6abe8b0b7dda5b95fc65370aaded9086ab27d0e2fbdbe7eaebf0abfe0befb3aa844eec5c563275daae53daeefebf8ce92abec499becabcfdfc8dbbf60cebf00e45195dd8ba2e3bc1cfd80f1aabbcc0cd805e402addee1aaeb99d4dcef8b37d6767d96c671f1d9115fa5a69dc14603ea8db1aeee78cdccafcef8dc8e7dedc821dfd8a6ede6f15aa797dfb3f5ebb2bbff023eeddce3b3a2f4ea041aa07e513a928dbf7eed9184fb54fc12385c4e494cea1e6bf00bf6f1560edfd027f5c98bd1a4ee38a3b14e2f2ae07ebdcd663ae1aacd5b1aeba14bae9f14cbeb4bfed399e9b0285cf1efee8f2ab31dfdf33b5e3defbd6ae6ab5b18e9e19cc5a35a8b1d76f9f90ae38cb564fe386da0a586d0dde1c7c80f19a442c365aa1f1c10fdb1765f6bf21dac76aa1e8ecbc31f8909605456aa1bf5d10851cc6c6c9ecee8cce790e4fcaccaecdde7a4f5a40cc20d18de0978132cdc4e5aa53b97ac84d942dbcd23bf0c8bb3c02bc87d0f3ac518b482d87dfa411aa795aee85a5b55c3b4e136cfc43fed3dbdcf2def75309ddaf34bed3cfa1bed1ccf0b4c5b8dd14a69e3edfb5ec17a2affda52193c372cecfb1cceb8274edcc9e49576d629de561602880ebce92a68200a441bbd0c1556ccc2aeb16fcaa78db1fdd755acc6c762fecedba1f2b78e9b5bcbf494e6178b63ca8d4f40ffc7e3bd4a16dbfd7db2e4e6dfe10a47f0cd6196ca7a2f4b33efa514dee868d0a21c6dadb909aad1eeb05eb3fcc7d144b1eaabfadbe027e3cafb4e4c8d7e0d2cfbcfba535200478f33f6a04eaffdaaac1508ab6971ab84e6845a528bc91d5d9bbdd1c873589e896c300d069ffce5ceaad93e460d992ec6b1becff291aec8eed5dd9df92ff389dfecef3dedf41ddebfb7186cfaae9df2ba8eb9fb331cdfbfa5ca5040ade7cfbc6e6d9719e4626dbc66d9bc6ceb8cdf2cffff78fe2f077cfdd7320e6e2dfe44eabcbfedae887ecc8d55f7844983cf4ec54956aa6fcdb9cf0e37d9ecc77fe1f8e8cc5e568dcf5e2d83e1daea5cabf7fdd8bacc4996163a168bf28458eaaa39fecb4fae8cd0fcbdb09bc8f41fc5fe332ce455caddc4a8fa8594b5f0d0109acfadfaacacdca2c59fac1a20a414cfd9a4efeab415be18e9a18eaeeda0faceb64a2aaa58ddbbaafb29dbff8f4b52ced51bbac4ed67ccf4cb711ac14e8bf58f17d50e729bafc3be97bb4e6354f855feecb504fa2f35efb184abde5f29ee1ae2c394be8efa2cad872b624ac2de8febcc55da95aa5b3998de83dd4deb3acd3a9fa4aaac50fc6e7c15fba147f0cf0bb7c62d675559cc95e4abaedefe4e1cfeadfb71efb5deed5351c8c5f56e4b99b13de9ffe6fdb27f4e20fe325af01c8e5a949a0d9ddbbf9500506baab9b19a5fd7222dbe63cedcbbddcc6e8d66ab2b05273acb9bc04d48dae12d4fbca9ed26fdd93fa75e010dc5e388cf3d082ffe6bb3f55ac4703ec56fdd1700eef433bd601aff0f321aaf4d3cc6dff15c7c719a0e2f7fc6882c9d4b88b78f750cb7ba1ae67ccf19b61f55c3d236cd0c5dc0e9cfbe0bf903bbedb2bd9e2e88ee8ca61b3fedffb4bbeeba18a3eac0f4c087abfdcfa279e9b9672dea173ece706a1a1bb04e937d52ad3d2ed27c3be082dcca4eeac9a2adfafab1ccfb15b7ecefcbaaf6dfab4eedff1baa59be84eb1dca03d81f0c6befdeee1ef2bc4c343c1bcab0b6fa7481ae4d9db769bedbd5d94fdb41992c9cffeca918b6fbccefcec37d55a6efcc7c03cebf1180be704daf2d9bce12ab6e09acb84b8accec9d34ab83fa7281eddc2b6a3ddbca9eebbf535db14153faa7aca596c2daadef89ca3dcc8da4f96751a38235c83f6d87ab57c47e72be6d9aa410d4d7bcf9d6d563ce8cbeba7ad6827a1c71b5ce31c1ee2c80fce8ac7c9e6ec8fe5d6e1a1a81db61adaddbaae52d07db73cac7e5cbcab253ef1cc3b7494cca8beda70f6adff3c7b730ff00faa39d655fb447abe997fadcd298d9385ebcdba5cd9f97b53c0a0bdb7bddb5eecee609c8dfb12e001ce4aeada75e85e0ef8f6a1cea84bee6aaddca7876b79f1ebd639dfa3b9890fbe7d80f5cecadcf37daaaa5b6c5142f951eafd7c16c533ab826ae1ce236f7603b2bd23e6629de1dfcb17ddc52f42780eb333f04fd2149aaac49f258a0e4cbc97aae3943d8edbc646f3f4ec652a195ead95a3e1310cfa8dceddd187de4bbb369a7abae6e8d95333bee5a53e6e5ecff7b8849eace10e8cdfbf5a3e4fff70c4e638ef22c7bae4355caefa0fb7b36baca793ad5d1be0ce93ef35fec8eeb8fac83a5da4cea7ccbab2e5b1ed5acb22197b3a75eb1fcde1e3dcd0a51aaf655790e58fabdc3aadefebbaed828fdbfefa98baaabda5d5b203aca7fc5369b62364d4a57c7c3e3cd77ac0d3de428b5ce61e93c05d8f11db6e3b0adc9c1ffabaa998ca827d8d87b69fb12caf5c6b0f70c7f989044c3dc8c8baebaafe0ccacaebaaae6026e596bc92e1bd6dcdc524ab90f3ae0ff0d1d252bf37c777f3addd72dbdeb9e2a79b563110fc623bed79ade04aab96e319621e69fde576eef79cc0e6a7b292f8faadedd9fc720fcbccfb7fcec60f930e4fbee3b4a2f1a091894c5447666f15f8a2a3f2e2cff0d1630ab2e8cbce90b4ecd8eb18fe741e8abbca937b8a430afa8f1a18b2ccb966fb42fd7237b1a8ac23c085b9229c4ccd0589e7f7a636dbabb7b706afa1be145216caff4e56cbb04ed36005a65202e1fb8bf6d7d2065d2ab64fa45fdbfbda455aaa10ecf9a51fed69d784dac36833aabc47f9aa2a3e0c60d6cef59cacabde633735f5dba4d5b3aac7c8064d2a2adff84c2f9763c58cfe0c794ca5bfec7ec65e8e3930ed78bcdf8e2203b04ee8bdb69faf6ea94aea5496fcf8aadeb233da3ccd4bdeead54aeffd3f8cebf50fcaaf55ffadbae92ece813e3d83aecfcf0cfb9d16d4c9a2e7ad3f972fd69197b84e2915d8bd84d0ca98acb296da9dece7dac0b7f068e2aaaa6f1cdf8559fb57e09fdda81cb30ea8bbf58a4e6d42bd9bced5c32a0d1a834ef33d37a31e9d07febdfdfc211defa2c5d4deafcdd9efac0da96ac77f921f3f7eec06418f2c434c66cfa1242f21b247caf08bd33dc8f78ca9abbcafefbaf67ff7ae4bcb6924f1edc88761e70eba8dc2a97dc31cbde7932cffee930163f916db61bc2c793edddcaf4429857cee1be109cfbfaeadb0c49ba6c8dba6ff7a2f47c05d3c3c3bc5c434fb058a807b09b1a2e94fa9a8fa4e2fac6268665acbdcaeaf7ab05e5ec2ec0f48601150e7c7aefdbe97ddfc09eb2f1f22a50513d7dfefa60cbcd7e42dcce8bceb2feca4d0ee4143b8848df89ce121df5acda10fe45ef707aceaad6504edb2aaaf668aab4ed3f1a1bfc5f88a009c307dcc396f0e5ea51ef484fbdbccefd110fd85cafe5c78ec95b35d63d0fd9fbc4ccdee95055fb23accaa875bda9ffde534bb9dabeecaf3e90d7f5bc5dd15dffac15fd811300adfdc66573abe0869df8c3a495db6ddef7beda9d52c28f31a5afaee99c3f64ace76acd8812dce37be20d9f4cad7b56a6dfd1f0a1edab62b3eafd30aeaaa6cd02afe6bc04d3fa38ea79d5d8ecba5c04ffecfa13cde8e54ccffdd812c192fa9fdfaaadfaa2bafcc7b3debcc6d84bdcdae4b3aeda5bd0b9acbeb39fd7ebc2eff082ecde91e1eac63cfaf1d4efe94f6ad44acaf5fd3d5feaaab6ebace2cf5ced0c02bce1b933fd0aacdcc8eeee9fa60e2ad5991eac44cf86eaccdbcb5ede1bc89e346bddeaf6032197dac0ab0ce8cd1f2bbf19bcdc0eb6b098e3b62bbb3edb62a8aca92bb8d4d01aaf1fca82ea3a4efb927ac507cecb93ce14eda836cdd83bae1a4eab4cad9f6f975a56ab8ab0ada8faea40ffb9f1f4f2c6d574dc5f1e1defc5a9ab5e0deb735b49fb3b6d10fe8eb3f51f77fffffccc6a1c57b17bf10285bdac91abc9c993f403ece1b85e1df7ffcf7bddf486ea3e9ffb838dcecddb89afb85fe30874b0b8add794cf3344baf161b9baff96b08ea04ddfa7232a66e2a1decafcdeb4a26e3bbac8089c63bcc4fdf3d42ca5d6d454aebadddb7614c81f53f5eee7f6d82edb98e042afeabdedaf573de15bb0a25c48cb1cdd22e1517ffe370db7f6bb1d4eab8236ca466fede9cd3fbb88eb5e1dec8e994aef3cc80c346aafbaa25ccce5d9b5a4caceb5ea7fbf7e4d5bd16c21fb16ec7d7da21b3d7fdc31ec54be605eeb921fa6f5c998a4fc2ce1ec059c6a6faca7e10ec7dad9cccfc4c08c0dc69cae4b7aeec96e8d49becaba3f43dbfdd29a4dddf3bf0ecd2e4ea1a76f816f00c7cb12b51182420697fde6859b6a01aecbbfdb02fdc6cfcde4a6d1e98de70d5a6dbaf42f7a2ddf4d5412a8ed5f36c719bf22261d783abeec2ae6da933d04e4aace69194ad52654dc48a9bf49ab84d0a41c9dc6c6fde6647ef0e1cfe7e5cf05dc15ebd632bead5a385f6da2114faea1d88baaabb99f7adae24d3b0ecf1fc8c9d0b1fccec2d6b2ae4bfacedde489be4bca282a1a8cfafad7ff2eee628da39fcdcb34a123f66aa6cfc9efaabc3cd819d23c8abdfbab31adff1c5f7131ed6b8bbd5aec4bfbb9a2b8fce8aa7c70ceb7fa774b26dbaefa786e449aa3794f7b3558cc84b2fc2df1a2d311f9d429f4d91c2fcd9cd07c0dfd924cd5e495851ec7433353beddc94326dbadcef6e0ffde56b6351312b2a306d4f4eca6eb2bbd19980f3567c5b02ae822717adaeb90aa843bd90c6368157b2622fb1ae69baf7a1ee3dbbf9c5c295f825ddb25f1791b13a7dbd2cedbe1ceecfa0bcca3cf92b8c7f7f7ffce9e982dbe7ca9e6f4fdf3b852a1479fbfb263814ba75beebaa1af0ff4acdfbc225d4e281069acf20f03ddceada3b9ab42a92adeb72f52a0a2e2bbcca6ac35fc39e74e910fbf0dfeeafc3accbf2f4c3ff88ba31a469bec96daff2adf1232eb6fdeefa7b764793b46f291bc27669d57e5ff60ea4eb88dab8f2834c4d26b2940e60376f524b119fb9881c4ac9644fdfae5d6656d7cd25136714a94af50dffcfe9583143abe0ad3ac9ffe6b42c2a5ae2d3456e5bb9231ef6e15f0cf6ff413ec07bbacc26cbe7c8f33ddb7c1eeb407f382a44ed12cad18abbbbfb0add2bc81a078b54da80d90bdc50396a7171ee577efb9577caa460c1c8debcf669481f4bc67ca15888c94b8381cfad6beafcfac41eb7fc0a7eb521667dc80ef3fd0b10f6decd72af98dfeedbac2a7bde4b481da60bbd6e8ee09a9bfb59beee7900aefb2c89d7f0d2ef6f2706031d6e2da3dc95cde1caf4bcfc4fcba7071aecde8bf870aa67feeaf4a8caebaf7c31ee1afe69fcfa4ad66e9afd9434c0ff898a9d82ba8de1b7cfeeeadfaa0d5bf57ccdcdc3a5bcfb0ddfd14b14cd6ccaf94119ccb13c8ea02f6edf652ee0f8c8beeb496d5c1aaa5ba4aebd0eae4ba190e38bd80416ba4ace6e5ed1fee4bfd1cbcac618a3b2eaa9bcf6851c2400e2cf7ae2aa5e7dc1aa61badc0944d4aee7f2adaf7e87bd6d6abcae1ccfcfeb7ff75acfdbbdcbb5157d49b7bbba76b8aba0f4768cc0acb8c549777ed5caaa6263774fa1ceb5aab25a64a92cd0dc2e2ddb448c36c8bbcc2a5cce68ce9c17890538ccfefecdb58aefb3aeeaad745a80b8b0bf7e751c8bcee6d293ed1abafe46fec88fbaef4b28c220cb36dbb7fe01b856afa6d8b748bdbf5f13c6dbd0ac9f2fdc0bdbf8a1454cbefbf22761aaa4fb0564ab569c7f78a91ddbfcfca466e3de9a1d4c8d3b9fdf1eb352aef54bdbd03accbd8ab35cdfbde2abe80eafbf3f3e9d8c1b4deba76ddaaab8b6d486fa2b92817fdbaeb1ade398a7d6eae2349c04e8bdaca4a1410cdcb9277cbe3d414aa57f6d2bba4aef3f1c8564bae93b2b3cface3ddcf63c3dacd67bc4dbd6f9a2e09eec18723a5da60b47eaeaadaecdf4f48d6ccf9ad873cfbb3bf8a4d31abcf79ddac7f2bd8e55107e2ecea8c7fab1df7d1d5dcadcf62afff4cb7ceb32cdb6f319a55476cfeaf0d5e2301b4ccb4cf9d08ac909f42f0daff13b6f0a7b2a7eb9e0d4ff7e63819bfeb5e37d595f26abf92fdee8aa7a2ec674ee4ff9ec25e837b2e63aba21fbfc5eeaeaeef9906685b52bc4bdda5d2fd65957a0dde7c680ea5e6fb324da2fdd551ff2fbb9f911b84c5babafb7dbb032ed0b88ffb2cbd06eedbbdc9faf9fb8ce5afc19febcaeca9f99c448887b91dc55fd62768acfa81c5ecb5d1a0eeea963cd8cfa0f80dfe17c150ca0dea0c18130eeb1a88fdbd6a31123dcbcb015cfece7ed2f31f0aab6fbd2c82bf7f2c9b4e19ce613daf0e07b5bf37dcc9c3f4d09ae2fb55e212bdda94d1ead77aaf9ce4b0ff658fc1e5d69b97ae757bcbe4fcf85b984d92357b64bb21e6dd253e141be9441cdfb706cd7e7edf0d1d7a3defddb1ef27b1785a560fccb5cdbb26ad4ceaafe4bfc9471aeb2db61773f522fb5ebe17c5679bba785f7123a47b2babe2b45fbf4e1ec92c1400cb5c2d6b4b75c9cfa018bb1ad425ca1e5f1decab7dcec177450b952d84ed6d8e18a6844dc34eeaf30cdee4cbe0d4ec56c5dddf5fc36f2ba6bdbdf19a99eca8460feed3dcd9cbeb4cce7d1ed0d668ad8d86aa2d7fac046b0a51dbbdfeedacb56f0a5db7eeabcfad863e6ef1a4ce9219febff0cd9f9a5edcb5898addeec181f41faf7bc0e1c7aeb961473cc4eb8acac46b7db6c79cfbcecee17a01010697b1ca5380ce438c93fc4f0fd26cb114dadca528c32dabcbaebeb478e6cfd35dd95e67dd13dc2df6f8fdbd2d0f54edda6c73ea63cd7d9232ef760f40eb0895b14eb1d2b093f61908e5f2673d4bd7d9363aaddbea90f878fa7f9fdd6628f5e7adaec780f88e4cd4c8cd8fdea5c4cbd09caea7ebbaecae999aaec0ceffa6db6598720edb1145eb479fdacabfdfc58a8727ffd05a9515ac0dae0acdc082c1dddcbb6cba729d25f208b00bd03c7f36e44effbe6c1ca7c2b0daa46cdafad4c4d01afed1b4f2c2af6b3fcfccd33963de2e85a3ffe1cfefbc7b9dedc27fa153dabc462dad095fe800cf1e6990d03bf94deee2c0cfca5441f397c1bfbb6ffe90a13dbadaea22baf7878ee8ee6b9febcc9b95eac4a1dba1cc28a816bd1d37caff08bbffbee004b0bf200fa1c7f968fadbe49ab76fb0ebe475a7cadf943eb0cebf7df87bf9fbf8aee807d4bc9fc53d7fef5aff32f3eabfa5ddafcfeb4f4b0d9dc2e6fd50695f1fe3a0bba14cd2eb94b5d97c8bddf74e9a47208d21105e3ed92cd78afbd3ee13cbb1cfdbcda6bd8fe31ded1dd255d09cd8e9d616bfe3fc9ad2165e6d98571db8eb779d70bcdf3ab75cade3e7a4dcded77ca5a1ed77cd0b203f03755ee5fdec84f97af902ecefd2a122d0a0ea1ec267ce2be7f6bb331e632bddfcc1dc32a6ae8f5e6662afaf9f7ff430eb412c071fdce1bc8e908ee1e17bfc3e6ef1e6a77577efd302ea9bcc3b10e1ebf11eb2aa7bf663d2e8ea286daeedb1dad3115bd3edbaacfbf9deedecc28bedce2fbb19ec10df16d739b003efbadf50e94c5cb8ba8f5ae4b639b3f6bc7e7bdf416bee17d09b771bd9baea355d63c69fcb909af4d73de7b120c6dee5cfeabeeec2059fc69f06252caa9baef1c5d33bdc6334adac49dbb8f1fef2cdbf41c42f5ebcdfc54bbddf5841c8aeffb58a6f3db38f8c9ccf25d4e7f3fc89e177624c6b698d33af5eb3900efe830c94af8feacc7a2a363a58128fb9cbedf2b9b6bede41f6cdb70ff55e5bfbbae417c92fa6a84d4f30ffa83aa34796cb6ab1dffeef7df937dc490ea7c9ad34e5f70f67f1b3bfda319ca1ee65bdfd9aaa9f44b809bcbc09a4f3dc974dcdd87bd22a6acbaf0457b38d3add82be44748d7b00c9665bbf1aeef96e58e6d89f2c5d6ec3adab6a9fee16f29be5204a191bb3bfd5061fed19e5c69302be04d96e67bfffbf1dee44123fa6ad799cfd6955bceada21caafe9350e03a01704dd4f6ecd4ef9bbd35e6f3cad57c9db744dbc4ceaf5f0e5eebacc1f2d5b8ebec5d48aa39daffc9c7d1a3acaaa7d72d06c96441306bbdb81d9b951be4f1eda8f6fa1c0eacbedc71fd3d1439803ebba3b56e11ce2071ed6495a6fb69acc6dfcf1718afeabe6fbf7973f8e0acc117f220bd68fa0e7723cd4adc84eb7ba490cbed9eff0d0aeefe1a94ccf1dafdc8c65dcdadff8c1cf9ddecb9c09bada29caecdaee2cbedf8b780661ab4e696d1f69ff8cbefa9920e8cad924e8ba766bc8541cba6f7ca850d3f63e27e0ecb40bbdcb9b7cd7bfda9aa4d0efe1de4d06dac08606efc9c16accddc22aed4f2d53da35d8d241770c9b157d09216ec5e0f59edeef93c4bbf223e8b2c2c863ccc37ee2c2d07bfd964dfbfc66db44cc2a1cfbb5ba23aedca07c753b0a0cdb3be2e68c07b3546af624ad0f9d4f3d1fe0cda95c3de9db51f3aab1e90df5d1e2e30389fbf350eed613f3a1eac940bd77990975436f152abd7cdc0ae49642d0ca2958e8d8eee5a6cec4ab9d852b16a261a8af537fde21e59a970acd5d3c784efa2534056bd827df9aec046dbcc2ecccb5b0df9653ef4a7ad2c64ce3d4afcbeaf7fcfc1a8a6fef2a5afbdcd7f6dba58edc7168ef149a9bda5b2f9422deeeaace01db0eb4dc9c1fa8d5a89c3b8e92fd4c7b81e6e7df39e47617fdcebec9329d5bfd6078587b08a7d0890ac7a0f2a54b8e3e3f28f4ddbaaed0de2aaafc8f3e5e7f39ffbca28f5e1abfd9c5ffa1f7adc36a68edece08a66c1d3ecea56572b5c1abfd39709cb8decc0cddc54ff7dcb2eb93cfd7acccc5126cee21c3e4ea91cffb4e5182dee6bc11bd721dda301cf41e42d5abd8418e3e5af3df6d5acffd012faffbac88cf23d68ceafd3f0cceffd4809bcdad320211b7a032ee09e51da61d22448db0a590dfe3a97e892ebb3ab736d0aa6d6d96d6d2ad18b0fd6eae2d0ec374bad124aeb2b4a1adb0d7f3fbc740a0be9a12ef5da86ba5c3d40c9e203dc07f81a062c7acfd410a4e6bdfa19c8df1f1d8aa995679e7d493ce760edb1e8dad0c2adfcc62b0abaacbcd88ef90f5efa4e20adfe5fc7a1024b4eaf8d42e4cbd2dbbaa48e0bbd9a1761cb2e7ad119f3652da3181cb55f8ac9aff93cb8d23e361deeca4dae907acaf09dbaebcafacf4ae3ea78edfc3e1793dbcc0a8585b0352faa31c4cf60cef8483982afb0df1e7c5cbe270674c8ebcae667fea4cbd3ca8d7e112fdb96d7ff3ea3dedd909b1c28900a57a69bd5cbaccaff6bab2d8a7fbaaeda11f2ce6ff856ae51e029db6717bcadb79d73a99a56e5ef35dfc5af3af7f15f2f6fb7a91a08be9e8af979382337acab6d750638f0e9eabe5fe4820da5dce1bcbaefc3feefef2f6cbb664a5beda1bc702e7fc7c5f1fbf03236a8dab3fefbc05eababbbc97cb14bcaf7c8ba3a8de71639b9d4a9efb0f8f26dcc3bac5fc0b4497917e35eeae493ba6eb47fa1748c5e6aacd79940739fd11aaa91d9d9d3c17e1fddfe2cf1c14deae07545b71043be9ccc9deef6d4d947bc01ebb3dd9c09cafca4dea4f69f1e74bba0eda5e6c96ffc0f0b0a58bbfadff3ade7cecae0f1d419a3ad7e89e7bed01bccd3f449b0ef1fe4eb9ecb0fbdee65defaece4f1b1444842dcbaacdcffbaacb2c054aaa31f9dadd5ca22cfa367b5fae0c7fccb434c0a1ca4fa3eadd8f9ec0bccfeaeb94afb9eac9269df81cce3cef8424f8ee09afdf8bd346b9314b91ddf976cabaaff5d27ed4ffd9e4b53e63d68630d7e55afb8d6bcfc4c13bc89d2acefef68e82d5649a8cdcfd01baa129600511b3cf8ab0d94b68e98f42ffa60decb26720edaf50259afaaf4dedbe13e72e9fbea2e4943fbf777b72ac9a1caaca9eaf9267ab851dc44fa5a9add92e22ada4f0c6fcdff3eafbb842bf8d52d8cd57ee6def44b670eb46f08ad2f08fc9caeecbab6f928beb4aa4fcab5e6bcccda1e3c61aac6cd85a9b274dca9ebdafedd66dfd7bebabac13540a8cadd5c6b7c2bd0c043a625ba2d2ca6e7aa559e2aeebeedbe85b0d539679eb9df6fcc932d27984b25aaecba93f0c2c9cbed6419b56532d2e0c80ac4956da2bbe3bda939670c851a5cf55cd71b8cb810ae2d034ede81b9effaa4eab44bd0dc7c69ac96be4fa2d511fea982e6fce8aa9bb0fca304efff4c1261f2e0bc042bdbfe6299e1eeac2ba7400ebe8aecae85c5bdc24b6e102febcff721edcb2bef81f7cc1c8e2b4b4e544e2a37b081af96ef18eb6bbaa1dac3f73a53bf4aa8f68bf2f0bdbead885cfd25ac5bd53caa4ee4a433e528e8dd5eebcef375a7bcac7ddd4c4f9cfcb8f7a2aef0c5b66aeba577385e3a3ffcbf7d705cc4beaffedb0ccced0e0ccac5aef6c254f0ccc7d65ddedaa5a0d3cd7567c93f28a0e1c0af7ca738d7ab0d096dcdebbacefcc6bcc16ee1a1f224fd6a94e3b2c2d8b78f9ccccfde1edbf4fcbc065a3d08e1c19146ae556ee3e1d1b32daa5f1b4be2f80adfd06ee7ec24bd4dc8aa7cbae33bbfed50bbebe8603e474fde208cdb8bdcb93bc62c7bced97ebca1c01ac9bae23bfedc7d888b7fef3aa0c3949fcaf4b3ffea1b6e3da9defeb9ae99aafc94e97db56c704caebe845e5bdbc6faebda40fc206d48f09a339141fbbe6a38030dd52d2f0f5b9f09ddb12b8f0ecadfc545df243c028ada2a6c877f558deedabef2e4b97b3d2a36c6919bce4d8fbad0f5cb163bcabcaf6eb644665b0828d04acaba9be4c4dfdc4b59fbaa55f5d966a41884aa87f3f4af2ea27d8eca1781deeb44c32d3f5a833cfde73a9a0a75dfad0a5a2feded1bf075c0af3cb47f107f1ec347dbbbcd2e78dca630daa089c6c8eb69ce9adde2744b0dea5b3337db5abd1ddcbdffaed2fb0be24daf4714a8008189bd1c0a8e411e5b5eea346607ea60cead0289ac1bf334ac0afac94bfe762cde4aa21f2c5ff686a4a6dd9ecd8e27f00be2efe0801488cefdfc722599b1fa4ddfa94bbde8db9d5a430aee2a2bfda15fc86bcadead9679d41bff7f8fadbbcea3d9b829e8decde446f5efbfccbda815f4fbec66b3caab0bccbdd06a2aefecff4bddb2c9bf5898ae655cd4cbdd9ba9aedac7ec78b1fbffef51ec6db4ab28ae7e85b80bb7cfe586b8ec9abf6def036d78bacfabedd5aa2e1b1d9667f5aae46dadfd793a00bdeb7eeee164852064ad848761fc1bafcfaadc3c21dc7e57ee7fa844a8aa1d9ee32567cca3fd1a0e108f8f4cde3c50b6d80ddbebb493fa8d5ae324a6d229aaa8b81e7c5efb6ab3810dbbb30bfbbd6e4c3deb0c6cf8c5619c30c1dbfbac7c8925ac364e5d4f3066513912be3ad9aded8b1e73c95bffbea4bb2dcda7ebb5ce7bdbaae1d72e997ecf81f71bac1e3f6bfbaf51fddbfbcda79c02cbdfce0446efce69f72fd39ceba4af9cadadffee6cb52cb672ddfdfc0da4f46fdd6cdd0e68cc66e0a2de3f3d3afa1b70f42d49dbd3cf95f32eaeb936947f8de4a810eff41fcce901737cac73bee92db006b1735c0a0b919abea8f887322dcfed9e8ae6edde8e42e8da9a059c5eecdcad9caebffd9cbb916a21460eaf6eeb481ccc41377ffbeaeebf70833bfa2f9cc8f0dc3df4eab5eecd9d9d8ae66eacfa7c7bb2d51360ad7a7adccf7ac4401bc96a419bce85e98b0353ebe457cb6b228efb8dcfdfcceefea9d9ee485afc764af4baae67b88e8e9803bc7e6bed8c2ffcec4b210b9ac1b9a15fe6dccd63bcba0dc53e789d1b02acccb3d834b3bfd3d0cb8c80f4bf9da4ece4ff286e16c7a1d2eea31e82eedbd6fd3aae8c5031ea2914deebaefbf01fdf48d696a6ada8b13faf0bdd5126ea1bbc758bfcffd6d0fdc1fbadbcdfbbb5f7d947cbeaedfb3668ee788b631bca58c1db3c55e4de1ac571a6c1b9ce1af4d88f39c9abefba128e2ff40c48e7af841ebae6feb2eabe4fc5aef54a55fda0b94b1ad0ad9b6fc26e04a5c919cca9ba1aa5bfddc81deea0acf239164b55eccbdce674d467f2f3bebf05092daf6aac8a66dfe5efebce64e14dbbecdffdf645ae4aec2befec35f916ed9bb82b36a2ab5c1e8f266ddb1a70fef2a4bd3cf8f9e71cddc8c7be19a93ff8c6fc98a19f6a7c986d90f0d1ebc950497d8a0d6fd49dc9e6f237da1ed7cb4681b7305aeea80ffec7da2d4eed97ee8124caab90af7e0a3b0a0eaedbdc5efe5a89eeec22aedfc29ca1879e2ea813201cc7be594bfe9fdd7dabca37daf2cea9e3aa40ed2d22dd6653b63eabc5eedb2cbc6cceaeea49fadcc6aafa0837febce0d41ea4ff7befad7507a0f6afc92b8de1bcaecb3e11fc3266a60090ec342c3c0cc363d72e11a5eca95d4ef9b2badb813681af2e5bbf5aa1aa9bbbfed5dbfcee2adcec9abe161d4d6aec0ff743c7ef7d2fd95b7d27831ad863c48a0ce61ea801a7eb18e4ae454afef0d51ba55a719f0436aaaa8b26e1860ea5e4c8b11d1a258e5d4e9fc4f3c33e18b35fda7bdfddfebfe41c1ebdebd2bbedb34bffdccdecdcde6eaebc0cce76ec4a13c4a1c8ddcacd0adde2f4588aeef63f3fc33f613aa42831215cfde9c508a5cd2fee1e446cba942a19a2e8efc5adf6301aaf937301cbdaad38ab4ceac5bac7ae576f3aef98fcab97ffdf4fe81d2ffccd6bda2e28ce8e918dda98beb64fff100b1dc9a556133cac119c9ffeee4d4addeacafbbdabefe0db3cb48eb06f8d46526be73cfdd06607dfaba73a5ffaadddbf2ba23a14e6f2e2bbaf1a3bd4f5ceabcde119b7af89ed90e5c9ff88fb0a2f6f7d8eb1c3dafd3c8cfd52d7afbcbb1ce1debb84f9708eca3c37bcc14ab8b56ed62ed1a64decffffb69da0c09afacf2bbba2aaddcc0bcb51d274e8d2a5adfd367f0ba50ebdee7ecd07b4fadebd99dfbc7f1eca840a1d83b1f9b8cc6ac9f9b5f21eca2dd5cfb5af8a8b3dd9769e0ec7620f4cd23b2cd4fa0a8ec7cdfff8f451af1afa27f7fdf010a66a962f6fb015c32a6cd53ce7b35ebce4a6f6c7e868dbbbe21fa2ce8efb569d6b379bde7afb4bd6b4c5761d92ede1cbfe5af9bc42a114c21fde478d4c6d5a94edaf95efeec2d67d7f486b84f7b24eef5295eebcf3c3c1ece2cfd369cd4ccfeccb1edb04b162d899bdef35faee327ceece11b17cf3c3ec68e9dab88ffc9942efdce03bbfddd3e7421ed847d8577633c0fb8f0afd47c9b6eff791bde78c2f9bdb01d67aafbb861fae89ca2adfb51d8420db39101f16fed569a6edef3c92a4dbebf74fdc423a1dfdff13c5bcaa9a32c0dca986ca14ceb54dddaa40ea1b21d3bbf7a761aeadede77b6aba2cfb35eaadaa642edc03337c0eca213e8ae51c32ff61798378ca2ab370796daa38efa417860a740e27abce38c1ab8ce0bf0a1ab58cacd13330ff9c2fc74bf7de87b2103361c6d8dd09f5e45ce5edbbea819afbdda5f5782a1b8595feffcbf8e6cd10bdbd6a5dbcd486cbb99eab1c71bff7fadcfc78d31fba7efb15bb7f5e9e4391e4dc46fac8cecac692e97feeefbea85780dc834a8f9ddcb6a5ccc45f0ae5ee42914902d1c6916c78cf187cadd39fcba6a596e75fcd178607e3781beffacf76bf05d00cb70501fff494ebb0aa24c165e2ec8bd8fa91f8a8eac12b8e6aecfbb1418ca8713d0cfd0dc4f6ab1ab63ba39da63226cdcbac81cfca8f040dfbfdb6b1cdcf5e6a1335e56cbab72bbee3053f1f3a2bace8dfaeedc9daa6c9a2f8d77e35dcbd1fc29b61acfefba3dbce54cfc82ab881d6be35ac2bf5326fa6fefb2dbed80648e1b16bc0de51964f9bf5531c21aff09edca821fda33ba2c4ef179c87ace0b0b09bbabdf3f7e2d387e45a1cddf1a0f3853281f39b5cdde67a4eabbe6e38b800bca1faa8a3d545fdec553d62e57c0c3002f7b9c217edbbc4e6bb1f8bfea56c7ded8a7c981cfc4d6f9af03beaf5ddde4bff386ed5bb7eaa4218449bf3e5df2808b3a1dcaa8afaa3abe48b48b4044e1ed4c3c6cc5b1cfec50c5a22ba9dacd81140b6d374bdae09fff4aeaa0fcc7bd2b4b70bcbbf0dde3deaa4fc14bd17bfe0f5fdebe98a1e80d3c1a9ead8ac151fa8213269c3e67ebcfc6b115cfcdda44ad84ba9ecdab619f2831e4efdfacdc896aebf05fc5c4876c9bbbdd2eb61c2a502ca61eacb4d9a1a8ecf5fe6d4bd977cbccd91c97a7f4106d00dd1b4ed002477082722b26ab8a5caf316179422dda0c4af52efd6bd0ae9adf8f270432fde70ae5340a8d8022ed8f2bc5da7a7db667e85ddb2bf0dda0cdee42c8a91f6174e8f0dc9eb5d451fe5fd3b8aecf332cb204abb7afd90a150fe535d8ef4eb42b6fcee66a6e7a9e39d8e0b69ae8d4103ca6a3c2ae6cc28ffc5c4f1f40dafeedba0ca8f2daa8b7ca5e3da2c4dfb6fc44ca4a02dabff72acef98b1d031fb2c9ee421e722c064cec61bd92a4edc3b5d0e55d926a33dab2abce3fd31ed1c2009bb4b443c3753ca11edfaa4aa906fafe3c07ba12fa11fb44e3aabe131f7c95fdc3e20e27fbacbe3fbabfc1ac3a62d3e3d75b5bc8ff30001ecd3d23c80c3b4bb048d7e228ae10a7fcdaf9c3a4736cdd7bc57b2a612b7ec5e8d12b50abc4b2fd4ba8ba20b55cba48beecc0a6c8cd944202483faa9ac2605035bfb1fab98208d2a1908dcc3ce72d0d9c04ca6a8ce27cb0273e29bcf0cc4cf2ae79ff78ce64f6a4a047d788fac0fcf79406cbec24e7ad82b9bfed0d10119be2c23a1a9c02cc05591c99af789fcfc92be2eaf98faabaa058fda500afcab232600b3dacf1f17fcc45aff670b1deecfe9babb0552d46252d7edc794bbb0331d51fbc25e6a1a921b893baaae6575ae24d82cd527739feea0dfcf26ae9a4ed6644ac60f6108c7eb961c3acc5d007c0e2a0141b2da5b8f4e85fec3e2b7f275f47bf417e4bc5bbadd7632faeba32a0e481d7b8fed3ab9711cdd4c7dbdc716ffdb3af7a3e05ccc83564ca1fe5affdbf51a20fa7be4b85c8d9929d24bbfbe897cd67b1bf1fefbd9c7cbdbdf0a32fada822b7647a1c1510635cac979edf333164bfa2e7bc18e9eafcdaaabea4b95acc648eff2ffe45d352cf02a5a2e40cd2d2db5abb73e18fe16e4cf47c1b222dbb0848d5a5d12eff5bdf1aa52bff9f8aefaaff6ddaaceddac79bfd5eee7f2b18de2ad3deae8bb2245430ea2181fd49ee8419bda96eed1bcba93d30dde6b54ccaaa1c45de7cbcdbb977bad9fa42fda02ffe6c7aee7df14721b12a1eacb13dab90e18ceede8cc9ff6be49fd0e011ce467a5b5c9a49cc8f705fec8fd0284cad1ee1f1df34e8fb3e28de0631c6e7558a538af8eab7ad63b5e2bf009b73ac226c10a979b0d4ff47ccb71995523fd5cfe5bd96e94ec27a3da8dd8ccbea91fe5e8d4e8c9cbac75d01af11b8da4cfbcdd0fcbc515a4adfacbd2d6eefe7bde46f45892add4eccf8db4ac18bb6eeee7afb3ed5cd1b3c297ef34ba6b6ac8b1d1f117d56e2bb76c5b31f25ac0d4a0ddd46ac6dda8a5b8064ba1ca4cbeac1168f3a2a357bffe7eab9fdae7c3ca749cadbfdc8c965cd009f6ba3b6debaa4f16dfc006a4a76928affea2781cb2db7efcfadfabaee5b0f1596eaadc725fbe855d7069a5da0cf2c5b483f1ba4de1eb1fac7fda2dc70d84f17d47afa07968ab3b81dee22ecc0475ad7a061ac7193adea1a7df97eb28bba3d2342d6c3b4d0b3b0ad4c9afbb3dfc1850dd33ba6633ac5b8c34cfdf3dc317b77d02bdfdfa6e97d7fa184eaedb1948d62ab8cc35a1854499afd9161febd4a9b2f8cfec3ff9ad7f6faefa2ce65110d12cefaab7c462ba19d15a0acba85d4a9c79b1946fead2a580badd7dd0b00294a16cb2a4cde1e9f929796ba8333c45bfc2345b09bb0f4babc4dda29d971581da4ece8fa13962d9ffe9cefdfc5c8f3f62aabffe2cce9b1cc5cdf36defd055f5304bdce62bcf851a38209dbaf7ddaa07e4f4d0f445039fe8fff6ef6d1ae7ca48c62aaaad39afc9ddf6828b7428c684fe1b73465ebea95fed8d5ebd2dc7feafcde2b9ccd3e19bf5de98151efd60b93edfd1556dd7af3857bfc59bc37d029b2bea8a4a5a5efc0ddec401be106a5c9fd3abbafdb3ceb99c2b7b927212ec485d02e4af566a283cc5e7ac1b0a09cdea6e16edcd9be6f906d8e2e5ea5ed96d62eef84b5c95a710fea34b9bb693247bd5c27cded11e7bebcbdafd896a0ffc8cabb3ae8ccbbcbcd2f6c329e1df8fb7b7dcfbabd1daccf8a82dfecf707fb8d191ada048bb0fe7c8d90842e9d9eca1ed23aebfa812a7a89d51cd766cd6df8ecca7dc4dee178cb7de6e8efaafceaa77efcbec0b879de2ff56ecbfccbadad72d6d0dfa8eac1faf7bebb40d69bc47c4aed2e7aad7252a1ebff0eacf0b62718b605c9be9fabd0056086be5eebfdce5f6576f179deadda96dd8ae9fcb0dd5a80eed8bbbe2a07c5fd5a8e3ff6a0e4fa3bc285dba5cca3bd9bb84eebf3dff4e595fdaca57d97fae65b5e55f6dcf099ab33d5e6a57c43e9fb9dd5effef6fdf01e3e5d94d1a65dd64913fbf079ca4bfcff0fd7db64962911c9a0c9cf62a28fbe2b140f31c76bd85ab3d41b1d8f01c450dd4aaa39dd9cdb7dc0abe01e04eba3adbc43433cdbdcb9f1c0ce46aace9a2fdbc523f2c6ea7cdaa3dc475212adff2d3be0fcbec0e85ec41c1fae7a3accc6bce52e0d204f1622d94b37bafad7ddfe295bbd97ebf07ecc72f03b8aad80d709c72ac654fc4ba9f261dce83e4ec9fdd6a7eaecb4e2b64ccabd65a675c2ebaafea829fdbabcef881b1b2b0aeee16cbc722feb951dfecfc1da8f989fc5f14a829e2ed1fb1f21f8cb7d69031cfdc4d7a35c6fcf3f2fb4bbe5acedbaf5a701ad61b0c1662b3226b0ed7cd30228da85aec8dc096dab9dbfc9e39ef6016c75b328b50d032df87ebd8cda9cccb1e9f32d6bcdbecf2d8a679bc4b5c35bab3ebdbb9e86c133b8b185eb1fb3cafd20f558c8f27c15c6eb1f1fa7b2575b1fd3dd806c868d36bbba850065c18ee891bea9563dddfcba58dcbfbe3c4a86d9a4dfee92c7f1ba98fe1ea03c9deef2f5e2a95d740a00b525797b713bc05108293a1f55cb2adccd1cb375b7b50e5d8a5953fc3c7e0376cb36dffef0b1ab2cef57f6ca7f4db4d52eceedcdc1acc21c7da9efe2d79b7ebeb5abaeeaadbfba22dfdfdfc0d591cbcaeee480dfcaecfbc778c7ba8eb7faaf2fb067cf4c5a18ec51ec03aead9bd5ea20eedc6b062c2e7a8907d9cbc5a8a9cacd1aace7ecf255bad409d68b36564cf9bcf0ad0ce0be94d6bb6ead25cfcbcbe3d8711d6abac37d31fe20ec729ce20e6a54967b4d5d5c9739ca2ff7fd790eabd9ff4ce7df4ee4cded3ebcdcbbb9f2bbbc8bbdcf1b5df67e701059daecf8c4fedd0e63faed4bcbf0957e4b2f7f647efe79a5f7c6bab4b3a4f8af226dcbe4c37b37fbceb7fb4ace8d2adc4b6643a626cef76efbc653c4bd65dccdcbaac41dd48ae7aaeacddbcacf7d48e3b634bdbdbbcbccae8603becfd012c6e69dd63a9dea68c0389f91c0c4d8b2a05b9be57bb64d4ed7d5d6aae37b3aed5ab651e28b8dba7d3de68dcd7ae271fefd67b7632efbadcd73bdaaac3f93d913af2bf32791de8dee44c5cc2c863f1e5c7cafda2f1a9c9abeffd84fe0cb7fdd3af4512aaff9659e9d363caaf369ccaa98345f697c9fe650400a1e4538ccd1410d48d41a8178ad4a832f0c1f8cd1a41ef8110a5cee4a7045402a550bedc1df41d782fcbe562bf6ecfa163e97f34f712cfa9de08e831f3a7b6e888defb660081f47b1d7be4e9b2ff3e9ab9909e1acea7960c1fda0e295cf62acdf9adb02aef138bb0a0a998bfb61cf1611563d3a97e8bf9085dfaf8d84d86a81e89080d8ee6b6d6768bfde0aa9c7ceefc2accadc3eea5427bc276ab7edcaf6abd194f4cca9e57d20a748db2d8376ba30ce6daf0f1abcfa2cc3057532aefec0c78ec3dee2abaee5ff810fcbe701efc7cbe4dae6cdebba97bceb6a5f8e520f9e10bbefa5a9c1bff02802ed84faacde02aa0cdf926c314faed12ec9af1feacc3a59ccdab6d1cbc5edb78abcffebd7fa13fcc2caa959cc9c1adffd5c5dabfebafcfb6ef546d30077a5bcb0bad2b693e5b3152dd73ed9afc6bbc72faf63fe2fd39eff1ded9e5caefe2635707b03efe2eabc9bd8e5605faeaa2e9ef5dba2a2b659d2fbb0b8b4174fb22add0395b7f3b4a73b7e4d21ed6235a49f520790cc297f3cfb56abf19ffaea3f615ea11a086887f6bbf2d4fc2a4094cf9bcf5ecb1a35bb2f3055860ffefe9fcccc5bc6c4cfad10caaeda5fe85cfabd4ce66d3ab5c372243a6ab21ebcba9bb9ebab2cb86a7a4bf2ca0c82c05c0ed1bde4ee4f05812bf196870fe8d3ea0c417fd3973497dcbaccf1d661e0e8f05088837ba53fe54e1faa3e5bcc0ae5c6da613d3db3234eae6c90adbdfb9ffe56af0ad28cff7fbadadc7d7f589fa352ae18aab65f6cda97c5dba343c7cce4ce5be7c522c9b3fcce6ad10e04f95e2dcbf12bcdc292bdfcc6deda65c7cfea0112dfb2caaf8d54ee5ca4b5484db99ad7e71dee8d08b4fabbd14abc1a3f03541dde9f94efeaa6e1dfd90170cccacb69be7af2a7dbf86320ff5ab9ef5dd660ccaa9f261f96ca5f5e0e44f00b1fdb3083fc3aae6af65bcb71f3939b73a155aff8e2cfc7ebc02afa3fcf5965f3ba9f5ff3fcf7fcf2cf0e46b33cb0edbbf41cd6a94fddf3ba4be8bebca9b0efacbb8f2c5f59ca35befacc3f1b300da18b15abc9ef311b7c9b87cffc375072020525bb36bfbbefccf386fcc1b5feebd93cc713e544a9f3cc2005e5d4af971fba9b9ae1b74de70bf0cdedae5d6d22a825cd91bc63d2fafe5fb69ef9d3db9f412bd7f08adb5dc70ca56ce0ab6fd3fb2eea9c4b5b7d27cac3b8b4121a73e5eaf8f9eb5bef51eb7ddc87e19bfffadd87abadac2dea99ff0e6ca8af1db7ef0c048ce9f924fdb1def9f1bcea7e2deac0771cc0ccd7bfea3b3ea2fb98f03a4cdee954c6ee08acc033f5e08ba46f87eeb56f3c7349bff3e0cc7e54feb647beb4855713499bdffa2bfe4c6efaa1d6daf64dcb9e0495bb4b9fb0cf302ffe0ef92073cab9966bbfb7cbbabd95b5481e9d6d88b11d2efd3a25daaed08bc1cbfaceedca023ba7ffb102ffabdf878ee0fdcdecfa6ecaade06c29ae06036edde24a56ae1a28f22eda51b89ad6fdebf82f7075bbb5feae7bfc6a86e43fd974c5df6b07d5baae561f45fce35dd7bd8a308fefffb835ecb6d2044abd0f8ff3ba5dc80ffa45f26caecc2dff41ed0baf03f8325feace5b8cbaaed74c08386d14d77fc7eebe2a766b4c127c9ba412b6d6bae130a921cd3a2d9ec91fba1b4dcf24a82aeeb6a5cf479ccf46e75fa0ab514c4bef38fab6fd5f27a2ecbcefb9c87eaef2cd7cd01cfed9a72ed25a2eacfbed86e169d035b27cdadcce66e8cccbda1b83b5ab563f9b4a7adabede6bf5e92ed55d3eedc2a5ec3d4030a01cf0fff49c1bfcb9b5ba6013fec63ad2fcc18a8696ea7bbe9fcca8e18577b3bf4db546b2b039b416a13fc001ddcb19fbae5ccc4d6fec27f1f4cc1d77b271cbe5cbf5f0df595c1b12ca36ebbea3ad14dabb21368fa7a498fb9f2fdeaa5a4ae02ee34f0e292d8083dd00c22fedda603d05db8d291937fab444f9a5d2be0a8fc56cdf6daeea66d3fbb3a579a319f27ded0e7737c7c2f4e6fa8cce67119e9c03da176628f857ed0d7d5b09391b9be2fbcda45eb8bdefbbfcaab719a6babcbee8f7c13ad0e9d799ea514bacaecb37dfcfe0282b90ad90d4f85c8f5c2fc3ddee3f25aeeb74ad6abff8ef94073fa973f52e56c1fece3c9d7f32d2c30c31be3edd3a7a79ddbe0ee8eaf7fdcdef50d784c60ee115fa6bce8f6d3b0bf6a305e7df9406b6302538b55369bb900426dee2447ce9b00e9ba37ca91cc76f5d6a347edc82e11f348dfa971c5ad5bfc159f66e1b3abf03fc8c80b1ca7c173e87fa7ec1b5e32aebee07e0e817ddd6374dfcca4840ecf88c0acad4c25d3d35e3758eae98e386e3abc9fba3a46d4d094ed59ba9f75b9653d6bdacfffb2d394cecdb17e4e406592d33dfcaecce9af75bd9d4c674b9a7f2c4f9cdd6e67bcc1809fbde7fbcf40aeabfb853681b6332bbbfdce4c25f629ae2efa2376c3acedc0ebdd4cb03bdca881f64bee8c42eb9afa9b1e3bff67fa0d24fbf11fe0da152ab6befa4e3380f85b2ac4d0b6d1fbaa0f52b8feb4e41508a8892cf2e774d8cbcfa84931e7612e8bf1af167b627e9ada0d9d540bebb424b36bffffb9164ede7d19b28b46ace227d8d23a7e385d97dbd8e954dfdbbe046dc1735a3d946fcebaec41e977d3f8d4d996ca53fe588ecf7bd2fa7cbb5fdec788a4c0110feb67fea5befdd50c51eef50bd1ee84171671e49eefce10cd4fb38433a1167b8c60e3a503c50e2dd7ad2d0c8aaebef67b24f0f0e7d4cd8e3c9c25a25a82885f4aaebc4dd66cddcc36c6cd5b23147fa329af28fe9c8c974998ec4cd2abea72bbeafc8cabaa70db7e99dc3a28c7bfad2fdc4dcccee7fa8fff5dadfb31effc6a96ddcb60b4bfc0cc1fe96c3bef3dffd9a697e25ecadcbf9ea014ebdacaaed69b9a6bfaac043afac6d13cd11a0d2dfe36cdcc3569cd3d467bfc13edb4ccecf2fac8a2d81defba0629d767ce1e33f54de8ea17a2813b6e868fc9bddccca808cf101ed41c7a3b3fb05bbc0292fd6bacf031dda14cbb67ebd9fab292fddceffcafee49acbafb0d1d854b2ef5c9ad0ca5c57c3fac1cd7281affdb73e6418ba25efc3c8c721cacb0ad550fad8add55a2177bf536a0aab1cede6d36bd883da9db1c7adcbae540ebe9e7400b5e51f2eefec6fde68696d3d92b3eddeaf3b9d7aa5e2ee2bc1adf4c3746aac7f8ca6ed9dada76dcb5adca6e5dbc10eab4ad2eb4d903ce5d9adbaafb0bf554b27e54a8b2bdfa60090bc0238ea7c7d753341deedd4baecbb5accadc22dca9dad4fef3bec07c68192ad13f3f194d56c222e39b411b31ac4fcf7c0d8153d0c53ee857d93ec0e078e13754be6b7e9ff0ed966d0f1fc9bc63419d1cdfb0ab1a2f9f2ba13fe2ff71d8307b77fdb202fcb2bb6e4e3dafb8bd9e9de20be2decadf80294c5ec2e3e77ecce0a4ac9bd3dcd5a87a622e53b6a7cccddecad43acebdcbd4ad656d62ca7710a3a29e9430b09c9d5c7f437c41a3b486deeffbc7cfbf2bac16e7db5caaccc497f0c09d7b2f9c51ecacdfedddedda7f6eee0de4dc11afca8bffbd53371efccaff77e4aad9fab7fec58ddff6c4aba6ea214fadc6ced4e1047daaff4ab89a8f0aba4e6ea0f6b011023a5e53ef9e76c5f2f566ddfe4e2d62e1cf08e63baab61d9b5dea8c8d2ce3e18c2c3317d824a2a9cfb3c431d56e258dfafda81ee67a07ad80fb9af6916abece6d5c74fdcf2b8d10a61ab0c4eae03906fa610abc78a73adb7ea3cbfca035c00b64cd566d0367e5d85c05b1396fbb9adcb4fd81ae4197c9edd9c5b5cb6deac9afd6dab08decbed7ebdb03198ed234135338acd667db3e9d1e4403c0378136e21c81c0fbcf673f2851fcada0f128ad64c58ce8eb8dc713cb24ff1adbec4adbd40da2f5ebdcff4e1aeda7eede191d7fdeccdcce891ba3dc858be6a4cb22f3b9c09cbc4e28dde7c3d925fc5d31569b5a9c6ae85c41a8118daededce4b9a434ced2a311edb5955247c03b5f9be40d356ac0eda45588c8e027a1c4c1fe2f0f6beddafcaf3eab5e4faaa1a59fdacc0aefccafccbb03ca30eee36f220bbfadaaeed3cd5a8dc7b3f087e95de1d97f2efdb2dceaa0e6e02f689eed90a5abb8c934dad44f85123c21a1abd4e011f4dfd55839cceaa788419621fc082862501fddef8c54ffbdfea7b3d61b37e7dd9e7a18ad058e9edada1d8c0e8eeeae84ea6e938cfae4d7bcff42ce19b49badda1b45adcc80a73e0c38bc6cbe6bccf7aeeb65fe3ca8be8e7d8d84caceb27cbab4f1baccf5bf16fe0ca0a1b46ddbcebcdfb658ca9f92da4fc3cff201dca83ba3c971dc37bab15f44cf17ad7c4f0b72ba46bb169c1d8fdfd4f2f9e8c109d0dc14d29f39be60bfeacfa2fa473cd7c172afcddabb66cf089bccfefadef7c4e82a3f38db87ac7cad29bbb3bd02a0f57ddcac0c9b3bd80ba365bf976e08acbe3c5d8bfbdd320809b64dded39ac298a961e725fe5b13d8f496edcf6ab30e9fd4f94bfd97baf0fae02f81dba840efddd7d63fba91c7d7b6ac222ebeafd3ad1fbe6de5cfae0d1d08ac7b5fe435e5af9faa91c5d6b519cf3ad6bccad1cbb83ea52efc1d4fadcd1d906fdebcb35dd0df07ceabfd2e210a5bf60ad9c91cb9b18fc76a977bf4c9e2feacbe1c8fa98bfacaff4df61edeb9e1ebae3b3bf8d6dea5e9dc207bdf3f0e34ceeab41bbe00a7a3d56a5fff4feeb95b0effdbe4a8eb49c58b4ddcb0fbda2c4aaed35b066a44da5bfb7bd89bb70be33c6acac2bb1f65dcb3afc9da6bfbdacf7c8aef0d72fb900d4a6a0acd1c47393dafca1c5144f3bbebf6b228ee9e8ebd00e6e6c8af50fab33d0eaa7a60ed18507ed45ea88977461bdd8aa40faa889eab556dab7dedead49eac93cb50c89d7a6a97fcd4a17c5feb8ae6a42dcacde3305df43ab2e58c477baedd75d03bb2ccbc4d7edbfebbe3a3ead2ca4f3cfc850fcdfa2e84efc1e60c216abfeccb31a7dabc47ca6fbabb6f9ce559e7faf8bd9cebb88f0f296efcd6bd7bf0ddbbc9db9d8642abefa798b8e9988b9caa901f2d663acdcdb00efbe513cb9ab450bb50606efa1ea7ad21f3ad83cfdd0f2a6a271196a4642f712beb8be8bcebfb33d9ba8d133edbb9a5cbf92cce8a51fc8aefabbf47d2be91f5fdcdce76c6891fcf04d7fadfc9e709ac4cb6b7ff56529353bdd0fef1a150ff5d19b0db4d1a98a0be429c94fbf7ecc1a7ff0fffbb52bf9fffd7bfe7c1f7cd2c8f2e57063ebd7ebaed6b81d827dd3cdbe8a5e8805e44a3288301aebc83a555ac927be2fccceae74174a64467f4eaa91d2ac4fffa51d7ee4788a8fd6a10e8dc1b6e15b596a0476f449f9facc70ecec125aadca109ab8f66dbcdd7e856f3abdfcdd944edaa4bdd8fefe1ab5ecb6bb79fdeca5cf5190ba8da051ccba46ffddb7ff4ae695fefff8f8d2d0ec63b88e78ea7aebfbfef1fc5969df08700d0868175e27deeb270bbb1ab8fb6167fc32fadc5fb2b8ed3d0fd395e98afc81fdebe81bee01cb2ca385eca0d8f3afc5aacaefc9c1efbabdcecdc9ac3b62d893faef266de1edfe852b6da0ff6fa056e449dbdbfb3fb76fcd3c5c57eb2a26d79b1c5bfa6a39ed6bd8d975d534652e0dda60ddefaaadf0ea79f176ce0cef8aeffceb3d98cd51c8b9acc93cfa1fbe76db28ab6119f2d79bba1cc36010c1eda9549d2ab855d8ce1a9fa5e0faefb9eb408a7fec6176780b2d2e99450cc8dec1baddbaf9e2ef2a3ca4800de52dede2beaca2feccae663ecabffdd7cee1d5da5eeeada912d334a7ea3bc043c5cedecaaabfefedb0cd9a340a1e9c58d615b5a864ab3d0934b711ced0ebeb584163a48bca7f46aa8afd2480b5f8da39576facc9862e8716c20d43a5a8e92a13fc77b1ccadd2cfec6ee6a0388cbbaec6268dc11efff37ca3cffae90079fdfdd88bbe1bcd48e91577cfdec0512f8de4cd0ca5c3ce4ff56bb0ef9bdec88ab9e5cea18bcbcbb4bb4ffdf5e5a8da8fbfbb9eafb071da26feee46de7f6904236a13ceb796e66cf8ffb7e8b4fcba25b880e36db866ec709edbc84ff1288b0511e1bca2d078b8cf503877faad92f3ca02deab06a5cae0143b9b42d50b4af6b0d6f405bddea0035aba1614aa479eb810d8caceabaefbac2f769bf175ee4e9ab5f16d98d7d85c88d954e8d8810cbd13f3bbceef9b19bda0fbd9ca6be328fc2dd64bbe08922af37c32771fb83a628a1ae545ff8a4fa4b6f54bbbee5e612da18bdf21b1a5262f40d65fdb64ceb7e7cc4fef673ee3dfafe449d7355ac964148e61b08eb3ab71583b46fadbf48d8f0f4a9fd3b46a67ccffacfcbf7ee4aee9eae0dec3cd0fe7c7f8ddea140e9dfa86bddf39c5817cff6b3ddc2627c4df3dd83bce9bbd5d7880e99cb14cbbc079a2bc9e4eccdafb42c69315a8caa88055b691beabd2eaafadb9b8cf2cb240fb86be24d3de9f3df8fc7dd07e05bee2bed6eb757aff630464f604b0cf9a5d5db1e1bd7fb5bea897ba66809b7e2f4623f2d5a5df430b8aa3d23ee3514ba174bc95a0e343574fe5f4b11fb3f33d7443f1673e41180ad2bdbfdafefb3c9fbe232d9a6f16ca683c26203c5ed92aaf15b86eb1fdc2fbf84bde56e27ebddbf510aebf1cdd8be8caa9dff19ff72fd8ee7d3a8987efee2efcaf0cd80fbbb7cc3a2dad59b7bac6eccad7c1cbaefbfb9362141bbba8fbc2019ac6c5c6a6ccecff8acc359ea30d63f94c2bee5ca1450e47e0dcfeef526d6ecce580fca2bce9ecc755681de6748c50fa95b19531f1194b5c0ee1cdbb2afc6e604e5a03a910d7416c49c4d6eb128efcf2ac9ef4d015dedf044e54dfef007b5bfa1788c879410acbfd92e825dcab1e6a5acc0adacbcff1fd7b09cbc8f8ee3306559141ced65b913c9fea2d08c9da626dc1d4dd3edb8aa98eea527a5fc3ff936bfaf13cf289a5e3571f63fe75afabec6d1ad8e1d9133a0bcfc39f8b01ec281fca06ab61b23aeddbac5db8e4c51f6bbc7cef39bd0cedff0f2eb5cf244c00c6b80ff4f0ccf38e3e656ebbace5d0c4bde46c7f37b3b8ddf369ddcd4d8ead41d7dded53f803f25a1d84c925c25adcbdf78c25a6ef7e48bec7bbdeb2f5bfa6f8cee7d87d4383d161b1eabfac5e7cdcaf5ff92bbe37dff9f2bd0a6cc12b24343cdf3ea9f2c3f82fbe2bb18d31b997deeff386bec7ac727e9e9ff89dafacac4729cb6bb71878d639448cab52523bf81f0cdcd0d7af29df2deb5cbcbb44d1f6ca70eea7f32fe08a56d5dee46ecded5c03c61bdcc7cedc0ef0cbce142fde4998c4ef1414d0d8e3a913f0074c1ed73b1aa567f2ccba7da2bfec01ac8d9edba948962adcaf43205afddfb552bc0dfca42dbcbe676852da4daca619efbca48f298edeee8027ff58df6f3bb7f9fa5e9c8de688bcd31d7b77a978dacf5e31e8eca5e0cd2cbdc3df95d3ecde870ffcc7445bb3ee6f29bf4db19f65096fee9ac8ea4d1de50eb6ef15bfc01cceaad0064f656ef4c068a19a712dfcb64dcdde3442becb74475199d848af790c83c4dc45bfed3ec9c83cbb923ecef71c91c7dfbcbaf34daada3f9eacd322cfefc05c8000380c334c099aceec523dd8bd6bf6ce3105fdfcd7af9dedc50a8e7e1d10e0ff2f4a4f00ef8eb94fc35ed0cb9cdb3957af9a09bfaee30fbaec68aa1d50abdde5d2a6082cebb6f7bda1e377d618fd4cbf2b1a8ccbb4883f0a6ef87faaa8c4d57bea8bfd5e5fc3ce4cb4bca7bbeb9a03a9b725ebacda7d9991fe5c94dbe3a1647fdf1ecd9fffb2bdb0caa0b91ad760d837cc6bc69ca26d2ffb0165f4d73ca0f7e6889e9fc3fa5f36b56bfe75678e3db0cdacc3d577df0abd86a02e7dd8bd62f7f8b46f8cbfec2f250df025da3eca9397d83c73628afe769e74d0f8c88ca6b7eabf9c5f8bd4ffaeecfa94e04d36ae0f5decb4028ab1b954a4b4c33aa668c2efc3df320efffffa7b05deabe16be4afbb2ff612a66696a9ed929ca17ecaa7eeeef6ddea8445e5d1d0cdaba56e493cdfeca6dbbe12a8c056f0449cec5b4cebb45e6b2ba0eff80beb484d6fca94cbecd5f590c0782fecf87b4bed6ba2843ec6257de7f79dbd2b2edaa80d9d0ccceb924a59dfd9adbdc282f1a725d5dead258b2296d1adefdb3aa14e6542bfbfcd6af49490ce41bafd1d6ad6ffe9f0d70fccbba2541ed88938dff38ec5e57b856742bce12fdbea7f8a71a57653a3de397f6eb1294dcce2fd7f5c8d63ac3abea39b1adcd9abf6e432d4dad32eefd87bff88f2e78f546b1ce4c44b7ef2ef3d1afcd8e95dfde26b805bc36d85442e1aae65ea3c10e8d1d3db8bba0aedc4a229607dc5aba62da5294c6e1e52b132aa0acacd9a7eeee71a398a3eb1353d6a3f68b3f13cacd6dde33cc42d8f3febfec7df51b6beea4630e23ab2a5c93c106b9390f310e95b623535baaafb391d5cac87aa3cbc332e5ec8baeec343bdeca5bbc31ebe9d7bfad0ac8d4ef6e79302d94beeedcec5f12ed63dafe3fe0a3fc37f28b9ddd3315a9ab4b07f26e0ec4b4a5c2b7c55b6748e1efc585898c3e951af9dbf1821e0eab51187bbfb85c67ded1b9fcbcd4f8c1ceb87decaafb38bbc7aadfeab70e04fcc508f1d41dab6ad4ebffeadf0cdcece5c65a4edaca3fe372bedb0c3ebdb9b3cabd54fb93bdf5cdccf57476bbfe8f35df4f90ff16fd0eabead2b7a19d0f21107708a74df3b0dff55e4d928c8fcc55df73d8dbddacc77328d4df9ec59fc7ea576ce5cbb3e49bafd7159b3cef7fae2de0aaecdbce39d7faaf7cada1d7de988fbae416e3401209d0eb0e68ce11dba6de924faf1db0aefd2cff4eeb13601fbceedbbeedde2c5bddd7d4534dbfcddd09366bca6dfcfd0b3ddafaeccaefe953d18c85b05381f6dddc65381a81f51c89e2cad0a74d1e4de81588a9d27b1d2db4d3e245ae7271cc881aa5b8528b8acb9fc7814d71f766eb7fdb95c22ff3f2eaaece7bfbd112c115ddb369cdb20ee43e031d1a6b06cd1ad9a0e64bdd74bfddaeb6a8fb56082de6fcada2aff2bdb3af55cac6aed6bbfa3d33ea93d6ae4ddeb2d4e4e75bfa7cdcaedd1ffad2ab8a1ffacfdd7a9eecacafc82fefc6cbbaa8caaa60141ce4fccfa69a377d1522bbd55cbb1d071b2a7b1d5d5ff6d0d36d8b53924afb0c5bedf7eb14bd5fc169aefe5daf7b5f7b19af09e2f94682aab0ad4dbd3d68e0949e8fd4234adebb3299d309c3edd58abead53c3ba74791eddecea0a208c3da448f6052b21fee17e58633780fd654a1e9d8cd97fab5cbcb0fccd19ce94d872deac381b6ee7dbebec57aa3773ae1530376e7338a3baa2f1e8ebcb78a0f71dd37d04e77c3df497a5b5728cc7eade1e22c979708e904174b18b0be471c77df2a6ed4e0b99baffe5b1ddaec4ae4d1fb7d4cb7be6dd2ff4c57aa7cf659cf84ea7acb19816dcbb9a9fea8cbce5dea0a0c592dd0141ccab3cf12ee2bf45dbd64996736440632e46cf5eb1effa70fcc12a1aca0fc8ee05952c006f59a21755f94a1adcca46c292abeddeedec5c8c360fa9defe9a8dc6e1b2a625baafa81cb92f4aebef8af3afe2c1a686f3a19c307d5c112f0db99aadf2ad51d7b4c182cba4dcf768f9eb0b2fa0447a4b38fa9ae5358e6ebfadbb24754d70ea4bdafdaffefd22e723da5cb417ad9b9a19cab15b2e7b0254a3b24d1a71bc8d7b4ff6aaa5b4c6abdc85de065049268e7eaa2f0cabecf23fd540cdfcfa67faf46ff5bf062b1dcc3d370eaf70ddc7ccff407bd7e1dedeaecfcfffebd29d4c7a1ed2dd2c5869df28f1f33eca1ae0c5024a3dc7cd488e85e18f26275dfba76edbf0f82ace46c33b50bcb961eff3e8826a3bcfbdd85a2bc78e6debb50ac1401dcaed4dfdae7f161a9d841c69c35a58080781dbdbd93c1caf562a73fc44e8ca49cd8bce5bbcadc660e3da1a78d1a54dffdece5a76fbf4b292a0c58b3ba798ccc8eff4dfa4d73a4c3cf26499ad6181b5aa1ebdf8ccb2cec7ce030baee18aa3bcbccb16f574aa9f3a2b078ee8aea8f641dcfc40defe7c8a49b0af8d83542f0fcbfdb6c472a883ce457fef18eb4139cfe6403fbaefb88eaaaa3ed78dad23fcee71350b0d1b6c8b0e4287d3ff1edd22e81dc3d0e1e81e816ff0df0bbc3bfc3f250a7c55ee664f85cb3d040db8a7eac01a35667f2b2907e6ad85d279379d2af08a3af46c8af361eab5f7cdca6f93c71db1caf3067e8381cf4655a155bd60742b5aac8b09fc275fb0cbfc0ed6cfcd229dcacbe927796d20ef4efdb0ed4c4aee70e99cbfbbf624feac7cd0bf7edfd478ac1a509e4bd710bfdd2a4b1df2c8cf7ae86cd5e7f18a742c7dd2cdbeebff4c10be5e8bf8d0cafffb03548e65afdcac063c6c27d5e2e6dd6a40ce3aea32709cc999d8d8b31f1a65aacbc4daa8faaf68660e02efaddeaf9b6ac8bf9a61cade1ad10be6e552721aecfb599b8e61ff5c1f0fdb8f9de96212f5577cd1fe041762e6b7e3bb93d07a2c1ce1a8f4d333f9f62f9c9ee76052ff68efc7d4b46fa59a36dfa1cb1f871d8f0ad21f5ba9f8dcbafda38d2913837b6fcb944df83f9fcfdbeec6fa7e53d07b25ae0fe5dc64698af48c857df4038ecbc1bf3bf2a45b4da0c385c954f69c113e9b1dcfd59ce265cdf46cfef893cb3fcffaa04df3e08a80eb3c69a6d6bcaedeabe1ad9cc7d0dc5f880aff1ca1bcbcd16469efc4a9adc5b8077aa8adb1ec3a62216df650c8ae956a74f7c83bac1d871b1ada59a1d66ddd6c1e0ca8b923e4f3bc95b9eacdbe6ef9ccbeea2b3d2ffceccfa5dafb5ad37bb368d35db7d619a3380a773cc4bf5f625fad3dd0a3dd160bfbcb174aaf8b58f1dec2cf7137c55cbabf4e3c06bbbdaec3cd49dafdcd2bb9e1abcaab1dfd78fe4cdfa0feddeedaf0a27bfadf7d4d06ce7274f7f95ee50432deed16734cf0e049ed33f0ebfbfb2097bfeaa2cbfa35cb7bef55e72c3aea8aaf5f7e5c4cbcf62f5d2cf650da17784c49dffccf1d7aaab0b0616aadeca55beddcdb9eef714aa69cf6c8e3b6b5a4d4fdfc3c7dbf9ef0bf1ee8c88116255b71aeef98faaded31dded7e3db3e3ded6e0dd53d81c9658ee1d8279d2c4ff4eddcc5d94771e63fe44c45de96c2ea3393a17531bab6ef72bb9db1cdefcba1a8e62b04e62f5f3c553f3b6bb22f1ae5bffbb09b1aab3f0875efab62b3cad7c45fddebbb5b7fffdfb3e21ee2c53ca2cdc2c4baedcbbe5917e2b2d5b253bbaf5fbbf58cfde7eccd7db1ccc2dff91fc1de53aecfac87ace7cd16aed303cebbe8120cdc79071b98c1fdc0dfa7fca66124cf1be411e6f1bef8daed38ffb0b2100cc06e3351ae53b21ded32430d1c2046dfc3e4bdb1acf94f5cfc5cfa2a9c3a9bbd2fad5c8586fdae0ccbfdfbc7aafdf9c387b36ab3c1c5cd8042a6cb0e1cfa03dfeaceeaa9baae8df09c8fed13ccd1da15ee68f93c2c4acddc3efba62bf24aeed6db41920652cfb701dceee2aca659d5771e82efa9aef9bd9e31bcfc2f95dcc976c53079ec3dc481fc17b9cdedbaaacd6a5b7dd3c60964ac87560eb6a8ff2155eed39ec00e31b0d245bbf5952a31ffedc58ece4dc60ffc9cdaab8bda41b391b1c3a81badeb3db9fc437adbb8cfb2ceb8b0e2894ce369bd03aa96f8c4db11bb594aae65d6add9ad7ebab93c714ecb7eff2eb2b09d18de14f3da18bde2acbcccb95ba4cadbfb96effaae0cef013ae1897ac5ab4a94433f0be50ace8fc5c2ccd31f42b353a7b588f0befddad821250cf20acbf85effb9fe07c9fb6de77cfca68cf4ebab8b8df7adefeb0e59fb7f4afbc3f30e3af02ca5c1cec32cfdb4a5bcc30ddbb6ceecadb7ee595fbe4d3b60cad1aaaf318e440ebe44ebc83ecab729d0ddcf47ce1daf712c69d1e9afecc6d5c3538a34db0cef1ca0a51ede9e9f988dfbeb9afe63956ba6775e4ded809bdc3edafd1ddc9acfdcaf789fdbd1ded0bde966c2f34f600b3c959aaabcdb3f97ea2e94db92d87bd359e940df3a0334ecfa0dcf31d44d9cbb91fded625dcfe835e40e16aacb0b5be6fdca81dfdaad88fd8c86d09b1bc756d7e42cb50d5f390dc8005d166aa0036e3ac6cbb5a194140e7aa7792df7ef94c4db5c98ad0c2c99cf5cb43a7e7d25fba9b16a8be675bcfdbb9169fc78ddfc44cf85fc95ee21d9f0fde1bd2fd005c8dafca8401bd3847a433eefff5949f9fb4ffcef6da2fb5d3818acd70dccc4ee85dbeea9d2baf4343e412a42905449017b535a3e8eeee7c9d3fbcfa1e56cc9cffdef40eee40f33a8ea66d1abfe4addb1cd6adddb1ff8fa15ef34e05fdea2b3c4a6190d6efc3adfaf887d4e0d2fc1de7b22cd995bb63669ad2ebf32aa918a0cfd9da6b32ce9aa5f2fadec03dd02a03f3ff1c045d071ac0d1b6a2aeadddbc284ebea7f18345ffa3c2c2aecdbddac1ffcddfe788ee7af41498a631b84f1bd3fa8e9dfea5bafad439fa7eabe3b0f67f1e7f4aef2f0ec7dcaa6bffbe0b02bdac7bed83e4caeacad8e9b676bfe2bec80cea48a00b8aa599a1d1562494dea6ca2dacccdd8ae5fd55f8f4dca5ff6abec6cecf00a6cde4c26fdfac3cb3ce4bab290fffe10cf7ca6bd3dd45b07f4bceb7543fbf4ccb9a5b9a2bfe1f3dea5bfc23bf77c98caa4398e9818cbbbf2236f8142abdd682ba68e999cbc1bbfee79a5beace5b3815c0cd54b02040dfca8c99e8b6db6f98bfa6c7efcf3f6b5d5c3a722a3e3bdbfc277accd5bfa8c5873d489aedf5a3c93fe9a4c6a0c9eeead6ff3579fc422cdb55b02db715cbddbbcf5d0de6c2ac6da0f4fbb59b45e9acfeddf43edfddb03eb974e97adbed1db0cdaef657fc8e5a1abefee3f8bc670a0f8a5c790caba43529bcb7e2afdf283ab85af441fbbbd042a4eff8fb8568f75e5bbfab16de7d06d57a6b1208a1fa5a5da11ffb9f84be161ddd5ebe54e3dc0deb3b9ed1a430535188f23b65d53eda6faedb0bcdf4cfaab6adc11bec2c5c840f6323663bff0e46fca3eed7d8ac2c041cd4beb4a32678f33ecaaa21dc0d18fda5dbd2deee7bbf7dcbfe7ef5ed8e5ed2dfc6da17125d5bf6ab65a089aa63e7f9dccfddea9aad4eb31e7efdfc31a7ab6829ef1f11880c4ebbc8931bb727a6d5aaefbf65bce947c60ef37e6d50a9fbd4c93e8cee81e7a0f7ac04cd2fc0ec87cfe5cdbdaf1ef8f23c6e965d75a4528d5cdad89f1bffbbcc360da594f2c8ac3def9ae5fee9331fb3fe2983d02c9cb01e6a394fdd5e3ef5e0eef7addd3d0142bd8d3b60bc898de0cdc15bec9b794adc30f081aaeeb7e052663f793e7ade7fa024cf71ef92bfb2f8fc01dd93fbadb77ec07f2244b3dcbe095a24bdad5f10d51a99c4e246dddc2d2df8fffba34ded9f9fcf5dce0efd9cb9810c1a14e514cfbc7fadc923a601ed7ad191c76a3e9100bdcffc611bcf6adfdba9f2b591696e13a57ed7bef206a4ad8beee54fc03faa4a27b41f2d861dbb0dcff8ab9c12e762beca13874540ecb5d2767ebbeebbfeca8b32fe7aaf699b432c1792f82640bec6abdb87e3414505bc8db9708cc16fcfc19aaceae0fbcfcbe68e50a8b24b4dbff1d9dfecba7625e3445eecdade10adde3bf017ca68dd480efdaa7fbca1e7039f1e2f20ef061b02d08e5bf769e2ea23854d3a60f8074bea127d30e0ec39efcc53d1b4b10ac4d2aa4c56fe9f178fadba6b32bd79cfc6dcb482dda4bb15b3cd082bbee81b8bad4bbd4ab98ee679413d352cb221d7bd3a3e162a317b58df7e9cf5f10a1ef161fa54b9c0bb5b51efb1ca6846a000949a4f3ae0dea3badf1cacd763ffddeaf51f0bdde8ae3ce56f00b91a7d2bfc6eae142bbbedf0f4b2aade8f5e365ad29c753afa9c48e5fa6d77e6dd07aca9a922ba94fce8fb1122ffab3a744140a087b20edcab15e70599f677bb01aed9bdcc2ef10d5d2845b2a6d6c607cfe0dea4fefe1d3f96a280d2d4fcdc5d61bb5a7eb7f6dfa278bcddefba3c6f5a69738a0027b814bd84aee015a32fbdf5e267d62bfa31b809ae68fadd37dbf3bed6ddf71e999829bcf1fc7aeadad738c7ec02fefdd28f407c8cd498ed04d2bb1c5dbf18aefeae10da51be91afb7eda5f27eb7dedfbc32d70cb289ea0fbc8a4c2d26b8c0aa75ce355b26b6d7e3a2decf098ead7ec2ceae22c0ffea7b9a5a4246861d9e9ab1d9cfc9be31da595e7e0a1e5ccaaa574bbf3b5bff825264f18cc5bbeab317d6c6ac440efec6b80e8c74dc3a618bbc59bff1ea49a586afbec0fb6d9a0be61e72aabd4cbf3cea4c38ff7bbbbe7deaddcf28ec11a6a67efa823daf1bfd4ec9b4fc01e7a5ae58eefeba21c7c9ffc2eb675551cb6bb68d7fc9eef420b4e49dfaf4f6e714199751ccfb8218d169edc543c576a77ae8dbfbbb63a2cc7dc5cc95a1eae72f6ef2e42a8cc9a9f520ab8942ebde57b8cbc4285d5905e6adefb0bb3febd75003e0d584ee19b1121c1defbe2cacdcaefc78b0c6f35bda70cc31c24ebffdcbc1b6d68334ba02112b6dda8d226a565b45ae7cf6af45f8db31aa5ea3fbba699aabe9dbd1f2eb2bdded9f9d0d3cdffb92bbb5e42a80ddecc50c61ddfe80e670ea81bcef5cb87bceb3bf52cc064d0dacb565dbf26c2485abbbbda9baba4afb8de6efb5afdedce2e5bdb7d8be2076ed715fb485da8c0be420ebbf67f17bc2fb0caa23ad71ccfcbbee6ce8d2fa5eb1a86fa92edfb2c3636ce73b81a3326c1769b4ff5aea47efcd7fa2fbf8ecd0e15ae1dabd9873f7a2db18c44a780cb53bb811c5cf216f1b7a05ddc994c4bc4db7beebca6f0eaeaffeda50fadd047999e52df0b31d0fd6c7eee8fa653eef6bf8bcc27f7e6d1feec56bfc2b128bbf1cffced0a223ddc6acd3d8cbc1ee99cac922a8bcdaa72a51f4affcae18f7aaa7edfb41aae04f8daec40df6c5c2fbaa5ed5ae0ad8cb5ff015d985584a75ef6cabdb29385d6edfd96fdc6e9179454cf24beb4a2a0b063ccdcdeb4d2a9754ff8af7e5ea5a5f700dfacdcaab38ea48f4ddb94c3e929345a00c1caa76ceab040abc12e2e1c4ae905112959017fa07314f7bfc426452b2cab7d7e54d23acdcdeca564d6cf1b5effc4322be3b86bf05353facc5e040ac3cc5a911d606bcbccdce9feda748914eaece8cd0ba3a8df8bc36b81ab9cfd42aadd2394fcd6e62f9e75df50aaed2a1ddfb33b4dce982fadee1ade37a02fee36e8d19f7fdce7daddd4793fac5030c4d4a7abfcd0baaefadedea5a9e8dba95a8af26f3b693dae6c9caac0ba8bee62db4afef41b6bfd4a18cffffb94173bead55bfd84dacd2de2b0f15cbf3386bd6dfcd5da0cadab0befd278f4c39de66331e18c6daea1d3af5fca73ddfc7c642acea0433ebdf1c932e3e6db9da22866ee2dface2b0ffdcc7ce94accb413fdbf4206fe4d2c8d77af8b422bda45c46bcf2c3dfbd5ad20ef2abdc68dcd88e152ef884a32191ef5bca6de79ff8cd3a79c325ddbaabb561e8be555d6bbbf630982e9dedcfe84ffb5bf4d01a640baaba337a63ef7165b25e0bfb994ce8c7ddef6fceccc10adaebf73f3eeb9ea4173a696dad2c67e747ab2c9ca2573a41fb9a16c3cecffbb4913c3edb0daf71afa4becc53dfaef9fa1f2ecdb0b3fee46e34867f9a9c3fd7e9eea483a5bcdd7c401e8a2f0b35fc50e6afb6b84c5bb2dc0abff08aaad5efb9eb75e2b10f55e4a40c3d095bf19d89f4bf1808540aa833bff076667e445c0ec3de103bd156ca03cc1f02eac53c5a72aeb3b02e19b29c43ccbf8633a498bfbb80d61441ad92db9449d9b7114dacfdf3a46adadf19fabff8bc2a04b10cfbe14341ccb34c2c635ceb6dd2fabb5c6a0ebafc21f43fc5efdfe7665e157d29df6dccbba3dae73cfae01cc15d6945dfe5b18cc0a3a3bdccf30d7cda7e8c8c7cc66dab3931f35eccdcd7143b6182141c39ec45bb5d7f3ac0f7d88de7b1e6b37fab0a32bd4a456fe2c68fd0b113aaae5a08bdfaec4af9ec4be6d92a1463b4c4a44a4cd81d9e40d9a6ab5dddfdb4ef09c65a9cd67dbbf5c3ecceebff7e8a072fcfcac4d17cd256acc5bee307e5b69c88ed7fb7a6abb3dcedb67cd803b166ecd988fa67a9d1a0fd14e2fcae21324eeabcc8d9d4d03e8694e772e0b392bc66cc90dbc99416af0bf42ba50f6dfbacee8ebff5dcb7e118e8979b2e7e7cddcd4f64000d9ea8ff5a151f3b0d21ee970dc96e5fe8eae7eb181fbe3c8ece6deb3cbd3b3cf09cf12adaff2e22cbf2fce0bfdc99d25bff10ff21dab766d720c37edc8fa9bf6832fa790aacc85e3ebebf0eb8f00e14c2c35fed724fbb08ca6a05f8bb5c19684a90dab22f0cde34a4d0b7cc9cb4aa1f8bafea768ca4dbfafa7486ebca3bdfab46fd9cf13ad63c485e146b5fe2dfb84447ddefafb4cc4b2ae4bb5c995bed31cf0fd2dbeb3bea8f29629b3a71b10e8b428ce72ba642e1dbdc69c4b4ed02cd4d0fc7b72d4ece6c2ec8d8bf8ec7d65edd4573ac3aa6ee92dd166a1f4d5ebfdc4ecf915ecec2142ccfee4687d4b62acdc0d7c12fce1cf541c5fdebee2deecf3dfbd2bd231dead714cbe5df062523cd7abac3cceffbed5c14abfddc49d7fa9ec7b8fda9a63dfaef9dc137f0fa36958e286f5ca8f9ffe8304bfc3b71c06f704fd0ef59f863a5b4d01282a1cef7b0824dfd39c92379afe0acd9c7b9c5ed79cbf9b13ec78f5f7e86ba8e672cac6a0d70e3d5f9fcdddede59feddbecbdc64af3151dbb9bf6be15cdabda4deca957ba9afbe6ba68abbb2ff878fb8e30f10463c141f7baf253edceede72fc8b5b9f1d2ddb6eceb445ec0c013ab5c8c8af4bbe1d5422d0f7169a5d3aebe7a7380ea0d2d87decffdda94ef2b3346fdc718ba7214e0d3aadfc1b5f9a7b6023563d3fcecd01cf8fe52d867ff23dd6ee4ca72da3dfd1c1db01bf7766e3fae910c26d7ab4d32e4427d7b441cccafb4e1c8f70ce3286604caddebdadbbc3c99537e9df4ddb590c87b3c297f8deaa50ff5cebbffdcb28ad8dba6e7ec1a72b2a14bdbdec5da79af90e8befa72be518cffe2fcdf873e8e8ae1aafae8dab4854dca8210fce4f3c6b0ef86d8b5cbf2c584d7f9175c848eb157cd6e2bc64c62ebaa13ca1aa050027dc0abdb9f4c3e6a2d22c4bedda10e3d67bb0bffc9b8dfbf7ff4e0bbbdfabd00d7bfbeaafdce2b1087d2ac5221fd9b8da5f2c68884348daacafffc2a4075bcdbbcdebaab265befdceddfa8b27c43b49e12dfc786ef5eabc8abafa0c8dedaf9d60fdeaac7d8f0bbefadab673d5dcdaa2d0a735c5e3d69b3eb7ac2a3a70f441bce0d86bfdcac7db8df15aa5e5a5aae7fadbfaf7cf41a1aae6dbe2a26d73b570d60c51ba2befafe8bbaac0accd25f280ecedca06a2eea1b1ec1dd7975ccb516b91e3b68734badecd73daabbdfbbdfbceef85cbf0b58495c24fdfff81bfe880364fd841fe23dc8c1fafafd2dec2df68eae29acb9cee67daece5ed8f850d6ccc2ba0ae49df72df48d6d8caed6cd390df464be7c33ef2df7d7cfaa9d5f6a133f2ecef8afdbcaee34b1abcdbeda7f1dcfdb7af1dfdb4b9cecd7fc6c1bbd41604aa34302bb4b78ba3f170e6e510a01ae6f29edcd23065ebc13baec0efca3b65a4c32aa0d1ab6f0e0547cebedfd11897b5dda4edceb541db087141eb8c9d9dc2aa6facdd6ecb6c5df1be3bddbd429e2dddabdacc6495e63b3c4bed6c36bfc75f49fcdf44c9ddae0b1aecbe6ffebd0ed426d2bae3275bdbfee9a108efbe7eeccdd311daa3c685aafe9bc3cbe639de8cbc4dbff8780d1556677bbfedcc1a3d46629229fcaaa4bedba016eafaa4f91dcbe06e4129e0ca71e073d2aa9c3a6abc0ebb0ea40cc2c881ff8bafb6c161e21b7cfacc8bf5bdf6dffa2e0daa8eded8bccfce47dffddf39f99bd2d94cf5f1d6faf6a9d1cb654ba55d4bfdbbfdf56bde5ca9f19ab3c50e5dfd5edfe7ab1cdfa33b8c0dc4fd5b65e21d85e07d52eceb2747b11c21a64b5ce3cfabde9af4555e2a7c79c1538b31d2ed367a7c21fb7d27dcfbfc263c51f362e62fbb834de1d4e67c25116b4d39ea7bceadb95aad1c7c57adcf0aa6b3c5f1c8a0f4d9fa4fdf36ca894caccd3a2dacec7fc5b5961399c0bddecfbde4156aaf3b1c9f6a0c11affbbabdcfe1a93ed22aaa7cdbdfee4efbae7e8ad03cbcd7e0f7da8cbaebe4faa1abcfb029d82c0ab61daa5dce3930314ddeb31f58cf2bdf6c99afd6d89612bdf5aee4f9617b8ce7ec0fd08b42eca1dde36c4ebcd6295eddfdd81e9ac66eaaf5ef12d4c045a3a2873fcf946e9fb2bb45e30d4fb82efd97bf7d51ff8429d5445cf90e29c50ac4b2e7f0d960f8c9af23f7b61c3d3633e2e1dd8ab8a8aea7abbacbbe4b1dadaf9a0fea14ab9fde0dede3a07a28eafb9c0cbcbafada46bcdcc240aeb52dcca0ff98f6bcaa24ebca0e7208dfaeffcff4edbbe4a2dcd7184ba46c0ab0ab51ffc99fdf76d77b41fcdd7cff924b6d79fa6c315af7fe63dec5f0a1fa185323f1ba0c8ad523c0d34ddffeb1eee219a5e5caf05c9c4eabbda77aa3c8dd8aabdc7ebb4ebc7bdbf6dcab6294ccf9eb115afaa2ccca2c5fcdac4f1eef0aebcbfad427b9ebc26cba6ac91c449f3f106e0d55b088bffcaac5a6a2d9a3f9beec0d83db49beef02efadd8cb9df4bec8d14bba9fbfb89d85f43a2c1ebb100dfa97ef9fc3e3fe0dea5d5db1e79fdd4604dd0dc492a2509becc1d0cad7fb4c01daeb00f2d8518cf4ba23dfec5dc0defc0aec571decc9ede6bba5c3e36eb5a121a8faae6f21f6d41c49b4fabe806a5d174bf892f948ffaa35ede467c0eafacc9c884e165bd728e315b5cada2b20246bcec5de4a25ccfb17bddfbe2a3addd8ae34b6227f0f997de42fda5f5445fd4b2198aafc7b5b3681b80f3dbdbdcbe4b3f461e5f6a6838718acd4f3a5aefb5e0abdc2f2dba5eea97f5a702c4607fadd72befe75a1442bbba7dbdba5648ae5857b1bcfb243691be0d5a571cbb820f56ebbd0b87ee853c3e7b18a29c69b512abcef8acdc14d3fccc7bcc6ad7cbb2ef76d5fd8f6f031137868d9b25a41c535dd7bb83f84070ea6affbc0d9fbacee00402f0cbb0be18a5eaf76ee3baeccbbd7ecb1fd4a5d7cdca7eaa08901d955aaea26a5a7da9fd8deb5a3c7bebcb4b226a47f7efea4e15bacbbcb7ade0c9d4567b1ccf7fafbc11af4faef8db7a77e85a4be5e9bbfcde372decebd21ce0acd315ce0e3fe20cf2e54bdd407ec6c10983add9e38ea1cfb4d75fba90fdcfe5d6afcd1a568e9824a77a2830c3d87caca5aff818a36babde22adc38aedee0dda1b9e3bd253bcfdea08df97a7e03edd757ec0d2cbfaea01cbbe2da4d309df375ebab827e0bc2cab2e99b0d2d5b23afa8ad64ff19bcec32e36fcd66aaabba8980dab9cb1fe2943af57edab5f46affcb06cdb9ffd5a67e6feffb347dae9fdbd9f2b6a1001ea881fbabbff71a488fd4c4ced8f897bf08bff27c5c1adb7de6abeac1583bbeba7c02398abcccdd9b75cbadfc6565aeb0b580aed618ee896eacc7b1078a990dad5be017db207fc55bf31ae77edae07dcaadddc83aa746bae6d1ca4aff9effefc1ace18dc0ced2c6b3b3ec6ef85aed960d299df79ac97e1c3c3d3626c0b6fab33afeddfae21a6cd5ecbaa56c769d44f3d6b041a24a2af93e60d9d2270d848aeb4d1efa3b6fea42f5ba5e75cf27d993b490ae2cfcd65f0421b32d1db7ae5b99ccbc9eec9acaeec2e29f4171f844ecdedc9538eac0d65bfedd2bc3b3b9a4541b3e01f2af8f2266a004dc29ebdadffb9c866d5aa323cbbc7d6dbcceeca0dfd5e09dd5d82c88d5a09da5e8314bb79aadaf0e7b488abcdfbbdaa0b71de7c19d30215b6ddc4fbc0fb95fec129b04ae253a6bf5abc7df4b8d49ced8fcb19005a6deda1dfffd1f258a7f4ed16ebf27dd10dd83acafbd4e6f957e41cfbfe72aa417ab5f2cfeec61efc6c6cee9f6efb3ab79ca5dad5d8e48ffb9833f6d3166f2bf6bfefcd5addb7b4e1c60e9794ef7daa3fedaaba47b2c9ebd6ad67c2d6aa53752dcfda2c16a8ef28eda23c72c544fc1e4e7bad52a40a99fc7de0133af83959e360978ca5a41cec5c98a2f9bccd141daa8ccf682bcfc7366d2ab1ed9bbdac6a3811f3dcd4f43ccd273a278414131ed7b00fa7462eadb7ae3ba627a461daed8c8d49a4ff48adeff89ff6cbbddbe6883cddaf30414ca7fb7aaddf709dd6f667d7de02ccddebb5ebb14e3b7ed464e7bd6b01cf4bcddb694e2c725cd7fefacacf6e6cdb8efcfeabb5d4799f7277ef703c3d907c9eab3b0eec8ddf7cc264e583fb37ef4dace9734bfa7ef12cc51c53d238f0f1acfa8b4fcc90909ca43ae38f0f3c7daf3b58bc1cdb1f5abeb120dbecd90ce490c27bfab1220523bcc81f2a2ba3b7958d0fefc9af36faaa951873fbd0d487286d671a81974dbdcbddb8e8cc2fcc4c154f8f79ae2a9bc1ded7decdcacf89ea91bf6cddddcbeb6f174dceb4eb4df220aac298abf404d6be942ee7bbbf09ae21cbb34db23abaac228a895d072cece483ccf50f362eaf1f7488b0aca5dd0c5df5d5f0cdccb1db8ebeb84babd9b6d7133357cbf6a4b1f0cb89d02fe4172bd5755edaa03ff57af41ebe22f64c3bc2ddd935019eae27110c5e417bdd354c9d5daec2a29b04483f3fff36dc3c221f5d13e04f3fcadcffcefdadadcacada8abb93a63b6f5d328085f54c6bb4da6f5ceef3dea642adcb57efcfefafc3eed9d2babaa97c8acd80b083bcba6b0cbb2b0bbc6ffba2bde9dd60f533dbeabdeea16caf3a60f59fb5c0f068cf37e2d615713ae16a773e49a6d606cb2ae48d95bce6d16bb8cfe43e4286fb54cf6ed9fbd08a4a2b4119852daca099bebd99859e64bbdebb983c5bdbce07be5c996cfedfb688d24f1a25db333d1ff5e690ccbb0ad45a2ff26ffbbbe53dede918b220b4e3ef0adaad3c9aff04962dab1fbaf476c1b1c60b2eb7edd3c99fbebecb8fcac676a5350b9ebbafed40a4ebbd756bb99218a8b2dfbdcd55e6a71af128d8a2a443cee49e89defc60b1e8b8cb7a1acbf07ca3bcaca83dddf8f283eee9efc33db8c0da57d2bea6dc1d88ce03fc6fe4eeebcc7ab345e16c0115be0f8c3eabe598aafecbcfb71ef6032f509cda93edfb227ebfabef287cfb0c8239bca08dbd5d26cf65fe8380856538a1efbcbfd76e5fc6f8bd23bba43a8f6dd0cd408c9ec0820f9bbed2bc3b2640fabc51f3ce1dfc3bb6b3eefea5a5c5dbbccdb4d50fe2fb4febd2a15cdbcd0ae0edae6748bc9dd9e7883fd84eedcf4ccbf4ca6cba4af1a53b499bedbf8a32beddf1f48657c7674078b1b75b1dbf3af2e4aebbb5c24cfccd7cd651d84a5ab3a4c7bfbf206fe3bccad471e051eaf97aaf7dd7937f4089e3a72397ec4cf6ac32ea229b72ca4e761aec6dee10aecee7e3eea7a491aecfb2f89ebb2a2d2943a6ef10cef62dad58bdd48a27281abaeec15dbf4168cd481e0cbfd43cb45a8abf3965eee1986ada7e4ecd778ee000b3bdb02a2ef91ca5f455724aeac4dab4614e4aebdb5371effa4a285406d04c53db5f6faf1e0b7d7cb7becefbdcccdc09e2ddaccd34ed339fc0811a7572af47baeead5d47edbacecdf78d3cef99cd313cfaebd6b5b414dfbce6d4c3fbc5e95e508fff0fb5ac48c88eefac7aacd437d55bf975ca832fc50c1dbce7d7991f2eeb56c93a5ad7cebf94bad669730e084d1cbccbb47abea27b3dbc9d766aeee0f02682bd4c45b12a6f152e4ad04aba9b0a1bfd0cfd3d31fc7a684fcdfa48d341bf6dd8e3ac93e8737e77dbac6cbebeab1b8976f8ff4d2c22e692a7affcc730b706b69eacc0cdaa5efa76b3ae54ef8e24b988067abaecdc78882f6ca32f0bc1746abbd6c79f0e2dbcf7a9863f16a6bdb17c5fb85531744b36c6c6930d71a15ede1a2134a82c2e4f2fcf6aafb9c7dbcb768f3405a6c9eeffea9169cb6281c6fd52edb5a8bac8ae4839d8c7a09f2cecb7cbcc7fe37d1166acdbeafdddbdbaa1cdda9ce1c17e07fcda58bd9a8dfa87bf0ee8603e48fc5aeb0de0bdc872deedf7e50a14e1d99fb8a8e5e169ad17fccf34fdd4f44eb3e40ca3f96ceda4dc9dbcb423c1cb66b6f34f5bc029cbb9701999e81d9cf7d8fe34acefcaeb2ec92fd66ff2fb3873a48dbadf85dbcb5adf2a6edb904b3afebd67a2f63f33c2b5a998fa008fa8c8ccd64aeaf327dfe5cf5d8b5ec31c4c034c338016059f845d6333e4d2a71a12fea197baabdd3fbdc20c4cc8aa4e5d62ddeed1d46ffdbfd1a97f6ff56313cde61ce5e85738ddaa8fe4c26aabd8aaefd2cf26fccae9a7d5a4bbfee2fbecc87976425ce951af12ce4f8dcaa7ef4eb3ea040dfee294c52c1b5b57ed3813ea86aaf7cc8f4c2ef8f60c779ef949debdd2dbeec56aae2fa13be0e3a7a33ffe3bcbcbe67b01ca458ceeccd56e7849d8d44d2bff7daeedaead5ccde2d64985c2fb35a24af05fab1cb9c4e03ccd34c5bf6fb2f9df839e9baeac79c9cfef56d7bdbc4fb5eaca9eb9154e3ecf2dd6ef9b43c26f1f9b781af0c13a9fb996c949cc0e4acdf79dccc3a876daafb30892661354df158bbacff3b6fd2a3df0ec7357ae8d0332fabe39cecfd66733deadea0ad86e73fbaee9163f67edf75caeede1f8134bd2e456f8249a4d3efe5fcda62ee76afadb00ec5a6e9ea7ac5fef9e99fd8ccb4df88c8bb6a85c1cac6ef9acb9447eb6c9d9c3be438df3c4f87be93fc2efb67acbc9c3f16c7d8f84aff2c38a36b8c7f0efdb79f9a2af2230acfaaca9ef71ededf0ac53377f39f7b3102e11d928baaaabf513d2eff17db89b742bdcccbebda1a1f579abe45bf472ffaacbf25e6a6a0f0b98feafcfd39cba91a5de473b0ba6beb45c73ea59acba52ceed25dd68a0c64823ebed4b40edfe852baef23ffae21ea7b3c8d542cd7ed15e11fec1a1d9d2d6cfcbec8a625b1e5f1b4ebd6bf3e2e84bec9b78bef1bd7b8a0cacec4d852b2ccfa722ffdebbce9bc85ad68ae78ec0291ea2cbfdb9baafdd7fb54f9d4d03b12cedbedeec5c4a07baad005bbaa3ab575a1aff6a3ee5edecfea80fa522d31f23af24b6e4ebbff68d2c4f5e77e7e7dc4df1455fb0c05abe9eaf1edabe74e4ec84bf0f7861300f39bf9f8ab2b30d28e8fffd620aae06f9f2aba445ae8fb267bfed56ce97c5d83eac2a9c0d6cefafb53c45e82ecbb5f982038c05ff0f96f5ba31d9f4bb7e5fe8fe4a1bd8ddf194ad6dd1ef0121cd74eb6e8e3ed1e0d6ccccdb7043d1f505f7592f2aba19632aeb45bceedbdc74a8f5bda1de5dbfaf654b430deec051c0bdbc1dc0af74cd097fcab1e3dbfee671c274fd953afeb0aab63f5e53a3d5024ed814401cca6feda5ec1c3616cda9aacfd84d2ee1f54f240dc77b73194250648d08cb566cdaaa203aa75d2bffce43e5a70dc9e25ddf1a782714ecfbf2464c3ef63a71ddd4edacaf41d77ab6ea5ef98de5cfd5e52ffb0edc518d6cbbdb43076cf42ff4aadeebefd8d930709d21e2c26b2feb6fb5d908384ee5bcbfd34fcefed6a4571f90df1a1fd2cdf97db272378242f9f3205b7a2338a38a0cfeee8f26cb52a626b5c4c804b2bf50cbcecab1f916bad72372bbfefb9ee03fbefbaca4af83eec7b5ecca6e6ad55de7ab9a11edf5b8cad82781c0facbecad6f499c3ddfdd70002ea0d7cd8c561dcdcdf64d96750f92b7cc25df31d400ee4398831fbe536d4aeddccafce9ffdc9e4ba6ac7eabe439ebb64a45dfa09510041c86817bddebd48d6c5254fcbe0dfc893f53cf35a3bdb060d7a27c6dae1bbbf0bc8e7ddccc0bbe60be1fed361ca21e5e1df9cea1dc3ddeb4bad6fcadfccb77d8bf4ab6dfb7acaa8a1ecb1abec92ec7fe1afe86538be49db1e9ecadadd5d1eec5aa98513ce2f00b24213b39ce0a4dda27ef91b5ef630fa705fa2efbbeaca1670c26eeab1ec4149006a9f49a63e7da5aadd769dda7fe01d4ef62c78bef2aeabed234e5fa7f4deefe4a24b35a1cb6541ebad95efff3ecca7f49abb8fc9a9eacccac28c2f9ddd88aeeb8216d735afa8cf9ea1aed5c8cfeea4d5e79027eadcc963caa6c4abda89b11dea2224c6b34e7fb6e4ecfed67fbb75f06fb8c2e09eb2eccc716a526e1d63abe96effa4da10c0da6b2bdbb40826aa55149f625275b4dccfc8a9ff7ceaffb3ffde02bb663d32bf362c33cd94a6a1da977c8007adfab72fcdad7ec5c3aaeb5ef0fd5006fa831298d8df7cf1ffb620c98f38ca4d91c1e10c8f0ec6f7fc67e338acefacd9ddca8aafecc7aac05d4beed6fb35ef7bfdbe127795ddd78cd2a38c8d165bdfadb434c3cd4e0da4b24d2b8edca0d2cccc5f5c9ac081b4f0e06bb4bbcaf4c1c784c8e00b3a47dbc4ace4bd8c014ff402084a84cf94a1ec64feea15ebe8224a206eb3e2b7d2b4f72b069cda5fee46ddcf5013cc4a6e3f6addd8493533dae9cf3b97ba8ef8a58bdd599836bc7cdad0d3c1f3538022f43f3fc3dcacce045ebb5dabbbe8993acdd10409eb9fe3cd0c17729b77f8ecfa01dbdddf9bf18e827975a2aeeb09cb3eac2bce3d8a50ec6667a6688bf7aa0a52d3f32cf9f89d77bd414e7aa456fd90029a06b717d0b20eafd322bdbbef27af7d6722e9d20ce8c88eaa09c6eed3e17c769e7a9f05db1751e2cf03d37ddd3c8a6f8e752b527e64b73d432d39e18ca450ed53def9b8045be8d06a3be7af1dda36b1f8882a72b677fd29ae546bd2f98eafe26eb0a9f9072fd225d82b390f01e990a9f3f3de86c32bd7ad2dc16dc51eaa8dd3ede7390ec1691979bfbbfb530f8daaedaccdf003d753a8fb276dbcbef60baeebaf33db10a95fa61a7aa3eaafb86f5efbe1a417b45c405f55f25fcd48f6cfd1a0b3bbbaf43ac783d04838ef74ebd68c60fcd6cdcda7d9bf2b8bda835f88b96fffd8fdf5ffbf47bbc9a558a0af0d8a3d2320c2238e4d7dff4b00b39bf6d65ecb1dc5b295e5102ab1c75c1ce1edd3baeefc69c714be13645a5a6a4b43ec8df4a3bbdae57a2bae70d6c294cf4968e3bf74e59cf47af3e38b6f4ad5f83f9c3fd7adeee71def8c523e83de1aeee58d64ed11eef8aac1ed22dfffe369768de12bd3dc1baeadbf09dde7769e8d3d63a0fcc9b1aa5e47d0bccaab6d9e3ba68dabbc8cd1d4ddad0db6aec53d30f80d968e9b6deab4e9f4a3c1dff6c7aec62799cab772f993f2b9bc51da0adb07f5f330bddc470dfbfc021f6ec6e0a7b13cab9ad35c0ea29f6e05ae0adf2eafc1ffde233543cfcbd2c1f2db37df7acbdd5a3dfab13c0d251ebba5efc53b4893f4e53af4bd41d2340bccdffc0dd63bd5c2d1595314acd0a5dced8bc0b654dbdcea6e61d158daaa22bc3ea8ae3b547baba53e59dbd7c9f7e04a548da55322acb27cd584bcacafbebbb0609fbe5c7af5bfc0c1cdd33fdbefccc1aa6f453a6f56312c378eeac8adede3ce86cdaf440162abcba864cbfc27f5be07f5dbd50d4175eb1819783fbc231cb9f3ae1209bcef0c136fe21ed294a8495025f1c24f78dac55be00d1494dcc6d5dfeebf7f1ffbc2276dad3f8042cae73eba1e5cb135a06efff2a15a500456b36e190ce84a9daafdab570f9966dfbd0d6ee6fd5cc3e34cbeff5a81d000acce6f1bef0f0043c4ba7b55cbd972cab76698afd9b2edc0beacc42286fcdbfca90dfd6f693987d185efbea5bf860af4c4e95cdd97caba0ae7f699eea37f1f26f624feea96dc06fd8a1f6eef22f5c4d22d190be41ad03e8c049f74a042a1f452bdbafc1dbea9cc8bdcc2badd40d1c0f16daac3c2dc1cdec7e16fcae83adafdce8c6243ca5cb1d4d7da5cadf5d3741fcc032e824ddaa27bd23ee29506a24aabef432df5a4acfdb06a6038bd8501e427eaf2c87a7740a2fc7d9135f7ed171fbaad657c2d77dc5afbfc0a7acc37e575cb76aefa28abbf39c29cecea6bf1dddf0c4ee1bd7e503a3feb5233ea2cdbe05dbf1a7c1a29dfbe1b438bfddfa94b096a7a662d081cab540fc891d93b1cb8a09a0c3c2e7f8992fcc51adb20daf426956c6c8dc1774c96f80abe66eed32670ef0cc6e3cfd51eddbe49f14d8ac14ea4edc2dcb8ccea7beba8a88a76e53f65bddb282f54fad3f7a4badfe4c7865cf38de88760c0073f67c0ec4fe59f9ff4faf21a1facd4a6d2edfaa4e327185c17b0d97ebbb82ffa9818a83d0a438ec2d0edecd69134ea72ec73fab37a53acde2e8bbd0ceb7c5846d1ab4a139e2ff2f7de6e2c9c0b8e4daebfbcadf5e3bb6bb409adb5bdc5d966b4fea4fbfdcb71b5e02ac91fdc04cfebc396b5215fcaff2f3c8d651fe57df49cbdb0d979becf6b7c89693afc5c3ccefab36bd84d49c2e5aaf2cc9e75ded9e4da385c7afcacb728acafc26d6dbb2dcee18e626075fc2812aaa769d4fcfdeb3b74b28bfcc8ae3ec78cdac34f1fd80feacfbd858fbd6b6febeca51dffc36068fd47dea1c9f901ea2b5a0fff0ecfbcb25c0607c2b5d50550272d3ee6ae18b371eedeebddf2eab4221448edfa9a9c7c4ceaf732d1f7934051b59f3d2dca6e2a5a8151fde5f1c9bcc9ac585f7acefa9fc2dd9dd90eed1b092924d7882a1ca5fdeb0cf1cc0fd2b7aeeda4d6afe5dbd0782aed3d7bcdd7ba2e1f51b38befdae6dc76aacd3af6cd39c3fd920d7f950edf7aef3e4ea6fafbde4d8a1f88ff548d5e4fbefacbf95cc1f5ccbbde5e078da8c34f1ed9edad81f0da531adfc32444efc5bfb5e4ebadcfde2e2daaccf3ecd2deef5b0ee4dde15322c65bc52dca98c9c2a97f3c5dfd6da4cdb17b2b38b4b820e09e625ad03b0ca6fd85fdafdf1957afa16342fca26babac284c7c2ec0195b18fd594bc3d2ccdcaedbe5018ac3c9c434c81d853378add180caa7de953abf6efccfbbdbeaa0efccb996d9838c62a8d6e0eef98a538ffd295dfdeac71448f8ad5a7008325da56f2fc9dfcd9fd823eacc8fb1d00bb57df1b3bac10fe51c4be8df2fb5dee6b4f80be4ccc0bf17ad4aecf488d6d2dae0fd2e0aafff243fc717d0ab094aa1d620dd157acdbcacfdbc15f1c419cda295d94aeeed0f4adabe9e8532bac6b799f87dbfc1f7624b5bd74aa272f5efc2b395cdd187a5b36ceec1984cb16a2db4a7abfbb0c5afaa3ce4acabcf78afbfc9beab74faa4affbed6b74db11766a09dc2d33ad43a1d0f65b9ff0abeb86aa9e741b84abeabaf1badde5a077d9dd9502a39bde08bfea3b7f15f6def14482fdeb56eac528ab1ae866cbb1c0bb3d6f4bc9dad0f89faa3116d393ee9ffffbcadcb4dda200e599581c3c9b8e0f3275c3e7b9bca98abb0fa456d8e0dea8fa8f669a0901f1f50dda0356cbafbfee84486ddd4decf2bd54a7c4aa005db8dae6a6b8aab47dae598cab66cb2a9fa1ed6ba55fe345cac5f9a98abc6e4ae87559cd4c43f7f2edefcd88b0332ff7ec603e7986cdeacd28c95d1dad17d21b40e308ac4c550f353b3bb2d8ad84c4ee42975bfbcdad1dce5c5b28cbef3aff1e9bafce50cfeb76ffdc6d893fbec9c5f1fff7ea91fdf1bf1e7e20915c8eef2abfcdaae47c02aeb8f09aa5d63ea0dcf7cefd8c2d1bb63bfb1e9bea418ebe7ea0b5ac59a8ee23ef8adc49fe2a5439ec5efbdc28bd84be7e2d8b4cfb3e58839cc0aeb9b3409ae77f301a124472bfd6bcfd3eeecf8c9fc780ddd0d55efe35de4a04fb17d5d450cb24bd6106b75843fcc8573c3fdbea87dd7cc7b58eefa02aff1fc1bcdc957ac78ff31db760e1b040bad79c38b6fc07c9638beffc06f0bfbcce91737f0c9c6fd58bbfbdeaee9822d3bf65dfdeb7c6e5fca914b6cce008dbce2e6e2bd77aefdc0a3aecfaa28c4eb3afb3fb8aadd5699b7002a7265ef94c4bc7c76de3ba2aa0fddd9b87d9faa3e00a1e3ffefe8e819c88c1a36693c2f1cb4fe9a60a6cdc416cd62f7d3ab2b93735e6750eddfaf4bcafeecba7ace4f82c49e6fd2dd9b60fcfbf13fad7ac4c1bd4ed855add69444f664b58b16de6b3702a1fb54ae1e8c996cd739af71fb7c0f97d2452dabfd0faf1deb7ae1477041d8815957ae0a432b4ce0ec9acf0cdd5fec9c52b30adb4acbde4f8d6ce7aad2bab4c804c60aab1bcf8f7219eb3f2c5a247a81f9de26c8d6dbacf26bfbe74ac4b36cfe83849eab505efcca64a473c4dc5bfa5f35af295b2ca1fe39fcddc2e8d802b2eaee3539cfa15e1ee35c8cdef88bca55486762e2defcb1d8faa5e4142ec02f7c73dbfd484e7f3ae84fab4f4e2cdf0117d521cc65ffb2a3a61913be481ccccbd5d14283cab2e0c84e52e10836e61ccccfcacb384bef09fcc8ef80e80a84f0bfddeab14e1d6fd2e068b49bfd85eb663a5fbdada4cc54f77c1dffdfac3dfb69a21aa3c528ddf50e3ac34a7bcdc4aab0d1af5f35d22bf9ffb4a6cf38ae4a8d3bfc2d8ef5f43ac2f0beb46f5f89fb1aa7c0e1eb25c63df7ee04ca27d0fcc3ac6ebfba38becfbb3477fbd3d9fcc005ebfb5ea232caf1108a6591507fda282c407e5f04e5db6e0aca68d3fcdf8bf87cd1139f0bd30ab8a684b7a1ee37ba7e2de9ee5af328f0afb547aab1fdfbfef2fbf5bf7b5bd9d734e642dc4a784ab8af0a58b1e39323ae571a9f10baa6ab53054df3dde6def8f3bfad61ddd5ee3608137d7a6fadc64db0d8c67dccd099ad1e7c94acc895a096f37ec80dc64b19f0ab2b60cf4ec76fc941dd4deaf4f5f6d9adcfcecedc5aa46be759fc0aa4abdbaeb8a0b1b4c88f2b5ccd64cb19ffacf50dafcd4d4b3f60deaf4d1e7918df14ef6afa2b0fcc37d9c34c8fd0a0f81df320599dbd974dabfc1d217eabfb0dde14a9b8ddacf946dad46d2b12ebba7dfcbd8d2eb5abbd9d6ebd7110dbee0ea4a2c1d9ea194e96fc207abfe4f15cece67d4e3edb30200d0ee4b8f310daa2296aab0acbfab2f900298ea19390f7c2c30aa492e4e34db6cf7b4eeca02142eb3696ecad2dcdfb35107ba39d0caa2728bfa6656d3cb3edc8e5f6944c99edf8a0fd2daf08ba3edb0aad070dfac84e0adbb00ed375bc6f16d3ff173e71bab66af5020ddeb003e1f859070dca9d7cee57c63aebf68f7c3a3d3c82d3ceea5db3e6fb96e5ece2ecd05accac105aa88850f59ddd978ea3c8cd7e21dd2a09ff5bbdce8dca9db1bfb1dfc77bb1bce521dfebf91a9ffab91cc3daadf5237b49febc1ff6e4e316fbfceee9d4be9aaeef8f6a276bd73117df1c0aa0620d5d8d98be5dae10c8aaec72a8edfddada8ed75a5aa9ad55b4a29e9e0fdc7bcfa5ab026bb96a55aba4ed76d8aca87cac981fee42bbdfca8a3a5b9e7efbfcc00297c05dddcffcd19dffde6eaab9a3f2d2f8ccfd63345be1e792d3caaa68b6aae644cfb29d5e2b3e16bf3fa7d1bcb0f7a4da1ddf4a8db8594b9dda9bbbbc4abbdcdef8d7bfa37fe28d6aed917f1764d96b3e02a64ac6722fbebffce58ed7682c434fbff6adec73e4921d0aa67bb2e7b4afaff4fcec7facce5b638d0e647e25dff09ba0ed9f4edef4fe7e570ba50ec8b1bafdb19dde9cefebd6e20b127e57ecbecfb1dfc010e98ced25cfacce50d924263fe3931c65e44fe07ac673695d67dce58c26cecadc1b6f8eb8f4f6e74a26d4ffab614a8697f0f30dadcb263b0a4afbfe06c5d33adbcbd7cd0ee1fcf4ea69b2df6dddfdec42efafbb8bb8c7cadcfee8691c9e3564cbd8ce252e89bb5bcf927dc88a2d517caafd3714b1cbfcdcbef9ae383ea8abc83fdc93cba3aa72bcee257dbf8083a7582afddaf645f9c8d75df0b64eff05c1cfdafbecbe82aafaedddb7ed00490fa369f0ba2105bb4c86f76a8e0ffc77fb4918c60230bd4e69ae0f6fbcdadb3edb31b394b6aaf9cd98de3d3bcd416e9bc4b4ca715cf243e6adc7dadf477ad0ccdbdd9b11c049dcfa7f2afeaecfa8d75daa29a0c392dd1bc78abd5efb9faffa81aeef7dd77234f67d403e4cb5cde5fc44a284bc27f7c625bb31dd15aefacea675f2db0c29cd49d9caeb8dfad54c817deb732a2331386b3fe7ed9d1a61e23aaab23c6d86239bcb0e7d3e8b068426e5fcac1839ade17b2bfcf1e4151e4dcf20f64868ac62fd4fb2cf44d893991aebd3d29fc6072b0da10c349bcacab9acf68c9dbc3eee6c5cf9219c8acb67dfbec8dbff97fae99d2546b7babbbbf1bbcc2ca1ae0ea6deeedddd5a179a0ae76b7c6d8dbbdd6b5c400ebd34a1cfeefa9a244dadbadd88897b8785fbb9ecf02aa5b9c7baff9fae80eff5b65fb35abfd3abd41f65b656cc8ffafadfceb2d3bbc07a694cda81b83bccae96dba47ebcae3ba52f8f94bbe810466e29f9bbfdbc6bc730eebef226b08dbe00bf0e96031d848bd64d95cd39cee3b8b9df6a9fcf6b9e7a57b91f30aebcb655516e6bebdc92de2bd52e9fb9eb8df8d495edd14f1eab5a9ece6bcb9cbdefb54b54bc0f7c6f68d5ed1e9bd4dcbb873f1cb4e4caca3eef4aa12b068acfa0af99f37eb9abbfba4f1c9dcc1ee8c85da474a9f067d17459190f36be06accaa735da27fd9e21f0d073c2930cc9b51cddd81a12a46ef87eeee1f1aa94fb6a05eb8b7d8fdbf6da32cd62104fbaba68b3ec6f1b3c4ff9d3b2096cadd097124ffce3d0bb11cb3b102eeb55d58f416ccff4b10e32f64527bba1bd3594abf0775c283b93d4aace47dee1a040dba4e2411b36bca3f5cda62d1f7ab0b207ff3798de8dcfbb49f57073cdfeabcf5beeafbda781872583d6e9bfec143e1f3d962a4eb75f94abbff61289ebf0bbf4f6ebdeed64bd69a4a3fd83c2b4f211ad2c221aa946adf0e7ff0ad732bc3ca5be41ec12ec9a8a458fbe5956d3b6c72eb7dded5b32ff4eedcbc9c2ed4a6e4e7ea55bc0b328cdede49ac8593faea41bffaea7ae0ab7c2c6ae24f409accbe0e0fa82091f65eea6ffcbad85eff30d76d9f8c40bc8b0a9cf4c73cb879b3769f05a76c2bbb3eddeccb0efd787ac03dbaaba888a2c56abeaaace860df96b4fc81d8bac1d1ed18e8b30c6ed7cc83ed86a42a5e618a6a4beaf0341a66941fed10ec4bd7b40cef0cfb6f05deee39cb2029d0edf3aa961bee2fdcb9bab1e4faa62b4fc50a8abe2f6de3ded6bbcc612aafbc28b7b11f9dd7167ce91b7cfd2858a0db5e03ca2dd4fd4ce1b1a7ade5cfe2fd67070921587a76a6df54a2e589ae0b84a40dafb93d074ed3fdf5a1b2ace12d0a65ddcc5dc1891beeb1ab2dcfa6bee5aef2ab3a68224dad417023eebd3e4af66344c7ec0cde7bb5537f59caaeb2814fdafcd1cff8d745a9df36f5ebb9945f1dcfc7b1ee8bfeba17ecb87dacaebd6fcca1ff301bc0adea418d8fd2defb3bb43cf023d5cfddccf602ed7dd68e72da9e36f733ecd8fee8b66405abbad2edb3cadfeec9c98718343b7aaf53c71b7db55fb0cf1ff3fa0db7bbbfdc78bedad4f3ada02caf09e3a7dc2cced03e888e2ee20ab2a07a9a74a1afccdd84edefed40ad1abd62b7dedb954dc8e0d2dca88e31bd25aa2ba2c2bcddb0cfdef9ad614deb9eec159feab03392feb376b54e726adccd5666e8fdaf130b6f1e2e472de3ae16adfa205cd45e6c67776fbf6c75daddff6bdea24e3b7de7cf2afc54aa270d5a562480ac91fbaacbc7705eece6fc6116ec3b44ede8a1b261b1e4becdc594143f9cee740c599cec1ca81e2eecfcfee3aa0bcb72a8e7e3c6eed27e024d105ae7c5aaad45dc52e45dc0f253d77e47d9efaac6686fdca6ac9c52e0f32a9aefea089faaab0cb24a02ed3734ecbefe69ebee1e73a7e4f3cfe7f7cbfed33bd333fca5865ebeaa2bd8f7af0cd83b31e04f4ab6deecd56debce5aba93213e7f9cbd632cb7886bdb84eff7a0be63a857edd544ae9c3f89b4125c6cc3ebfe3cef3f7bcbb055a6ab22fe80c61ff96e0fcce0ec34ac1ec84d59689aff6f38cdacad66d7ab71c26d0b77ecc9576e5f4ea14f4c0dab7fd04d0da4eb7feb1fcc1c82f17e0f5bfaffb9b1a5104741f6f5cd6accada374a7cebe1859adc03cce17523e9beea0cc5541b0e0bc1ff7ee969abcc6a6299cafbca7606ef733d8b10676ddaa7d773cce6ec749df6a9359b4bdad99cfff931ff407edaa02733d1edffdc625db7002c21fdbb9e37e51a527c9cf93ad8d3d1f5244cf9b5b9fa58fd4a989ac6aaa4c5ed4b631eadbebfa3fa6b110deabccfdd7bf3cacba6b38b3c2d50ed33627dcc6eb576b15e13dee5dea5c3122b0bcfde7f5dce3bc12ea2fdbdd0ae2aaea6e3a2f3b9d1e4cf2bef0e5ffa12a66ee36384ffbdb15be5bcba1fedca17de8d60ebcd57cebb1ec4edcd7ff81c5aa5dc3bb721ab578ecbc234eaaba1b8aa7fec1db84ffab703ef207d4acdcdc0397a5dcea50bffae4cf5e2f55a0ba24afb1eafaabe0dedecba7fbe3b75b1df1caaaf384a57d94b0f9b1d4ccdbae72dcdca464a2ba26ae6cd1fcb7ebd6ba1dc6d01317fb25cb4ab419f059d956fdb26cdaa4db8a8383c91c0dd253887ca19aad7dfa2d29beba91b9122605b0134bb51484bc2db053cf1fe3f7ad5d7c4bf2b71bfb1bd35cfcc7a3ecce9c608fd3270cf8385f54e9a09cd7ced7b4f307ae9d4bcbcbcdf82c06c0cf8aba115e35fdacadb2e45f0bdb027afaed2af1efebd95bcecabda8efebd71e2be2c0d1f3c22d2cf91edc297592fec5fde8b038604baf25d5dd796c49d48d2e9f613bddced3baed86f48c9ac436cdda8f169cadbd06773cac934ded2cfbfeaccece39a50e09fcfc9cdd40a3c5f9483fe525e8b9d1d513dcc43cdac2ccccda79edb0c2e66abf94a8adafdcceadaaaabdc65fc1a88ac6dbebab0307dfbbd8d021f8dff58b9aa1e8b170b660ab5cee701a9c1eae505b623d065f30fcabceb41b69be1bcbecf051feea8f4f02c85fceaa4c0b2d77ffdeefe4ffb8eeaf6daa4f3d72bb6f6aed0ca1a32fbd03e5ae7cdb0ae3e60fee6e3dbd98c8a0afe9404f6adfc23c490f3ec473fc7ccbaedcecc15e6e243d94bf643a2fbd8e068d9e38898876116a4ead75f8693771cbbccf470b7e1eba9c4bc7eaeb37625c0e9ff6ef48d5fee72beddd8d0fae312dc6bb4b3e2b438cc11be4e88edd520cd252a45dbf0fa9b59fab9af14ee48deede7a41cc2151b51b30eca2ca1c5f7fdf0ba622d0d859c2dcc76b8a372a35adf6e2cca7a431ebb56379f9415be5ef8d37b1ac59ba95e6a5ddc82ba7ecbf1cbac1e47fcf32f3d9dfca331edeaeaacea846c8d666c8fa722320723b9ccf5abf0decbd5d1dbfdc63ef87e2b9e3faafe6311eeab031c6d5cfbd5e2fd4a4ecf2e7bc3aa35aa1fc13d9ece5ebbecf23ba66bed3deec69fab8ff857a7b46ccf89a2dadaf4935f7afaacbee46fc223f9c4f54af7eb5507fc1c45bddf97a18ff486aeb209602b92704e443fff5fe767cdfdfeadbbf3f2a421db7f331587cce7d175b1c94ae592f5db2ae1eba048cfb894c7b37bbd00ce2d1f0fa11abff5e00a4eb10eadf9f48bf91014e9a9edbabfebd035bca8be5e25c7c54f41bfed033ed6c063de4caeeb04be56acc109d14cbb5beac7e7b12febf39aba644b0f20460f57ed34cbab4f2d2db0dd5ab84af3600c1da1cc1c38a9a1c28d0fdcc9dc834bb899c5dfd656b15bf5a66f92da91692d4dce39c0b6f8ca5e8951af0ddb7da7fa8adcc9f7aca4bbc542fd87e348ad773fa51dc8b010aa459fbc77de433b38d8a99f7fd89a5b426d54eabbafc30d1bb8e73c25b6b8ef45bfcdf13d5c6dcb1d1dab8521cdf7ce6bbcba9d43d7392b62e18e3a6fdfef791971818b4ac2c61f1dd13dd780d3ebf82dd2814d4dababc379ffdfd4d1d5d1b5b892efaa9bebfaeca643ea36ff77e3f130831cbded1ff56ab6efa46e0b9af5c89dc9df2856850968d2b409a6444156e5827fda8d52efb1edd8b5dc0cc6b4358b1ccef13f3ffffeaa754fef89bbbb5f52285201cf948bccb741ac0cdbf0caa2e4cddffffdf352b15864836b5c0cb4ffeb9513255afcc55faccce9dd605118b899d38ce9bd8dff8e64a2bcdc7afbd380d2d3a9ddf3029a7a2157f6bc495d8bea93c7e17ab1ff28202cba2e8bfbe7c4982ffa7ca4d8fe62bb3d2b396fe83e7fbefefee62da9b6dd0a9fe5dec16b3cccfd7d6efdf0fce7f34efdaeae204bdcb611ccd1be4dd6f17b0afaf8ce323767b6de1e0aab3d88e862feee84afc1caeed5b591d9fde5a5cdc48481cbafa6ccfcd77c2b2e2d2bcedb9b04ec25eedaf79ae25c3f8608ffcf4cb7d2ec6a00bf94f2bfe4c9ac9ee36dfafdec929c3a29dde2b99f66abac702917de766e2f9637ec5bbfc3cb8cd631a3eddb08d8e31e6dd0ef6631cffb77f1fe3db1ec61da5626d9c2e76bdb6c1e3cc0488a79beeebd58ea545a284d4ee3d3c284d4eaef2deb7cdc971afaaaf8cbe39fe3e2aca0c1ef6dd0c53ca6bbbdf47dcbb57b36ac5543b103258ad867b22b790be343570b5fb39acc28b2cfc04c89efb46fecc4d236dbcfaead0c2341bd6c23c0ca741d6e6f868fb60ecabe04f8332d3c4c09c321596beeff5d6ae9d3e0079a9ec5e0eaf1aca1fc8534bc9d058ebb8c02c9b77c97976e71bb1eb9b68dfcf35a3941afaf9acccbdf40b7ddfd8ee78351e9539a3d2ed47c68f8c3946efecafe450d584fd5c123e6d27a123d80cad8adcf6eadf5fa09feacca4713fbafc285b4bfae8bafe4d28dfe7799d9faab7effcfcdd9f86e31ada737d4ced2786d37d0a5fe5b9651bcff3b131f7c7fae6385b0fa95d750d17f508189d115a4cc1f7cdcf0f5d7a01af59203a847ee422ed0e8cfc79a52adcdeafcee9f314db20a262cacfdeaba1bcebf37b9a9aa8bccabfdcdcb55086cafe1433e42aff35e70ff591282bd9d9e3dac7e8eecd399bab8adedce3ebedcd5ebcb96fdfd93c7c6073f57cf04efd83ce7c594e5fc0a0ba399fdfaa45513fc7dd32cc0cc2ecbaa98dddff646aeabad1c1a9a3eba964e5e4bb9c53ac9ea65af02dc7bfd3edbb97cf9eb0cffe531dfbf3eb5bd6b051c45d236ab24d5e8c2f8d8c89e3fcbb9d5110dd0ca1562b9dcbd809a2573b9abffabfd2d22a67a3a28f5e7849d2bb83a4fecdf83d06acfba0afe8b70f5e630baad1fbb9fa9b31dedb9bc5ffabebe7f4f36b0b7e05eba8cf4e121cd7b8ef4abdc22f0cfdcf1fe1bf1aaf39b68a788adf62cb1fca3c0fd975bc7918dfd98ed28ba143afbba6ace0baa7db29c25dddb0fe6a89e5dd43d8b2190c2a0f09fb2c25d729c2b16a8793e1b697cd4bbee879d446f4e87cd933faa0ced0dea7ec24bb9abd1edab58edd24c1ceacd771c7c5da7b20ec81c873a8eed4f5d5aeddd5cd043c41233bfbdfb1e0af0a663bdc06e2be9f02bb9bafde8cc9efac9b9478add0a92a87cc2d8bab313b24cfdcec2e8df6e9d5384d69ed40dc2dbc61736ac6df1f8dd1d7c9c4b3dec9aec7923fe73187c0a38bd5dfbb191bbc476eef3a8acf8b7dc22d8f27d7adfa8330b94cafbf1cafaf05bf936a5e887d246a8a4b9b568f777dd61feb886d76d9f06e0d83e6eba2d4eb4abd3eaa6acc81cbb89c7a09fac8bfbfc1da15c162f1deed7e0bfce2057200db2cfbdd9cfa00e839abdbfdbe2a5b3edee20b9c6cbad9ff5ac81c7259f5ccae5cd587cbd4ccdeabffccb4ffd7d10f0d0cdb6adca7d1302d1c39eaabba6c2cfbd5ec9a5e05ecac1d0eaabf97a29d5e8b00a415afc3a22d1fe0f375eafc6afa5da9c65bca27eee0d718fa2dcaecdadc0c6fb4cfaceaac19eabaebe6e2ce3a35747fa1fcf7eed0a3308c1ea8fefb00835ab10dc93a5bbe1bae99caec1c22c41fe9fd62bf400d91e07ebbebcaeeafeac902aaeac23fd516fd72bafd0c549eafaf5b70a978bb7aeab74cec0366ff8aa8e87a9f68eeedfc63f958d55e0dd0dfea421adaca729fddc4b2acdf8bbcd4267bd18a329d602bbc53a28c71da9ee1cf6eccefcf4aecec76ed64acbfcbbae3cefffe4cf8ddf6ad22f27fbdb39f23e8f73e3a3575dbaf76f45bf4dfbd5bbeb7c8b82f1d4ef50ef97d8dbaec38a3801bad96abeeec398b9da4f7a2b8a1b3ffbbfb50dfb0a6a4ba512eab0842ff05d9dd2104f3c208a09cdea09a5d74f9934d4e5dfadaacf4ab47baa828de7cdc6ce2ae28fe1faa9e30fdf5dea2520ae4ed6a653defc8c0bb56d6bbba2bf84482ecf573690aedc34ef2cebddf574b42b6ad6d44761ffa481f609ca42ebe493da2bebcac4dbc49a8ac1c3aea45c60fdca3b4acaaa219a53eb97bb7a3b6f1eb9cfdcdd8fd19846fc229b2bcb87df110d4030fc8bacdcffc64cdc285dafc498fb7ef4d2f1bdcf9ba9dfe137e4e3bbffffbe15fdefefaafdfbf3df8ec5cde99c3edd785f80a5a1eaa0f7fbf925e8a08e0dd111c8a9abc4e57ccc9dccbbdac15c0ebf609b46afa5d865bcfd01f6bcfdcc0a8eafb24f4b264ea63a2fed34f1dbb618cebbfaa22d8aefea7134cb804c6f5d693dfaeca6ef9a76b3eb2beeafc253b8230bbb8abfbd02c2cdfd5f6564efac9cfb6dec7e52848a1dc8dfcc400a190b6cddc1743255edb2dd0dcd3673bcbeaac0facfe941f59db2dce8ae180262062b69f1c69f77dd6a53256fe4ed75ae9bc06fddcadff024bc7ba1e832c2bd07e2f619afdd5bb0dcf37caabb0d3da0b2bd63cbf6dfb058c18df2aa5497daab75bf1ccd4657ca6e01ddfbe2c3f2f383ad3dbd3d4dfe82a7d0f92be5fabaeedfe9cbdf8d08fe4754f6eb48bee5a1c5cfd0cc1fe8dcbcffa5fd07509bd5803f50cddebaf1befcef4385d51e60f02aadcb85242ed55aaafa71bc4cfbcb28ac9112edffa0acbb29efefdc0e9ddb6d58aacabbaaa75e3fe0bf823ffff8a2d3755ea1aabf67e8a2ff1bcdbf4bffabfdb110b574448fecffb4fb08fa36c07fa0d5f2dda5bd9ab8d7ecaf4f6c540dfd76b8aefe81cdaa86f64dd406ad632311fde0feaa1d0fc2f3342d1de8dfbcf7b42a81aa6fa4edf493feb6cd237c3bb27b9a05badc40df0afa11797a737ff2f85bbe80dcacccfbbdca9df49c47bb5cd14dcff346d294b8fceb729686bbcfdabfb0d0eef57f592811cf7fcbac4ddff38bed58653d5d12cccbe6faacb03e2e88bc8db0fb1a8aa1c6e64cc09672caaefeea15cec89a0f4cf2158b2bd4cb01ef7c9a9733de4df1bde8271bdc4ba72ed8ffaaf2d1d255a4dcdc2b7eccbbcc22ef93edfd0b4c3edcc5dfbea1f5acecc8ea276a8c63f97d5dc46843c6d2d57a7ecdfd8d84d6beefc8e0f991ce39c70cef99b5ffbb86e6141bbccdba1837bcda43bd39fe3caa7d1eeccec8debcacb3a4a6df3fb6bbcc3866cfdbea514329b8e19bc0bb2efbee0bbb4a9eda7accfc1d55ffccceb0dda6ee8ded20fd9515bd53a4e525db6a2dce0092784560b17b710b9aa3ef2952bffec5a5dc99e3f52c0b5badfbd8acf4d5736ffe9995f4e3a3a4e6aec2bfcdbad9cbfdc51caf32befc6a15dc94a336debca3b410cafcb6e9abdcfbbfb837d953aaa07d2d6fe0e5dddaafde7cb696f5a8f3d0cbaf43bc5265fa3cf4e8cfe8d11afcb487dbdfccdfdc1511a3fff35b938df13ee9b5c9a6ad028a80600d4afecbbe0beba72aee4b0035ddca68d29c6c7a3fda9beb0f66b73e7cd3aa11d160d2b6471417e467e72abce0a1bf715fe9bcaa9faa0fa845414aebc2effcc17a6dfc1a06da2a8109b6da21aedacb8fff05974c25e6a6ac9f5ceaf1ddf28a32a75ab5a9df1afc01dac1f4b68cb2ebba2dc261e9a1d6fda3fbdb1b4b6bded2be1865f8c6cb5ce93e2cdfbfebb68eac9de60fbc503be7eff7afab362aee81cde7fb7556bcbba6ba9fe3bee5301fe342eac2a33ef0e4510de45182e3e3dbfbcbd953d5aeddda6fe0f51d5bdfb8b9d4f5ed4cdcb2a032ab02c5ce79a6d2cb7dbfeafd9dde4121f0357e1ddcb2daaa6b28d1fa65d5fa1db9e3bcefe1b0b795acb81acfdbddc6ea5626b3a3baa02a12df6fa74f1ecb42ce5c6f0eab6d4ff44601aa8bdf21fef6e21765dced297cebaadeeb2ebaaedec0caceea5ef0ab40d9002eeff4acac62f9dffee0b6ea4d53a2bc26cf38c714ea086a182099abb44d8ae3bfb4b4aba10a3e5a7bf179c3e22e437969ffd81aae83c6fece59afe97ff5beb5c4d3a7ed8b04fadbbedf004a2af07dfdaf5b7eccb825e5e1e6ab68cef1b95e0d3dca0b9b3386809e44cecdfdb50ef76c55125c6ad0a93bedac282f84efde455bf2bc94e26dcf2d1e5fdb7e40caad6bf01faea3fbffb315a588958e1dbfbb76fa1b4644af27a43ebf4607b3cb4cc01d8fa1d2db3d39e1eef1e3cacafdcdffad1887ac0e596e8ac8bdd0abfee1c4dbd5eef54f98d4575e42676eca83f1acd12af2abce9d4dcdbf1d31cd09b41deb577d265af3cddfe0397b5ab7f6dd9a1eb2c2fcbc5ecb36b0f05fa54838bdbd3e6e5cd96be09d9fbcf73ec964e6c19ad3949209be9b193df97fcb78bce9c8df790f41eca7e7d04b7b8422af2a34b27d87b51fcfcba1f2ad88d57b5dc525febda4beaffae63ee24c3767b3f22ba007bb3494ebfb15cbbf90bc090cd6d5bc951e1db607a533148d8c4d5aef4ce3a8841cb9ec6c459255ef00fb4167735070da5dffa5bdb8b85cd8cd0bffe99bc617d40152c9e74cdd3eac11e8072dcb5cf5e5ed7ef8a7f2e25020db8a82a59a362b599a1e3e63d9b845da3afcb1160bf227bfdabff2248602d1522c5fe993460cd1220de1dee42879dde457462051cb6c5a5dbbbade008ac9bb8f713fadfd92d13eaeae8cfde8cc4cfceed577ba31fff8aeb2aaeb02a5ce45c8adaaef7664548e088ddbc422d1c46cad2af5647df071060bfe95fc565ff744f2dcae5baec2b7dddfc1ccb06ce8f1d6e596bdc9ce51418a812a0359bcc4c16be6beb60cbf3876d42c91db3800e24aecb58a5a3e2e2edb4d7fe587d4848f53eace3cc0bc96be4fbbd0d13c63bebe198b0cfbcbf935cbded5a5ceacbf6994db248d04abed42688adbe83a3fcbfc4faeffcfc26a558baab9390db9fb68ac1df8721486c77c0fe375a25ebf9ccb44feacecf19c9b350fedbd7a4e77a2caacef4243b7b1f0b2effc18942ac4d7edbacf6aacedcdb389ebfcec63035c44ab09b3acefd0dcedaad37aceb92debf1fcda5afadf997d874ffc4b8bf3ac2bcf4effaca0daefe2ff2a496bf5a8dc4da4eeb93f08bdc9507b6128ed0c8751ed465cd653ded6ab7dfebbbb73edb69ae024d868f57a1f227d60568a9eacd39c4caef072f6b3c05eadf015fc06dff465bdca65ede49c3d30fcebadd0c9af7a0e177f81510ccc975470abf9a1a44693e798156b0c63efb3ddc744f457ea2be7d31eb5282db6298d4e6904029bbf9aecb43fb1f464aae391efe7cee6ceae7685d50503b9fcc7146b4befabab24cfb2b164aa3ec1e046b88e54dfadfdc86dfeaecfeab72fecc44fb6acd3f07cc9065c3afab0fbc6a0dc8bad5d4651c9adbfeb36e2b42ca60cbd4f30f4ee4770f1dfdcacab6f8eac52df6ac6649dabcb8de9c5ee5af6ea520debccc0f1b7ed599c96bed32d0ffc5d1e0862d79ba1d5d531bad85bbed588ffebfcf6b0ee0ba169df02ec1b6d6bc8bdb1fedb2abd0ae964fefbb5e3700ebf91d01bcef09cdfffc20e612ebd721017e6494d0a1dcf241cca2a43fc234c04b6bef7be779db6e6cafbf623eeffb776adff483c13ee2550fee6f874bf1bebb9843be55babbedc0bf0c5daa39bfc7429b07f675c707cb83d419c83d6f02d32531ddf23708fb68fdc61c96ac99eaa828de3d0cb02dd5fcaa9518adafbfa052fc6b9e8fe94a9e0eb420dcb320e6c5eea7faab2ea372cb1f90908f2d8c4d3d8a99a5dd6abbf90bbe610b5bebcb85d59d3b4184f474d86ed4ff7f1b9ee4ecbcff3eca267cb1adab3b00cb2e831cc283cefcf797ed8d3286b8b2241dc012e89c8ffeeea7c8e11bf9e9cabe6d1da00d5f5fac52cdc07a8028bbfaf911f0162e0aed492cb33ede16e59f0092b730d1b2c1b1cd63ead3e3a62e3eb1d5eced5a1e842da5df3bfdf5a12eabcd44c5968fbdee7c8b669d5fd7f7c3f44dd413e1f4c3b18d75aaccba743c1fd95fea324a25f2cdff8fbea9faee42c56aa42c56dd5989e625dff5075e87cf8ff626361cfce86faef41e0d7dcfed59aaec566f9be1c05cbfb74c6f3a3fac83dfacc74d9c91a02ef7aef08dff5e6ee95e5afed9b14ac7ad76f31afc2efeb632aada7524fdfe1aef8dcbf39aee3bc6fe553bb74adf4e03c1fdcc2a024a53ed08aadbefa8bf62803d52cbad6bfc97b2e9bf80fbd151b9161307e310efa6098a6f9bccb44d82d117c3ebfe6bbdcd6c4ef2fc1abe905c8cb87d5cd7dcc7bd32ca6dcdb44fcf78fac63df27afeefb23baaf665fe87a5135c05ca419ad028d2dcafa05bcdcdf5a0d451104876b4bae4ae3d60b4abb0cece374846a8bef74ddba62c788fccb63b7a9bbea5bff539bfcc6983e7fe55de49a81eceb3df786a9093bacedcb7f43a36aaa7acf57e7fe38153b4fb03dead5d3a9bac9b541da2dbbd15eab67192ed0bd135ad6cf58d8cbf661d63182c332bf25b1f95c13afa6bd7b6abc41d54e0fbf32e07717d7cb440e61cf671d1d64b066df1320757e73088fcfa22f863d0a8fcfdfbd0e670deecedd3f0085f16e6b55ca25dc0ef65c1adfaf5169a12dd0b96cafbdf956edaf7ab76fa35beb6e3d349c9fd3f8bba7f6eadeb1a5eb9f9b572f4afa06fd3ca2493f22d77ebad578ab184b96fffffb4a7b1f1aab05eb414f4d0aad5cb64b05f15e1d94b6b25afa42b76de2f9308ce0feebd810193e52b0acfdadebf16f04ab28d6eef27ac9bfb44bb72ac6d91f6b4b8ee2d96123af5b8ef191bcefedbebabaa2ccacedac0860ddeedcda6b5cc69b9fbcd2a16ff6cccbc10e1ecab1ca7622ccdd054b9cd7a3b7d400a38ff2a85ec5cd3ccd8ebf9bacefb1f351fc0dadeb271d44d946a01a85b6b3a0fd9d85245e7b67dff32fb1efcac7e70d8934eccd0a17b3c2a8764b2e7150efdfeed7f91b64c623b36f0bc67256fddf0cb2ac5de80342f2fee33dbac16f5a091c11bed1f28decbefefdbdb326ccd7b6a2e92a1b9dcd9245bdce72cb3bef2cebae3bd3adbce12ece60cfd2bff4acd61d93bbae5fe77cc3ae9dae6c24e46062df8c6d8fac39499403d52d0e6052d2402cac1aefcc3a5bff476fab60dda2bafaa3dd88d692cde151ec13dc2dd69d0285d9c439817cff3dc6d030c973cba7a7da475d2ed99f9bcced21faffcffebaa82bae4afba14f3727ca4b487cfa8eedb2bd4f81c3fa9de9359dcdb9b580faefc6f7e080baefce6c7fcb72ca12829fcf70ff7b691b17601ba7d2f9699fde7312b52cf80cef8ce247bef6b85fb0ee1a45db5d29af810acbe519adfb5abedeb8dedb400f299d6c6f6efe165940fbffafb852deba608b1d9fe76f4fda2cc053aba30c399d7dcb8344295eefddc99b7e9fc5ceead2ae1e0d071cdab5c5c7672cc6a690897d29110c6e67bc850546b5a16ef4f7dfab05bcefea207ca645bb70d95dff947c78ebf037082c743542ceedaeb6aeedfe2cabf9e0bd2dfff60ebe7a83dca3d307b2b92de270e415d7cca5d5d49c1b17c22a98b29493dde20c881c1c83d67ead3fdf6d8f0ca3cfbadd975cdf3aefa519cfe6d8b9997dec5afff36cdde81bbfc27d25fcaed0ef6edae22f05dabebbbffc8f839ccadac7aeb88ba1f0b951e0aac192bf0ce4879cae25d3d6ca7204fec273ac4fd66e66fbdba0c50ad44b1cd6dddd4b61d6e42c3bd2bab90dbbfa0b4ce849aeca95f1a032a1ec7606d52d446f1da8f6bf3bfcbf1e16f9f8668c27d2912947a6be4cd10495aea222532aa8ccaecded4fdafcef4d7c62d9b661211efd09bf1fd6c70cc76e986bbeeec4dfb80ea54dfefc0f3ab9e0d0e84713a8d716dd528f4e0fd67aadecd0ce6eabeed4eeef3a873c9fdaa8a7e280bfb96e6948c1ecea24405e45076fc4aa3c31dd449eef8aa1e3aea53ffa70353efdefd7eb670f39c38fafbabdc6d1d941fede5c42eccbac68ffc2d9fb34a50947d987e5e8cf90a7cf3a5f9f6ffb6cf5ad387ea7eb1b9bcccec8ed9acae8e4a0e51a5b3e2641fdf9f5bbeb523c56a735ece68ded252a0aaffc05bd2344d78e5cb8b5661fb0bb91aa32dca92ca7b9eb37c7e52f6e56f2bcbdba90daf01ebaaf3bafb2abfa8e5c6fac372861c42ce4d76fb4c2e5179d1b770e8a595b24b04d7d31e2ffcfbd0be0cdebfd72e81a66ef915ad757b42eb809ded69e718f4b31cdddfc7ad3586767f9936fabdcefcdbbd8bedc8d6dcb0bcd2ffceccce39fdfac276be263eaefc603a0ca5af1c2eba3b6b3c82fbb0badec90edbe7fab4aeddb35fb9eaafeffcd40c3e078df5a6e7abde4bb3d4cd3b894f560c59ffedb1fb9c67c4c534af9011294deca5ac1b9cd63a50224acc44194fd0ae7fbbcb8f4c8e7d43f6cb7aa2c821b17fea0560a4ad0c2b42d6cd8ff33cdcb4df5a6f88af5cff65ed81e5cf7c8bf57f536cb07a8fd78fee314f6f8b712a5efb4c75a0cae48a6759199036c3ddedcfde88a967f8eb9f2fb3bf52ebffdccf41bf2dba3afcca0b66ab3b6eec7dcd2fe0b194d53e6ed92b3adc22afaebaaccbdb6b81428cc56dcfc1f25b76cdcfbe2e4fca04831fe2acbd96da6afd1f5fadb3bd9e1bcf3a1bc02a63fefdc4369a4ecdf24f9707f81e0b1adbbbbbf6cdbb3dfbe8f2f2f21f5bd391ccddaa98af8ab8caa3e2a8af5ee91c39b2a4ff04ddd01684838df9eff7e422bf3070c9f3d83d0e32bab6d48c376f68348c40aa5cacbcec17ef3a3b9d4f6fe5aaecfddea602616bbaf2f1d1dd1ecc9dbcaea943c4faa55fa703dfd00e678ff279ec7b9be04adeebcbfcb3fbd2ea476dbd0b1e9b604ab4f3fc1fe4343adaa5aa1e9a5cf994eed6afeda5ccf5662dd4a11f6c3d42ea9fc6d7a1df6b974dcba5bf34ffb1f7bdf70adeb763ab40b5be3abed45dd4fad86bcebdd3dbaedd2ce0ba854e880737d93b24d7e8b2dc369cbfe0dffff86f7f83d4dcc4da4cba9a446344f10bad8faec7bbfd391e1b70e3dfc5e58ccb5f2009ce0a9cedfcbf24f917aa381f86f53fe8ad0f597b2dc8af24fc1511a7162fa68bee6d39faabbdf3cd9e5f2e2d7e8ac6fef9a8ec64d6c3c5cafb1dc4ebcab9cc1aab297a3ebfcffb0fe1bf2731f02a6bf64ab70a89345cbe45dd3b2aa68c0f2adf415abffbb72bd2f95b1bb26efca5d1ff5bdacad9db8dd8d77e9e787bb7a88ebedcac8cd0603f0187eac2ebcdad36bef9ba0e718a03bdda00fe0ad2bd3b1fb3a24fb6935645217b5edcf6b0f67f1b4ddd0a44aabf2e5cafd58aa4fb65cabe90bbf9d8ae68a4d3dc1cdbedf5ac42a3a1f994e4fa2290653bc9d18e0cb63145efb4cca20fc418b8ce8ff65fdcd326e5bbe1f02e8388c2af5aef14dfeb16283c2f3d82cfcdc6afb93f96e8ebec7a54da9f1cc9922ed25b8da19bbab3c8358f6fbb2fa675c2e07fd53a1b14bed6ba31ab54f5dd53d629fc6e754e24e8f67d5f73ec3a884becaa5f4ed85f2afd8afbdede830cb0ff1ec6ab1efaca4bafdacdefd310a4be3d193f9c8ac27b78abca1ccbff5849cea3ff500b9f4f4bea7d64dcff2de6cb1f8afbcdbfcabaaf667e817acc1ba5de80374ae1e9f62eba2e5b7ca153c2d3cbb58f4bdc8acdec5bcf33f1dbe5e10f5904ac850dbf8feee147efe15cfadef43def10393355da1bec348b570eada01cbeeae6ac0fc5ae20870df5afba1ba7b7c2cd7dbbbc248e36deae8e9e7ba36ebedefd45f81ef42413f9d4c7b1c246fb4db57e66e8dea4efce6d45ed1bfdef25cc0cc7a8a80b5270ec3d85bd8e9dcca5b6ed3efaf0c1eea1537ef1f4f3272e2ab03c9d382b14bcc945718cee341be34a0753e2f32dba7d3a35ccc5c452cc74d86d9342b73a5b033f0257222dcf9d2bf75a431c5d92bd8e5584d4aa8d642f366c7aa65bec5122ff9bd59c7cfaebac669bdced61fd5e04b24eecf4ff7f55ebb1bab01aa56d3a1327d43b593cffa5f2ec9fab8918aeacb34347a6f47ca95b427bdad7cf1cda2f3e358ffad12f26c18dbbb315c2d5ccaceab294ea118f9cece5cbafc1c53fafbae4faddd1dafe0d2e507af4b10eaf49d4c3baaa13eecf68d88fecdf37c0a4dec43daddce7e998bb4cc15cd8dd5c360b1e02b60a9dab3ed3c8feaafde6e18c0e17c38d3acb7ffa3d1350b0fd772430e9cc282ea7fcdb1cfc61d6cdc41fc0f33b2bf1dbed6ab42d559abaeeda38f2efd15a0aedbe73c13c46555fc1208de24c3c8ef20c9dc1cefd959c8305dfbbd7624c3bfa904c5889cc9cffa69d4eb7c5c4d9552293c1dbc5b4dab04063042eb7e6c25ecce02e3ae1fff1712656a5aa16ff62eadf61afbf56ddd9b72badb7d0c07cf38c338ec58eb4ffae2d0ad5dd9a31c664d5cacd06935339df476b9db9ee8dc9d8cf6d7532df2891b51a32dcba7c3c24a5dc4de9bec99fe24999c2fbef16cb3e9cbefbefea6eaaa0838534a09aba02ebec1bf319bef71c6de3bdf5ff4fdc9c93abc96a4b9b5341cab109db83ac4e07a2ee16bbb4f82b65e3ebcce7681fcbdc4b9d756fb09dae23b56b2d1ca261ead6972b5681f20b879f9b1db7ce559e2ac306633fa98c5fb9bdd24a6a0c54f4739ef7e462c2abde8fd047a78408ebc5c0a6dfe2fad8dd4da85f019d2f5fd4b3e57ff1e896dce2bfbbef0ffee7eabc117bfec2e0c0db639a5386bd74a0adfef759a1e0a9aa7644ae792e8d1ae40c6d3c2f6e7213c56a19d1ee8cf20acdefefd4fd8fdba20b44ab4a1ce3f0674e0f9dd231071efde77baa12ebeefafec5cc977cfcf5b9a4ac9e09bb39e77cff10ecfc722f5c1a69ec584aa4e4f3243c25ffbc1ee456c96e90efddb78155ec723d8b77ddc2f279eac4adbad030c9ef1c3aaa74e5efa6bfee6076a6cf8c2ccbd0c4a767eabc8ad3def8862eebd23ea401ff9625f20e4dcbf9482a006cc8fab7bfcacded3dde17ffdbfdaecfc2aaa64d0dcba201acc3fdfbe9b3c814cfcfbeefd3e071a9f5ab9bc93e91ea130234621b1dad19c946325b04a76d2a1d09de9b4ec5cc6c49ecbfacbba7fd4ecbc07ebcfce5bf8bb5615cace5b17ef09f04f8db9eb78c0b23c4eb1cbd3ca96bcbfff63da2f5fc5ee4bb37cacf5d29415eba5f2d9bcd9c095b16cfbdd08fedd6add82bf00eca2f9e8e902db8cc8ea6c32a171337e6e54276d3faa8ea8daacec316a71e037a52c0402bc90fddacf3e4dea6fa0edf9167cbd2b8bb0b2c99e964ec5cb9fe430ce4b953de6aff78eff328bcb1ccd48f7d5f0ba0aea36bde44b3aed023176bec2e49f36cebeafbb0bb9f0fcfbaef390bca2b1bdf012dffd6fa4c8fab91290ceea28965af132a08858c05e6eb20c5f1410cdae9d49b95ca113c74df6e4f09251bf9e1ec75eab3d6acf207ddd8fd7f6a5d793468c2b9f7fdd9d67c29c98dcc51566b5b42addec93cfca4d34c27df88f0d9abcb3bc4a0d3bc8f1adc9b27be28abf7dff2eeddd5825dfabccfcbc2f9e8c8bbfa09dbc7979330078d77c4effbdbbb4cdfccc0fbc8536b8eabf9f94acd8fb4d517b4b0eb5f17beb6b8fdaf2b3d9abe9becaadaaa080d06e2f332be85b4cf1ed73e8f55deb0ca3eab0b5c8beb5917a465e38bba23f6fb92cac4eeaaebc73993ebe9a14c9009f79b50ce178de1edbee612f39ee9b5d8ab1cfae783cbfee2daa86f7d5b5abafae7ae7c0ee7fb5e1129f28bce3e28ffadb8f3a0c03bdeb576bf497a6f66f61027bef1eab1bef346cfb5cc505ab2c2d0b356ffe4e1a1f0fabdd6f2d7c34474eac6a92e52c0dd82c14badd3db637d72f9bc7c3ede5cbebff76a92f36efcbbeab1e3be93db5edaafc3ac63b0893e6935ffb3b32fed183ef50c6162bb422fb69eaf9a856b1cc6a6b4e05a11484a2696b2ab3de1dfbfd6f6537ca129a522d6c1fb8c3dcfc0ae1bfbcbebb708dcecfaa717a36eec9f66a68ac2e7cdfdb7eff9d5033a58e9765efa0dbb9f8d4b0a28af72db8f0e3bf6bb180c3e190cead5abeedcfb067c3b78d018cb2e4abdf6d6ccd62818eca99d3fbedf628bed8ddaaceec8e65ebb566f41aeec83e5c7d7801d3ed0d073bdf3d52b1dc37536a161d52775e37c3dbc12e6e12dad8b31c5b69aeb0af3ea2bb164f4c9afa93dea6eaa9d652eb149a407583bdada35c1dca39a85ec1fcd3c69a7982324eeccc8d3cb92a5ebdeca7027a3f646bef7727faf4e3de3c668bd2edc86ca5b4c1fe87d4b5fe4e1afdbfc66dbeed9ce2f4d50aaadeeeed38baecf1fcfcfd7484c5eadd059c3caba457dbfc1ad58e1cbcded98e76aebcaff9c240eccdbaf7bb1cebadd7b67c95f260beacd5aebc2eef6f9dcaadaef6ebf67a01f90b8a54ee2fcd6f7e0256d1fca4e70f3913abbae674d2afe3bacebebe57efdbd3d2a4bb8f1ce6c0ef7cc6f673d20db99cbdd4b1c77d0b98fc92aac3b389dd8602aaa5df95bdf1646b1d70d07d81ef059cdb2af477ec02f5caa1bfe48f9baac14defdcc9bd337df9a2fc7c1addeb4ca44fa75dd0a7adba343eadb9f8ded3a89dbd010b5eb119eba9ded7b4bd8ec1e39bc7fcbaa0f5bdbb0c6f4ff780cfa67ab7a12e1e06e4e7ff9c8a113cc52ce5eaef2acbe8fa90483c5ba0f31fc15ace8a2d19b1dcef1dd0a2fadab8edc6b4cbe629bda98fa0be3b65aab6bb1e9f5dbde14def7cbd54e5affa5e45acb28a32bbefcde7c6d8012fb0f02b3ce0e0ea3ea9f5a3ba0f0fd1c2220b69dead21f6debee01b7fa6e73586fe83bf662e63088dfc65eace06ce34d01bbaa7d0e4caad9aee5ae9d08d32a5e9a023f0ac17a7efb3becf7f47287c6d7d8ba5019f726e2c7a09fb0fadccc76e6bebb56eccc3ae2c07c99a94edcceeb5384a60ed0bdc95dfb89e27209ef4bdc0d25cecdbba3bc83b5d7bce103da2f68dcd17a480fe6b0efa6f1c0caaabe316d3cbdf309f7c5e07d94fc65dc6c7a3b9763ce8452081acada2b8e20e37edcbbccafd0ffa3ea2121c62b5ba82f8b87b7ee5dd614a74acd6b867ce1ebeb9cd6c15f761ea6a2be83d3c18f98a899322debb666cbe1ddecdc8bfedce51e2fd2669436a058f081fb7f2ad53b3caabc9ecce5e7f3dcd9ab73ecc295b2720e38bf3f3b9a9ca20b6faf3c5161e45f0e5c0ebf8b0fb04fec61d54477fd3bbcd8c4e4bdd65a5cfd5e74cef02c17ffacdaa5d486f7e5a55cc2cf1d6e842eefaf7f27cae270ca30adf024deb81c8aedd86904deef543ef92eddff90f94acd1189ff8fda08ffff26c6ab292dc1be148ae0ed27eebd3aafde764a01521fb5428cbbeabacdcae18c841665ffbc1bf99f7ae98e66f3d0d8afa50f08c4bcc5ade311550f7a74c61adc70f4feac4ffdf24970ce6f7f2cf5a065c2eb3468fbdbf0f2aeacbb2bf33cefdc0dc9c6df37fe1369baf0d5b7a434fdd8da492e9e4434acebf9fb8de77cfe40fdb6fa6fe647ef1a393afc66fcf62ca8b8fccfeac0bfbf37b20d1d07bbd7cf0f730d2cb0d985d6ec5bfe04ca30c0d107ed0a382df9e1e2273aadcc3dc0dd5b6a0e59ad2f3e3eb6b74f074ddcf6fde9a2ecb99ed39a1bcaffea2bef46eaca1d7a8358dc7d8e3fdaa5abbfcd99b6114025a07d67fe9fe11ee783cdd309437d581358ccdda598fef581bbddd90f155a8af8b04efac2bd4b7728bdbbbadb2f17e4cc72f071c43da9c6ae691b1abc8c7ba8ba078db6dba25ff05cb41aa6befce5ae420a4d67ecffe5fadee749d5eef0ca8d1ffc1ec877caafad104abc32def2c8d0abad0eaecbe4afafc3d2bbe66cfe1e0a2aadb76db8647f9fba8a2fae3fcaa87cecbb12e05aef01dbfeccf0a9ad23596beafb1ffddbad084d93c1fccbbf37eadfb4b4ee57bdb634708cd11e99866e0bd1d78af79acabfbf7dabde55f15dc83c9cdec73f7bf50f4fa64be45aa7a19fcd1c3a499eaadeee8bc5d2284eff7882c2a5ecabbc5edcb18fc9cbcdaa6ad9dd391cbfeecc02ee68ee9ae0bceff42d17a62bed3faffecf63bfee3fc35e89d5915fc71a20fdfe9a7adc1a9adfeafadf1ff563fef8aa98751eeaccd0fce2bf239ec3e8abfef5ffe54bfd7a6f5bdb3b3349af68f629c38fedee5524de9e8abb646b60d8ebcee8c6dbd9543af8a55d0b1d5b0cce2405dcc49b9846da1a0ee60b5afdc6cc8fb1a2dcb592cf81905343ae69e57f556c551dad4ccc9b269ddd0bf171a03cd3d3f74eb75653dedac0fb5fa48e72cc40b5e11cd6eac66fae51393e80eabd89dabbf01d27dbf1d2c2ee5d1fba77deafe2effeabad8c9ffdcfabb2b7c969affdf0825dea7efb16a69b36d4f51cbbbfd7e1ce8b8a9f7ae210cb248aada0cf2e1880b5e2def03d4fcdac91f2a8da0ed63fdfa71afdeeacafa2fccbbde0ffdd6baefc60340f869140bebbaebef4ff55c1403746077df3e9e708e86b5d0b0fcfbcceea4dead13bdff874830b81beab92ddaad41e5d8bfae36ed7a8aab01eb615fce99bc2e1b84d32236cd2b8edc87b2f7ec4cc9fc8059eaaa763b0c939b3519bb1d3ddcfc39adf3dfe8717fd685bf3d02e3f8d458f5c0a88acefb2efee4e050ae14eef1cfe6180dbfcf6383dbf97edfed27729d0dbf06bbd69ecdaa0f5e03bc23ce99edacaa3d9e9fca97e4a8562c61d30f5abce1ffb95e2703781dad7b3388b7213ce32ff406ffdfdff98eeca14c51d3629bbb4243ca8e572ef24c346cacfa7904a2bd2aa4632e02235b4c626bd4cfdcf2874fcb78ec5778eba0da9af40dfffbb31ac2ecabea2ff707bbf91541c929d8daf0ced3ac489efcfb3caff8f82ba3b81dfbb9107a53c685aed9bdd86ddb4aba0e42ec02ee5ed3a4cecb032af062bfbb6db43de3bb4df763530ccacf9edcf2cdeb2ace05fc48769bed1f3354d4eb4adfdb5c3aa4c0e2cda638c126061303fac09deffde7d64d3934cca27c75ddfed7d6c90ffb5f3f2c5fab5724e7faffce693d983eb6dc7dfdd6d5fa11b1ecce15489a4cb5c4b01ffe667e1430906d3706e777dd7bbae95cc11be77debea8911af585aeb98c83acad0acf2b4add5ed9d4cddd9fbdcfdd8bf9e1accabcdd311248a3db3ca84ededeb5c7dc380aeae89ef8787a80ce2e82bba1a52a4a0ce4f43a30fa0bbaae3daa4e7a6c561205ca7f68bcee3eabbcb2328f54bd147ec7622bbafbd2eb527bd9dce8ccff94fc125b3cc509d3cfffc689c0fbee0ef0afc7164bf3f6baa676a9caafbc741fecca40ec47a1ae9150fd21777baacdf84cacd342d5f25a9bb7ccdcaeaedabeb54d26b337329bd1734bddbf2e4e6b5daec7e5bccb2ea77bf00b360a1ec131e5b8e93ac1b7f6b517481ec45ab7ceb88aec2c8e9d6afb65bd034a9faeb62391bad1cb5ddd921dc66de229b63cdb7dc5f36447162cdfeeafb123ebf5c3ceccc583b6d13e6e766bd78a7ab3cceefbff237c20329d196adfa43caaee2cd8e1fafefd8244fe7349d1e96c90dcfbafbc8d32aaeebaad04e8fe3f86f8cfe661ef7f153095a1e46ef2da5ea119c0537eb7b43f4728a4e8cba08da45373db482d9ce7b921da97e6c9e5fdbd9ecdfd9abced783b5f3cce034e7bed7be9e0277b82b9f7d7db7da7f25f998d4e1eb526d739a867d60293f6afe00bc74ac9cdbac62e7d3ad865f793cf0f0bb7c70a7bf48a78cd83c3ee5c1b66aed0c66ef7b0dacacb5abe5de549593601ebdca1ac76e04fcbccad43707cb3d9acacbfdbd9ae8de715fc20403bc402ca4e5e07f56edafee5fe5dbc0aff9cbbe91474cde7d3920f8a5c2b198f95e0badba508a7ef59d52ef8b41f9be70ecc30dcbcbf2f3db866d0f3ef7af1facadaef92e633efb4ba6a1f9b9e54031d5a0efec1bae8aadaea56d408e903c60e4e4fd83fb2debe4afcba236df92ccc639210068b4a19c64e83ec9a9d3c0c0addefec408fcb845bcdb5dc6e42d9feac1c26b0a4f1395bde69caee2f9faa28039d847ddeb6bd9f03fcac1a79e8efb88dbdee424e2ab1193aaa876c16fdc4bdd4caa9bee437b1ec60fcbe41ab9cbd04c1cede1f5ebdba9e70d68fbb97410da6d324f6b55442e12be6f5658fc54dafdfa8b3193cea845aaf784dfd925d61f1bb71dff2f4a5cd3aff3bd8d06e8717dd35dfc84203b7bbb8bde9c3d1e278fde76cbef6511048d8024f31f6be55be1d1effc51641cfabbaaadffae395218ec0facb1d25face54f2d17bbb597fe2dda8b644715cfd6b6e2f616978466feff76cf4ac44fddbeef5caa6ad7de28334dbff1a6bac5a9262aacfa10bd29c6f7ac1aeef138ee5fff82ffa6bd5a2bf9323c18b81df7c4bfead867dac2b3b064cef33e7ac7b05dfcc65d8c7c0ced21cb4d3aaeeff6f7d8033d2e5180dfbbcf6d8c2beddd7ff8aefc1cfce27cc7e8a8d5fa8a1596d5a655b3afc1281f6e65c0a0a4c91bc0ac6d546eeaaebccdf599aa29cfa06fa33fcb7cbfdfe87c8d4e0aacb13a71ec62deeccece7aeeaabbf5ccf3e8ee7cda1ba0c45ddf99cabfdf9da1c7c4aed86f9fbea2ca7caadfcc78c109cf6994a01f5aeefba25e8e614d67bca2fc550ae7edbfbd3d9deccf87dd10557a201f9a67b4acdadfd3ae43fa42d106cf8cda5fa4efd5cfff6f70eba48af7b89ef5f18044cf43adb21fd3ef9c3eaa70aa06e4efa07dbfebb29a8adf7aabbcb24bbe04152ca4cc920cafed6fa1f2eaddd2cfad3bbcef8f5a8bbba520c1d62dddc5e2b2f62aaa94d4f8cba4400bf2ff5c5fea7b6541aa6ca0afeb325cbd1bdab8db5a30d0fe46b62f242c2db17db28ade9f7bc3aad5e8c5d7f19cddbfdc7dba0abdfdb5336db5a6ed7db9107dcdba1e0df2ef3ae13cec69bedbec92fac984e4b09556e5c78beef5c6905f62fdbeed4b4f61a55a4aa86530eaa181aa4fac1c2cc84adc0a17dcc8e08a40d0df3862de7dfe93943aa2da1363ebfa1180f3cddc0af9fbf81ba4c0d4bcdc1ac8ccc1f770cc07c65b9a30fcabd9d4202ea0d7d831a0bdb9e97abbd7e19c1f66d0eaffdc66ea2b6fa1c11fb8ee6a00bde8add7f5a785a8cdcbaff0a55e902622cbbf33bbfff9bd6033aeafc8ecfbde0c5aaeeefe321c89b2e77fec88ed814b96178a5c5af3f9f60ef3c70bb5d8eafa4dd6ef940fbdccdaa1ee5eaa557c94fdc58af99d154333cba62e5da8ad90c37e7afdc5d3f8f573a84a2defbdf5dae490fbae4b5573a1916dde804b2be2af59f74cc6296b150bf4eaebbad8e2f1fdbb5bb19aaf460ae5d5ae7df49fd8fbd73debb6fcddabb1d60c3bd9f2f4b81c92ebcf7d15441ac96cddedcfece4ea997e43afbfc9e5d7c7819a0700a8acf5e83bb0e6915830a767a634e87beabdde3afbd56db740c36a24ddc5bba559cffc5cae5ad5a0b6abfadc5c7cdddaae109eaac69c1bd8cf0fb7573e22c5999ec2e18f66ab81bb3acd6d995bb5bc8cc20bff6fb23a5e1bc4cd9aa5fe3ef49f3fd4cec8fdd785be49b5b1b14c1bc309de4ad55beee34ff7c8ba2112ff7129cc638c09b6d8bfaac53e8783bd11e427e4e55ef81c9cfd5bfc4fa463ac8bdad90aa29fa1addbc29bcfb5f7f98bf2737cfa4caabbd6fbe68b92cf8a98ebae9ed8ee82feebe7f8e518fae0c6edf20ed315e743ec5ad17196aa0aff37839be1bedfe0cadebb2d309bbac0ce38c7c63dcd7cd4cb77ac9e5620fffccde589dda8eddac1cda1d5d895dbfb6bd1efd78676cde80c52ef59ad22ee3d42635bdddffa2b2d777bdcafae3d7476c14e7e2a08ebeaebd5f7ca8544c8dd61c5b5c2d11f0ec45ee56c701d0cfa404fdbee4d58cf6e4dcab8529ceabd2bddb5b0ad67a631310c401a987b0be5d7a26ce5ec7a894a42e1eb1fe6c5128aef2b779169efa2fc7d9f4adbb0bae1c2eff9ff8a4e11ebbc1ae28f8bcadcbf6657de18842bbb4abdd0ce1a6acf9357cfaaec47a4e8d5de9f04ccb33e75f3c719208edd92ccf4314ea2c58fa9f988fd2d3ec0cadf9b8be99cb5ad952893c3fa27c8c8a87d1e8d89e5002ddb686782cec4f492deff7b06dffe0cbda6d311bc9f63e118c2ff0eb894128fb7b8b9ea5360b9f05e4e750a9ecbf44eae76adaad064a6c06d5048cf99e603e1946e2b75cca0bfcc240bb2ed7dab8074eaa4d5c0cbc5ad53ca4642d2bcf0e62ba77aee9b6dc8be84dccfecdcd6ed1b0bcb8ac5ef2c6fdb7b18c1a0ed8c1dd6fb647f59d5dd07d2bf3116bb47bc752d144b1a4bafbdd2e6181dead3f2e6d2bdbf3fcae57aacaa9e188253cccf354c2b6efc2edf7208c5bb5294dbdedfadad1fd31f9cb4eb5c9eb19ebef8edebc1aebb73fbcad9bdb2dbdbca3431ba590df5122c33edc3f6ad2a557e3ced1a64f389bcf84d8abaee439e2d56d829bd9d63fba73f95fbdcfedea1b12eef08ec23c3c2fad4c0ecf9d1fe7e6b8c5aca8dabab4edece32596dde79f2bb78f30f3ce4f3f76adb8acafb1f8520f48b5c22348efb2ace3becd9ffd33f6cb1ab39976cec3281cd1dbf6fede6a3bdc2dd53e4a1d4b88e5be975be30122ed3611facc31c3eccfc4799c0eac595de390bc0c8f6de656eabd78929caab6bfcfc4ee25ec1badc2cebeaea8e3bee916ef2fc592cabefa7a5e227302fb6cdaff513bb3c2feb0e5182be6f35bf8fb0ccc3f0772dd7ee99d3acaea2d7fac3637ef5e3eb0eccc1ddffb068109882f36eeed1cc3ebe3acfcefc17b8bb5b312fbc67ee8dadee337f58fbdac4bada18aadfecfe2ed2fef051deccf2fd7ae3ee3fcfd793feb4fd3bd9c8fd19dded2fb1e96dafc9936d7c195b2d1ebeecdeb58dfd71cd7438dc91464c3d9a582bcbdccae52ac70c8a67baf346ecbfa1a9a8d662abba8baca4342efacd9a00bdc629cd49b91c4ea2883749b9b08be4497c4fbf83066fcb1eff606e6bfa2bd94c69c82dbd95374bf8dfdad46defc6f1b695ef5a5147ecafab1d6b8cffacfcd2c6343feefe6ddaff6ac5ecde4416bf2d279a66a7594ab3ef8dcf22efad52faf9de934c80387d9e5b0f35aead187770064da0dfedeee7d4289d56fe5f5cb106d4776705dac0c4fd6bb9eccaf5cc38750fc2c3e062dcb1bb835cd7c8ac0cfac3c2e5cb02ca3c7bbc3a7636eeabbceb45be5b52d20d6fa6fcc5daedbbd69a31a116cf8abaccbab3bda7fccffcdcd484f7fc39cdbf782db4760a57459e296245ebca63f51c2dccb7ad8caecff749efa51dbeca02dfaf6cffa49f4c8afb1b0ddabccc4cc3f99cacc68ec34a72bcb0cf6afea83f06fdfef5fcddcb3a5d3b2f4515edfffd26d58dd5bff5b823fbedf40b14afcaab09ba47d20f6caa010be294bcbc0c811ec1b87badb6a2be488b9c2f9a3e1bbe9b924b1aac2f962d7ecbd6c7cb1916aaf2d40fa6cc063dfcf5ad16edcd53ae63cc81bdbb6aeadb0dfeced3cf80a8de9e128c2f7fa61ebd608e26b3ec87490a76ca986768bbb9decedd8daa803c9b0d65608fd0dcc38e7a67de97d9ca6ce6d15cefe4aabdfb00d596acddafacce1ace22aaa6dfeced1c6acabdc3da20523b1d2e2ffffc71cc73c0e70ec531bc3eec8e6117add64ae4e1fcbebaacaf6af2e1cbbaac470e2ecfdcdcd04acec92cdefabbf143acccb3c8dd0b6aaa953da556d4f2eccdc4acc9fea1d95ab6ca1e8b8efc87e2e21b2df8f00af6654fd7dafb7f1c21cd550c9ce36d7b540fc37588bde64b242fec58cba11ca8efa2ab1f5bdcf8566e756e2b438f929ddc1bdc187aba83aceef15557efdbdbe51fbe71cf7ee747bedd34ff9eae68db79cfdeda98dcbaa8f6fd262cd0bb5e62b91bcfd8ffcfdc3ddacbf0f79566bcaaea0fc776cdc62babfa6340dfcd21a7ff354bff77c928ee2fffcf870bb9435374a08c203e391ebba6ed2bbbbfc08efba09abeafe5fa2a7da5a88d8093ee7ce0cdcd31bdb97acdfda88aebee7f6eecf434faead8c03516e3e141d0870b8ad6382dc5d358fedb12ed4d636d001bc87fea47825a6da588628d9fd5cd0a0fa15fef25cc7e7b50448c67571efcf1bf823b58241eaa816da415f8fc4e0ee1ade554d419aa6b01ccdee0d96a0b9ceeabed8bd55f0caee5d1adff12c44385d231abec8c8dbfa69fc7bddbc2fedbbf66cd9ef95c2c428461081fca89eddaedc8f83cbf5733154d2700f8c35f4be7dcf538b308b5349119baf24c248eb3b81db78524ca6d7cfcdc57acebfde03dfdae606cfd0e0baee8870decc22218f32db17bdbbe688ae4f65682dd12a9eb2dcf6f456652b2f38c99cf01606551f8ab4afcb0664d6ac66a9c34582d6cff71f0da32073caeefca7da63db39aafb0ab3ec70ba8bf34fdcdfa64975045b862768ed59a8c4ced5f97ffafacafa4850adefe4faa3e4ae3cd0b6714e15e1da5204eafe6c3e7fadc7adc12de3fad25aeb8796e6b70b8f0bf14f481daead7b53c825fea35d3ace4c4f28e2ad4dccb29680f9fd0c4c8aad6958ebfebe0c79aafceafdab355127d2a0c1d23cd2bc1ac9cedc483907ea808bf0e22baa6bffdcedf95dadabceb3f9aadafeb326ad84ea582dfc5e66aaea0e77d3dfbba0eb1e7bdd1452ffd8beaaacbaeca3521a84fdcefba1e3c24fc39c41e743be8de2caaf1f7ca1dc481eceb8ebdbe71a5e5f21b0ab4e48160d0e2f8b76cead0aa5fa77e14f6e8c92e36883a5d8bad3efdb832006589a48273b06f36eabdfa5bcb10ef2d0c77dbefed1add6abacea2b55db15c1eefbb548407d8c0c89ae70baf9c0c4fb02c124ad6bfb62171cafdc096cb0fbb3d4fdceae6adf61a163a3fae5a7cf21e5fd02dae96aa37dccbf8e10cd927daedfa0bc7bcbd7ee0aba6eefd69bd7bd8fbf67dc8f4b2e9395c020e1f46c7897fb1cf62c7c33f133f9264cffc70baa81c6bdfe272d9d3b4ecdda70ef1f8aebd0eeaac1ee04cceb1e8bbfc1266c9ccfc20fe1496b4faeefdfedfd15c49e178c4f04fcf5c160a0d5fccbff5192c4c45e6678fcd8fa27cef4efebbd5ade0eaaf27906d8b737acef5f32def9e1b0ea0141bae4aa6c32baa1d98fac2e1decabffcacd9ced63310f454e0ed47ced55dad98cb4eafcc4cedcc7dfaa08db075de937c1cee4addf74e74f28c7cd95f8db70efffebe23baa1aebebd7e37b9a60ae5960be698be8d3aec233cedbcb5a8acadaa6d17bcfeddb92c754aadfbbf5e611b3a4bb024108b17a600ee62cddde25bdebfd5ebedcecc8b74afbec0bec096fde1766c7a36bbffa9e95ef0355ba6a1cad9af405e8f8fd53fd072ad381befa8ede8c2fa3b1920619f1f93bacbb0b4aef7555bcce35d5b7de83b99c7b7e5db8cbc8afcfce0183eba1abc38379e7833e36c60cccc090f0feb2f9cdbefb479f4c62f06c501b0fbecbdc6d94ecbacdc1cf4cc83fa15ec38df9a0db13bc9b043e3718b21d8c1c05674f4c4ef5e1d6794d52f83cc1919a33de91a9c72fdbc8c6e4faa00a83be25bfafc96edaecd1e0f8adfbe83383f7a52a51ccbd3ea4e0f9ab39ee07fc1edf32adf2f8486d0efcf17bd26aeabb9f5d0d6bca988bebd2a95e07aeced2f27b36a12bcaf6bc7cef4fadcdb765e0a1b8aad3f47a8ae1ff3c0bdca14c1dbaf81d3a66daf7b9a0ba07ae5c64326eaf7108367ad0ecca5e6358a593f6221cb84dfecc05b9834a4db23dcf0a5ce0b1dfb321ddf8ab03f5a6aa7d15ec231b3adcacd7b8219ff899d58c73ad2dd0be2e0167f9fcade23904b2f7586a45f1bbaac037cf5cdf018fab812bf8aeda4fcdd2cfe3c38af9e85106efa5b2ca5cacde5486bea5fb5f2a2ce4a1ed1d69bd5e4bef83d4f14cba5de40acca62da2f492dcd7beebf201266cca9fa8f119e9b5edeb6eadfc74ab1aadfdcffbaa6a8cae4f59befdc5122ba7ce3a0f3a75ccbf5a4257edf73dc94cd0f2488fadef0c3545849ee12e9b506a62319c4a6ec608acd014edc01e9ac2c70dd1bfd6de16fed3f5c5b9eff6fcc9ddfcbd9137d9abdcffdeed5b622d1dadf2e588e65fd438d7857c6b6e4a75fd84ae9f96ca3d449d69f7f0bfa4dc808a4cb3dd1abff26bc71dc9a748bbe2ffb32eaf8946aa90fcceadd54a787fde34b1cc2627d88b9bb9aec03045e6f772fba805207ba99dcbfd1b0f6ae3b36cd655e6f7e3acc6ebd9e4cbacc35afb0b153ff4b404da73c127dd5e6a7cdf0ca2359e95ba32ddba568c6ba5f1bd4cf90951b6c3e45fc4abc84aeffbebda5e41adf03fba1ad1faa7cacb8cbd3de99a5e793bfbd257a34dd9bb3bc03ec8cfcd820fa87ba994214eb2ccacf8df4d2efbc9bafab565a33d02d11e3f9fb0a5dd4ec5affff7bebc020abcdf78753ffc08cef5fb41c339a590578c06b77bee7c5cb4ea453cef8b14db2f821839ebed31b39e837bbd3c4e5a22acefec9fbab6ae5ebf13bffe7a7f713a0dbf4ce1d7cc2fdf2111b7c11e6014c5d8938adee41e0caefe55d77bfeee12388d08344f3b21cd67b851975b1153a9cb1fe1af09daf28ebdf13bf547a1037bcc21ea49ac0e2725a981d23acc02da384726023cda8fadd82edd2dfe962e43ffd97eef4b3aa3b5be6c81cfc0caa9b0c6d6c39e8df12b84df11986dd661a0cad34cb745ef5aed8c913d63eeffd7b997f50dab1eedfbf2b4c3b0828daaaefe96aba24cd5d2573a632c2f57fd2a00ce65b6127afe1a9eebccdb8dffec1eeb62cf7f5d6dbfffdbd9c23bfc29917a5f3bbdf181771b6bc9e3fb0483abde0c0308afdebab9ce8e508f37507dfcebf3c3f2af7a2cce0df2f6bb71fafa1e2a17afaab6beacd5e9cd4feae7dfafd8d5286cbaa03155ee5d30c1d0addf2eb1c06cbfdc57f41ebfded4aae70b4a629f797ca7c2ff93b98ceaaf6ddfbdd1e10a14141ba9fc4bce7fa6e678f6a088bdbdeacbd897ceef8a7f1f0c59519b50cbaec2cda3f38349e95da28bed3af47beeda7a4ec6b8fbc0e7785aabc6df2edb435357a1ae0282acf04f1ff2e7f4ca809e76f0a69ea9f5a2b7ecdd3aeabfcf9f381ebb48a857a19daa19b4def106ebffaf7dadecfccab37ca45fdce899a6b56bd3e63fafdeee6cf396b1779fbfe95aed42c8fadadc0e31fc1cf51c2ac633fd73fe0d7cb17cbc6e8fb9e8bc3c8e44b9933cb2286f43e2d4e7bdba27aa8d5acbbf47d284c26ecfdefb6aeea1f27dda938ebe48ce39f7edf18bed5dbafc3bfffc3cb21166afe27e2a9fbcf4ab9353d080f36bc34e540fe720fdef339abafcc10dbc1ffb16ce5d7a2d416cb84ef636a3a40115522fd75ecf48f3b1f0582eb8b5ffca9fbeb9f93f2cac8ee8ddb62b56e826490abe4d8d3ba43f54a49fa670ea9bb0d7ee4c006c3eb9a3ec3a1dd72a2d8adac1c1cfa08bebe797aad5548c226adebbbb960dc4edbec9efaef18837a93c6dd6b8dcf2672ff5f1bd2fd89ac7cdd534fd2a3ae743863b855ceeeef0d2bd5c42369d8fa23ccafbed1453d790f95ac1af5df761a5784770e5e33aacc0ddbf57bd107b692dbbd33ddddcf7ebf7de24cebcc287f80eeae5e2c5f0bb06b6e7d3adcd6dedba252484dbcd56af6df1afa7cc2a92dfb43e935bacfbfbdeb3f7cc4e14d0bfb02baafddfccf578260bc3e73da1aafdf34bbd6e8bbb01ee8ccce491ceff4ca0bb5525fc34b9fceb1abb3f7fec33a6a8bc352fbb47e74e3aaa80cca0cbbe4d7b125f090feb095b6ebbe1bc7663e0576da63870aa3b31a2adfb416bdbd99cf3a6e933db3bf182c1c17d830a6efeaf1dc1aca7fe1b376fda2cae11ad095a7804a96b958fc065d7554ad65cfe7b572c50b71ee9569efede1698e55e2dd4efe0d8bda7fafe3fac2ab86edfa4c1cde7dee3b9e2decec8e4ce7a2b8408aaec521189977484b684a986ba17d71f111c91ebb1cbb1afd6ee6c8e649945bf748cacbc4cbf0dd4b0da1ed4ab35f21bdb05aee2dbbdc2b4f6a80ebc58d6432d171f6be3acbb7b3ba349408eba0e4ba14f63f7d908bfbe1c3f3fa03aeaa51d38ef7ffc7a97dadad45a65deef8031ea5d6ad97c0ec1fccbd4ea8ee6be78b7f8b8cfdc9c6d4536aeec3dd8beade1ce3bbeb6edf6eae9aff3bb6d2ed6cef22194cf6bbc1bea650f8fb06230ecef54ccf02f627cc72b6ace2a8536b0dd58821e963bdba6bfde51e8b551bdbcde27adfe03efa4ab33fceb2473df07e817442db37c62e1d6cdc8134e41bd5faecb730d3bfb9adb14060172eab1b8190375f5275b71a88d2913bc4ae2bee8aecce7eebaa88e7a8cb1272ba432c3efad3b3f0d3fa75569f754b2eb4a5e5afdbb560b7929e5f858acf3dd3eca3b6d374727a68eea5c5db7beb8f1ae9d8e2f1c25cfb74456e8d60dffb8cc2fa9acefb6cb141a13dfded6143e0288a78acbaebb1055d6b1a5eaf1e1cfdfc83f65cc2882f8cda58be0efacb200cd77d9b2e6e6b02cf47acc2b665eb4cebcc003a1ad947be5e6e2c9ba8ad73a22bbca7f3bdeb31c35a7c700006bfdfde2ca7f328eb1e3ccfabf3bec5dc33a45b83f9f6da1df346fcb53362ce8ad9115f2df7e49f07b09bd6ae85c04cbac8bea75fdd2ed40eccaf0bb3d6eb81292c169e1f99905ca3b3f843e04c8fdee57fdb072b4ecc976d64e1dbab7142c1d4b11aace50b1ec895ad78dfbabadc3418afd9bda37f8752b539e2d6e91e59af36227b77b468c5f6c47d53a51ba6ac97e9a5a2adc9f0bec65bf7eaebaf70bdd31108db31bce4ac9a0eacff5ebb2dfadeaacce059837d7bec8bd6f08a2bbcead1ae7dfd2ec1af744b1ed56f62d72e4adcb2dbbfbc304dc0e0b2b02afca0f8cef6be9b3d76a812dde6fcd8bf7a30aa1ad2acdfb8fd1bb7af7feb90ac03ebc3e534b25dc57d948b9b43eda1fef333fc1fa0608d0f31f74904fd15e8fa44cfbc7c282a8da97cb61d89c6e5dc9f40bc7c185dabeec0ffb8b2a296bed406ef09bcbbdeadaedaa2cdab9bf5e1fb2b1bc3beeea819c10cc5469510eeacca012bf1913ac88aec4abca7a93eaaee6363e2eada239fe6aa05c13cb7ebb0dc91a464bc9ea0e4ff461c51a5bfb47fc307c7fafc89feb8fad8c67aaa78dcbbaebbe95dedf0edaa7d113e805deaf049ddbe819e6b0a79d2245eac8c7f25a04eea3db5de7af814267e0f121e0b20c1eeee515bce8e7d23bc2b02ac94bf45bfbbc1adfa7de82c5cbadc27c62dda30f430bae4a1c761eaafc954b5bddc54dffdeba6718a1d17603c9f32c1b13ff4cdaa48e90a15caf42dd1dfddfdad4f54ce5bed7c07eab985c56e8e250d3bb50298ac52b0eddbf4deedfe7035e6fd41cf47c7ef7e01ed2ce889be7cdfa5d4eccaa7eabb3dcdcc1da68cfca1d3fcfb977bba497c517f95397d4dbe52dc00cf50e52c734ecab3ab948de4dbec238cc01bcca9d1bbd8f4eadbfceba2eb8e602374f7bcfcfcebfccfb12dcee69fcd24ec8549f5f0d92b5eadebea5dad077ad292c87aef16ebc14cd7377a0fdbedfe6fc15eebe07eea71bfde01601be36febaadb3ae2dca0acde6ca39b55fde11811959bbb69db19523b846b4b8d5d89e9cf94bc0b130cf7f12bbfc6aeadee99c2c4e44b66a6b1addfe136a9caca2cb4ebd7c8a8499d0581d1c5d13a9c50ddde1d76bf24ce407fecfcfd6b2c3afdd82ae1ac03bd2dbf8edecfd3f3c1afe4add4dcb2ea58df0cb8efdc07bf5baba2ddc4ca2730cc3e8dda2ecd712fcdac302f9f5bdebb00a783b9f7e2affbb12da52086ed9e66ee3fafd7100be224dd03c1e6ec5ce8c66ca440d4f2803ebbbae63dee4faf4da06bbca3f5d386cef9c1afe8fbad7c1ad5eea85eaeff21e8d4daa6bef5ea2d12fd94c54bb5e3dff3cb50bca988dc405e2fd2030dcf7afca9bc86bab364eed6acda2bd52ff1aac04d6ecaea77bad6ef854fb9923ad9dec11e88a6f0ff80228cb2d982514d5c223ddfb4a8a8450ebd2cf544a3bdedaba6a422faf78ca3c766dc8f6a7d69d9d79ddc19fdd8a145accb307cd1eef372dc0dd95dc75eec1d6db2efc34ab357ddd7aacf4de9b1adb4aa5d1f441ec107beefada59dbb70abdbfce2fcbf2f22dbad60c440eb2928dbdb0c63bdbbe866ced7dab7fb1f5b0485f4bdf69fa06ffe46cea14aefc7a9966afcc6b9c0d8afcf828e3b5afd5f6dffafbceaabf09e8e0f51ff0b4b100caeadffbdcd5666fccc3c28196d430ea15f9c6feadaecea47a1d92c36ec67aed7adcf2e1ca85dc64acb9a2d9a6d3015f4e8ff364d5ad1adfeb608145c9be926fe147ce92befddcbfc3ea016e1558f3e2baecf0af7c5cf6af55b934ffaeb5d9e1c8ddfd35cbbf77df6c2bdda10f42522e6fad9bfcbb51fb6fc98cf9c52d5fbe17a3ef7c2326cd6143b342daeed22ccf883d0fbcddbb81c4fed2d4cd36ebfecfeaccb1da648ebafc6944fccc8d7fbfdd152c4da527c3dc6e0ff200cbbd7c2d3e51758ddb03b66ae3eef6d7ddf888990770ffb92cf33efeaffb6b8de6948fd7cbcfa7b8cdeb3cb1a9dc3bcdff16a233809e70ae0e5d8073dfef14e21578bba77d4dcbb9704a4e74f98d40f2c4fdba6622a55d0ffcf538cff77b29f0abbf72db0c40ed6dcc0ce4f1cfb2941c183fdaabc93acc8ccecdfc2c9b73f9ac5b6adac316aaa0be45aaff08d8beefc8cb4eefc7ed707a6670d6ce02dfbfefa38e7a5d1a666b1b9eecc951f1e15bb5bbaeba5f4500d204d00055ebce66ab1c3a3cfc7001fd6df5fea2dedddcc0dec15f88a13dbf34bae60b2cd5cd449f8ade66fd5b9ab79c4174ec81b0b942cfab1861aea4b752b943be5bdeba02ff2d16c91fba3cbee04bca0ff7bb1ff3947d2d0d12fcdf7f96c048aedb33bce0addd3768ebcaeef4d5aee5ba46e87fd48aff3cb0eaeeaae8d7dc1d9bafa326b93d81df61a078b73bbdcf6b7eff382efa0eab9eb5dd6eafc9391ec99e245291674f82ae59943bfd5a48f4f775f8cf76b67ff6dd17a21d3679e1df1dc2dcbbc6484bafa5882191a1eb5eb3e7cb4ea3c8ab30c0463f630758d2bacc95d6d0acaaafcbd5c67c22a13db9a3a5e84b5aeea62ba6e0d0bdd0527ddcf0c4219f8138ed1c8c8d6b6f9d10b78f06f94a33790bfeb4b7112588792f01e9bbf549f35afffcc9cbf7a63b3ef5cf31d7f9e8fcc70aeb4d8ab61ee214929fb5c895f68cfb277dfc6a1eea0b1cdb89d914da9ebb34e6af54535a4b622f4daebad33ccff8ef1606dfffe8d82f2a40a65a9e90e58f65e0ce1e6b0976fdbcbb4ea05f37fda5ff4acc907bec9dd5a103ff0afce24daec68c9b8cadcb4c0ef98a5c8a4d5ff97cd0cdac6a1b7ee1fc78e8d70ad5209e3bc10af2046f4235a7b483c5cece6d1aedfada063d7d3df35fd4c4c3bfc58d84dc69a3bb3dfb0cf09bbf195beec088af73e1d2b7a3cbeaf5e78af5752031dd0feef4d6e262fff2fda6d772e1c7d9144877caa56ddfa93aa2272e6aa974d18dcde012a9ab2cc2cf47d23aaeed5b5bef5d34cab67b744c739d6ab0409fbaa878bebbdccd3446a0fd0ec51e1efbddfab82aeedf1ed885adafb49acbf8fa3cdb77419cda3db6d695b5be3c11f79502f14a94de45074dce9cb1130e8e8bec6ce8fa6c5d6e1abee081dd674ff407ce3b754bc8caacce449bab9abf9c7c5d3f9ebeef6f4ac16c98824ba2fa92bcc280ccf703afce8d634c5fc0b6e22fb96feadf9afa6ff4f33a63e3be45f3ff1bbf6d6c027faef7fe4eaf6e94fb5cdf30cbeacc2927d0e23e4abecdea1db8edccaccf76a0e8dbbe6fd013ee7fa5069e64cf3fb97faa7fe9ddcf76edaa51d4317242b437d273bffbe452897a0c7ed3bd0b2caffe3b94a1a3d5cb3a524baf119a9d8ba0b4b94a909fcb22a3efe7e4cf3ad0512d6ddfaaa942c984cbf91dd7ae1d3b336f377b2dcd9fe9c9c5654ccdc56aa9592fe3b9d338df8cd9db5eed7a50d3e48a1adfc41e0ba3f0053a5aaa504a8df43c8cdeab264d1159bcc3a5e5eb6647cb1917ef50b14aeead28ff6f9feca14301ce9fc4ee103ce328e0e0a9ef563325edd7ca5ece66c85affe200490fad170d8029b78dc722d9e1f6cf3cdbb1dc5ed3acba41fcb7cc4d66fe611fefedc95389e41181ffb33dab62ef7ddb6e51aae5d5ddf4e3bafabbd966daebda3dc56d54bddb67064cee3d8b998e4f031d41e3b5aeb30babffdac53f8fdceccd4c0ac829b5b0524f887c4e3ae22db06c1bfb75ca162b949f85d6060c35d3e48c3a4b32b0f52fa58dce4a5aae2a5bd1beb6b3135abf71ef476cfd5308c801face9f1cb7084fdabc63116d1abfabdcbd0eb0da5c364bcab8c1153e80dcf7a7bffddfbf867e5cfed1318be0fdcaedad0169faeea2cefc81724f8fb94888fbbc6d677cb4c2305dea7dceafc423e24dedfcc0cfa1339bb18b119f75e8109aeef70f8ff023da9856a710aef6aa884af54d9537b4ab04a1f4ff8f5b0adcc2ae5cef2ed5c6baa342edbf8ecf5cb5ea9ecfb176e5c3313d0e6eaa9d2fe198140fa92d571dbc04bc454bba18dad3bd90cf26118ffe020ce2bb0e1f3ec7d6bbba13fbab316de4bdc2fee20ea6958fc46531417e7e8e8eca7a7dcacf0d15ef0be9cd70f06fdc1ada3c1a3fd0590fcf704b8f1ecd5b38dbdedfaaaf4abeebefaebc4efaf90ccd3bce206bea9612d2e9acd5ac2c10ebca3710170ef32a82392c4b67e62edba3fe6e675e13513405ae1fadfff4f58f305b3104cc382ab4a38fbeddc3e9dceefa6be23cedb41eb22eecff193d8fefa3bfa4e5e3c69aab3e982ae9c016fed81e66bfe53aeeddf34053bd82385b6d1fd4378bcefea13017f9b76c73a2f507bfb7dcba264d5b6e8bc962ca52a991ff8bdbebda59e77fe9c62fcef1415a993ffe4cad9fa3a96984489bd9edcb1a4bb134735cbe7d6bbbc1df6dec8809a45aaecab1bcaebaf06fbfe90cbd8dab61f50bca34156b47f4de94cb3075d37e9c7ae8f7f540ed6cdd9ed7dcffb90d24add5dbfefd06ca1e6ebcc4ba52dd7dabc8106acccc7ad0a4dfff94d9ccc1b104bccfcdccb8e3d6c1dc3f88acc4e3fbcf5df561fd7a0b1eba7dd58f7c9b05d9eae7c5da7d5dbd4df7ffa1dfcb34f9fe0ef3bbaaba9cbabee477cdbc9f0f1064ee1c1fc1ebce136995bfb7c8cd22dee5fdcbdeb1f457dd7302caac50dc5d9ea07fe01cecc5a7cfebc915e8c7eedd68dc1178dbef71c9771f3c7e1febee6ddedf6cdcceccf2a3af1a93a3bb4eaa508f72adfa6d33b9b358cfca16d4f7dbe3ea07bb331dc552be2145932b6bf94deabf7aeb0efd59b7be6ca30ddcdad948a87b1044bad23cddd45abb2bae5bda00d4eededcfebc38525f58aab0c5c7dcafe8c6fcf0f44dfa44d38f4fd1faae2e6bff4cc205def25be1d1db0b50f2a57d9af0caddb95eee0ba96c435d2cb737b7aeb6d43ffa29882eaaf2ba84f9fe1a7bc10ef0ec856257a8a58d9dca1c47a6e214dcfedbfb2e4e5d8a5729fa2db9e61b2abdb5aa39addebc3e7a6ed4d24fdfbdd5edf21cb770df102c4edea8b6b0dedbe1e8aabe8cfb8cee5820e6bae44dd4d22a1e65fce8bbec9ebf7bab8db20e4e690068168732ade64edbfaa4164abcb5202dedc8e1fbae9551ac8c2f01a1ddda29fedbf45de5cff09b8bdcdc21bfa660ae5ad6deacbc0cabda1d63abfd5be47bf8e47babffd0ecfabbcdc99bef9f1d5c5a4ea0fbac9fc3c49e9f56640fa5afe6ede1d03ab98dc417adbf06aaafda17f4f5babc83e12cdedcdc92fc1bddc6007efaecf38a7ee3a231ab7e3fea538305e1d0aee81ad84b188fc4515da14ace9ae82471f2ee50cca0bad2f324e1eb88df5a55d8fb4faef71b9cbb50f8611d43cb9f83e40d562ddde15fbecdc0ead901df4f8aa25ad1dbba35ee4ff37da9d46eccbd51a4c03df52d42c1c2fe82f930c9dbbcace5c86d38a79b5fda30aca8c46ef7ba95cbacf11ae39e0d200de44c5ac6adf350eaeedc82d4cc8b7c37a67a3bacac95dab3eb4ac3dd83e5237ddea307ebebc9bfeb8d3b8c2a4020a67e19dfba305555f2c22f4db7c0707008257ead57d0fb9d01ed6bb5a84ee1afd86f1ceedf8cf2d59251c21222c67c86dcfdc92a21daeea401fa9cb7a165adb0e9cd739aa3ca7a145ddbfdfe8c5e2f2b1bbdf1cc3ffdae9e49f15f7cbc3bebdbb49acbaeb5abbcbbae7b891a5fe7a4b0b5c1d7ac26ec6ccce3bdb822cb5c41ea5ea06586f49fe08bfce04edb2306bcaf5f6ef1e987b343ef5dc10b6ad45bcd219cce26adff0d12bbae7c15b5bc5d5ad11b573b931beac50ac53f4ddfeed5de1dd5aeba82f7ffbd6dd5aaa6b7a1f3ded71c8b2a1ad9f337bbbf447ab2f4c7bf04ecb88b37b1c44efc3c12ce9daee28ffca447f388ddb5f9c0fcd4042d08241be3aea1e6dedb02fded70aab5c7c7843e990dcd2a93b3a9f208c9be3ffefc241a6daa9e6effc7d9d1ccd4ad11abb82dce281afbde2bfc3faef4500ae10e36fc90b6ee231f42e4de8d1bb67a5cb6502f26d2ad2fdcd379f0f0cfc29c0dcb33fba67ced17dbcb5ecf5afe7a4f505f5ecfb2e20e11adafd51dbb70dc63effbe81cbc67d5a38dfabfe66da42e8e09f420e4ef21d54ed112b6c51f9e6de590b4bea72581ddcafbcd2062a693addea977d8c6f42e44508cbf57e8d9b0bec9b5ed482c392d1d6b7bcbef16a3f89b446ea3dc90650dc3b0cfeb6f3edbcdd3c76fd694a268a4e15c6ec8c137cf9a9e76caa9c7edfb5203ced03ecff2cb7caaaa2abd5f77ee874ff7d4d7fc2cbc2875952c358bd4a1b1facae59ee83bfcebc5be7b6038b4d67794de3d4abc4cdacadfb0dc19e3daa42e4cfe26bdfa64a70a39f0e2eed5f7ca86fcea7ad4ab1d6faefbc24a9a3fdebf7ebabf0ca5ceb9270e4f7cbbe23b2fdfb0ec93dbf6f1daf5fc4cbcdeaadd8ced3032eb785cfed83605618cfeb20b74dbd9dbede9ddcdcbf6f1efc5d0e529ff24e3ffdd5ad0aab7b3bbd9a2f8c05bbee448a8ee8fb46afb3ea1905eabfdff3cc1c7ae65ba0ba2390160de6d9f75cc7daab2acd6659af93e291bb7a4e02853fad4adc0aeaedcb77fd672a65efdfc0aa57aaa2f15aaf6cd34fc60b1bba8f1d2bc96de82d7ee2a31b24bf7eae80430d7af2f0d883a0c8b3bc28bec8cc3ac6efe3c5353e211475cef82d2f1e7c53ef0ace6e0939ba59baf718b719f4e967cda08d0cbece3a60fbd9effb75cb52fcc0dad5bbefe4d1f7cfbfc0cca9c06f53fbaba19ac382f5a18bea27cd9d0cc1dece7dac3bc7ae63ce71aed6caa5a5ef6a4edb9e66dc6c3d489e17dab6f942566bf3f65fb45adb0f77f2cca8dd3b8cc5dde7196e193f2dc8fca15e272e2d0dae1a0c17fad5fa296f1a27a0eae8bfabc38c28c2d6dc0361f6bcec4f0bed6cab5726def4b564ecaa8b80dcc9e3c21c7839d54ccad2abdc88ea47f2127ae96e8f41d4674f46b04a6ff7eef3e5dcb4b7078cb6706bf8edec2f30bba58c96fc8e7b3dcf6dcb6acca40a42afaff3ea73dcd8ce2bddb55c65eef6c4f8b2c676b7e32e6f8d6fabcb5afcfe5c978c17091381911d4ffcdba7315abbed1f4dbf72dabd76053faeca562a2c9dc96fdf3a3a54adeeefbec36e2b1b4f4984ecc5ba7f1d34ba376ab4f0fcc4c72e887d6c33cbae1cc90f31b7d99d7f096f62f3ed9fbba88eef2cdb5feac0fd30c3be5efdfbade0eb4bcbab3f38cf42bb89dc4fbd0f8a7caf39f0dae4edededea17669bbaeae2fdfc231df5fa87dbf6deb41ad67ae813a1416b549050ed02acbfed8acb7cbeabf2a7a3c18602fa0dfadaedcf2bcfaa5dd0fdb9b39dfbd56ecc801ce078af6924f5ab76c1ac4b7daf34a6fd1aec4f9ffd13f8ec89f9f47c7dffc575d7ddaafff6ed18513a4d070776eccd33afb3b9ebd46ae7f3fde0821c8afa8de5eebafa7e55b85fac023ea3ccad1dcbdbb0e1d869707517c8fc0c45ce21dcdbfb1fc2757886739adbfacdc2bf7bd8d980996c05e17d87113c72e56a1eb2c1dabdf76549f2ffb882e5c6928ede090fad1abaf784ad28ad6ad292e98900ff982409ea707ebc6304ed79444c3ee059cb3e1ceeeacbd1e4ac23d5ae5a237bae75a8ddb11acc4d32e7af2bfa3382fbb921e6617f5ed4c3e9e3bf79def807efebdcfddbacda6bf4c0b76ccc28efe7aaf8cc4dcc4f1e00f8f96c05254fe86bbebbacde28ebdc0ef0c4c973469834b1a1e27dbdb5b9ed7dec79e187cfdc9fabcada8e7e3dfcc0cfdd2381e4ef2981a4c2975add70c2cfac327a09aef0fa7256bef58aa314cdfed5ad1bf8cec6fd48dee9a993e7cff4aff08bcaeda3dce8ff43cb2e54224317fcdebed4cfffe9e8acd4ee6bedfc4eb5755e375b9ed49ed4e9e00c7a2e931bcf90b1bbda4ebc73020c5c1367125b6aaaacb14aa3d6f210ab4c0baf89ea6f33e230be6eed9482debfbaad9cabeda3db6ce154dd9734adfb64c3d9defa84be5b35c01cdaab6c4eb782b4cbbbbabc61a7fbc1cb25ec46bb2affb50e3b536feafe6ea7eabd69fcd0e1fcacb14bfd7e1deb52c3fe6a61d78bce4e8ebdef6bbb210a5dee6fcba66bbca5fdffacea7dbece63ab42af9afeea3c2c9b1580fe2dec9c9606eababa2a7bafabbd6eccd34b0ece0d5efeb210288ceceadffe3c75dccda6a3983c8041ecb1fc65ae8edec9e63febe295dfadf6e4ffde29b31ff89ffec4de8fac4e9f260e1264a79f9628db94b419c69a4afeeb9ebadcf4cff5ed4ecbe5eaee4c2acb0fdc4a077e07aee9f92121f2a70234301ac7a733acd682749f83f13ed8537a21eb18bcfb65a28d44d5b5caa80c5c1d4deeaccabf6dda448b4bbf68c61bcc651a5ccc7aab9ecfcfc5acf8e12adee00efcce66a94099f05f9c3dfb0c9b0a89714c3d7e0bea874a2fdd0922fb0cbbbb9f0aa95a0caa0dacc0e497cb41fc41addfeac307bff7dadab0fbbdf4edad28ceffef943dc7a95f3b2f542b7ce0abda38df85db9828ac03c9d830f72ecddf6eed5d2dab0aabf82a12b32e9b9e8ccf9524dcf86eca50d7acbd9f2db07cb77d1bafe7bdcde9c2b6ebf78dd7cdc358bc5b712bbd8fb37ffc7fd4eaafefdb0bfdc1ee2f4da98ba7cfa0cae9cde79c5dc11e40dcb344a618bef5d0fddd938dac92493c5dc6ba1b6bf51c48bc0bd3c2a0eaeaf095c06e3f06ffaa9762ec5c3cfdfebe9e69fd6acae3f72cabc02c75b4bbef9fc4fb13abb9acd88fd5f3a5f7baee24beab3a6aebdfacafd9c7395fddd1484cbcadf68fcdcfc9c3757a1ba8a892ed5ab8646bb5c368b7661dd048a45fd2112679a28a058e2ebde8ecb4ce38bfdf4b740e72acdcd9ab6fcae4f8eef44adcbecc2ad91fd4c2aecbdee314bdfcb061b646daad0c3cc9a91370d22a00d66fb2892bab7bdcecfac6632d238fed80b6fee96513cc660ce1bf34b93bdb91af3e1d19f2cebabf5d5bbbaadb54cc269edefee4d4ddfcbecb5dafb588dd6cac3f2589eb3bfdbd0b99fed5aabfc9dbffa17f94cddadb505adca2012eede7560b2ccb264a8aacd2faaafb86abc44c77ec47e18e8c7bb1fc58f578bca6cc05be0ceedfbbd76b5d7a65fcc84bfceacb8dfcb3b0afffe97e63ba72bcdeac4790faba71179c6be75f018b0afb48db60750b41b596eb3d77e9adcbdef8eba5cdd1b8f2d4696073fbaf84eac07db07cedabff0e9d7fdd882f97f44ce77a8fa83ce34326dc7bf9e19bc7211d1e0fe5bcaea3385b22f09e1cfcaa01fd51dbcf9a8f35be67e2021a5a25a6eb9120deb0a0cac668e3545ff10bcbcdfe7ce641ddc7b2ed8cb0fe332c4dc73e7cbe63060ede4d7da3dfacc6b1ad70da4c58c70bc5b679c11e4bcac9e8fc7bb96af23eaeacc5469bfb3588abcc41de26a6740d8ae5aceb5e0d3c3e63362d6088aaa4fdc6e87bfe32a49e0ce78dcea26d9dbc2ab1c2255f8a094d86fcfc2fd4b7ad6a4232eecf870be3bdd9b5ded600d8443c73efbf21bcc1ec6d3e3ccc1b5b39babdfef125d225e31df8881dcfcbc12e0d7f5d7fbd1a29ce0effc61bdbbcd1e0d8ea44fe29fad05cfca4a67c9e24d59ba44def1f3f349130f2a66827c8a7020a3fdfe956bdda9fadfdabd2ea29cfb65d867f088dad8bb88f9a1c8ffeaa1689d7d4f8cce1439ff53b76eccbe1b2b655e3b8c9b3655964ce2b07cd76eeabab2ffcccbfdfe6f6bf92ca1c0bcc0ab1f8083bccef4bf52edcf34bc4b80dca3bdf7ba6cccdcb4f2d41dd554f9674a3fb8a4e4a643bc4b49bf2cda0abd20747c7dc8eb5f4ab0f7f7a0a1f9cfcb653ac34da8dfb88d485bf3f1021b853ffed4dcc9eba3bc8448b06d0fe8d3fe7b4fb7f20e21c8fbf45f2631e33c7dbfb8feaba089e4dbbecdca5277b2c89be7a1e9fbc750671ec2f4fe32b32de4a2465ddeeaacaace43d3ab74ccc6266d21bdbbd515f6edae53ebdf855f9dec0150f92e4cbc2d9e6bdbf77fe3e46facb2fa33acbf2cb3ab8bc8b2eab42323c6659d9bcfddf9ea87a5dd23339b02d9ab35ef84fdc42e22bd481d81ea4d33ae0561b6eadbdb6a130c49c5c1f6d7faddf6cd25b87baf49fffb9769b8adc316fced6fa8aa2edfa399adc7fbcea41544f7a8add3d023ecca3f17cae1977fefc23220f1f9a2ecb56c91ea625b9ee03cecfe58e4282520eeb91cfbdb18dce012bb7efacee73abaaa5ddc75beaabbb33ca2fb9eaaaec9d3e960eb88feee485cdfb9ffdac16bbbbf9c7b7a1ebc9b07fcefb88d6f6a47fe7c2a342d645f1acfec5c794c1cf36aeff35febfddb8eecf000ca81fbbdcb55b53a661ae5dcdabda28f3d04aaab37f279d37a1e82adf686a5b0bfcab3ec6b9fb0c484badfdea2ac9fbcaa9c3da53dddbcaba2d5bb9a15a7f4cf58673d29ce68899f87ee9dfddc0fddeecbbeb600f941f4ba6b1f8dcecc6bd9a5759cfdf688ada6c01df78d32aa6dbcd8145f5528e793f07fdd97ec777ec28ccb36de6edfeba35cce1358eeea17996795783c2ce5c2c23fca60171ac89b8c18ae4aa7fece5141a3bc34e2383932ffc73ecaaeecb05c617db2aaf4077f62cfdb4b9e05346fa9cb82ffde6d9f6a4e9fbb1e49dacffd94597e393bdf9efaf848fcfd3441bbd1a9dfe9e8bbd29a7efb9bbca9dcd1c7dc32fc026a9de74df70b8cacbbcbd5e4054a9dec5e80d0d9d7bcddacbacaefb9dcbf47cbbfbb503abc8411d6a7e7ccdc6fa90cfe8f8ad05cdca8ffa4e75fb9b81be08757c1dfb43dddf3ebcaf1bd4dd4f0c8962ec3c5bdca4c9bb0e4a951addce9d1ed87c0e39ffc3a7a189fd8a62dcb7bbe10d9248efb3de2758ab2ca0ab668fc8cc8cbbd5639aa7f2f3b802f3c699aea8e91ed8a58df11f2c4be4eb8a8eed5bd5ca9a225e8e8af37c2aec7d714be7ad0ac7ed64dbdc50251cf9ddb0c23af834ffe0892a8ebfbceea6f471cefecb3afe87f21debcd5010fd3bf79d3ee2af252f2612a2d78ce5d6e7cb0ad9b10edbaf07fa4c1caef66add93a0bfeedce38b17e6b2db88676c2c5cbaeb67f2d4facc925cb7b0efacddfe35ded7defe5e977e15c71997ef0479d97dacdffcbf2c0c06b3fe8d0bc9a71d7fdebbb2e910b1e3004b5ca88288f1a2bf84ceda3e5e1a66672cec6bb759db7faf6fffea4da7fa462f8b418157a90c14d8c1c75beadca0919043baea22dfc6b6d32aecebf7fdc1cf2ed5f7f58fc7c0c0ec55faf0da4ecdce7d1e97faf6af180412f5be6a44d9c64928ab33b6a2cac30def3389db95f7f32eb56ade3232dcab0c7b6a850d2afd70ed2bcfc0db9e0dbd46fbaf5d5bf31d97c6b26e3fa9908cd9aced2833ead9c2e4ec870d1e9b7fbf2233d1ec64aafde62ac0f8dc6b216afdd2b47b6caeeee40376ecbec0369aaca715dfdb77b99b0f7de8cc1cd6111ccc9e7ba81dfa16d36ad9cfbc8bd0b5df3b23dbfd91bc0a0debea0c1b7feef77eefbc1fa2f8eedb5f746f652c1f8639cbe67d30d9ba729dfebe41ddcc3ca1ff6cc4e7bba7c4fb2028b291b880f6aff9db3fbe8fc27f0150c408fa0eceef5ea736f8ade2b7d5fba43f487ae4980efacbcbd80dea9b2aa04ce4b8746ecc2fadfcbbc4122ab49f6d7a86341eedeae55c31748cafc29bbd4558949eff8724abf99ee54be6da344fecc8cf27ede8225a05fc5dafee1a131f060e92a2fbe83faf595bcebb6ba51eb2f6b2aa76a1f4cbcfa4c8ebdaa98a0a56151ad13ddda5aebfb2bbed57daab66a61ac77cbbed19ddc8a6537eafb4c86ca6dc2fd584a2ecd76abcafaa9866e81a8e5f5ecefd9bb5787f9d4aabefb83bef7abf597cbbfca8a932a6be19a28fb0a88eadfda2cdc342d14327506d094589eb95f4b6bba54e46741106f7211ef4c77df0ccfdcfadfa4995ea973f5f13ec1f9cdadbc1b6b48d2a11767d9ba5e7c807b0af2fa2fbbd03d69337ff17ccd63b0ac17d24a0de4dfe9aaee86bc7d0fdea34b52ca9ea66fdfde50e4d47bd71e10661ccbef40788d0e7d03eea42768a73f2ccc6badef6f6eb753eb6c03bd6acc1a420eb3c300afbfe8a3edceb02f6ebdfa7cabeafce6c0cad46dbea3a29587f0b068e389ae869b5ae47fafebfced6dea3a8b66dd4e6bca24cc3ffd1acec7a7fae6132dacbd9ec97f7d4b9f9cbdfefce60a9b6ffcfeb2effd62354b8f20c2b2dadbf0eec119edc74bed3aff645f51fd90621af8abb55d9cdc37e52dc90b3054bbc23a5fbc19dddd6c1e8f2d3fe57ad4cae2dae9fac15caa2ead9ee7e33be6c47ec516bce5fb6cf10e5ee4232ba8cebf5e7401f6c0b5bfe9b2804c9b92942e1fc8bba31bb26c404002284a2c58f583d8085cb97cce17e20ad7feeccceb478fec56c7aea01e8580eadbe8a65f5737cfb4d4d6d7ce30b16b6a2eb5fc5cfb36eff87fa1ddae6b8cfafcdb88d8de57e8e4c458af9df33ac57195af0bd40dfd4e09be761fd60faeb68d73fdbcf9edb1c27af0eb0e4993e4ed61bebcdc483eebb27aa36f2ecd2accb2d9d7edcd717be1cfe732fd7aedb4db28fa7ae12f1caae3c3f81aaf7dd6b0ed3566641aafc5be96e1304ddb48abb63e4ee0a316b699b66e6bbf2fcfde85dc9046c234edc8a9a987c687fa7a94e354f2f3c0230e109afbabe78d013cb015af289c49de59b8087eacb83ce50995eedc4b96d8e11c97c22d2f130b2afeb6f9d4dcedee4fc3fbcdb98165e11ccd6d5ddbe0f4cedcc8ce1ef012c3ddb3d17119a7bff8b1e9cffbafd0ab6bc5db68d5a2f50bebf92cf8df4cec32df1daf6f391b1bedfbd8f6cdddb5ae8a4afdbf05eba3f7f1b887a9994703edacf454d7bd6674baec2a0be83faf9862be5cacc8f6eab8d4323bf45d1fde09f4bce66b37c77763bd583f9a1e7cd3ddcee9adbabc58f304dce1aebccceaa24c23d9d09cbcd2ae3ad2ace95ab2adea70a9cfe5d5ce55d2cf1ccaeef7d371dfd75670cb9d4f3661ef2c5bb03946dc7cef49ebfb65df1ebdfafe26a82cfff1bc962fe277cfdbeb2d2fce36fa7c7ee1a6e75e0db68d6ae984abd55d0b80c2a3b3840c85a754819f56172da86ffffb6727bc5e1e832eaccf9082d5d903bb03ea96fab94c57cdafa9c9e4614a46adba4f09326eff20d63fc1f8fc5beec0f9f2ecdc3e7ed53deebb926df74abf1c50d82dd74a177cc271ea511af6363f8bd9bf9d4f08022029eba76acf7b617efbfb8ffa61a2663ce74c81956fb14f3a61dc6f8b80513ca9da0fa45ecde0ff980c83b5e8e8372dfbe50af0a6d26ebcde2cda6d7d0bc7bed0bd2184b8599ca626cc6170653e1e5f5cec15ac382e51bf61d21fcf7cbc9c8d49f66394332ec0ff2d80814f8aa5d06fbeddc31ef8b30ecbf74caa8b58fc8e49952ecedfa8675fac9ad5082cdb6dde939aaab7cf8bed96cbd4f1fe14916a79fbdfe5be6dd78f8a2ebfa6fcfe3de0b0b8bb4fb8f5dfc6ce8aedfecf7a5c9022f37aa98f08dc2e372b32ea18482b3def8a8ba8ae24aa1e63eea5174925982aa1b7d96e453bcd2e6370f9bfda23f1e1b2eea46bffcd97a47ae307d8da9ee8baf1b2eab8565da4dbefeaaa180bfcdbb580cf2002de1fe3c87b8ae6adccef1ca2f542bfdf8c8b1cfaefc4cbf9bbf0ccbadbf9f12b345cada0d98518daa4ddea459adbec72b07f9493bcee7fdf5a069eebb9f9dba86ed49fbd65e4faa04cd0696121609fe68e23ffe98f59b28b52a3263c57acbe5ccbeeed4a20df9aba219dba8fa5c72a7f478f61a1bbe51a7afd3bbf3a1cfe49ffa2ef285bcda6bf5e3f89657050e93a5648bac02ef8c3eec8250bb686a8f7895df53b4bf77d6f20649abc7b49ee9d3f4ddb696e04e36a2ce91abd907fc97eae5ff0baa9ee68eaa8cc4cd08fdcccc77c72d2b28f7cef4efde2a4538fca8cdc34fc77df7fe801add213c034fddab2c3c3bcdd55f7c046bf7d4f2f0df24a2bbed0fac12abaeeb23ebfaf5615eeca18cca7c52e43cef40b0fc5d3ecff55e9bcaa71cbd0aab6395183cbfdd4ef9b33dbbe3dce8bab3c0adf6a6ebcaaaf26c4bc8ce5cc183b6f0d620c3ebaad3ef3a5d3c2522d70fb50cafcbc744c3c3793aca5562b9edde573224afbc2abbba677131cfd5742ffb79b21c7b19f91703fd3bc5b4ce042619696d5c73d38e734c2bd37f8abca8c3c9cdcc842f57cb1aade81bd8f5caf5c767dd8b0dd74e5c3bf310e910fa6e69e9775ffc3373cb3ed6617fdb29f4deff3bfb02ecfe93cebdea82d7273d14fbaae400ba302fe3e0bea9b27ccbecc8de15acfd9b45c2d275e380acbdfa0c42199753346e38bbbdfacdbb5c63394e88c71ee1ee58496f7a7e3afda6e1f4e02e0ae70bbf0beb8de13ecdf0aabcf5fbc739ce088ad544cfa5c3aef3bffd4da900fb02672f32caddcbbf44e7cd0a4fed8f1bb3c37aef0b43df0d7e308e50bc9e2d1b6ebd5e5412f8cc325edf64a509c9a4deaefd580bda502c0e657f76edc8fa93967e0384acecddf9cf2918fbbffadddec7843cc4aeeb0e232ed7c9d0a5d6fec7bae7a09d6db9abeda3dff7e4764f456fcc194d2d23eecd29bb3ef2d1f6d1d99bcf09ef57dc89df82ee65ab5c1cb9e5fa30aad709087e15d9c95fb266fdfbfc9c625ac77ca4d3ca385cadecbdccee3fe6caf69ef8a5065a7ea25acb653ad5f98f2dbaefd9cad462b5141f5cf5df6b9fca0ebb79f50d9f9c818de557abbc7bd3baaada8abb4eb4a7a47eaeebe2d30ebec5ecfc75a49edcace722765da6daeaedd18dbfd3a4bebadcfade577beea1782b41f64e7a7ac878b6a356cae9ecb28af236bbef8dc79bbf6127f0abc657ed5b79ef93ecee98bf5705b5f92efc9a0ec847ddbc9b4668056861ef477b86cdae87289ab8dfb01fa03be29c4b7a1e600c444e96e888bb1eb46ff9abdafebac5a09a544eaaa427d654bfdd99e658aea82b8c7e3ebfe9284e49e1e8e9e8bbff199988e96ec4bf8bbe96ffeefa6d2849d5f0d4cacf7fae9dfb2ccc23d83caa3f1bb1aabdce8ebf4edcdecab7467bc3d0b2bf3baa40bbceabb9cbea5abbcf5bd03b2e8aebd3fcc7aabd5bcfed83da787c5ad57dd6f6d51be75dc5d5dcfc6d12206b0cbcabf6f82f0ecd9a355bc0a16fed9ee479c252931ea45be3becfd814ce6eaf536cbb9ba12ac42dbb7ac0f4327cf8e7afbe56dea9beb24cd6ae43dc21f5aed611dca9fbcd3dcf2e7d979cab801ae973d1dfdfdbf9cdaf9ac6198557b7a1c0cdcf46a03e022410e28d2abc0a71ce1329df61ee4cd3d19ed049cbb7a8d70bbefb617b633ff134ceeac2c667b53445c4a5df3a4ccd34b4efeebf921ffe7601aad3b0c04cffad3a8bbfaa5edacea6a7ede7ac7a8decdd917cbc9b59e2fea17e3c1fabf11d023d82edde8fbdf1e4fbeb221f1d7ca42835faf313dd9189dcf1212e4adba3b62b1e0d663e8d60c40ac02ed33fc8f063f8afb8beaa82eaab2fb6cfc43bdcda8902525cf11e7afca82c03b0e5bcdac4cd9c6fed46deddfd6b92ecddb21cc52a1d45fcb9faad3d7cddead6cd95bd52cf6031664cda0a715cf6c0bcebcf3fa41f3f0ac25ebbe8fc8af88f7afea2fcbbec4fbb2beb27f170e860b3ee1eae60e9fe43961af4f5a5cabfe3c15b49b74f28dcbf9ceed3dc27bb18da8e96b558a3b481ab2fd75ac084b102aa593ea32b80aefe4e3d3ac09fc5e7b09d84bf1e9ec81b4a1faa8ce0dbffeea0cf8833dacdf3020e3c9d07a693c62014e8bd37340cafabfde63f9b6275a3dbc1ac9cceebdd75bbbfba3e0b5c4cefbd60dfcba08c70dfe3ceeacc73f1cc7d70ecc9aab6faf3bfd574be8ac81cee7373512aa1a2fa36baadb8e08da0ab58dd92a1431da223454e4ccedad45881365b73c82cb789d7ec5c0a93dccb2d4aeb3692be46bfad952bbf4ec27c97c39e709b20330a169b7d5b90021e24e122bbadee24ca2a161f21a523dddef45bb3e13638a54ac7ade56b8f14b7bdcaad28efebac66b0ffed1e2eadd1ebc9b2ed6da78f610cc65faa75cedeabc4f614fbdfd070f52345f5b5c00af32fd2bee7c4a0b3025984d1892c0a72f36df7e1eeb1bd0b0fd448c9d99da65eb047dc772101efbe7e0da96ef1a9ee30a32863cfb8bc5c4e8eddfdbad4f4cad08facb1e6e08f3d9d4dacd73c41def737edcfda4cc5fb19980f667e107ca9cffbbe699d9efcdbaeeeff8d7f01dafba08af99fdfa36d7054e82094e09ade0b14cf238c6dfec95ad897a9dbbb2c859c829ecc8cf4d7d5c3a05805aafac51a95dbdfccd870a2c15bea1fb70fd408fddbddfbf05d3ad7e7cdbfb7c3c20a71a411ef3cf8abfbdf50fdab66cccfaf15fe20abcc8fae2b34f270e0202b1bbc91ccadafeec8c209edb35ccfb9469ca5d9adcfdfc9acb1c6defaf35a7fd8c54b1f9fffbbaebb294c089a70e9fbd5eb0b4eab7dd830c28a6d840bd7ba74719c5bc951dafbfe09c72d55fce7de4ea8a08fcb09276baf7cbefff6f0d043df03baecd7ba68f5bc3d9a0bc09f02fcef9e0abdd5a4184741ff1f8b5ed8d3eae388b9f9462e4371a8c680cba41f81f9dce07ecddd684ee5d532de00c5e9b58ab8cbc5cffcc6922756a0d064e84ea55a5baafcf29e272bd98bc4ae5d3eea799fda0e55e722b7c42bfca4cb2a0471e1ecdbbca0fe32ada9047c60d9ff5235cca6e8eb6ada43963cbcafdff2eb0e9c34e8b2dd3a4067ac65fe4acabfcb9d3aa5aad28cea0ee9bf2f603e5dfff47510ff3a796a3df2f3da0ebdffb87aeda03cce8febcc4ba13e8386fe30b1cebacc338b1aa52dba7bb880c72cf7ffd757097c6428dfeaf4134baf27bb5ea28dfbe39d31b64597d9cf462a2b860f2d3fed0167dee3f1ebb8f21bff9dcf6f9799265d9804dca3e4e1d36f7b5b02f95afa6f8cae923d82369f5d2fcacd33bbdbafeac5c26754baf14a04f046b8ac1e907a8fba0e0d80c0fc6bc768beadd41f39c1d111d2b6b2fe5d7dbbcdcabfbfacb04ebafdc0d7eb5e2fed249d8561f3cd6c1d5c57722ab2bc4af19efddafcfdf8fedfcbce06ba4d82e41fcb3bb9b70cc30b6accaab54aa912bdece76eeca6a2032ebbdf0aa9acbcace80bfeb2d9aaad0aabd3aaaec0fb5eea38eb7bddde50aaed84f439babab1de4c6b60b84965a23bb058edd5dcb0e4ba2dca3dce5afcc9fc11adcf18ac682aacdc8f575a53d3e6240794ebd59c10639ba7adf3322352d9ab9578bfc88d0cddbfba1ccbfc1dd88b78cc3e734ccde327cc14a2227b19aaa1af8bc9bacfd29c5eaf924cf8df6f60f87073fa0bb388a05f6e9b860ba5adaa3a62ced21d23cded375c939ec9c374e2c81cf0b4fb5ade8ca0b1ce0d7000edfe1bbfaf13cfe8fffbb64d1efcf41e3af85ccafc3bebb13ff8f48b3d0dcc3cfc5b5adbef8fbde5db73bcfdedccee7916d4acaa1a693edc81794a249c7ea9435efca5fba3e9ccfc839aeeead2c38c853796dc13ecbae8af00fc7fffeca4368cc1bcdc2e75f4fe88845c7db6cda266620cb9b1ae8abdadda4de8f221cfbd5d3cde76cce9ecaf93cc6dcb0ae3caea76da97dc876b8dd01fc8a703c6b2146c032e5be26df0dca0c5d0a953667c3ea67a08e6c4633878330d2caaca3e4e8b8e07efc67bfcf3945acfaffe011eabdbb2af5feb3da681a09041e8ccabb2abe094db6b0171ddedafe9cdea72a3ecae34c6f8e97b77f8961eaeb16bff9117946cbddfb236b7c066a4bbbcabc7cef13493b9bb828f5e7f34ce0387fb6e15ade89ddf8feffcb45476f20c21db85ab957fe98a2a8bb2f78266e48a91eb5f6a1079d9f1de9b726ba8ebb5f61ee5ded3e338c3b19ca1fb97f3d371acb9898fd6bae6cad3aaba2fce0aaa5cf7b44fd1054e0dfb26992ddb4220afb167463dc73aadbeffab58ef6ea33d4aab47e1ddefa7ddefaf744bd9638fc77a6abe39efac7a5a1ad9c30cf453668e8a15e8b02296ce6693abaff0d251084af3d3bafdaebfb1f1e0f617ca41ee0ea7c79f5c1b0e245efd81d16acd9f2bc7ebcfb3bbfac28908f7ad44b0de2a97dddad6398b1d31fece1dfca2b3f519334dd01c8a9f34a2cb9a4c7e493eae9e11a8ffc2e7747c56341b9c45bac253bcdfe8f28af1d5daeae19bbf8afcba7ca1c20eedefc1de223e6a8fbeda11af36ab10b08ceeb3223fc415a8aefba2c2e4ccb789b15ef5e31a823e3cbeaf04c48b98ab32e390da577fec2fa8bfb7d8a3efa5f90c68ffbcbc64e8fccefd4db75e9dff78baa6c8c6ac15bfe9e7bca8b2ef14a48dfaed511dd4a0ca1c4f74c1706e7ceb9edb584536cccdddf22a2dabf54f62dc5afdab64fcc1ebcde199fb4fcb4bae0d6daee54b3a3f4ae4af2fd33b13c27f3f97bbef0f6ee8218ef778c3bee130cfdd4ba33bd0a8db1659d69b0c741dcc3761330dacea70e4b6583bbcbbb4cdd13fd6c97d44543d9cbaca08fffe98df09ffffb732dcac6b4dcdafac0daeee0b6ab7b47a738a8df5d769fce9b4bac33135f793d9a476feaa65727b121a1d37cff8f370c5af086bc6b46e65aadcb9bbcbc066e4af1eb79c14c1b0c2c45a75f8ddb666c3967a299d0c5ac6e941cad0f01fd5bfecaa1be2fefcf19bba5d9331c54ea6bb1cdc051ecd762b876b775ef5bbc4ff6ec6ed09ba0ff386d4ef7f77aeceecc6dafdaf36cbab57ef0b3eb8a3aaffd72fa0bccdafaadbfc0bf90cffab9b02b094f0e8fc354d8caef66bbfebcd9eb03ec3dc1cbfecffad6edcb376f2e39c0dcdcbb08983aecb7bcdba61d7a43fcdaeeca2d45a4fdcc502a3ed19d7c8de028dd918874aef509adfd113afc7630900deca93de023bfaaacafb13fc28c35aadc9cc6c4cc85f02bbbd5bcb181cbdeecdc20be26fdd8c6acbfbfb1ba0b1f21e5ef1a8acb1b9c41eb4c8a4a2ecd8296dd62a0cc6c00e8cf124fd6e0c31ee63a7c068cd73db676f69d63652d9e8fdb7abdda6e6b6bbe635e5c9d5dbd8f93c6d2e1dfcd6494f5aefdb0608a6b3eecec11af63da9feacc77277bdedf4cc2f04908fa2e33aa3efcea30f94a63c3bb56bb494a6e5ecb17bd3ddbc76ba3db8ecf0feebdc5be94b0a79b8c85cc5d5ddaffdbae1edea1bfe1addfc5ca87ac7efd2a7d1db150acbee21f555de8cdac19bcaccde8bb3bbb7035e5a0d1c7edfea089e328ef8b0d614fe7f57d5cef094a97b9fc6fd211e97b7aa0beaccefdde1e80db9f18a59d4761bdaac34eca6c4bd7dcadf4c9c937c13cfbfe24ebfe82bef5b10f123bedb761a3ee96d247c2532bec66536fde332b0d62a0d13c3def3ab51e3e5e18f53ee06c48ebaa9302c274afe021caa1260b15ade3ecda6263ce37b5e2ede0c3eb043debff57212a2db2647bd4d6bc4027d2af3a488cf6d34df741b0ba448b36a8a6dfb9b3095bc7f13efcb42c92b5dc5e6ef2ca5b01acc0017b67ec7cfa8fee2b2bde0cb3baa1c18159edfd654977ae6afcff372e752fd032ba8e44e0b7be17ceaaabc7bdbbfe9f808daefc2d3db685e5ff7c50bf8289f2665da8409a4b312769629b8d19c02a7d379b260b3ecd771e6a7206caf5d5c9cd7fd4c8a1bed5db0b2fda8c9fe2734ecf656d0b92c87a5abadcb8f0ce8d559f7ae29efcc6d095f4aaff7a5ec7dbd5f73c84ec65aaf4fa5ebd3f7e5cacf7631867c1aea3ec4fe2ab47daf30c250b2f27c0de3753ca1cc0f9b8f38bafc4dd20dcef665aa3330a116744828da88eb5dfbbe2458b4dfdb77f07e1ddb2bc2ab88afa2d8f0dec6ebfe8ba45da27866d66b7ec2df85f4986742d82f2c302aa22ed722fba0cda3105b8ad84a3553c0dacd6d6f06efa0bbfe1bbcaca84c8adc047217aebb1e7f350aef9b5b71ac5f2f0ab2df0fc8baa04371c5ed363f5814adeac6efda6cfce0cdbd35acffbfbbb50ed181cb4bcecbf86bcac5e26d4bdcf13bfa97a4bcc1ed4eecdbe3bda42f24ec6beaa451ae66629bd3d162bea8a32aae81ff78c6d8d4a5a8ff6babbd1a0eaddeb2dfc4ce485335f27bc4a8f72e2681cd84fb37dca79bedc0fcf7dfafc6cd9b19afcd11c2d74f9de0ebdefd112cd0550d6143f4211c41e0e0552aafcf6cedfe3bee36eb37d40b75f3e2bf96adddbfdfaabcff2fd42de7df6f1dcc446d8ceff7b0ba0cd0ca7fcabfeddddbccbfa02faef728af4b23abe626fbc8c7d8a8dca5e5dfb0dfcf28af6a3e1d2baa4ba17bca54d901cbedcbd457cfefb4fa98d6d52c63addaaef9aaa670f78ecf28bf8f8ad64bd7fb88f3ceed27ff5b541ed0c6faa485bedefbb979cd16ae8a4d27222ac14dcce14a85bcbef1c8d28fefc760aa8a0ffdfedc5e32fc6aabcfeacdf3cf3f2a2dabb47e3ec6af9f4cbe399ad9e6df5a561d9dfd9e9835bc9ded628e85a0a2fe0e1dff5f5ad43e8cac01337dbd6e0cf619b886a73d487d770d107ab9e9eb2abb4c84f6ded10cdbdedd4dae27eaf2cb18c4847f8c3371c523f97dbd2efc3d65ebe619135b77ea7d13087b349f76e9deab9dd11ac46dd9bad419cef641535a112443efa3e0eecfef726cbefc5efad482cbcbcbea50fe72f053ddf686fbcd7ed2fcfe1dc015fb458a5ae2ec7f2caf783d23ffe116fe59a1cdbcaef68beeac2dc33abec19cb47c740cde8ebf230dfd9258e6adfef94c7668045ddbc0c8da1004ca9a10a773e3bfe6f19acae67ccbc0294fdfbc9cfef3337f6a48350b376ae56d73da8fe3a04b2d61b901e7dc3eff31bfce5db7ebaf87aecbaf2a6acfd21cbda520aacc4cdb47b4ff50ff344a52a5be31a61bccffdf4aca5c2a244bedd4ff02cfcf5d3156380a82fc0efd8504f94bdef2bddd71baeaeced03a52ecdea1bdbde2de4a2cece69d48edf2bee3a7f9ad66fe8eac3f12ddbcdcc7423f85495754d7dab41eaca58bb4ebdacdb1fafe46eaaf0fd1eddb4cfca39fdbf5d6d9babd3ed2b6138cf99a9eed8b48aa08cd48ad5dcea2aac1e7c7baf171dcecfcfa1dbe0dec877b10e2f530be8eaceea205c0490bbfcad6b0ddfaab776e18fcde0e895301b645ed6ccf0cfeee9ec5b86ea1baedbbadbd8133eb25fd71dbbbc7fb8ceffb2ebe2d4514ca0372eda63e70543daaeb9e806aacfef0bafe3d18dbbdf6f75f5dbeae3da2f8dbc7ec9a6aea855d42a0f5fe93aaabce77422a51cfefe31a40ff3ecbdb40ea2c9deed4b0ab4ba05f93b7cdb2618ebd9e64ed879cffbcc62cfddd5acdc1421adef7d044da9fdbdb03ca6704b6bee4fd267f2dbc5acfc87054dd74ee02fbc5b4ccaf90698cc2619c54239c2fd668d1a12bcc9eaeb0efc9b8c7d4d1adfbefa8ca5ee40ecaeb7afab52338037fd6fec1c74a68ef0e74efbbe7ae1efaea19f4aec79dabdb472ae0ea87ef2fa59e4b2bb4ace7f4a0ce8a7dcbc7bdef43ac2c8d74a76dfc20f4a5c7be8c38b9f7c9d9d1e1a95a0bff6dd2213d3f1f898bfbe7be2b5f2c6ddba884ca24a60ffedd0e9cefcfac4ffef89babf3aede783c565cdafcd6cf8ef17ad0ddd434ec8bfdbefcacf6aaec3f2fff1bf4bc26f42bb3d91cbed60a9fdedfcd91a2e3fdd3bbebaeeffad86edd6492d7cd1adbea47451d7fd270ea50c80ea6812112bc5bb1f9711be7a53ab32607b2bafaf564b1c5f1de0d4039f20c6fc67a5efac367a4dfa3e45edfe7561ddeb5ef7ecfcabccbe681ca62cb48faaea2c98f526ba15ef51aaecb2edaaac28ec5e8eb0cbfaacccc87bfc1433dee045ac2bd55bfb6cccccd236e722d5ac75ce3f682f7f87bd892e4edfbabef748bda9148ecac3bedff2bb023e76d03f9d507019ed06499eed0d353d2b4496bae4e41c92818fcfcdb1ed0bfb9f28bb49b6ebb5ac9ff8a46b694912f00cbc92266ba58a55968d5d404e058fdaf2efebccf4da6e1e1deabd910dfd5aa99f83501fbbb2fc145bc4aeefebb1afbdbd2b0b23dffd6db14fcf6a98160fa2ca69944428bde5cfa01b0d17fddfeb23116886ce3fea37868f5ba944f7ecc0d7d7df50ec6efb6efbf4edea0abd9940ad4c3af4afa568e50b3a2b4c24dbf1f81dd06221eec86aad2cafdc2aed2f2ca18310f7ace0adaec8da05124874095a1da54d6d2fde6e6fdd9c930fac9f71fae95a57bcf52e25a48f985dc2170ebbff76fd5c1bbc728f3dc2da27de173cee77db7f7adec0b9dce4c9ebef02097d6cc8da300d14caacac659dafdcee845fd0eb3e8deb895d7dd3abdfce3caf3656f0dcde0ebe47daa1ea593475a9edcc31583ae2e9c4356b357de1cfb8ba0d78f23caea5dffd664f117c8433064fb99eccd7be0cfb89adbfecc6d0e3ff0a2dda42daf11a363a43eff9c34a8ecbbeaa3c69b98dbf6b3fbcb68a5076e2a76ab46a00ffc0e07025fc4cef8b4b21f21f23610f909dccbaa61ad0af03cfb0cee9d0fedfcf02748fb2bdedf13b4da5ed3c0fabadddbb7f6f178004cd2f9096166d1ad3add4f8dcae646b7bfee74fa8cb7a2b94be1ffd52721ae23bb4571adebba99d5aa5b89f437cacc5040bcadcbedc14f2464dcb01345ac8fcfc7abfacd9afd0dc3719fab4cbbae4ceec6fe5e6e84cf1a6adee72cf131ad7eafd1f4c1f5e0e6cab4aeb7bd0607f6e0e5baae01c62d7c85cc644fb05f0f2e7bfc14d4361eb96e832bcaefec9ccccbbbb2effa87dbeeba7ecb2ddd49c71bbe119afed3c4d7cacf214297eacd58440a98633a6afd35fa6d7cfe292568dbb5db5ba55b48cdfa6ae9ef6c1d41024d8a4b1a0faa29a2ff613a10fd50bad1d3e968b40fb0aa388790098b9e24c26ebce9cec4a2baf9e1724b10ddd36b0492c9e8b0ccfa4c2ffde781ff4aa498ad7775c48e89660ced6dbbd9a4bed9f5a472fa5c0be019f5a1daae87c6f9dcaddba2582e3f6fabfdb67dbd3a0fce94f1ceaac333ae7ef5fc0a8a84ac36de6b3ed9caf46fce01ab3bd5c47e56ea5fb6ec3f1eb82dab9dffee24ad3a45a0debedd1dbdbfaadbaa0f5777eeebd44b89bdba45177abe7f6b99bab6b3b0fb1ef316369667ddbc5d0e67beea73775fe1bd8febb67dbd9edd6cdff43c3ca7645aba5d86e11db117a61ffab1e6d6c35c502eff35d58dbeb7a1c051fa00db8d237dddcaeffae31255c2fbbabca2fb541da6f9a3fbe0e1a354a74a5fec1d4aecbcffa86dd8c3a6b068fcf0ffcefc4a0191db69ca1c9aebbb5abe7c4f4eb8bc54e692bcdf93e8f4d181eefade07c976aa95a7387c6d7bb971ec96eb633cad97189e2aacedacf2207ee3a4c6e94a848c09af17dbcbdbe3bb8c4baa8287abf1b08d42c4868e5bf6ddc33feba308e4aa1e9abc3fd7cfc75fad65eb59b1da08db33cf05d5ede1bfb98bd8de88e37fc6653ef43cca9bcfa8c3b1cdecfb74d4c0e4b4cc69d6df3e0adeade4e2eb4c39f1cf4f2a1bffa27f3b1debda7c7231abc6aec5d389ae68ad1f1a9bcc73daaa1e5c6bdf14b6c2f3dbeafc2be73caeb0fca4c48538bf47039aa1a9d1a64105fea9fd7bdfdda767163dc4aa7fa47cdbfecf3bd1c8c84aef13fd8ff6d5e4353eb91e02ba129d7f8362ddbeade0fcc7838c60dce964ebdaa9b376bab23b39901b32da6837e7145cd025eeb61a304fce1da8d5ec90faf2f8c6b86b51be82161db91efe90bf2fff8bddf64681c3fcc61f2d4833b85ebbc4c8bd8b2aae61bfd21411235d71730967ae762bde90ac9f68dc0c7fbba28fd9e1a6dc7a67ffabce7ec57db8242eecaea79b00e8abbe2f7cb88f8c2ed71af0bcfeed279e8d94de582044e39ec87dca337cce68fbec558a6caf9366a2cd02aed1a1723b6caff6defedb006a00375e77fe205fe90ef73e6b18dcfafe645f5e9915ff4fb17ccdfca2f58291f5ffc258f66fdb5585e79222ddba6ce77ddf58114e85d0c66ddcabda5dd197ded01a3f6352def0f4ddabe0fa95e0d4bdfccdaccda3a948dfb19bfbcbcf9e9bccc003db64ef7dddd2253b239ebf2bed4ed580bd033c0fc55c6aa56ccd1651ec056e7e7bddb2ec42ca9da039cc0a397b2adaf0d9b13bc4ca5bcf26ab6a3ab5944fc563ba6d493eca8cdcbd1cc0eae45f1cafb57d059e7accd7cf49cd9efbffbd0ff431cab5baafb2714be5bc9ad622dcac0fac3abed804ee6f3051d35d6a58ae0dbcbe359bad67d5c9feba9efcfeadd51bafe1c3a3c541aa7bba51de4cba6e74aecf40ee07f509acef85db5dad6be0e3ad9c43ec19badf1fb879eb0cc0e8979c06f0ad40f1bdecc7720afee5c5258f10ddc0365504e66e9bded1facbabddfdc6abe0add1a31daaebeaed8ecedcd2fcef5fcc4c34dbdf387aad365dec0087cb0c987fa3543e25eccf7bec46a1cae24b66cfc987de2ceff2fe3d0bda1cadd4fb64610d3fb9e5ba345dd3337affa324d93c68eebf19de69ce5db4fd3aa95960fffc0dceecd96d04291c898ddd6a1eab388b9cd762cb0dacfaef83734bfbe0a3e5eb69cd63d834d4c92b00761fbebdd8c8e7281ad7ccf409aee7ccecbf3d1ac856115f1ada932547ef9ce85bcacad02dabf95ce4d4bbddaf8eb1f210f7b2c9e67daa0d81acefdd641a3ab0ecb1fdbc46488aee2bd582b831fe4dadeee4f6bf5fa6bac55454cca3e06edca197fcc8bb8e49dfdde1fcddd574f9e0fee1e66dfdc3f91f844ddefcdb3a9f452deeedc71f9dbbe4d19d0f1b9fcedf9a26cff71b05b942b24ddcfb178a1be3beba1d1e3010afd0f6cf8004eb5dbaa2b04d6aaceae505bdfa7504fddfec5ad6e48f8dce6e1003efd40dafefc1dee6ab9043cfb2f238bdf61e84adff9d6fbc68d9eca6bff7badb430af62e7fbf18b64f3a355affe9d28ffad0560305ebaaaf49e242567a2b47741dfffdda1dfcbccb790deaba3f30b4e447bf2703131dfd887bed1c6f3bcd0f4a2f807d17f89dd4130ed76aaecff700d6cb9cedb55b9fa0c8b86aeac804d88dc0ea42a9111efb9937d70fabe6ebd928893bbda6f7fcbe14db74cc07897b3605fec3459d2fa8fe13995cef09650a90e8ee14a8fcc2ef63f4ebdfffc372aed4847d684ad79dcec3ce2f8b3230e927c2dfe1ee01d987986f8bd48fda890cecadc4cbfc4565cd984dbcd21b3d44e8100a63d346632c7bc433b3eadf4bffc14b95be4f8fdfaaba31d010ed14df496167bbd5bc5abcec9551f38bb0ebbea126fed3a6ad31abbc98ce196d2a693cdd79c44909c406cfe8bccdcdeaa9fcdbb5b1f9ce7545a15f55f1fbcb35cbda56cae493f2daec8dea33ada56c4a6aa6ccf96f4db7fb6b35eeafcd2190fd1cddffc4c40194e0adff928ab89b1026ffce4c6aebc2e7fa5be19dc6d9ad3ef1f68d6bc22d46ed8aef60768f7b90a3234dc174c5c3b7694adcbfb273bdcfc5fad609dfaf7a99a9337defb0fa36cf09ccbd8de3f099dc07110ca2f8a74d7e2cdc67cbfe7ccfdaec7c2cebc66179f98ca793c8fddaaebce58edb1f8cbfa07bda6bf5f2d5bade395d6fbcd897dbefeebcb521ed4da90ce551dce57b552cdab0193ea1fc3b3ff1666db80b226d1e5c90ad2e4bff1cfed9a240c1188cae6627b889baeef2bbbdae72ab3adcbea16a14afb95acaaa8d304acb16c7bdc9e10addaae81f0fbf3005dfa02effbc72ce0e2c597803c9ddc64a18c0b6fb5b2be63cbbc8540bd5c56278fca7a4c017c89f57658bcd0089daac8ec84a499a6cb1f3cfec874f22b46057e773e24da1ead9cefbda9e9d08f8b7db9c45fa5ccd0ee956bcabce52dae07b9f7b9f7aaceb3971207ada3e4350ce7813b8ee3fc7dde2b4a62b911aa2bf25f1c2f4c7ad7a2be34c9b0a06a7daed124c4e2b22cdc115ffa91c3eff25d2ab6f61d3776bcc81ffbbe04aeb96175cb1dddfa9c84a7a9eef3ff7edcebb1e12afae66a85eaba5b9ef15bfd0cbdd60fe8dbf7dbf17df906caad7fc6a9cedafb8f2bd11f4eb37f88e07f8da43fffab03fba7dfce0d452ead84fdcdd4dacc28ca246a0d0fcdd1c7d85db8a36086aaeee2edb9b4ab9cabe14ede716deaef6c4f0e701b4ba85fe0b6769e52bbbdec72a3afd6e6fe040474b15a5dcfb38eafb69cb7e9caeec3bdc9deabd4f5aadf1603bc1adafee097cb9b3f4dfd540ac7ef6f1ca46aecdca942fc0c9e775f39a5f75fb7f1c0fcfeb7ea0d17bc180c355cfd2ecffad8ed0d0423a462b3cd6edbdf3f19fed4ad05999fc92f27bb0f1908878a3f5acac1aaf56ac3e3f233fbc75ff0fb0d6e81e22c4bdee4ba0ce9dc83334c4c9c9ee8650984c68df2af0d15fd6cde11aa85d9d55de0d0b446dfccbdf4dfce71aac4fafb9d0ee236d858928f28cfe4558c77c0a34f0fcd1ebdeeefe3034cbada5edadaab77f57b823bf7c23ea4afcbb9e9ed86aabdc985c967aa0026fea9df87ac3c99fce87bd9aaa5ea993d7d50b9af4c132caad98adb244b3c2df00cfdcba551c2a09df4efbab7cef3f264e49ea6ac5645dffc4077fdf854747bbcd7108638faaf198a7fca2bc24ef2abef429b0abdf592f1ee0ab3e92bd316b84f0c20f8fb33fe7ee7bb25dfea0d5f2bf440fbcaf4edaefcd6caf87faffeccedcac1faf7c6de7da0f56c314fabbdaa6acf1967b397ac509b33645b76ece1ea9ca41c68ae59a84b7be515fceefbd0cfbdb3ed7ed5ede4c7e79b1b2c7a7131cbef73ed8c5702ebbd241abea2afb8ce5fd4a435babaae81a74a23b1f545858aeceff66e7ccd7e49f0d31ffc2b92a4b8cb4aff5f290c25b8f0d8b7871af7b5e34e02b89aabe9ecd00dcaebcb6bbdc1e7adaa895527aa47c5a2a1dc0a27ba4ba4cedaa50fdecbbc0ee730ff30e78c44c5fdcfeccb6b2e25e9ebac07e32283addbabe41dcd1e4ebdff041a34b7c031dd9e1cdbbedfbeceb571959e40ebf204dcc54429daba62ccaf800b598e8d0064df6b5849e6cfcd22d3aefc38fadc07cf7e9d7031cf8ae11bfadd1e18beaeacb55ff161f26ee41ce3a6cda461c3bcc2b0c163a0b2ec927b795039aeaeaab9be1e2ca9ce2a532f5cfbc2b13ddf00fbbf4ef87c075c99eb96cf45fac35ac88e1b22f6ecbfeced7efb8ac26a3eecfe76a13ebd5d4086b571c53174c6a89255c4baff22aee409f26ef27981c27b4b67ce267ceaeab31b7eab8adf0bba24f5eb2192a5bef0a8522ef6e1c66f2fce2fc4aff2f5b1ee4a7abbf3ebc09ccc06c231ead4b4b04f8ef8ddf59a34acafcc42b3a99bf1bd33e3ffed458bccb79736dcbd2e15e0bcad23c3dcdeeebdffcefbccaead2cafaafa188463ca5f8cebdfe0c505c0cc4ebedd8caffcff1abed174c61dfab59ab3ed0067ba2ad39d7def88a53bc8dccbbba7a4ba8ce1fcb822edcdf224fd586da537a442281a23a6f1baa4b21873aa5344b3aea20d782543aeaedd1cb9a680cfe1c208a48a17eac9cbabcff6807f4948324afaf2cbfa19e0ee1edddca279a9e0a0aa5d99a1bd5b128c9baf0f83d7400a13dd5c268c2ac3aadedd67f7fa59256b7edd4386ece0ec1d1f2983adb25e0a9b0b1aa3d32ddb9dcb26d58ceec2f02d39fb4e232cad0fcce37ebfbc922dc11519cf9925c1b0de1152546c8d714e40dd4b1c1e3fadbd5fec452bad5b2fe362d6d358faf5e9afb666dee831dbfae690c1ab76ec6f6eaff7e3ffc225cfb426aedafd6fbb37dfe371b84a8e60d55ed1d8c64ef4f96d832d3fa69fb4cabf6fcaf8fe66fbcbbc3fffae6a39647be37c8a1bd3e946afdf17b644b2dc34928c98aa4d50ec70acdbf5ec041ab5fe389ed6877f274dddbade41e7eb1d5d7998e7a6e1ea7aaffeb42a44aaf0ce7f9bfcb6b9ddfd2c34f7cbb75331afd751bb2a8ebcebeaae394b388cf1f70cffe97f131dbcd3ccf419a63acaec620e4be7aa8db8df33e928f45f5b942c1ba0bf2fd0a6de9b36c947b05efda13cffd94a5c8b1b2c8ab1adfbb44d7affbacaf5f9d6f6e15b2df90ce3c0f9f53be10e69fe627a4d3ab4d79c99cf75fecdb3cc2f7cbdaa24c84cc07db5a21cbad482a2faffe24bdd2f0ace504436bb68edc30ae60efb3534baafed9ecd4112f1128c4216ae2551df29ba7158fcc278b19609cbcff0ae6daccd1b8cd1ccc3761ed8a6facd1dbf2cc72fb991afe70adbadf419ee1aedebc93b24bd28e2fefe2a2cfac38e78ac582cd60ed83e8f2de54dfadb3a52d4aaafaf3d3addbe13fa337a4d0f050eec96ce103aec5babdece9090e70d2b059da2aecabf9b79fb55ab65aab0bcd0d6aca7acdb665f04551b85ab14a080dbb40fffb69ace5ff0dfe3e5a79b3fadac524e910eadc1eca51459d6da1cef8d131fa95baead63af5e754ece737ec3d29e49d1becce4d62e9cc9ddcd753db0aacff5a9a4dd5b0ae8ce8c14bcfbce75a3be2d0f902cc3afd7b76db65bf4aab463643bff99dfb225dcceb71ed400de2d2eea4b7ddf5f5fadfff4742d9ccb81c4ab2b38f8fe3ad5abb8e3a31e28e6e691b74b51dfb40b99c8dccb3a63d3b21f1ab307354eebb0abe5cf45d2cd6eacb13f3c63a6aeab38f21ceeb78b85ae2c8f3f140336bc5eef6e62f4b55aaae9c6852d31739d8af9eed12a76387aa0826d9641eb1ccdb99cbec3dc3db4bfa69ab64713ce640e2db9524dd33ff6d2b82fc57a36f372ff6a637f3db1b7aad8aef38e8a2d4adb25df3c951dce141bee729ded992efb173ac25916be3cca2df3a05c4d0cf0bd5b05d1b0cf768addce3732e25b1e87ec79077e4bd6ea055e5c0f1c46d4dfa521afc7cd2fab9aa926d4fd60dfe5b79df25f7afff9b8d65bdac73ffdec4e0a69f66156bd51fdf42ecfdbcd67b5eba9dc433ed7dba89be4c3fe4fdd61ceebefe8278dfc16e7beb0820c1fbfed6c52ae23dcb736ee0982328b722464cd3b4d1e9906a27afa28b455eeb2b006e7fdff28e2e6cd9ff355f0dadc6e62ebfb6d35f2adbffab0dfc20be860c3ab70dccde11a801fe1cc9aac73b6d2abaf2c67fa265adfe3cc2bb7dac79aaa20f3df49b199db58abdf14e58ca7ab7ac07317d2fcf20f1d7bf8a2cbd3de6c9caf49e6f9e445abefc92d6b3edb6fbac9f75b6c0975bf9afdade5acbbeadbabd4aa017dc9de9d0d6ee7e5bc091924428bec8a6bcca2409b1afb68d2db804ce7a1eb9ef52bf0a6bab8e5bfbdcbeaaff68e5fdd2e3c4a04a542eafbcddda63eaf27d22b1b87b8b03ade75a7feeb2335cbbc77cacfcbf7a6ef4fef2db3eed8b697e5e06aca8d6a597ceef00acab7aaeaeac39c6bddd856b570eb62cb9103f2fadc5f2f31fdaefccdb57d5f36edacfbcbafbc9fb3c750ca95e882a5dfb9b00cddfcfbc54f5f9acf2f05f9c96baf3338d9fecc6fdeed239088f96390b91c1b44d6cd30beea87e429c432cb59fa1c3cac7c33f5f4d03bad2d5e27b2dba18bc37d9d687e650e4abbb4bd08307f06762a89a37a16ceba722cabe6fcfecc424acee6f8c2ef4b027010cdcfdb85afc8f41fdddfbdf9cf515cda3f7e9ccb1afba946f5267b0fcfa1d2eb12e4d1af40d661eac4cabdfba61b755c1cc0cbcda6e5cfde791fcb4b92e029ddc29abd6cc1ab955bfbdbc1cd04df5576810948eb4d76aaffd47ceae811ddb8dca2aa45c310ed9c25162c8ba0b7ab4f62b8c9edfac521e62bc8b4af88efc81be2facbdc438be8cfccde557ce3ab6adfeee56d6ac629cca87dafb2dd3cd8d6ededfbbef5e7533211afdad36d4faff3e0bd3bd97b41667fcfaf5fe8bdcfe93190d31e0abd6eec052c92520a962118e2ebc6017cd87fdaaa2ed8792cec40cb5608cf40fa8ba09dcec23d0d8ecdd08d7a8c1d2bc697dac9fc0513b30c585fffcfd77c3e6fbbad5c64cd38ee42cccf530edc3f0bb7fa7efb7d5a1d1cb5c497f4a4986febcfbaeef69b3ae05c282a45fe0ff1ca4dffc1a3b1dddd1a53cfd5a79b9ae62ddaebecc995ef5ade23691f8312a1c9f2176abda4ae8edba49e1e48caa31d7962bdda7ed2c7ff4bf58ce57ccd9f3bcbf5ebe211fb8b1f0cbd2e5b1343b7a1e2e34fad6dfadfb84417b13f993e91daadbb8f0dca76aff40e94be5acd294c7ffb1d77ebc4caa704fe0bf5868ba80bc5c7dc1fc260635c96ceea6beeea8d4ff0c1ddd6fe24fded9cadcca5db8e223bc7ca4ac1bb80dd6edd2aa4b0a20257ac5d9d5e1c3ffbf87d2e8c1744ea6061e3ef9aecdf55c48fdefc2bcff6319cebbcdabe751157be74abe66ecd3f3c939cdcd0cb88fca910a74df6c8fc6b48807eef5a2a34be217b5988f0da6df5114fcd52c6576eb7f3b0d9b8d4a8847deefbfcf4ec3cf2eff3fb6b0cc08d7db87ef9e9a7b8d76b2fbfebd546a26fc15dea6dc0cb6feaad34b0bc9bf8496adeefbaf2c0a86cd3f02b11a65f60acee041d87abef2f3bcfa01a06ae2295bbc02e7bbb9369d3fbbe147d0dfcbca367efbf4955cbf3b5d5ebe6b7f09d93e17ad8dce54e16e9ce8b95f9de0dd6582a9a35d5e9e00cbd7debdcafaf34ff7a25d18bf188dab605060d74e70cfb1ceedd18dafdf3a987e1278f0deff19bddab31e747b32ebf5d10ccaecc9a1bc4930dfaa76e6eccbc97c3defeb3ebd5240bd5aa86bd0a8a5d28b5fbece1a8b7d8e2e2fb8cc75cfc05fd97eafdaa61daea9d66bb7e089a2b2fdbeca04b1d1d9bdddfe0d0e0b7cff2bc12c2b9fd1615c80e3bca55e5dbcedca2f1ea65ebb7cdad1a69634b4c5c7ee752893e7545af2daa4c428a1ddc433516bad7914bf74a3a2f677802fdea38afdb77bb0dcfb4ddedaaaec80d9ea2ca3a7fd90deeeecafdffbb0cb77acce761ffe8bb4ff95bb7fdfd9eb31daea4ebfebd9a1aacaaadcef9d2bbf76e9bbe9e8198180eee0fa8abcdabd0375e7aded743b4035de8661068aa6fc13fcd1be7edf6f83d2d98f3804c553926cbcfef63daf131dea5c76dffa1e2c941ee27182d55cc10eb2df3acdbd33e41c2168ff5e3ebf1c7c4d2bd72311e2eb8087c57bdfbaacf5efc53bb9e6ebcfca5ccabdf8fdcbc946c7accb57c3be33b7fdb4fed4b2b81ca0abde6a2557c79aafedb4de59259b3c0f9779eaa9646a96d5808f6389fa3fb4a4169aeaccbbedb803673d35e6d3fbc1b66346bcc894e8beecbbfb88f5be05ab11dfbe6da7be2e271d190e47c36f56db1fa39fff5db44d9cdbad7e2f9406bf9a43cbeb9a7cfb162c2bad7f77c2d9bfed6307d2afada1402cdb0df6a5bc0e2af655fb102cff34afabd3a11c4cd9f015125ff04bcd1ea06bcddaedbb1fed6ba69c2aaf4634c0e8adfa02d73d04af849bfed278f1eadb6ec9fe26cbc4a8e69f44e4eefa4d8eeea4b3b8d94b241e3960c909a6ba1d8f4abb31cbeaf1321beafafaa8c126da47e6ad2a2ae6c79dffaf9dbf2c6f0f0e395afd0248c1bdb9f3bbbe4841c1f3589d906fa82deceef62ae8fb9952cac1b4eac99f5e1dbfdbdca21c9b6b7f7e25ccc8a2b7ce9dc2cde6607dabcb82e5dbfdf064de8b2b93ab785cc6bbdcafbe2ee7fb41066d8ef8a7d6e61bba979f36befe433afcadfdc85be0f526d980bbd9cf0bbbb40faeabdeac5f9b0decb1ec51da5e72d89290a5933bcb8b92cd738309bc9ef2effb643b54de300fc1ccfa7ffc13ff6ce8f87cfc246126c8f97d7fc1a0db572dee2eea377806bf08c2dec05cbe0d3c340e7dccae9796de6b7163ddac7efe5eec62ca8ebdd8bad5041cd8ed5aec1fa1ae48ae7db1ea37bbb2ddb7aedae0f4caaa4c48f22ae3957f2dec91b5ff6c1fa0feaa45e17eadbfc46bbd0cb9a77da0a1f2f4e7b2bec3a4d00c3c0c55dfb6deedba254406d27e1fb7faba1acbe6cc6dfe3d0ddb0b1e6edcd50ecbe56da59e9bd75befb76facbefa0dcde72acdef194a6c1b3aea4e9f5d2347aafe12fe4baf5318c3a9fd5f27f014cf0ccfedcd3d32f4a3af0fc784c2fcabddb0e9ecae3e0b48ee574e55e3e6a17d92b12ebdcc1b6cbfe71ae0cd02e9fd6a2d77c2a245eb0cef90dee0ac2aa6b422f69a87cbab5edc12db8a48df734a96b0b3e0c6772feaea12f87befe5ca5aea9e7a23df73c3073845c11ac5595cfa81ff9d2f4babe1fc82fa3ab6a20fe6643441397de2d4edee4838a812c63dfff9f7bdcefbf40c20e0e026d3f7b4befcc86a99f2a1ad6a73dffef4a74d124f3970fa78af5e19e690acfb7595b690fbb1d83a3e0f2feeccaed47451a99bde504c1abf8d0a36bffd0a2d7b051fc05dfeec82ed7fccb2dcbfffbabd9f9cfef5bfa2e2c5b7fbe1af8ee8b32ad3b8a7e7b0598b8dda06949d8f3dd9aa1fd5fa865cfbc0b1c2bedeb250df3f09deecc5ee65367df8f7c9eeee5bdaf251fffb05e10f3fd3bde3fd462dca3c8ce0a8fdae34ebe9812c4db23e51bcbbd1b9f53cd8d72e4b9cc15e79cacefa3ee4effd8ecfffbaaa141749ecadfccbe276aa9fa6dd6b1ab87ab4837bccfb2a4fcf4bfe9c3f0780c6f9f8b7bd6d812fe68d6aeac7dffaf8db8a85a45a2efc03b0eba8c3ab7edd9d191caa6b34ea7d45e9bebff43c18f868e71acdaff6be2be3c54b98ee47a16c10e4fcd5ba050ce9aaa50c57ec3ea592aaaf544ec6c2c8fdeccb3eb9bcb7cfea493cadaa5a7c44e061c58f8eb17bfa08a4dcc947d245ca09d43ce5f9f0a1c853ed3b5257cfcfb29dd5116ece5fc60baadbb9b37a55dec16ddfe2b9e11eee778bdaddbacbbcddb1fd0dec4dceccdaddc8b52ddbab92c2b73b8c6c4bb0c3df18ed9cfe03e169cb3bf90e7acada801bcae9ae84c913afa912851de811cae53cb5ecca2bdf11bf4ba8a82d10c653e2cfb3c50fe5ec25ed934156dbed11f37ed8bc3e6fed5c0f9540dcdfc1effb3cffc43ddbc394fc858bdbede4b9f431dc88f5dced31d14fbb902f9adaab02c219663fa8ebef97bd2fbe4e59b0fca3ddd8d988def23de6453f660a2eed74436d0a65dff2fbf6d3ab3a2fa7c7bbd8ce76cafc5a93686df1ccf3d30c1aecab544a0c25bea5bd8fdfcf72dba7e8cbea0af75fb39674ccf7eecc57e97894bcc0fea0f8c62b954bbb292d9c6ebc18a8f2d25cf4c645a2bc9eedbd68bdf90328cde89bd795a4b2c713b966dbb3164a59ef9c2e7c7fdce1fde1d258cb0cf27b0dce8ed4ef52ecffcb5fa2fcf354c8dfa6aa2e9ecc3aa3ea63dcd52a06a3732978a72a38d28d842c4bd9be06af9cdedf8218e7efed37ae38fc4572eac7d6eb2fdc8fd3520cbfaa845bb3d7fd715ff2d9c5fedfe9ba3dfca2aa41bcdabc18acc6d0eb50f22ac23ccd8911aa9750e26732da730c7ca9b8ebe440f77493aa09764c1bc156b5cefb8d7f2228dea0ee3edf5ec886a81cad57ec00be23fed3c4784d4bc0cdcf0ff8b0a27cdee0980eced60cfade29eebefd3f8ac25ee75d6cc37e499df3ef8a177e183fac1bebcbab3596c2fe87f3b5f8fbfec2657fc5f3ceb2850c772dad0bde75195949b770d03abffdae0ebcec369ab49ca1c1860e79f2e7c41e3dc8c71a601a37abfb932c11622cdebdb5fd3d4a5a31e60afb54def28f518d5fb9b5180602e20f3affbebfcb85ce60f3dcdaacdf5adfab167eedf3cbbd3d5caed8a83e4fe64d80adef39951e7bdf85ae6ab3e3d8a2cdb7cfb6f4e8cf9feacc4226e0667ec4bebae01d7b8d4c77f2ce396c6e19c4ecac58337948c3adff8cf0495b7bdb0bbbaaafaac9f90d6c207e8c65c15f6cda9d5f79dfea4ddb175f6bdfbbd1ac8bb4aba1c10c85f946f54e42c62dee4a2eaf2dc10b29ce60a6a46ebf4e8f1362bf3b1d445f32447866eddb695ac1ecaa6e49058d0fa70cabf77d1e5135f2ae198bd3fa040dedafe1b6ce4be4c0bd5ac6fb89c1552b076aac9cf9ed7ccfc28f0df009de130db5ed6018f733bd5ddcce88b8aa524e6dbcc905c796449e088cece75f11bbf0f240fbdcedffd1cc22a72de24ec60eacf7989a7dabf505939e3a0ae915e22ddcc05d2be031ccfaf3cab4f1ef1f95efc6bfc422b77be6dbade2e3da86ec137dc72bd9fcadf7ddf683c62bfd2c0fc35eebeb6aba6c8a2a1cf48a4f942c4a8ff2aea1a4c65facdfb904efce8dd4b7fbd08f3f487fecf9fcfb5d2eceb15ff1de11d21ce64cbae7a2c919e60c8fea9ad1bb79b6fc2dae5e6a5beb2dd677fcdd81f7be7cacafdfac318a4fccd61b5e0a4b1cb027cbfaedacab15f4b3d296b48f4cb8afbfbdd3e5899cfaf38acfe5e7e6d1f0f647358a57f3c7c410cb5e35cacf75ea0cfe9e82ffd2839edcfa7df6a0c7c38cbbc7e93e5be4f9d8c1ca2b87863eafefe4da342d1472faa1dbfdb0cbf741ca617da2f89df1df6ddadeee10d38e09e1bfa71db74adcfcd9ed644ba50fb153dca4dced46ecd5d2dd2a825d0e877edee7ae8c43a0197facd6fdad0c3fface83aadb4fe9e6cfc2f70a6972a76edebbed61bf8498ba081e7f7edcf64e4638341aa8c2bffe0f64e789ee4fb547b2eefe786a8025dffbb9ef1fcdcab20ccd91c6c1d99ca6accb1ae0d168fe7def12072fbdaeaf91b68e4d47b1dcaebeb7cb7f9754b8d742a3cfb73b4f520e6ddeda40ecfbd03513fcd53daeb4f782df72ea5ac8c9abe5b33cfb344b607ddff0c91bd088109c5e77aadeff68cc3144eb506e466f5bede4b90cbcef70baaebafb8cebcffc8cbddd309f3db424edf0eb5aa38e9a9722a3d4ebac1fa9cdd7c2f3f8dc0142fa2269a82ea3f7e1bf0c6abef10dbfff5bee9f0dd83d0dd6bf7fd4c8ff2c1a193beb5b4ec3ffc3a00afcff0ebcb5fdbf8a9eae5442a946efc9e0287ae52b5ca96d1bcf305eb22deb9662041aab35aaa91f5dba98c7ecd82ffc1f2a3459213f7cab23759fefa7e8f7dafeca18d0cb6b10a77bb3bcaffd7a7be3fa67e828eb1b1b5229e02dae56159a6b80fba0fc3f7c1bed9c8f53e7a2fe9bffaf6dd6043ccbdec7bab66aac25e6b8fa3fdb5eb18ef9aa6e04a3c8b4cd504e0bf9ad10ad118e0a0efcdfa052a8a0c7bf5be6a21b981b70e0daa9ae35abf2fce418ca3e9ffac8d4bae8df6215d3eb0fea1facebfee1d6cba54bd61236ce3b0b82bd614decc6904a36a4a3cce1e0da4fd4cfd44fee743d41ce433b027258aa8eaaae9cf4fc3e5544cbea4dcede808dd729db39cab725bbb60a42f3e4ff0f7ad51e260af41cff59422cb164390ccaa9ebdced979adb17cbc8c27deb8ea144e14935bfee1cfe8ef3f3c85ede816f5e4ff4b37d3a8bf93bc34b0ce027e4ddcea959bebcdaaec6bd540cf2b5ffc3deae0a49fafa2ad3aaba8b5c3d2ea1ca1c2b3d9df344b650edeaed7439415472c05dfca3e96ac64b0cc3ac3cf4bf3e697a35eedb0abebf15dbaea37b8ef4a5c4ca5dbcc1a17aade50fbd83bdb531ee16516dbc6ca3cfaab1deaaaffcb68afdea29e44f210b67fe2068a02f2212eaca9c1cdc129a98bcbe7df1cb070e50ef0e425ee6a5face2aeacab73ab2cdb2f6ef0ba21bb490add5abfbfb99fa32a7cca9efdfdeee9aabe229884fccf2838cd96a9fe7ba199da7bde1bdabad552dba4adf48655ac3df52eda1df119f2dc3a9fefa3cb61d7dc0665c4b2bfcebdd5fc67dcc1b03e5f8ae10d96feff41b2d9dd0b691733cecbc9e71075800e77fa7ceaef401a1a836a6a75582a19579ef44d0c9cf1eedf6dab35eea41bbed8eedf8d6ad08ddfeb4cafdcb1a96b838f12f7e4fdaff4df48feefc0c0bf3c79179dbd3ed7de1dd55ccb55de906b11854b19bc8e6d1c8b0d0c8c20fdc2e62bc5e96dbf76ca3386cd1e8f99b8a5a4ea240e6aa77008bade3a118dcaca7dfc5d435e9fc9dd7fa1ce2cdfacd7cc57d07adbb0b6c9b9817581d987c0fc7b1d6d0a7a52baa9b18c39114fcc2e71a9583143a60d63ab1e32c0f96c0aa44ad9190de9120d2ad3bb2f41ab422c9bfe11df049aeafee11e8a7b87faed87ad21d8e21bcd90dc8acaabf8e3eebfdab8ca15d9f8729f11c00b66bbfddbd741b85bfaadf9d3d8affd4ea44be7f10faeb67dedccbd1e8b7b8122c7aedac8e74fba4caeac0bf58aca0abc4247fd3ade7edddfadbe0ea328214eb5d25b8fe8d65dff90ec7b45f6ccd9e7fd4dcfce2d5009f6b5b845cabcfa3b7a6fe5d0f9be4dcdd4b8de60ea7ed540b1e5039ccf31ab14d9bfaedbfc14bccf94c4aedf6a13a7b2c7bc320ee60a99c755c7f0dd1d1151d8ab4cbdd76e2e610fefd2ffe16c2db11fccc96cf8cacae7ce8c96bddb5a48a84123581431afc84dffefbbbd621c96a58fde0afcdcf2f187fee518a53e5847ab2dab5757e756b1a3e8f1aadb77fedd6b4ad201601b0fcbc5b41e7dfe7e5d4a668df6482dea4f9c6ad0c01eb02e9c580defa98afaf74c9d69e15bbbb20f89086decadfaaffd6ebd7c41cd1af1412b5a914a4b2d2d1b37d1f6996cbdccdce472fded28bcdbded48acf1e3eb42d7eaade8fdcda88adaca5f9317cbbd42caf2fcffc1adaa8f22a897b6bbefebecb2e718aad4f2d0c8f7ea6e1f3ed1faabd253dc6e2ceb2d11a214f5d1dbc44dc234a3ffff9ede3b9adc57d0ddc8ff0dd2d38cfeb00ebfd57d3d54b4add9fd1b8e4e4f0c15c7e8a08deef5bc02b3accfdeee84c9a6205d38d6d7eebeed10fe8999ebf4dbcc77ba6bc718319cfd20b48feb9b05fc3c0dc56ac03f8a2ef90aed0fa3d7bd2678cc17bd8f0ef57b6a332c3da7b335b90b0d507bff4ca6ffbbff4ab58df0d83de64d71b5ede09ebafa7e0bc5b43611bbffa2eaa38adc648d6e98cbdd3cefaf40abfc865e6ac42befdfa1df41deb5eaead7014aedabcb54a620ad6db3f6c2a3cb3dfaebac6f9ee2cf5dfc4a7ccde270ebca77be3aa2ccea0b980aa96a07851f30be7e53729bbac8ef7db7aabef93dbcfe24752b8e1cb4db285a25fa0ba2aeadb2eb0333f7ebe0bc103206d965a0dbfeadacdc7a26b8cb487ca6ee77abd7f011dc2de2fcdeb3eb2dd6ade6b4fbd79e25fd6b84dbbc0e926a9e42d35dc6f9071ae0e1984adbc20012c1bebb4abaaf91f24ed24d5ddc02523ccd9ca4c0cdc5bcfdf85a972fd6b23a9c0270e1244a9cfbd7b6b81db55a5da92efba1a2ac9185fe5ed5e7bdbe1eedadf2d129f7ce98c2dc59fab7906e2baea57ad1952dcdd18beddec34e2aa575aea508cb3bba9e17762c81cfccd53b9dabde3a4aeadcb2aee5e9bf55b8f752ace04e929fdfd3d1ccc96dd9a45196e1b6b2dfe2082abb8eae545ee6a2ae3e77a70ea9dd5cc3fad6e0503b9acaa945afdc85afc62f40e77ebdf5a6c6de35df6eb15e65a47cfecf3a1fffce5e59adc328cbd25267a3594d0f0558aace9236a4bd1caa5109d7b5c3590a01cbddb527ddb469deb3dd4d88ac1c8ab39f6d6762def2e7ab193edb7c1ccaaf6aadcded2f1ecf92c5f16a94fb160ffa1c8a4f6aeaed799db2379ded0c6b56a54af6dbe4b6aa91343ace9ef8a36ac71cefbda4aa14769fdc0d3befeecab36dd08abb3836afebcadbe35fc0eba0d2beae44dc7ee48fc52a19932e0b84f97ea49aa0a257eb7cbabdef29937eeeab91fc9f8184a1d0eca34aeaebccbb6cfdda3df4af9eebcaa0a539feafdbcab3dbdceabda676aeefed8cffad6bfbf05dfafcade32954dfde24a0646fcfde0bbceb1fa6edfffbfef56871caa0467f52e65edb8b9ee7b4678f14ac2e0e28f9dac9e89dc708a24854084ceb6bf58dcc121a7adce1fd1fedfbc01fc9dfddc3dba47ab9eceffc6df2220e2b0eada9efc8e40fabcd25f0dbcc767deac43289e152ffe24b643c7aa9ff7be67724daaa299cf7df094b6cbb6abf55eade33dd2e23f76fe9235fef562333aeb7f158ed2aefe019584d32c8711ccdcdb7a925c695ca6ec35d0c23892dcc8cf69290b22cea1ac697dc9ec86a35ffca907ed48ec03b1ef5f73dca6de4f92191e3ed1edf2728dbbc85b3676f2b2afdb0cdec17e4dfede300166ba620c06cfa31ebfd3b8ca13b6337f6058e98b31ebf0b2bcf2ba9cf2d6fdb44e0f1e9e7e9aa7f3f5ebf0aa434aaddcda30f46dab4e9324c61bd76e88dead4024fe68c6872f3ff7bbc1b9eeca6723ee45dd4eef91de61df0fe4eee1fa385ec869ae7e5f6c8d8ead668ae67eceb03a4dd701bf1ca56bcae4478adee966eab2bbedf751d7b8f04d7edffadbc62fbdcb9ca353feabed9eddeb0c6db5a10eeee1d8aeafa340d1df7278a2d1dbeaf9666ed1ee4ae5f4bbddd7f8cb311bcfb32ac80e46b7b9567752abffad506c95b9c1badea1e597bdadd45a8ff1add93ddeee6fbe15caa230a9eaaa4d57e8bbbe37cee1ab4ac3f4feda5a08bdb9dacced1f4abdd8caa8affa9e00b4efc6bf4c94c22dcfb6d4e5fdad9f142a9d78ea9f0fbddc5de3720b131aec918e3aaea9cdc2f1daed79ee3bb0dd3e434cb17f78f56dbaf7996f8c4e7f37a5f298b5fdcaff2a659d51fa36fbe6fb5f3c69c24cc5b74b2ec0b8ceaddfb8cdfcc8229844088acc88e65a7f2daaebe224ad96d2fa6cd6ad2afddf53a023e2eebf63ddaefdeff5a696cf3b1c04e3ed79da5e24db7f956d87ebd68f2e815844dd54b3b2a181738dfbe6ae3d8f16c3d76a75c30b33083aa81654a0e695a41a3fbdfef98a86b47daecbe7fca7bf50d57b1dbbee7ed7d3c6debe9d1e3eeb967c9bc7f25f583339fadfc51d526f8469bea633eac9dc241da5e6dbc5d9dd6f7ba50267c2a734773809cde16f1fee7079afafbb1459bbd20ebcb554a23f8584ab8b3ab013cd8bd0ccca3f1066d018404ffc0a76c7dffb3faa16b3aaf6419af89ef69ee6cbaa6a9d9cf9850b9ab67b773a56ba16fa258b9e4aa0adce4921e5cfedfb9f146891dc47cdab2e3246f0daa47fbd70d963e29bd0b5b6fa3ffa9e87cbb8ccea5fe04b457903c9fd610bcff87d91fcc53b4f414ffca8d26d2f7ba75cb1aa2353b304a902fea6e856fafcaee09ef0456cb87eef7887d09a2472dbcfcf6bf75bad2dfd7948ec23e7cacbb070ac1cc6ac91845dbc6aadc8f4ffe1e31a6c1fe63f0bc0d7dc43061b8daedae2fdd315185cc4080738c53bae55f827f188b8ef9e0ff84aafbffcab25231ebfc0dcb2ecceb7aed44c75aabcb32488ffd5c5d1d9bc9f433f3e6c3eabbfd111ed5d4eef9fabf341d571a71d6c70cf69f2cec01ff345d1cbcf7cbed38f3ce59a13ac6cd1efbe65f711cba24b3a5f190b21ee37e5e9ca9b5ce0863dd59d8b9199feeb6d3db8dbd58eacb87ea288fff22791d6b892b124066bb88fb563535850cfb19bceeb1d9bdae139bbfeb85d0b279874228aaa25c9b9914bd98eefb6ee83eab666df2dffcca6abee58b5e4b37711a98bcf4db4a5563be13e4dcade7e7f38171eccf4a96a6510b9d3123a73ddf1c42dbcffa6498ecb3abf9facfced271ff6dc3b78dcdeece1ef3310fe199e02ede32fdafb3e0cb9d0ba06a542e6c3b71a4a209e23f1dcfca9bbfa5ffcf82b16bedeaf3cbdcaecb887eee8ecd08f132e57ebde3cf82f875b4013fee0aec399549177601bac38837e5ffcf35bcd1fe373cffc1c4679a60610cd4dd69e5a09b12fa3effe6ef67c923bfa7c2bceecfef9f190328a4d54b601bd3aa060cd21cd8c385da2bafeb9bbbaba74eced25ffa9cadd0d2ad5d32fb9ece569badacfeb595f1cbce2dc11fba389caca7aeedffed014f49f7c5dfed35eba9ea25dbb54dad3bcf1ac6dfc71d6415f35de1512b09cf1cb0273e3c4054410d8daa4bb93d8aa9cf6791e0a4eba803db270775d8519123b639fccef201dd0c3beccff0d3ae72abeabd5e95f52dfaf9a3bdec7e17ee921fc6935fa7555fbc2e7a05bff8bdcf5063d7b5edc3b8ffee39efa8ba6cc91e584dd098b8833f2dce3e4dfbbce7d0c31f9e70c1bcd8a3cb19d5ce8fce7542d6ce1756919c0b9bed46fa93caccbecbed8ed501cf0dfbefaab80f8bc0fa6eef1e4951fdb31463d82d48cbfbc929abc02ce13ca1cf8d0ec1fc88d8f1bbc94c0b9e3ed6e20e6c80d6bf06c2c8ce37a30920d1b96740889f72b0f26b2296af44383fedf26a7d0e639c8e5d7cac962f166d336c8c3ddd2ddefafc4ff8a73fc4da11daebbca2fcac86bac1f3870260b1a520d4d297ac22df60729e06ea2d03fd8f5b0d6649fa7ae2bb5c5cd2ef3aedfcc99ec5ed7acedc30b14af0beaacee58e28cefd3cb975da7df4207b278df3f767ff8927b3cd23783ad2bec11acedc1a6cb7b921751ba1f0eeb9c4160c39cbded3aaef77aef50d184835dcc5ad9d565a3eddaa0ac5fa1e8d34aadc9fff7e7fefd10c7f3c8caa0cae4220b5cef5ce5c59de3fb4483b2e0422afdea4fe6b622309ccef85dae5d9cb4bcfbcfe54d0311c5d90999cadc9bcdf61be0bdd479529b2c1eacd02f6b2f4f62c82ae2d1e2b3d9eac7cd00747ff8ceaf8bd077fcf1afdcfed05ae98b6be05f9acf1abf2da00ff7e7eec12b3c8dbb7a4cc55aefcfdc2e0adf2eabdb4ee47bbdbeefd8f19add88d4ce3fbb8eaef90d906acffdd5d394afe910870fe56ca6bb2dec361ffd50e2a280df38139cd122c8dadca2c3a9ebacd30bf3f1ed0ffe87baeeccab4d851d6fe2a6261e2ed3f0bac1c8833986e1cb28d4a2e3c81bf3cce4ba7bffafbd9d9db7ad04bed4a2da5c91dba8734990dbb2d3a194e324cf1f743ec1db0c5dacdda0a31af2b19dbbed8a8dcc0f7c5ccce9abffcfd9c0837e1c4da8facb19ecf62d0ed0d93be4e647eae8f39ba8fa693afacdcfdea4f46ee3b1fb05312eb52cda561ae9bf601fe1d562efdbb0cadfbd8baaaeacad8433cceeebead05ad53b32fef5e327dee5a34aa861ebaa9dc2a3a1ebb340ff9762f5ed7bf1fccc5b8d5535da5c5a4e3aa2dec9b59beeea90fbcc08db87df06dd4cdc7d582f0c0eba66e0c8d1afaf7c6bc4bc4cc9f08c30e662add5d3cf4d2ff41fdba8109d468cda5d8caae8567cfe313ebe721e9ec7c3b5333b0e6b6cffafa0c50fcec756ecd42e082e09a20fadb0703ae7d317488cfddacdfbd533e36a00cc89c1bd3724cec85637d5c1bb30ae52d878ef65ee5dd9cb46bbdedadfbecef8defee0583d64aeae32eccba5dd67bebbd93ea232075f625e984facdaaaeb0a3bd1edb5ee6afd5abaa4ef2b893ced39e948fd91e176548d6fdb0b01bdaa27bd7acb0e344fcb3e63a33e87e2edb3bd07414005ced37a3bd952aee5ce5dcddf9caaeebced344b4cd6cdf4cc3c33a679b67bd539c2108b25f5deaea964e3dcb3fcd9aaabbefd1bfe1de7a4b05dd9f5b63bf7bcceacdd766aef142a720a9c663cc839ade15401b72ea1908c37e7b6bcb168dcd2cfc3dadadcfe2cded8fcfb8de9cc1eff73eedfc29b63ca45471efccde89fbedff158bffab38d201ee4ceda6fe8cc5f76ca203c7de9a4ebca76f6eaf5a40f0ebeebefa05bda2a347e1451f4be0dc0d526abbcdcbeca5e873ade2faa5e54a09eaa43e203d77eadeba3cf8fd161fadf2c26b493c5d04ba4be6a307c6172a27ecf3aa09ea0e28bc53a8c55afb08bcff638cebdeecf48a88c1c8c2a352b9bfb53d2e28cd70c051fffbcf433e28067f63bbdafd7bbf129273ffd90e08ba2828ffad7ff8a5a1fae03252da8cd7ffa4fa46db5ba0b2796acdd4c5fdf311f0d7ad3140f732b4d0c583faffa72a3bbb5b91cb442c15fdae8d7f823fbbe384dbcea14c83efcc6ccebecd68af0c27e0829ddcb0a53b0811aedcec60d08ea7ea4ec88429bccf31677b4fcf73b2db6f4ea6de5d3aab79a782b414a11bbf54da2d412bbccf7fdb0f21f9b9aa0e4e1aeabf36ecc61fa4bfed1cb07e46612de1bf73cdac97d98e33eaad8488d610d852dd7ddb092ffddeb19f9de397add5deddbd77eefc3d6ba63c6fc7fb5df85fcb0a5decfca6fe1a1ce1ec9d8ebcffefc5d3a87c0acfc54c16389ea57ea857a6e8e8bbbbba7dff57fefa9e2b547f66106c28ec9d120de94b4aaac5116bc333cbd2b6fd345c30a2ec5f0bd0e344fa7f2e50faab8f4a941bd0cb09475312c21f26a8dd46ba86dcdedfbf3b76a86b4dee13e5e84ace0f15178c3c81cd0c100a537b2cf26ff6beffbbae36f0aadde36cfea0f5a9daed8d38f7facee9aac3d559ba0acdba3b053fefd31ab54154aaae71b6b6c7c5e4cb0aaa9e3ec299ba1ddda4e28d36faa8e7caa5ce4eec4b5d3cb38d83a94b0c75af6efff02292cdabfc7abdeb4e9cd511cb4bd486080e40c4cfebf1ced3a0de5cedab96c91cbf97faebddffdfa44a7f19f84bcd09018ae8ecedd02f3f0ab20818e3b4a08f71cfccce5bef15384be17eb65d0c4dd6cbb6acaf0f2efb58cc8cb1cee93bdb6d962bccaaceb6abea0c2a2a26debafbc1d8c83ededb5ca5455f10efe31735ba7cb88ecf46f4dc77dfbdfe58dacb994ea2d4bb74d06d1afcab8ebc5790f8ec9d9cbc8ccadd961dbd23b10f982fe1a52b9a6cc8bfeabc7b3c34f2dc8f7ed508d8fab44d3f89aa436942b4efde5b3f67dbac506a5b54d9a69fd1bad9ebe83acc4a666569ee3e4a82c0a921befc70b59cb78be00f31fda4a6ba89ab52cbab5befe3e56deaca58692a23dbcedee73175e6bbee72e6a6c3776cb81be4fb336bfd5ffe721660a58bbf81dde56e475a85c87eb97f165dc4ce5bbae6ee099f11daf43d8d35e1cf4bc30b2b5bccae1d533c580ecf1b7bb2eefb6ca8f5b405d3ef95ecccf5a054ac5c0d3dbabc987eea7575ebb1f000cce17258e5fdaf38afb98fd5ffddd14ca9f67b62c811e42c118bb7cce0bd0adcd5a3cfe7aeceadd6c5c5aa5a0f7d8dd3e37f939fdef8c1dc33ca14a5ed669bf53eab5dea64eefed1ec9cea6b5255c773bad3de3db42ee661deea90fdaf37a0dfdf6b55d15d82c98157be7edaa1baccfda5a1daba6fed5e0e05f556845384e9ac5f6a19ff1e2c8461ae11bbe1832efcdf92cdd5da3cddfe004d7287d389a2e2de52b9fbf926ee41f6fc116fcc5d2d6f078ac4bb1a31b6b6ceed98e26aab4f2875e07535419d28a5e3dd5d2cd104edd7685cf62dee3dfe2aebf097f76f938dfb6e1f84f99dacad7d84c1bc4a8491dcb99cdff8ff05edef9b6253f36298a705df4eee7ca6e52dfe5c81dfc3173fb9f969bfa56b4ae26dda7f3bbefc1cfdab9abacedc8dfc4ebafbf0fefbf07c8e3939feb4ed299e18b57fddbd9f8aa3ae5f28be5c0cc0cb8a2250ad2afd5a0fca411834eba3dbccbb4c17e2ebcdda1bd1d7da13cc7ec6289cec7bcc5d02d50d5e9a8abd3b87dd19d3def615ae1febaff132992bdcdac834aa6f79baf7df677bd8f3fa0ccf81cfd2f55204efea9dca829b80cb2bf4aa419fac1d998f20f70eadad3a4c5c7ab7fd4fed4cdf24d6912d7c9ba54c5aaed7ae3b4e1d85a6a9bf0aab5a6cf4aab17a1bdccfaddd552bb13aa674e69e93962e0dd6eaa1098a67a1939783aaacf6cce9feac6e62cf3c2dbdd1bc54f0eeca20dcde4fb651e1dac82eec3326de4410c7cddbceba2f42d6387838e69fef6c216ff9fcb6ee67cb9d6fdead79ecfddbaa6f6553e312de58ca6db83fa2b2fdadee8d9afeb0d4d179c640c626e9f38bddbf0cb50fe7ea02da34caed4e1dbf3a54aa9f1bb8e8d8f7dedcda546f5cff92ff00a50fff1a761e7b05a54eaeb4cdcbc014aadfbd0e5a5e722ccb3e385bca5ef54fa6a617722d5b8c783bef6c039f39d1db794b94dd87ee53adf6e30ea3ac64a10a08eecd64d2ff55c11c15bbaaf97d16c5d1a815c16eaa1a5ead84fddade697f5d50572637b09c3abe4400ab22e7f7cae55958f6c77f1b0e50aabde4f5c9d5966cfa572fcca64bb7e4dbc6e33e6fbb2fd4aafc6dd613a359efd1497f0a1bb5ddcac8baaeb25fc04cd4bb7bafe91deceb255b2f0f23fad924f86c4b29bcfdac793cbc7a2edce2cfeeaad255cfb6a653c6c95bede55ca51356bed0c63fc9bac31225b99cd699e0f4bcbe1fa3bf33dbd5d64e7f1aafddebffd1fad8efb5cd6b797b9fdde7fcbfa8e23eb90c6adc30af7291f054cee00fc8dcf9dd3e8c1bfbbdbac6d61ededf4f71bfdf330aec9df40484bb3038b1a1ea097e8f2dff1242b8afe039ddcad25e38406fef0a7e70a2f7d3d12fe82cb5a54ae8ca456ee51bcee3850d55ff64962f4cddeae7ee6d8a73a20065ff7eaa9ffbc28b35df8d0786bcf9bbf6e987b64edfb83b863471ffd3c6e028cdadadff2662aaef6dba9de67dcf29f32bfcda6a96e2c0667bf96ab90a3e0dbcc80fe5f5cc94201dd5c29d1c78505ad598a9ae0e527ecefad39eceff8d82fcd8ffe2d62bc322bfd0f40daf5d91fbdf99f4d53f95bf9e3e4fbf98dcde2a2d6fdfa719ded127ccfdecf1bca31adda8ac1be559ca10abf1ebfa09f44f3915cbcd8e9e9a1d4dc7d3e5032eab1d94968d5e5ac449756762d5127dd1df006c4a8a366c1cdc45c08fc0986e889afa652a8bfed0bbabaa3a4ff5254e4d409a807be0e80ee0142f690f0cf33dcaaff0d4f078334da53cbccfbc18a8fb22e798154310956938411ef9c5aeefeb1d12dbb6dc0bc7ad1cd3f8dbf25ec10ae4aeaab15e1965b648ea7e8ad8ffc33662e0cddce7e685aa940fdabddd86b9afa39ccdfeb3f4adfdfa6d8218515fac9e405fcdd8c7cbea2f4ee5c6fffda3cfcb5decf0c09fd4cdbf87a9f72bf5baaa3ffb746505f38c9d6889aa1f1c7cb63f3f3f329953ffcaddd9f0ed7fe32fefa023088036d2c632e70bb5cdebd6499626aaa76b87ad81d944d4dce23ab682bc3c361f5ce186bb4dd3eff92dbee55b019c654ff325466c8cf3a9186483f6ddd6dfb5f4f6d2039feaebbd4beefd684abe4f461640d5c5f1a1bfba8a91c2a2dadbb1d8a7d932b6eefed8ae82bad52ddac6464f141bb2dca9bb9de1becbdda521efcd9dfb0deb40cb02fb8e611bf8bbfdd3af813dc1d8682ad494ebeaef4cdd69edc3e2fc1ad76cdc223630fdd6acf77a40c47a24aa8cec6e24183f8816d588efdda4eb4aab5cbb1d8b5ec8ca34c470e6b26f26ebf7adf065e7fdeb1c1ecce359cdd7bbda1eb2d52ddaebb00cae323ebbbc04fd4a2c13b3dc0644dfacdae7bb62e1f5a158dfdfef4c4dd83c8da8b0adc1fdbc0eb05cc903becece082e907eedee574b760da9c1bb32e6d8af7e7adc7d800fb245ebf5ab04acd7e6d142ee6b0ebe78dc5f0ffe3fa4c7940eea5b9e06a3f8dfacc036ea66ed1ba5605c4b1b4075a54c852ce9912f9aed88cfeca7bd90e80efd3ce98627a233ce44ee56ad62e9e25fa0e2b8d1ab3f8579dbc47763ae138db4f190df1ed4dde7beb0b6a0dc2b20cfb3f7c9bcefd4b3fc158dcb3adb033123ccbdfdd3bb82ce27acf453da9aa1bf47df278b2f0289dbb876ba70cdaaa5207cf4dd267cec783bcd8d7cbd8fc62b4a0c3b2cad94dad8c1efaaed13cad639ceeffff860626fe836be4adfc6f667ca5bda34fbe74e5c36acd5c0fe3f624ccd27a70bed404243bf41beaadb4eef7d5eaa0eeb24bccdbad2f2513c8d08dbbd9f0da52e7ff0f7aca7da106de3ee9c2314f8f9161ec0cd5e0edae4f9dd4efe1bbf8cae18cbd90f12d0d787f8b446abef1d7567cf6193eb47eeaebd51cab93eab1a1da8172ffe768bcc355d97184efb0dbad7c91deacefd3a04c7b29aacbfcf0f03fc22d0f10bdbcfebcdc0993e1eb3208ac201a72029baedfdf9f68cbdc6310d3dad0d0acc774cc77de627dd9cd7cbfae4f7af3dad08fa5d20a8b3b41f8ead7cf5f2bce4cdd6d1daafdf5e2efd317abc94e6bea6dd8fd8b829e6ce2f4eb698bc26730febcc08ba83e413e9dacefd2ca48ddf39c17b3a3a1f6dbb0de8e96c394a281eaef6abdc3e4d7c594afc6f649b25df03aee61d7c90aab9fcaf3c41bd5fb4b7115ea1545ebf3d4a78ce2cc7dcdc4d730ad9f9aa7bc8f11ca5fdfa0ded8fabfd1d3cf5ee7cab3e9c8d2f53b6acb5dbb5ed88a7da1b8421926e57cf9a5c68aea5c5ac7ea7d00afe2a4bb4f5ecee11cf2d3e7d4fb3243969da441b6ff5ef3ad8eedefccbaa91cea73a6b808879de7fe2edbfd5afeefc2e7f3e68c1de1aa8d6ad3e1d6be2e48067d1da9ba9dd4cfb4efdebfeb8d0e9129bcb4ecbd8eb3cbcdefbea299beff1dfe36a0da4bfd4fd6ddcdd2c1f77a167ab1c0d3f4e0121324aa4e3a8f42e38d8b3cb2dee1bfbfbde6ed9441f7c10aac9a80fe4daeadae49dda18caf2f3fbc482eeac8cfeab7b3e7a6bba8fcde74f7dafe5e27a90fbaafeefbccac0bdef65a02b4cdafa394cac3e0dde31aad4cc0ddcfe9a2362e9edd2c9ae2be91767d4defdefef4a38d6ee07bd3fe06834e5c804cc3bb2bce2a0aefca7ac49a41d65cadbab78a90225ae6edf63bd713ed93c0ab7d35d8d00623494ca08eccb9171229c1cd3d1806d25157de19a0d1c53b3dfb9aed2e3f8e5d0e78bd91dfbdbb57ece8fcb7c65e56b30fb0b75acc4dc3c0bba809b96bbbd808a7a1c0fd5b9afc172134eceba0eedfa4a70ccecc3fc531b7d9325e34adb93bd7da26ca11ad4abe2c66c42b0d3cbc8ef455aebccc30cbfd3dff0a5693d38bfa4f23ecebf5e42ba8cc86decbbdabc7e833bae03ea1d567f0fabf0a0c54994af7cc80dcf684722f1bfa7a77e2b16ae6baafef4fef92eae55ebbf36aa0f404a1fdfbd1cd7d2752b6f6eeac4cb354f92735b9ca5e8cc8bcb03ac894aaacf97ead12fbecc5c423d8a86b4f41928fd537a2ecbe57d691ede7d0b8a3db6f70abbcef7f6ebf1cdc3434210181dec41bf5be76cfc52464f6bebef6ad168ae204ec06ead1e6e5dc7cecf21656bbcce8a9c9f6d5be7a1cd656c21628b6ceb28d3d65b5d8afeb7ecf04fbeeadff1dd4ba1c922ebb829ebebf5da85c1bbeb5565125ed4a6c36fa491f1bd42aa1fed8d1882a5b01af1ffb28c87a3349a0df1bac1bab6aeefdefc9f34debb16acefc1bee058fcbaa0d5138cbc54e7dbe7d766dcda34d9a51eeec89aadaa6aa2f75a75abce7ad0bea22b7b14b9a8efae9aa0088dbce0f321c70ccb1c6afe86d58dffa3dfad1c1aa9be035aeaa0ffafc0b68ffb6e9a6944ca46debada27ebe4bceafac44afc5d31af04cdeaac9c2c918beefb3c1bcc8bd8ae2ab32cc99ff4b37ac7a6ecd67551aae5f02cd58ff5eb543a907224ea4e73af32e837cbbeaa6bbd06a2ec9bf7c59828fe21d4faf2aece37fa09d3bba8274bf7d2bfcb71feefdebaffcfe0cdb2d942e1dd9b3d11ed6ffd66c87288f68ab651de675e28ccbea33b10de6ac405305772d616fca9e4e16e7cc522e09f14831d26c4fdaeac1f9fbeef6fd4e7cf7eda2caecdf6351af7b37ce070d9b2660b861509ee63dea3c38e71ef9b10ae28a93afdf26cf7bde48abeaeb5674cce0c08102cdbd09ec14c691fdec8bcee16f1dd87f5b31bef3a10dd0faccefce3caafe205fcbb9bcef34acb422ba7d3d5530fef5d5c04570b90e2a95b51c3e3c53da1b5237bdfccafb5dae469bfaba3fcfdfd06a8f0a5e7b66e2caa6b8d188cff7b5ada73ee9b97b7fcbbc3b9bdaf86b2b55a5b00f9e4c1bc8f460ac3feb0e7a1ade2ff5dd582bffde5a1fcc06beac2fa28f571eeb1f4f5cde2d35bb8ee1ee284ab181c5f049a6ee6633b5e0acad7f0eed50e38cdd78593b32538c13d6acf7fb346fbdd874bd8b094a42923ee1df64cfb6dcd0d87e33ccfaade48e619db94387f90775edaec161fad5c0748c01ace105cfacd81b03d51d7a60ccbf43775db638fbbda0c3e7cda6feeadee238a5fccb65896efdd3febaff5a2d0c1ddf746f4fea7d7c5dbbe335bd8befcf69b8ffd9ef35e23fff5e20443bb7fc0adef49aa23ac343fbe8b75cea4cd96a1bfb42abebbb53a4538f7de3f8c630d353cbea2747bd36d7debfba2091cc925bea8fa7b108c0d62bd3e2e983be4d0dd50afaffb8a8aa48b5a87dce9f82fbdf9ee82ee0c81eaeeea69ebf5defad85f66ff0dfbda6cefcdfb1ae8089e97d4d230ef17376a74b2dacefe5ac2a78d75a3f64a2bd2ec4438ba6adff0df21fdaa4b85fc91cfd2955e84dac8efcfab3d7fa7cfffaa0a7385f0fd4fafbef40a0b939d8521ea6da2c9dad97bdfff8f56bf8d24b0f2d1f4bc8b2ae21b43f8cfccaf4bd216d545f1dadde450d8c5360d2dd88b30a5afe2fcb1e9176a2f34c6f2c3f94e3f2ae6bc4bedae525d52e2ba2c4f9a1edddb50f1ed0bbccae2797c2ecfedf8f652df9d8f0fb50ddbdf920f884a59c01e964f30b1fecdc2c477ae4b2808d3de6f211eba7a8f8fddd601a0464fd08fdca5115f2a19d5ba809c7200cb3cacbecab52b28477fd59b55aaf4fec40ce0d82cda4def5ec556cf938847cafaad903f4c4ca3f7dd74dcfbc7b2a3eb770a0a6eb9c6bf9ebde5a38dedf4eae05f29ee121ecdee9690b1adaa6cbbbecaac402bcdfd4298be2bd5aa28ec78d0a42e4cbca0ec33e911ac5ff02aabb5fb6e48bfb879ca7cdb8e34e072bde6fad7ad02e0a5eb68b0fcafdbb2daedb36d1fb4f2ffdb1cfcb7ada54c0d9e276a428c5f1ac0b861629b4df756a6bb0fd68ad5cbbbce6feee8bb7ef8c540e88f7dee705aa7caf2bbe60afe1616bb4cadf4bcf5e4dd9d1ccc3ce4cdf5b3fc0a5ffb1f2945dc61f4f33342dcd386bcefccfc1b4c7bac78cce75a1efb243b5cce6df1c186a35c0d5c0bdb520ef8eeddfa57aebda316fece80e66ebdedcbd9ddff6efd32aa30aa0dfab5cd4febf3ecdafd2d0ade7d3aa20841ea9cc2dd5fc4fca914f36aa75bffc51df44ba396eb13909ff2b2d3b0c9bebe9bfdd4b6dc6e67a97ebecc47140fffeeecc0d31aebcefe465bf6fd138ffd993676a4b4fc5fbedb1fcfc8a48ab33878bf5db81e7aeffbcef5d11f51a3aadcc3bbe4bd42c87dde44a1a2e4fe2dcd8ebbbbe36ce1f68db0ccfd3adf8a9fb9fc4e3898c65b87a4ed3b5a3dea1bd06c879bbefce51ecf2f656d96cacf80cf3cb8cfc8a38ef6fc26faf26a2dadcbf6ce883cfcabdfbfc922d26dc61ce7ad2a8e2b091ef4f9685ea6de102441e194b53ec7ac8d4bc0df791b2e62bd9deeefc9dc6dca5a9fc23e70e3026fb3b1afafb375cc2b0269991cbe57b9c6bdc43d24d8ecf6bf9fff1eca07eb69feecae1c101ff50ff731cbe88e1b099a830ac51e231a1d3afb0caea381e697affd8255d83bde297ed8d6da4a7b1e8a40be96c69b28b19fd5df04babbc4c838ab0d39a4c2c2a2eceb9dabfbb9320516ecfe6bd24b970c9e5c7eeea59b8cfadf1a089da141fca3dab481aecaf3c32a1a1eae0b4db7c52c9ce2ddfb9b8cffffc51afc3ef3bd2cbe35f6e5a455da1d2fdbfa86f9fdef24baaee8b8790df17fa5e2825dd86ffeb796c3d8dcfeaeeab73e7bedbcad2e1cbed3d125eedbb34fcb4bf88dbcb07c4c4a2f7eaf9edc06527a22f34f7e0b62dc53c9393444d4aeef0a7c5f74ac38adea23b65a0d1da60138eedd6e5b7c78d3fee1da3d7d24e3e1ab1ee96131b5ba1c5ff719d3dc56f3bcebb0fda6562fccdda88cb2b985cc1b824c3c8873adcc1602f832b5dbcbba5d72e868c8dbd8d7ecaed1d7188a7a94ecca0dd3afa6ac8a8e1d8492b86b6140c91fe787a8e0f3cbfec5b0dadbed60ba62acefba9f11b41d5e39aefacba3a9647019e50909843af8ace879e27a62ff56c23525bfbe8884afdb570358fa5d47fdc4ff3c60da1714d0af0df0dcdca835d732aef6d7e62c36ee024dcee4ebef002a24cdcbaa9b10e62f3ff8acb0ecb2df501662daba3e1a3ae5d3d16157bf9186ee4a4ecc1ab990db14ad2bd903dca1c02dcee9a5a8c3eae6befe19ce4ecff5b9aa1e2e074aaedea695b9fddd1ad8b1fcb7d4b3bfbe4a6bdebdb1cbca8ada1c6cdeb9cfc083aebc34b6cc14daf6692cd7c5ac978c0f9bef08678ba99e4cdefe2561e9abfd3fc6c7cc216cb4f518a0fb69d1bfd300aec106af30dbcc6c7edca5fffd48dfd3b671f07bbd4ee1e6e1a6b5ee7ffeb9875aef52e4757bb0bd30d8cdc277b75bcf2df6307de6dfa69bbfc9a9c848c2f3ac0670de7b8abfd30e2bcabeef39aef1c7238679adabf1dfe9beec2d40abce00bcd0223ea079fdfe451d1c5aff985e83fcf492b3e92dd205faa3bfaa0efdcbe4efe8235ceafb674ee573b4a179ed021f8fbd2b91dfca6a81bd3df26e60ade0e0286eebb6dfec2e9abb47bfb9fafce1c38cfde2c595fc2d86d5f20c12c665cf5e4ef63d6eb3e8c77a4fd3f31da041abbbdcfd2b629cba2a4abe262daadbff62ecddcf0ce7ebaa9c071acdd1ebfab5da3abd2e7e84b75a7d9d7f13eedff7f5402ec048bb83a4e849dfdd6cc9bdab867d4aca9eaecedbdcf0ad5e0c56cb8ab2ac6b234bc9837e1d6438dcd9cbfade477bbe4f356f84af2052eac1f8af94afede79cc3ae2fdec11beb720f243efa2ef5763fe4fdebe55b162f765119baa2ed5f8d4eab8aed83fd3cbe9dc39454e7b631eefb0bcf60ca91e634ec5b9725f7deabad2ceebaab0eefbd8c22d02eafc2b6b2b3dee6836ad213cd7b79ce8fa25cfd1ebbfdee3cda770c7e604fe2f6ead2d4bc06cadeca1fea47e38af6a8cdef7d084470f1dba2f24df01649cefb74ba0de0c7b8d419e5f3ebbbb71acea1da2fc3d05bb64aaf7d0eea75b0efbef78dafcc943c35b2bd5fdcbccfbfe5c5cea08f4e55e74dafef2bbbaef20cafbbad7a205ca9be2eefec83b9e96a4fb8bb4eff86fdee05ce23bbed4d78e69f44a12e398929eabed23e0dbcca9ee57a566f1f01b7af6ed9d2a9a07bfa2bca7fda2ed19f0b37aa980fcecec78fabe1e3fa0ff61e5c3dbd4bcfb5e87857c3fda2db83e8a8dedcd1b6ddd0cbd9a13a12bede8969eddaae4dc228db628bddcd2eb3a0f9ffaaff8f4eada3cff7310cbe5a09c7c8595e6d9dffddbeea8e7cc6e4bc15fd7f8433cae29a5803979dbbe4cb6d0a0d36163b6904ee795216d4b82ef9bdb350fcbce8a33c1cbef932228dbc4ab447bb207b7cad2464df4ebaedefbade52dba7577e0ce5abe72e3fd851eed3f38de84f0115c1f5b8aec019e11fc486dfa00757eac2df2be90eea19cfbd9ed9ef5b8daeb2c6e53d9fded1780f603dffc3bfeadf036aac30138004e4f1f2ed6ab07eee54f57bacaadec4415ddcfbe080dcfdcdacab162ab97cec062bdcaaefebfac771e2e7cffeee45b95def2dcbbe8ac7c09615cb5022ef1daaa17fdbc4ccea8b99cfc9dcf9c7fbd8e7ea89daffcac39392d04521113140e7eefe23eac46cccffa0fa4828cc3d66f90af116fed91b0fcfd0c7e1d2bcf3b929fe5ecb24480af95abf30d3dbceae7dae8bc2e82ac6dbfebd6e0992ee2fe75b9326ac3e5ba39b35fd7eedc1cf6e3f09ab23cadddeeeff983702a3a9cef381a1182af2bdc3e29f5a96e58af1e11df3c504cf115c3dcdd44a4ff3fce7ccbbbb83b3f2d1fa4caefcc83eaf6ea161c74d58d1447579ebf27ecbdaa74c31fbd571d16a07ceccd4ecabf7e06b1a6d311d9e1abe13ec404fc64908aa64f10e8acd63bae4cad87be343aea7ce190cbef46db83210afdceb8eb11c7b8df2446ebc0869b0cfcfedb613bbabe6ac91fa2e159a8bfd5dfd12e5ffefc1ee54a6caedfdeda05e60b6a3f3fd9377eba68ddaff9b455b02be492bda4f0fbaffd346c04f766d2a4fb45ef4ca085d95ce6a71c8efbe2fbbb2ca7fe80a92da3e66dbebeedb0cd446cbc4be96db641abe9bdecf43a7ddcbbd15bdfebdd581d7fb34e7718a1ee56e5f7ad1d029735ade8ef01a8bad6fce919be607ec7bbade65e3ef38a78d9ea8fb3a9e80bdb4ec56ef3db8ff833ac84233302e2076ef9ccecdf46a50f4e462a306c972f3abffcec398cf59f836db1b9d0fc379487f12b87e04d57f72bea09ea8721a6ce3afd76e42d3fccf7a553c80f7e0ef5c6d2d35db98c0b6baa5fe781b55bc69a5a00ffb19f3bddd0b3fd9f9948bbfaeea9c3f7cbeae0b2feed116bdaaaeabfae7dced8a5dafd6fea20459e2fca01b6d6a7adc6dcddd09d8cf97dbeafcdf11aa4ec0481741ef0c110abdaabffb24ddb91138bf9c3b8b505df7fa6a4e88370ea7eaf518f6761b308d7e2aaf07bf65efb93e3f5f9ab087fa3fc690e5f25eeebfdfac625bf98b62bb7b0ce41bfbf2cf7582985dd8fbadddfd7e7cab2af95acf7b14040a072b14f80eef55757ebadba7bc2394fbc9d56b7fdab023c53fed92bbb6ad6a3e3a6439f2c226d8db7bdc77ad25cbae5b5a5848ea94c6eefdf8fc754afe94d6aa4a4db8bc4f0f5f4b607ac13bdd3b6ab4ccc2e8aafda4dcf08a4eadf3ddeebf3dcfa730c1bc5e7a574dc5bcef11cea71d4b3bd13e6b1dc3e3a436dd92ab4d96c2d5ceb4e7e2d26ecbe6ccce10d9ed64e0eff4c6fb8a58164c1f3790cbfcfe6efd891fc4dcf99a4bf4d0c3b5ff2b75a5750a976cecedb5c53dec9d1195abec8af2fcee5dfc7deaa4c9eeb428744a0ff0dcee574bed94f54c17cd70debc25cf7cfe489fa82b4bc3eab2eedbab58e6b9aeb8dfa4c3ae5bce37a1bbccf3acfbc5b7a76f73d49867b3fd0f8be83afdefcafde18c4aacb82e31ccbcb484e48ea27b5e0fe2acf8ee717cfba05152ae6c1ab7cfb959cc41dc218ad930ac89d44a1fa15daa4ceacac4aaa556c9038ff8ddd8c56984bf4a42c45495fdfd0b8c3fe4f9d7c44235721adcecb611e8a7ffb2f1b3cebd4dea8275b12a58fd849a5b7dbd0affef79cfd2ce10e697a66bd5a788b16173a49fe88eddeefbf6825bcd0aa74fd2e968bfdbb2f7bd7e1bc5dff9d0f27debb66bdd4d446c1a29ba6fee8ed53ff37d7d6ee170b6fedd5c40d60ddb208b6ac7da7e2ba129b7fef0e72addd1722b8026126b20c47f27fdb0fa2e9a309a093f9dec1f97c9a642be7cbdfe0f4f7ca4b855b35915248f39abfc7d381fcfd7fbc816bdccafceb7faf06c1ef9bc8b39dffe9a72ffca79e48a8cdd4463ca5d8aaaf238c60bb46c18bcd01ea3fcd9f0dbc9f39011b6cce7cc9eccb735b5ea9eecfc95e51aaab675cfdbbdb0bfc4a9cb742a3311acbedfc3d7ba307ef5faeafdcfccc533ab638272fc8c7bd8d477697e38ebce0e3c2cb924effdd4f55deaab6efecb12f70af41f2cb9fb2ab4bbe0e6aaceed5bd9ade8bbdf2c155eb49a7dfa366c9bb6ef0eb1980b8bbe8d1afa4451aa176749fb94ddd1bfb9e27c9bdd35ce5abfd8bd7edbbf70c29d6abcbc4a1b37a964acbb6ed31f9ec5ba9a06dc2c3235ab04bbaa0aeeef9dfbecbef3ac69a4697c1d7c8cf6dd20a7fe8efeed6d2cdb0506c53f41a2f1ad0e20a92df8bcaddec3b0a2a8d0bbf5bdcf2d1daf6f35cdb072285ecbcdb9539fc2cac4cbf1dc8fd22d0fbf8e4d99cb04aa2496b8fb51bcda9db114bbd63842c08dfa8b83a8d01f73f7f1509ee38ce75b7a5c0a5cad8b70e45ac6ef03c916cbd183f6caf8a3802cdc54fefed71a6df146429f4dd6d1aa4fe0fea27bf222d583ca40ae329b8e45c64fd6fac3f385265af1c023320df581da243b72c1dd5e17392dcd6c84ddefcddcd3cc0db3d3cca19ab0cac330d7bbabacf4d4f1216aac30ed09e8d1eefd1bac23535c4b5a7abd56baf0edb1f6cbf6d4ffc9cbf24a6adcbfb3ad48ee3299a6fc74fbbeefc1832ed673dac4e73db3ed7bd83072f38fd432a037d506bdd9590e780b6aedf1e88f04bd9ee0446ace6fbbfcd4d01db2406ae8ee8adcb67ff6a7f4e405bbcba08b68caadc37ff2da23d4bc8fbfb7aefa1ffe1a95fdb5a8c1d6bdbeae116f15dcfb5a80cbf5b9be1a7304f85a3dd71bc55fcbad6e58a2a9dda599dee2ed2bbfaf6b20dddbaf3dd663b17cbd65decea492adb265bf860aef9a3f8e5ffb61e40ee56dfbb145fafb08bb7abdbe17ccde650cac6c2dcdd26a2b85bb4eef0ef0d9cc067e8e286beca4cdbf445636aa7d3aecd5afbb009d9aa3fd7e20aee9dad7dadbbb40ab74f83e09fb1df77efff8b93556dffedefa7a5ab281b8f1920532aaab25852ef6acdfae5e4fdb0e5ecb7bd7ccffbeecedd7fb5791c06da5aee3af2ec7b224e526ad1fa953d3929aa6e72d85ad0858eb69cbee3662e861c2efd6ef141adb3bf5b001bceb8ef3afb3c7eb31c3ea3fd9ba1d1fbbbedb8199e0ccae23aafec73afffe1f0532a6fc32bda497382d11dbaf5ce1b97b0c2ebecc8d5e0b80cdb7eed98003f09b4730fe6acda7ec3f9728b68f54e3045abed53dddf699d3df85ef526df5cfa392d6febd864e0a1fb4fec047be6e06127ade6e1dc6dba31099964e76b024dbf4ce6e1ab46c5582a82aca4fac4edc1beafefd8cde38cbfcf5f18045db436ad2710ddc0dd3d0da7f43d28cb69a00fb3fc7847d50db20ccb7d2cbdc2e55c1f46c95f7d31cfa7ac86bef61d3ec04edbeef23d0ed9fd497cd3aae3ea9b91923a5fafe1accf3c3c90839cecc4a9cceeecfd3dfcfd799e2e6cb3a085aa6ebe97fb99caa1aafea41dfcf0afe2faad927ac3adc1dce3d4fe05474ccbe9b6d6e7d29f682ecd15f4ac6960dabeed1f6fb372cdcfe022e87d9a30fb10d317ea0df9d3dfabcfb8ad2cf96c59735add2e6dba6fd30ce8ed692021d0eadddee5aa6c3a4ea9e3be0aa2cfabaa5917b41b60b77f53fd10739636baeddd00c4ca0087d7ab931abcfec432947e165991efff3fd672d8ed4cda9f39bf7cb64da775acfdc41f7b407fe3bfed48a06ff2cb53d0ddadbccae57cbd58fbf9e39bdc464fa710fd3befb9c5b4f5bacc6ac8f62acfe0c2c44180efdbdd171318fd719f21720b07d1aa3839cfcc8ae708a3f6cbfa409faf5d69eea9f4cc58586d88ae81b1edbff470a1bcb9b1aadcb1e04ef0bbf99fad2a5edcb3f96bf0bf6ddaf7ccba9c325d3fdfcb1e8ffae6be22fbbb76b3cdf60cdaec82663a6b4cb6aede7c44cb9cde77a80b5c3c7a78beb2b082e4c8f6c79a5a53f01c18a421aceddcade937a7ea2c74c9fd22ae04933fcec9bb1a0c69dac5df52deca86fca964ecf4db7da793c5f034c3ceff121101fc6ab146bfbb15ac7bd7d2cb188488d5dae7a0dabba1ef9d1181158dcccbbaa75d75f2d8dbd76c162da74a71b1decd9f4332ad9cdde5cfe56cb66d166a7fbfae91f3ccd1c5e067bee59217cc2f2784cb6fcd081abf95ea6ca95edffbebede6b3eef0cfdf64ef1fce60c1cf33c9c3526adc0a9c9e9d33b8bd8e7eaf4f757deeda0b8a21b6cfd14a2cba8ae6816afcc59da26de4eb45faaa642597fac3b2b4cc0bfcb1152fa8d2a5acb962f8d8e9f80eece4c5b68cd11bd9f88a11c8af6c05be48df0953feced98421c93eefc1ad6c4f6eff0da930ee099c1bc28349f7a4a7c4d2ae919e3434ba1dc5f23cdda4c6b2bffe7d4d35df91eb7bb198d4deae7a8efe2aa9c5af2afeba4eb2cfedee37bfcdfea4c3d29afc9091fa2b2357cedf4c22e2af3358aa595f19e3bbf6d797fa5a39db99dcbfedd549b3dd8f7f6dff7c000d231a33a4e0dd7d749c9581c5feceb0acbfaafe63ee15a90da4d7a5baca25007ad9eba0efa5f7ba77a72b488a8e88a9a2cb1c2fb62afa633f0d1ec9e2de7b0087422b7bbd0a8e15bd03f5f191afd7ef3de5568f7ae0cfec9e737cd4dde6bdbf02da5bf8bebb98327c6117275e0fa57dce2eb9afeed3cbf1388cefdbda4ee05ddadfbbbeda55f5ac70b0bcacebba030a21d08fc044c9a37f2ef1949a8fef8c3bf1bfd91d43db1c45bee6717d016dd0f6f6ebfeef1c9cacfbb7c7e1fac24df4eea0bbd5de66bb27cfd678b2b14578944a72fa2214fe7c2da24a21b8fc0d5ccfc76f0d5cadabaaacfc1e63ebeb1a2ea4edc7c3efbcafafd74deacfe75cdecc63f0d91b95aa3dabdde54436c511c2fdc1e78dcba0eee9f0d2bba9df37eeb2aa2eceefccf2caa00f429cdab4ba9089db62f2e8ab19abc56a0a2a9e8c1afad27b58681f2c9d35fe08d3b7f05e0252abc0fc695fba2985fe011e4caf8bcfdb4e2517cac3e3e2ef1bdc5bab24fbccb94dbcaed99e64b8bdbdfc1e8efd319b7a2deee7d45fa7a05ce692699ecacbb72df0ef812bbdb614a63fcff7e3bfdec221245b6dbfd26573e61a12d5e3470dadb7df53fabddfdeae1a0e99f568ecaaa9f3e4ff8b1ef7546c1cacc6a6baadcc6f6e8ea8acbaaebb0cbb1eaccf269b1adad1eedfe64ecfd82b86004da812ba9a2c0af99cbf1c30a82d4167782b1325ec1ebb30409ffbf0bdff4fa8edc18982d0d1d03116b4e18ec9da1da8aa6a6fcb8d2eb5ddbbc3a5bb7fcb87bedfa4c98dcfa0bba8adcc5cfbfcb1dba6bd48b0f99fbe8a2ca48f1c2a6cf182ab5c0efbf509e33f5062df2dcc7959ca7d0fd1eba6ce72f9dcdab97e69944a7c5b283ec94d4aa01fcbdfb25abd50bae75a7fbba7c52d2cadbce4ffb2db1cc33fa6dfb3e173abc9467f0c4ff35dd0dcb1e550410013e0bead1ffb4ddcac617f14cdbb1515e77dbf19df0bb2efaedce3f2b0f992ba2c4d1a3cd1fa15c0b6bcba3fd2afdcded76290dcd3ce86bbdf125d93b08dfe8caca45efaa3d28a20b8ac1bcee1caf0dabb1ceb3a4d62691b2bec138d7a64fbcf7dcf2c066b742ee95e726299d9ed8f0aeaaeded85bfebe36f984ac3fc32ce05505dfb062beaf7229fed6eb5ea927c53edf2f49be35f4dccb2d4d9cac3d190137ecfd4ef5d55cc7bf79f867c8ae0c4b42fbed52c7a7b2cede341c68cd4cbb6756b594cd9dc3981dfcef559ef0fcb6bbec2c7fadc7dd8a9a49cec17ccb8b0e3cc5f5873d483fc1478b22dff3f6b4c2ceed48da03f7729435af2fd11738a40adafebb7d9ef2e010ccf601a51c7edbbbcb6d50de2ad04ee5e7f6c2aa89bcde90a931c1acaf14df3e3a9aef551bb14b93c047200bd9be9bfaf53daffbba4faabe9bb2caae83a0c1b5bff7ff0ea6aaddfc9f6eefa0bff67d4d82958aead9f3a9decd71cd93ff7eb4f41cbd005d0b9b1423fe6dcbdba599ae42faeefdcdcdda60249f77f7ae92294dbbe7b15b9dbc0d7ffb0a588cc45a1f40f7b354c659aa0bd5a4de8bacdffca47f3bdc22e2d38211e3cfbbdc1b6abb466b7e4eb9ab6e6e6e842ebd07fdcec520d2a3912c27f855d2dd0edf6f0c68ad0f4f9baef2debff579d7bf3b6d1f2bed9674dc7e7bbbbd84cddefdac5f48d3dccbad1b1cb6b8b8bf0daf3b871d40e6ae98cadbff525fbb9ff8ee47dcfc5f3af8e1aaeb286e1b0080ab5e8bac2fd3b1cba15f8a1b0a5d5e2f5ccae5f11d5b1be17adec6f1a819792de1ef47bef7a63a3836580e7d74a3a0fd792f6c311bb9e51dd83e994e1e4b0c1b32d73b797e4be806fd20c5df71c42b9771fcdbc05d44c73fca04e41ebdef620e3b8fac67c87feecc61fcfbc4f3a83f4b2a0f313c2848c0ecc4b1875aa09cc2ceefbc7fff64025aa21e6b384fdeaf6beb2c1ca5c3bb6dd0dadaa96bd26fa559a4204ff1bb1e5ebbcb2db60bb8fbe28da5f44562533aab2efbeca3aef2dab6bd22c6fecb41dbb3ddc5894ffec65f55df08d06ffb9904de867b954ebbe9b9c6b26c690fd509a4a6acfffd0ecac9ff601f1d1ccbd1f517ff98e823bdded4df4a039ab6ea4cb6bc442bda4efcb94bd3d850c046ee69e9e3bff4fe5fb2bed62bbfb7e0fed8876fecfcdd1de165ef282bbfa83e7bd8dfb5abb65fea4ba19a2dafa035f16fdfdb203b9fb8cf5ff7f04a2dcdcb1b2200e7d9604d5cb3ff8af9244a4847fe7dceed89feb03bec9f0faf0fd2daf013235ff9cbffc2cfb3abb0bfcd97fbc9739b2ef10ce673cf03f1c17d986a8f20bfcffd95fcd5dde4f4bae1eb94cabeff0b11ec15a63d9e8b38e1235b9a5c86eba5c64fe86de7475eb8c1ae8ab2c90b86ef37e3fab1d8caf57da857cea9abd9fdaf2bf5ada00b46a6fabf8a15ab20facacd67ac6326c0d159015c1bf5cc2dbe84e7f6cade4fdfcba094c1ec4245b31f5dc1facde44fc76665dfb10b4b6af7ff77a1db3c06eeebdb2732a4266287c6bafd73e596aec9edecd65ebc3bfbade740fa44f095acb128faa8fffc1d9fbaacf5bafa8758f05edf065c1ca37fbe2e1cc9c5d35a2a5e2e5b76dc5ac9929d25463079fab27a7af26ec41a1abf3c4f387e4e8cbffaccd5bc70a8d3cd4acaac5d456cfce69b8af9ba3cd0e03105b0ee68eedeed2fbb5ea8f0e140a561da71914c11703fcd8e8c6cd2d0eec0eeacd6f8bbf7420e6cf3dbb6575ef3eda77e7f0cb1df8a1a74cb4cdbbecb7dc0bddcaf49b94f2f6bdc6cd32ba36db8f24cedca9becce7f22620ad38cabcf39a2454fd2eb60ed4fbaa849a7d958b4ec9bed3ba901181fd2ffe551258ed30ba785d6b31910b76a97f8a3afd894e1d2ed01c72a0155a18d497bb91ad75c0ca52ae2be4caec92bbe0c77d5179d34e2571c74a9ede5cb2d31ab472bf33617bcb8338fa701dbd03e6a416b61cab1a28de778fcab8988cae3ffdbb56f1a0d857aecbb4330d3cda8a73dae8dd0d7caffbe1d50ee271a20223ec154dccc10a59bdbbfcc3ddbb0d73d6079d8ad5ebafdbfef8fccaefdfcd500b0cd458c647a714df0cde0c5cab4f0e5c15ef54af3fe5c5ad4a9fc5a6515db262dcfbf5f2987ab18caecb4f68cfab6dbcfb5e434cadb77eebe4b1dce4d5bfd580114c43177e8a6a1a0c39dcf480abe5f7d9bf20aaa1a92207cbf050eddefa61aa2dfbdf7ca8d5fdec5aece5cde3db8fc4549e77579cdb88d259f4813c16be92a67adb4837ea6e0d60d68f3c6f05eefcf8b1b271b1b26c74e63d8153c8b00799cbfc1cace5adeb5b5de3cf5b204efbb185ad09f267041bdb31c6a0ac09efaeef3b05fe630debcd69feff7e5459cfcf13f9e3c5db11e68936acfafdbdd276d9dd4f8cfa14253e84226871cae3cb5c9e5bac39ffe886df7ad06e57f408e39ce75f138ca4ad4d1f6aeee4bbb142eadb9c3dff123bd2f6c5009c6d417fbf0dccead0bbd3fede2ddcc0fcdac25e15e6c7ad34f20e3ceda39c89ed21f54f2e2a8c85c34f0c1d39ef6535bff2c6dc7ab6eead9ef0fe8ad1decb108975b4bde045c2ed0927e15bae71e4468ea3b875fb5e79caebd063d851048eedfaa4aaa5ad9f7b8b1f80ab2dceca58d380b1c977ac7d6996abb97b70ae558fd9dfd1b70aeac5c0936ddca99b2a5aaaace65f31bdffeb2def275a1ef4ffedb0feb110de61b72b14de6d02cadfccdc8cdccfa89f1c3bfecc39b184217dcf1b653b6ada63f60bb1c022e57ce8ba8a3bfe364eee1ad8907648dbbc5ac26c33e97e8ffdc2cead9356f7aea1bfa3bca1bfd06ee656c0ca9fbd7bbac1f85f4e5e1d4b5ac2d22afb9cdc208a56c8cbc5a7acc07fc68ac9dc9c8202bfdf5abebbed6cdedb4b4a5c52c503ccbc0abe0a5d665bdaeef7c126e62daf5eebed8af7c674f4daf6d8ff0b2be9344df201cc1b3efd5a62c7c278c69a4b03a1be04abfecfb5decafe938ad5950644a302dc86aa10ffaa21befeb9ef929a9df103bab7c7deb0ddf1e4f9e0b0c5cdaacfdaf1f1caf32dad438cecb8bd6e29e7a18bd5ffffb6630ba98d5a5ee6eced51130c6cbebf3e91a9da4ccdb5eed871d0bddcab06fd5bdd4f53c8ea3f17cbe5d0dca4dfebd383084be4b2992eefbff25654fe98687da5faeda9decba9eeaebfaafd1d9a21fbf7d6aa4b1665ca494f8efea8f3a5d0fbf1d9511cef7e5d79e2a29042eaa196bd48705d341dfcb7aeeee864efa0f764d37d2af07034a1c686abc9ff0dc6f6486d63afe82ebeee1d994cdd13ea7629b7be4ecd31d59bdda7520e6a28fdf7a38038dd758aa6a2a67af09e93fcf6dceecfa4dd945cfd19c5ae46bca7d0fd11f19e853df40f42bda163b532b76eacc1585cf7bbe9f1fbd610e5b6fc8cd8a3e6aac62b23790ba6bc6cedecd16fbfabb8bda806fea0ee4aabfda16abe4eae1bc5eadeb4dbfdb4f12439acc5b39ffbc37efda9d4df6a937384d2ef10b0c5ba5cdb8f5ecb3ac054d7656fe30caf90bd4436726f3abee83008ff53c03b9bdfee6cd7ceeea0c0a5800dc251692e2e3a4173dacaaaabfdf04c9924c14f5ab3955faffaff4f2c6bffbbca7806ee3f85d3dc920f0e3bad0ca43f958909dfa9ffc6e9fded0bacfce384ccaa7ffc5c6bc2cf13bedff3cad1cbdfbffbbedbb8fcf7ee5ce488cd9970648cfe4eeeccf302507afd9ececd361bffb5ec8f5a8bc5bae78b0cb8d744a861aea23f48436efe799c02fe6ef668f9709def8ea3217cefdec61bf15709c4dca269a8dbaee4afd7b955db7b59bb4ca2daac85dbe3ce4d5fcf12aa610f8b80f3ccf1cca87cf55eebfc4f31cc4da6bc6859b06fdeea7a3a019c04f44d8d84ef32b48db55a501be4369fea6e8f67aba5dd1b12c211a3b2ec2cf33cecadc5ac6b98f7ab08d1db75e49926c48c36cea4aa838ff0bb4a08adad3bbe4faa5f87bc6bc57ce04130cabcbefb7797c15c7616c2e1ce0de802d23b09f2e5fd2ec83c4dd1bbac9144adde8cba7a1257270f1fe4795392bddaa5daa981f817dddf770faac61b5da06b4d9c4f158fd11abce0cfebc950d5bccfacb26c2cf3e14caeb4edfa9aa7f9d4fabecedc204d85bce23c7e08dd0d9c7aad935a8482b0d311b4dd71d7ebe4b4db3bd6cbae7d7baa43d0a6ecc0e489da3d92dfdffa45899b48db10cabfecafe0b6df8e00f2d06538da5b18e2ee511d1f229bbf7cea949ecce68094d8c1ebeee31af3c3b01bc3a96aeb53ffc690a46b1c851af09c8d4aac1ae59ad4907412bfe1f9f7aebf605f24f77d2a3e2ac71257bbbac61a5dda8e934e0b4cfdcb56532e39fed67ba3b3ebaef7db7566b5d60cc16f470ff8e50a3713e15abc1cef7ac80556e4fffa4c4bb6288b4f0d6ea1a5e9bfda44fe619a8908d6be97da8bad6beaaaceeb2a2c4dedbecf0fec48f06bb0ef36cbfcb42fea0cde92aabbcf41d27824eaf6a3ec5ded2efcb454be14d193fb70bdc98db7c1261b1aeaf97db2e124ebda15b3e4ecd7e650bf45e31264a41dc62bf4f2bdfefcbd9fbe7eb5c3b565feba8d916c13191deb4637597eba1b2e9f807d06dbb6af8ea17dbbfe4bc4b2ddfc90ca83a60d46e644ff536a38fde4d917cea2cf722febdbe35ef455f77ccd4e78ff7fec38bf1aef5f73ebaf8fd7aed6dce05a4d0dd3ff0a9dcdd98c99dbc3edc30b176b0aaaab65daa5e22cafdc5d31b6e856c7d1ff1ab0dd8cf29cffaae5b6e235ed4e1ce0989fa74bdabc5d040cbe6ce9a7b4bcf82a1fe3ef5aede6ae348a63055b60449a864755d8f37c69ddffecb32a4db6c2a0677450682e3bc8504b7fc71bca9dcc22d84ed9e9128d08803b926d90b55cec4ff94d1bbbca4edefd969cc3619abafad06ce5bdeefc1d11caa03bdae66a41b2fe1dbbaebae038d91f6e0d6972ccd6c463bfadc7ddd526bc3c88e5a9aacbca8bbdaa2ceab0ea9483b613d6e03167ff39cdcebdd9c77bdf7aa8e4709fdebfebb15c6cae72cbcd104651f06f3cdb7c9e8762a691d7ef1ea11d67e693dce3b7abb2af7d850ffaf38a28ff7a75b225cfd0d8572b08048fae17fe58e9cd4471f168356aa859cdeead3bd56c8d289b17143aeafae523fb4e5f3b2a9d88fa8ecc455b62f29f0dcaa4cab54d0a768b12e1e3d3af6dbae4c9aac61ad2673f7bae0f9ac4389e7f84b35d5bdec8acaeebb1ab9af1a87d62457d5ad298ebe77bdda8ecd19fe1db1eb05af438b0457bcf3a78a0ddc029782133a0ee812af251e7a2ea1f707bf262b9bacc66d48a50c4ffbf8abd54ec1ed9abce0b004bf22fb3eedc4ccadbac16caff8d767f4a9db163aa45122b200bad8d8205aff7d5f8928bda82eecfc2b85a52f28ece6ff5acaf6907a1eb7a1bbdcff3e78faaeced98a7dfff46a7f9e41ad39aecaad4d9aacbbcdc3bd8b42b83bd8ad466dace828b3caf0972ebdbf3ca7ba2dc3a4fddb08c6bf451c317b9db99cd4c4dcbaeaa95c6f23a62bbd16123aa5eaf9f6ce4c5b3df68f964df0dd71edcac30ac7fb66e4f3aa98bfc7cd27a1d012ecbfaeb29ece06f2f8d5bc462da5d28b9f8a3e6cdcfa7c278dba56d189c6ffde85166e2caef5595c7b6293bfae7d3ab4d94bf3acb792307b4ae3860f1a75cfcebdeaeef8bcdee27c2abe5ab15c227c6ada15eda16b70ddec6433de467fd4beccb198b9cdcb04fa058720c402fafabfcac0cdf48cf4e5af064d1ab1c64c8c03a7bf78540cdfa82bdce948ff8cbac79e6edde3dafdaffdddf57de6fd01efffc7fb5c5ac066bd0e94d4dadffcbb2e8bcc7c1bc69de4d1d2766bdde4433ed7021385eab7ccb8656ce3a90f77de98d2d8db5cbc6a4650e3ba905a756be53a5e7abfa7fcf5987a976d5ebfdec3ffb42c031e346affcb7cd6ddd3eee9009d397002f4aadc4eb4167cf4ed4f7f25cfcd22c28bf0a32ccef39e71d09ec029419c4fd2b7e51e35cfcdabb9b5fda7fb344c288c27e377a8d9afb3d6e154bf9b2b2028ae2163edecba26d05b06a9c90c4b51f3ba5d9688c8194de2b70edfcbf0f7e53ca4b7bfb9d2d0e629f06a2fc71f9edcee5f7bbd8d0b415b4a32ae4f272cabaec470c8ac2a1afaf825338ac1cbe67ae2354dbdaecd4cb0d6e7d296aafc8ec7e09f27dcea01f4ffe1ead77ffcb4d630a11c10fe8b91e9f027daadc19bb2b4b860ff28c0cebded0ce86f1d60a513b58efbcb9e5ad7fee49bba98ed19cd960477fb3930e6dde8ecc04c68dbefe4ef8ead95f4ffd1acfefd1df174bd7518876e1a0a57e7eded9a4b3abbfafc9db5b695afda73b228bc21047a70e4a63b9bfb8f6bfc1a6ed9da25d94d0d5ff5d3f8765bc89cdec7e16a34e34ce1eb10a6ff429296bddf68adbd4bc52aaa61cdbcbdf1c44c9cd33a03caabcdb13568733e023fad3038c8b0b77f70abc7ebb80fdcec9dc8acac22b166c5011e987a80feae3a690b6dcb3402a56c06d0bb5a6abbbaba6df7beb579cde1e30aeeda5f04ada97f365f48cc249bdfdab05bebdbadb44ee09ccdedacab45b345b8fb89cacfdbdc92bfe3381edeeef8e9f7d7cc6125690acbcedb7dbedc414acada12dc646fa78fa77bbd6fbedf08a0e2bddcba9f5fae93eab1ec69c8e5f0ddbfedde5bf4392aa6e6f58a724caa6add8fce3f94483b0ebccce1b3e268b50b3e6da3ed12cf75eabe7af1cbbe5571daa5ffbc99b8f5aadbc7ddcca11bf5c5a4f0aa36c0a4085458a36c392edecde61477afcef98fbabdb0bf6050dac2fcfc3d414bc198bb8bf24bff7bbb7abc3f2fcdffc03da0f8356eca2f8178862f0ca4de83d9a350fca648894e2c7ccc352bd73b39eb9abe655ca7ffbf2defacdf008af328f9b75bb784ac8670af559ea2afb23dbfc462ec40f4f3469970bf1aa393cdad6348afc97ac92ca5d5dbfd1978cbb775977d2bacc48b1d0a834cfe35dadd4eac11c4490bbca9e4cf6e1eafcfcaf3cbad8a20eca3b0796bf3a9b2bbc47abcb2a404842be4aa76cc4abfec8a47a0aefffc44e9cacb8974469ddafee0d1b9b1b6bbedf587bf1e26da1d2c684c4bfff584e4282ae4424ddc141dd43dddb299a6a0ed8ef2f78fa7ab68af3e5ce99bb4aa9bfe18a901dadbdc6def93e51afa6f953f94ff121beddca6826fe8f20cc66147acec01dc75fcea0fd3efcc7eab03339cae22e1674ad6277acdf5b7a30e3fc5ca1a30c6ee5caaecea6c6ffce4cf2a92dd3f68dc51f6bb42c43b2f6ada70e27220eb4a6ebaea4ee9cd71bdb0be0bc9cefbe20bedc9b0f184b9eac8b56b0503bc22122a1c8f0d3af0b37cce0d24afce3ebcf3b983a56bfb12b1fbda5dae62188ff2cb7cd73d60a8e2bb1cbfbdbaaf8acb32a8ae23bddf5b062aa3fe79e13ebdbc1aebffcf3b1dad4a92304fd1c2dab614fd82b1febeeedebc202068b0fa1df850e5e5f9ac6bff24ed22daa90b6c44f2a3ad94e07ff35bfd9be25142ab6ad96b1b5e5efaaff58ffc1d34debef8cafcde6fdf9ee8cd2f4cec3af1d767d18eadecffd71f2ccbf169c49c1edfca8fe3faad1a67f0242ed5da471b97aee81ec5f5d6ef23ccd2ab3d5b85df0acfcc9edd9808bc5f8ac5c1ee4af6ebbc40f1ecad24d8c86aa54a14a54df7ee1aff2e66be66658aab9fcf2f1cc2b2c6c826df4ba6996ebddef910da513acbb46af6cb7aaebea6fa968cbfaf682c5204f80bce1f4cfea8d1edc24ebd1e1c1588a5e95e7fededdecbd3bad96ceb8b04ace74465d16b6ca0fcfed5e34d0ac70a394d1b379df40d787cc9dc439cac3ffab3f15c2f0bc1ba76b5d8a1fbedb07e5bf5accea409687abd7da060cd8bdbc3fffcdf027c9e544d16bfaaa9b72cc540c7dd3f5e06fc7dcacecebf79fed4f98d84af5c5fe22af4904f89cb01ad0bcafe4ac5a4bdb0843712ddeedda17bcace4407adfb4c5d1a26e65aa6a52c99f22c129c29669d25bff30c89edc1c9fe5bfe9ef8d7b75bb832bebd21344f25d8d3d28489b6fbe673eecf4e5fdcbd928dae29aead1c61ff642ab3c77737fdf4eee520b5ca0c99abebe1fd6068aa31667db3dca3e1da1cd63be50c6c6de5fdd9cd8f02ce58b48535d685b79f7fbf1e056cebd5a9ff8c7d39f2eda6fe7bbad5da21feff4dffd91ac573bead5d0ccb4dc8dab9ad37ecfa7cabcae6e9cd3bf8db65aabfa69358dde5a546bae25bb8ae80acace29f3bd209e60bb2bab407da849a14d6d7ed605f7c5a9f4dbcfd6edff1dcf8d5faafed0c5b6a3ade0bdb6d8dceab1bfdc3225ce045190eda0f01dcbf3c8eb4b33e42f01ee5cbca74fa07dc502c8fc23bcd25f35f4f0fb829907b3e90aaddfdeda3cfbb78cde2dc5a679edd60f0f4ed699ccacee226aab7aba8aabd94d65ea204c4a02d27cfce50ac9d4b054ef848b566a7a112b8ebdc947afba97f8962e6bab20ef02e7adcafdaaedab8ccbb2cb04de0acf888d1f0d9b7c51e03df0138d48d3eb53fb0816fa2dd75babc15202a30c6abab8bd212faafcac0e57d0c3ec8e7f6f97ec9e5f0bdf5c80b68aca327a1eb8f863965e2ddfe4f08a0f3be9fd58c72afcb6dd0b0c2e88b6a3d4353bed988783c9ad1f7dfa5cef1ecfeab87bb3b54c6385c2afacba7deed6ee11aa8df03f1bba0e5b46e9bfbbeabdac10233cc0a6acae9be1fd1ea6c19dde32e9f4b546aaec4763e7c3a5bf0689f09c5d8cf8c5375afdbd8f5e8eb90aaec1af812f1a13e4a9af0c6decfe7869465ceeebbb852c0ddace73d5fc00be92f01019f2cede12faeca1c9d8c6b310afad5e26ccb00a903f4f0573e8f0f43aacbfa793e01ce2fe1ddba7bbdc922431efcfdfddcca0ff9bff035c61ac8d8ef1914e9c15b2b1b1aebb3edbe6f5cb44349d65d65c03f0ab8abac6bff8c76f5a2fd9df3fbccd9ad31af2dcadd3ccc0a5d9e0efcebcaaf4bce0e9bd882826aa84088d3cebaef4dee0b0e6bcec60cb8cc8447d1fe7de81cc48c9d7a0d451ffd0cf2e0ac1a1f4ea631231fa4f6ed4baf37ac3848beaaf8ab53b45ddcc95b45c5ffdc3223cd8d9c7583fec8ebdd3586606a744bdbe25a537d1edd1faa58af91d39da9fefcced7c9bb8aa09cc1aad9e991fcd3fee8752e96d1ee5ba79c6c8458fa2d4faafbe7058dafe8fa3c4dbade4fecb6b1e03d76ef2abaca5da906f305ddce740ac152eeed95fb974c9cf57c2e489c9ac0ccc2e1d4f91da1bbc2e756f6f24eddcad7de2c998bcc4bfa0d5e02d0dbba33c152e2cbbf1cfd8aebfdbaa9eba29ea6776debecedce7b72bebfbaf2b8ddd64f07f7c28f79a6bb1fc6b8fdf44d5c4b51689dcb80f209741adeadb7e8c1626c3ef3d2d6ff0e1cb5ab80bb49947ce3abdabbb12cdd9eac9c0baea2bc281827ff9f6c8698cf47c61e1c07c373c3e1a766c679fccfe149b1b8e92befecd5ccf7f027ee9f25ac8b78bbb58a7c9545aabb68415a97a7154e9b4e1cdeebf1a30eaca39c703c913ba0e1dbdfef1646b3ec33baa40c9d0ddb0816b2c9c5dd9fb6f7a5d59eca7bddcc81283765bce6bc2a4f30a5abfdaeda0cd48f1736be5fb27e230bca7b9e92d00dc9ee2a7059b4eefcbfef29b4eacd03e976fce5e9fadb9d051cebbf7f941d8b640424a25afe369dc00f94bed4fa452feb1e5cea39cc3a57fac6badd8fa6c38feeb3fdbea187bcaaf0b5a1fb4b8e457fd6332802aa6dcc5dacfdefe47ec8b6e07a62dedcdf11db4eecaffc074eddcb56ef83eddd96217f6bebb8fef18bbef1ef7558e8bc3d215d9f22d854e5fe7f155f73db54a05f3e520efdaef5bed0aecb62aeca77bad1da97daecc852a049e2e9fe36fed729db7bfbffad5b91991aff1ed0c38c254ae1dfcae8fd58d3dab7eb50aee77539a231a7da89ddc2ec5ac18b2fd30db19fac28e1ebacba08ed6604b8caa47f71a9aefcdd9b4e107085ed76e0eb6c1c811dc203419b95d958be0f3be01cfa28aae4f5b1fbee7226b3502f3aeb6f575ab28a23bfdd53aba4dde47daafce1bcd5fc64fc71fe454779f809574bddd0cf20ea41af4ddf16b26cbf069465f7adf554d54c0489cf039b620953d78064cbaec8a41b7eadb1cbbd8fdff3e7da4c0a00ec5a470adec8b08793e9cfcb5f7eacb3e0a7ae8f7ec87adca242ff001fad0ffde9a9ece202eed62695d8a53af6ffa06e26b5b261658c49f3f9a1293eef40e10b7fffa68e4c6cc9b1cbd8e0fce8c2dae166d1bb12bcea9cc63f72e0bed0764efacaaafe4e1fc8feafc6e9d2faafe1f2f07dfeb8ab6fbe941e9f6acc1bde4cf11b5ca7fbbccb9ddff1dd92c347dcb914796b3ecaa24be9fa5bed7ee69516b8f9baea9f8e4573dbbf8e591ddb5bb18d63bd2f1ebefbda5dd778cb305ffb72e6b2a9ee7ebc0dc37f9d1caf6ec70d8d0bf05e82f82cb81a0ec0fab0fa92605373aac837cbb29f8f24bc3d94901ab7ded8bddb64f3ac7cedca7615dddcadcba645acfec371daef69201fbbebacbd30f3f298fc853edfcb24c86bc90425a36fdce4b5cab6ca4819daf0ef9decb0e18f0e4cbc52e9ef452583be8af61a09b3dfcd3a5f7d8cdadb2839de93f8f0c47feecad7da385fdab1f8f1f9c1cebe2f857ebaab354960bad4ffbda8dd24c5be72c5f8ba4dcc4b7a46d11ea3214f3b1a7ae66fcdfd2a21edeba9d66c4bbf76e2eadb8ee86deabdd4bc7eaddefea2862cfbe1bcda48058aeea6b10bdfbb5fa4aaeb5fafe935fc7dfa5676ae3e67bacb6a9b0d617686e98c2aff3cbc1963b316be68cbfd7afa6b2cac3488ad4e882bca6f67ca6e899cf324fbba45a78753bc58cd37efeeefe85db2ffc512ec8b1adba67c6b1f6dcac40a8fa1bc166a2ca2045e81e507da9f7be29ddad96d2f9f2dfc08e5f5ba4e06f7f579b7adc86f7750b20bf3c85fc4f2ab8721ef2521e0aa6cdbc7f504cdada5ca9bca03cb8d12acae474ae4c8c9cbea8eeee65ced81ff6a8de7ef8968dbacc108d9ef4d00bc174e1cfeb49edc8dff022bebace3dd70f1b92bfd6dbf5b3c3e759f289911090deb1cb51ccbc991ae42b0dfe528edfd5b12aaeaff4237d9cec8f15137a3f85dee0200a68c052dff96ddbaa4b662cf194c16fb35debdaaa115cb7ddd6b37cf33ef7ee8b93369ae183455daad9aa1d90d5dcf111cd175086d0bc9aef2a7feecdeb6607ac985cb2ae2dfeca9bbf85b35b044eb1ffbeec3f1ce193ed1fdc4d4ad6f0da1f9ae33c4ecedeabeb9c4f9f3e810c6bafa513c654ffacc4bad10bab9acf79d5ef43efba99ce5cfae68dddf0695c4acaad76d7be51bbb1dbb71fca50ecb049febef848efee4d04ea99c3bfebe91a5162ec3c6abbfc05d91b844b8d68ca527a0f11eb53ab3aea4b1affffafebfa23ffbd8ee04a5fea3cb0ab5bd39b45b0f9f0d1ccaddeca0ffb1618aea12485520fdbf01a6dcefaf1deddbfd31b3fd03a0d9bc02abbdbffcb1eddcd64fe8d5ad05d5a4effc9213b754afc7a5bca7382a53c5425eaeb5eec581c2e9ec92afea02105fac2404eb233de142bbb1d0aaaef6ad5c6893ee3acb7c33d2ebb1fffd504aee020f876f8822aaeffa2b6f6dd95babdbd2f5de1acf9b5e9efa1ceb782206e0bd24dd2ddc4d6637cf4129da46efe25f3e33277aab1bfc1eca13accee4abb478d8aa3cdd337e78cccd7fedcaa9dfab9ea35f2ab29a8122b7e9b9afcf7faeddeaec79dc860606fdc64c82709c35fb15cac88ad4bbefd971b6ffbd9ebfcd1cc7a4193ea6e68fe88f34601839b8abd08a64aeedeba32be321ac72c1ebccec8d8ccdfe46bacf6bb7ba05ea5d7d3b857efaa17ecf075f2721629d42e56d9d7e7a3cd2bea68f4ad022eebdc57e2cdd797e476d35546eed6ab2ffecaf80c65dbfadacb250caac5bb3b5dc5794c08fe7b65f5a6e822b1a8f7cb1214bbf900de29e25fceadbdbadc1aabd198da0d2dd4a94bdca4ecfa4875cebac62d9ebd3cf84da4dc3436dbd8426903cda63cffca5f5d9ca99fa9938db7a156c2ffbe82a7c918eb65dfc0241e7328cdc75f12fd5a6d10fa3ec77a83ccebaaff755b7cc8b03bb1dd7634d6e6c037c46a696a3bfcfc356e69ad5e5fed71fd02ce310fa9ed5a67e51df9f96cce4b8a3fbcdf2fbe9d4537633b43cedb58cdeacb3d45ac9a78f6cb90a9ec34cfc96b22ccca56a98a9d1aa1ace29c54fdf3eb05d4cdb90d5cffcaeb4d8b0ed0fe09f6786cf5f2d44dcca10febfcdb8c9f2fb03c058f4dd6f9a9ced931b98aaabd1a7abd889ac0adbcf08f0f310d57c3a4a18caaba6bb27f120ce2f01e57aaab3a7b7fdefeea4345af5c6cacebf07112a3557004dbccbe4bef9fbfdfad69fa993bfdbbbd8e4eee35baac56dbbb1ad04326cfedbcfed3badeabf8ccab2883f2a9cde0ebed7befc737bf48b8bcd84bed1b7fd0cdca8bd55fc2ec3a4cabcedd8a25cd5dd5ccdfab3bd664caa3e1ea6eebad9e3c8bca33293eabc78dbe109c99e29e6cbaf5d08e8e4a6108dca58fdf42da6e25bcdf0bafd9b3a76baf8be35dadf5ee3fee040cfdf2bc6ebf0ebd92d075ff9fddf3a8fca9b4b9eaa3baed2d3f93581fc5ecdff6ddbcdfd8ba27bb0d3cdfe263c3cabbcdec08e57cc6bca02a9c400bd0de7bf66d13dbee829aed0f5abe2cb60f459cb44b786fef739d074ec7f37bbf4ecf710388ea669eeee64fa8bcf1dcfbedac4baf6c2dc378f6e78f2eb82ec5abc1b87069666abc3d7b87f4bde2bdd1edfe7eabaae27cd34ed1aa77bb44b17053eac0617adbea9ecb2f252eb6ce83ba4cddfcaf5fefc9bdacf2d43b7dbd28b8c737ddb09f6bb99a3a0f1fe6b1baae1547c108040bdfaece48891c6ace9ecc60bfdeffea2dfbef4ef093dd9fe18f31cb6dbac3ffeebfb8bafa243ad2aa391cc3ea88cf11fca6e1cde97acb9dadfefbce53af0f91cfe5ba48ebdcdbb5a11a0fded6409f546afdfb638e3f5ffce7cdc3cecd9dcf505d5a3bafacb9fdcaab58eb6e577b48a1a3f75bddeb1abfebd5bd1ab7cdae8ac18eab824f9ffae9abe8cbfacdb6deac1c02e93defd5a625bdbfcede7efce4a8cf13bcdaeecafae7c74db0e2ac5d85d3b28fbb5bfd5bcdf6ad2dd1deaa429beccf5ff6ab5dce89a92dbbc5221aaa193b5dbcd4adaa1db1fffaef747ffcdf9cbccff7a7e20b3f3ceec08d2ae004f7402b6dcc5bf10d1dec0685de84cfb9ffbedbfdd2ed437092e460ade9bfbadbfdaa9d6413ada2d8cfbaac5d8496e9f3f00a0deac9448dfdcefb29e9e5c28a69d334ea0e8cc57ddea7cbc7c45497d59ebaae627e451d9faaf35251ca5e86afc61274c9d6bf4ebe3bfdcfecbec780c3f20a29b1bcebde5b35cbfeafb0ebcabf6865bb1fbd99cfd6683addcb4e885a3a7e08d9ecdb696ef0b90785e519ffb652fa75bfb8dbe5bbc4eca010cf2cfc98330cef9dcd56deaec3afe1bb8ace3018eb10b8fcc8ea7b2eca096183acff41dccbf1cdac4d64fae3ed0edfc20277ea97ff144a3f809ecec2e699f7ffbe5da54aac0ea39d3ea7102dbf226ac806d07a7cffc602dd5dca7a88e8eec18dcdacae10c3b3ef5c325be136923dd7fc62ccfdee0ef380a9be4d89dcdbdcdcec560febac1501f377abf5f3ddc57aaca2faaffa37c490bbd5339a9fb3a1d5a145bf40fc97ed8cae35da31bb121b8dfbcf4bde06c817c8df949af1e35ceed4c1b7248d4d25dfb75b4bcccfda6aa9ffe57cd985ea02fb0338de9a43daee2d028bc1b7f4b2cfc32266f1bef19b0c03f53fc62e2c58db9998ee7be0bde4ad5f8bac0eaa7a3bfc2edb79cfde1bcfc85aaea9bbc3ec0dda6398eefe5b6e1a440c94e3b8ae4ea3f4a16f29cdefdecf49ab9ac58f87d811b3dd6dbeff7d328bcded2a1cabcedfc3ae7d073501f6c877e2b6822efe46b1ea3b69fcfa29971ad938cfc34bd4dfdb3be3a7a7f7d54314dd2d13c87c4dcffc3be79ddedeae27544cdda357ab8cbdfec318abcdb84e3c82f6972f3f2e07df51ed8e969ed9dafa3230c8caef0f4438e19c3eb2d83bea9988dab37d19adad78cb31de21eb4a2a3fe7fef1d72409f4d2b0dbb2603b0279aabd7bff22206ea8b3178f4ffd25f2c2e1d11df9edeaec10bd4b8d178b0bcbc8cadb75f75e86bb3fe4dacbba0f40db5031750e5f6e2be91ee32dfbeaa11be7ca775d521ea1d7a2fc76f44ad0a038fd8db01463ee3aa6dab3456a1edbdc3bc241b1fa0ba537aa3ebfaea319ab97f269ddafff120dde3d91343ddefdc9dd1b5ff324cf9218d3627e741d165678afed7fd24cf1966b119b91c75adea6db2a3a106425ef7d6ed715964fa909dc2a4348b31e1db6f39d83c5f2db6eecc8ee4f1be24a8e7edafef6ee05a45d4a2a8f72f3858d5aeed865ccc2d82e4bff9deb9fd94ca212a3cd8e0afa7e2affa9806e325c24fe8fa2d80ba4e2cfb5f1b032fddcee7f3e14fcf2ddd6d666abeaaac488faab5d75e09dcfee436eecce2dc29fe1ed2577a5cdb3ab7c2bf34cca3b6bab8e6436f55ecd0c91d9958cc5d7aa06fdea3faee78af3edfed3acf1edf2f4edfbdb65bba4eae8c26fbbbb273f1cd2681b5d84eadf683c9e0bae26bd7ef3be3c1909bb49afeaff1265d5d1674f8fdb0d2d04ccf4657bbed3770fefc302ddaa46ec7e52ccef7ad9a8eb2e6fbf0b1d7f1ccdf3a7bfdfafdee8b8a67625bbee09aedb7719427af364502b7df114759b1d4c838f5f72fc76ec7bbabd06d49eecbf22f79732eeebb1b607068baa40fcf6bfb8e2225c9da6bb62dfd2a7f1f2bbbe48dbc357e6b2aedac8ae499bdee2eb4fdba528d59beff79ffbf67dafdb86ccc161c3fb0fddd9455da73e8b5aadfe0c9a3e2c29fcba27ddb1fa7a50ca84573b38e78daac2c42fbbfd2f1cfa98e9e130cfda262e0ab55703dbceaadcfc62ad29d95accecc0ad50dfee8ec449cbd8ebfbe0777977cfb35d3f3d38dffd53ff6d483f951bc5fb98bd46f57079f32bf8a1fff124f335a79d6d31feff9ce9fceecddf0ab1a8ba9339a5b5eee8c8eba416d3ceba25a2cbf577cdfbd8122a976cbdb4467f575d6dfcdabf50598db028909fcac21d7ccfcbf7fd4cb3e304beb2260ebcbb2fccaeab65b9d592cf4d1786a84db39887cbda0b5f14e17576124a696b9cc32f3786cbd90cf4ab4ec3ea5cfa78b5bbde7c53feeb8efcbc09bd5a4fe8bb8b4b4f6a77dd0ecde2354d9cee7bdfca0bcee282dbc25f5931cf5effcafb38862f8ded3ddedac0a71fdea23e50ff1f72ef273d80dff32afcfffa6f773dfade7ab1ccc828d6edfeccda0cda2af2ecd7f9b0d8fb5c81bfdf55aeae615bf6fe131f289d03a8fbcc891e348c3001dd69038804403ead326b3c335b7d3bfe6cf63efefd760c37caac5b2f1821cbfecdc97aa0e44b93ca9eff9ff38ab6fcf6f4fd1caf5188ad1ac2ae26d3b0cffa2cba0e6edccfef02eeedeea6e8ceaf2d8c1eebdaecfbec854fa42aead150fdd39d5de2c8b57d3ef51dfa5e1fecc5eaf2ccaf2effb32a17fad3c6b42d58c6cc6b33ddbcbdeda18bec057de5f9c88bd111de9ca2e78a5faddcc3a00dd4aa8d8bda6ffd72fa687edff606fe6d037fdbf6aeb355af2cfbdd0bedeac196f8bcc40b1ed3fd3c87f6a209b70bfbbbc3b5a7c13fcb502ada4b02cddb7dc9eebae2aa0ff94f8d7a7866bb43c4bcc7ddcbfffc4640654326fab4cd0ba0457cd3ecb74c07bc3ffd0dee632c3daeeafcac93c0d5edbe9c0a56fa68a677e5aaedc3ba5e2bbfdd06f7e03498c1fd3461cea9c9df0bc300ec6cd8ae1ff6c2cbfe0f8290e1739b8babbb91032fe7aab20c9ca431124592f357efc7a892605caf7af9f5ea39939fdb83f8cd42a8debbffb0fc3c5dbd72e9cf40720ba175db1eb68da563cb0aebedefecda1be6b0eb0affafd26b6fdd87aaf5a1e0ea4dcba2319cabab596ff9dde5da1a9e8dd04fbaeaddacbbfb62fffc991abee21a3c1facbe9f561f22aa1ffedb8a1eb672eccde22244eafef6ff1d8efcb50ec1c28635cbefaded98cf2c260817b6bcd2bdccf783a5d694a83303fda05fbced36033418c06ab9d9e20f179cd1d2b0fe4cc6cfaf04ced9e712c28d7ce6fd19f2b4a05bd3c216bfe6feda5fadfdddb5afac7de84dde9ccb474f18a1dd1f9a34bcab4ae1b9f6d3967d4fabc2f5a7adfceea5692bc2c8eaa6beaf6f127da5aa0ace539a5ff591cd7fdf543fb32fd976789ff7b9dcadccf4df77d9a5dcbd56bd7663e77afa8b4fd5eb9054f3f1dd710914a6a6de0d499cca39e4df1b157caa79b1f7b13d07618cde9adfd089fb4b1b304139b7c89d2f5674f0eb5ae9c6ecf32740af602f5c5ddca550baf7eb1f86a2b5bdde47cb9ca2a12e809f7034e3ad6c7fcc9742efc1eba7b9ba69d93f3f0d98b7fbfed64fbb0f3c7cc94348b090bacd7fe75c7b4f9d6a83bc40cc5e83e12fc2c33bf7dcce1731933d25bedcdd6f311c7f99dafa5ebf250cf24528b3e5b26ea07f7dd7fe5f9ee2efbd3abf55b9826179588feee6efdf6bacb9d69f8c39eda97f0d9ee28ad1ef1fe89cdeffecad2cea5c2604ac936f0ba04d1df0ffeb8fbc9b42627ec459cc1ea35eba8bdb299ae1aa29aec23f3fbdbe86affabc3de7cfaefff0bedff5a0e9ec4f08f288bf9d575bae1d2fef7332bbd5aaabc7af61b81b6a70a87fea1a430825feddb5f75d23ead515b53020dd2d3ffea9c12ad1a8667ebb8e1caa6fda8f6da2cc0af3261f86bd8defecd0f9dbf5e0cb3dab91d4d59fede9f612cfbdfe396e033ffa6dafb9ecda8de3de319ea0edb60dcb14fcded6eefbe2e0dbe41ad7ecedfc5cdc6afc7b7b0f1de3cd680bbec3c9f400db186ae5239ea2c5488eadf78b3a99ada5b857fc01946afab4ccae0e7db65a58183df5becd98a9b70ecbb709d4d2f4ac2e9899a8b71bbd34379abd126faee09fa428ab2bebebbbd4a3aafbcfd6b1bb0b05ec1a43cbddfb1d3b992369aa555a89a47e072a274ab53f02cf94a3da83daa81fc9e3bbf8fd9c0ab5bfa39a1ee72f87bd4396b6b12475a0ef8a68f5bea4b31efaac9c8fe3b1b49d78cfa39ced7dceecddbf8eea51ef8b2602aedeb02ad5597108b712c638d5e2d1ccbe3a6410b4983e52fb940abe4d3f3dfaa0adcfcdce252e3165bdadc071efea5b22ff5f1e51b0f8cb58065ef4ba7a1cdc6c2f033bd3538cab0e750fefa2b5a7127cbff6d58fd4839c43af579b5c82c114acaa5fad9dcf46ee3dbbfdb85410f1eee187652638ef733fbc5873751fcdad20240f23cc6a0bf5130f0cff5cbfd0c80fa2a5fc306fd0eeeb7afec8c8c6aedf806b01fe0a65a49960e5d5eb13fca1eebddddf3756e0d684fcde612c233aecca278b53f76a8b8e747a9cdd31f0adbf1d5fbe2a938e7aaff6cabacdd5aaa7f1ffaa6cbcbed4cdb37fbfa2d5bb9d6c150181e22ed40efe1c53c02b1aa9cfe3b68f4b353dc5caa5cfb9d5ebeff1e62b3ca8ba3b43bf0baa81fcda8cb06cf3be04cab9e2fccbefe5fa4f09be1bbcdf0dabe4af455c9bc9ded5370fc8a44fde8ec96ccf5ac3e0c20d2b9d69ed12b87e7eccd9e08f25f304cee5bbcd41b9beacc3ffbe3ec989d9faaa0a11ddfab47edd8e85e91b52bad037969ce1ae6bb4f28c4bf511751af591dbb317112ce691fdc2be1fceaa8481f6adc4fb43e68bebb0d4a93b77ef6a07d3edee5b20e56aa4abcfdcfdff31ef23f2a7160e00ffa3d8f8fdb7acd6dae3ddbaedf76c2d808eeee467e26e3f04b2a553deffcaf8a7fbd746925be42fe146a56063bf1feb33cdc28bbb0ddae9e8a2bead0f27b83efe8dc1aaa5f6aaafb6e6cf57dcb0c3f2ee49d4ccfc66b90b702ffccefa509bb62faca7bda316fc7aef9c9d86befadab0571bd6ccce31d0f93f7deab8bcc716b6c6bcb1b4dec6e92ed49cd9caa259ad62aaac6cbdaaedbba55b42ac90ad3c213fe0c59ff3d16ffb0fedea3f910a45f69a1c3dfa5ef63e8c3af12dfe5a9e211fa92d9ad9cd1fb580ab50d1afea6c2c3d3cff5ecccbce63d3bad3ac18ae50b0f166230bfc5a582aaf34adbfd05a9bc63aad7dec2e2dbe3337c96ca3d207de0aceaddcf304fffce4c7beda69d9ca7a19ceaffaccf3525aaab7f3a1bb3e6e62777e9cc67ffa4da4e1e52d5e89e4564fe4fc37dde6cbf1ca98cfbad509ef1df062f9ecec0ba27bbeedc6c947fe844049a3e8e97bb2166adab6118be875b3bbbe75cdd4a7f57828c6e0b35270f257e3fea36d65e51a45431c8995e15b78b35f7b1bb6faffdf6bebfbfecd3db007ede82d83fe6b81e73de58d93b6ac4a4a7bbb9d240fb80ffdbc9ec061eaabccf361fc5d3f322c8a5ccb6acc2c0c8bec5a2c5c341fca94bc0c5eecdc0b08707766bda0d0ce2fa10b0b31a9aecfbeb1be9c5192fdd5ecf683b1f69cdfb5fdf6c2725135deda035c9a8bec755af712c5dcbfc40deeb24f8324c06b2e7fdfc74127c3a4ade9666bbb115a05fad0516deb93bb9dfbe8828703cfe3f5b40fefe9d5514b06529ee306edd67edb32d0bcef9b027aac9dfdca24f1ffa62beb1d6ea3f77d264dfbdebfd82fcd92a9389d7dac3dbacfe3becdfd2a784f4390c4a65c8a6138485bff692c001dfcd1c6f87309fd9fa4bcae9eecab2692731df4e86a46263295ff174385ba9c1d6711bfcee99fcebb9c1cf5bcab1ee5f2345e6cbcefde444c8e0066e6fdd4e2e26aa5bb0dcec4ecbdacf4ee920ed19dee6ec62cfafd88ce278d12f9dc4fe42cca5dde597eea4cadeea986efecb2fd0fbb438e9f6c1aff99f41aa46937bada8a42da9ac31abb5edbdfabc3514defebf88dac9e22a2a5bd031fb3014b8c07be21b0bee5cfefdaf6acdf4df0c8d42fc0a3a0c9fdf67cda93cd5a6f181d724da2ef31726abbd7eb2de463905f3eab2ba995a1b55fd09da580f09cfd9a4bfbb45d742dd1da36c2dbef00af73c5beccfc6cdcf1d0afef03cfe3ee3daf0e7433b5ee5abbfab3570fce94c7921cc75dbab70d3a213f8bfa10c7af3bce8ef5aefb3adeddec4bde5abd41baacc1db6c6d24ae13b8245a1dc57eda5cde15daac8675bf3c2587adb1eac70772adb42a09061e3fcbbd6ed5e8c0d424fb2ac589ba7e4059835a95950bb25af3cee7edc15fcda8c31365bddcc22ac1bfe1cdd5cb22d5b27f1d0ba9eeabf84db0cf0e8cacaad7cd5eee4d59dddbb1f3f02ad6ddcccbce4c00e8ac7d559cfd72eeaa9b67c89dfdfdadcadff7ef23c0a75eab56f5f5890e80b37d943a87cd4d6f2ab383947c3db180bc9a0b10fea8ffff94a8398af31a2f3a9a058fb22dfbb3ec00b5bdfba5fee78b0d6f1ccca41c0e11d72de9ddf1ff6ae29b47503dee1d73b3badee1b3cac974a636e5a9ea8582fb25a2ac7444bf5b615821fb7ac7fcafc950ccf6a0b5a3543735b80ae527ded5e8996c3c9b8404a59f5a4decdf41aa076ee8a8b6fd26ea2cf01ae1edba3f46d32b3d8e7c2bc1c5b6a8fc1b5c6ba284c867dadecb19ac211fb25abcfdaddb2f9a481f42bcbbdd45f20feadbcfff8dd4c129221c8b9dd2daafce6ab72fbd15c9dc31ba63baddbfc17c94b003de1cb0faf9df5dac707e6f2efa5efda0ecebeea14a9cee696e9a5ecbd4298a24149ccc7aaafd7aedf62f613ea5c6c668eb505cd35d3d54bd1fcdd5a1c75bbecfecc6dbca88d8c844fdc842a12f9a6d29cebad1adb6a5acfdb0edc88deac1e02bf1a623df7aefd1d5b71ae42f72154906bb03b05c2bfd267bebe04c9aba47f58be8df8becdeab65c700ea96abef64ae7bbb1d364fdc0da6ea97db855efecba2cef2c388b4ef217753bec2ec0d88dc7a456fb9cee6beed1dcf7e6bfea51fade18a8af87bfe0b137ebc0e6c69a8b0b5b637d391cd839eccd889ec32ab0ec1e12dd8a8ecd85ded77adaaba9cec994bb6bb8ecf777b29dcaecb7dcbc2bd03b44cefd41c0fdfee32d0ec9d7ea39ee72fce9ff47c2e008eb51e5e134b7bf48a09be9a0bbe94dc5ca0debe599e9e5b3f79b3a10bcf6f0d95bebac6b30ab028e9b849854a79bfacba9a2911cfae2449d8ae015a720bcdb33fcde0aea4b87cc0c5abd62c51eb8e89454049d83efed6cec2f7fee544dacecebefc0acf6c6ed5dba9f4aa1320ade5eef6cc8aaec9a8db90765abe2cbdee02a4c9818fa52b1d23db8ac0d1e6c7de7b6247f6e7adcd12fc6b1df6d63d5dedae8710e42ea8176ffb2d41065e9baf54cb6ec499dbf4a2c76697ac9b0ff65e02f9f34cf4aa806a065e4f7e70a41668be5ebeb2bdf98dca4fbdb66855d5b1d8f6822f794efbdcc9e56fd2eeeaa3e1e9f07b22cf5a4ee1eafa2a7aeccd5b506dfca5eb0d4dff46ecf99db060aa0afcf8fc4d9e00ffb5ec2eff8e06681cfdae57ecd7b1f4be36b23ea5bea3b4d7aedb42c7c483c23d03e835dcfbc16ed9eba9fe7ba88ffacfcaf4d051a7c21b03621e7adad811afc34c7be8cb4beb96ad5a262bcb2c3d7883fc0f0afbfddaefa51edeb0fcc03e04b35d3e2c0df3c57d5d51fbe48e2aafbe9363ecf61ded37835b1e133bd4c6196827ceec7cfadf365b5adec722d4b45df8883abddcd3bbba9b3246d1cd0b5baa8d0f33afd0eab91c8fb9705d67b3081597f8ccbfdcdfe94a10ee9eafee2fbc9dbea077a10bcc6b7bb5a9cc6eee7abda39d7e00bfadf783772c98ef13f0cd2dca2a3ad332cdb4634e988b21aadb52d4b5c7ade2ee0c4d248855a7ab174bbefd396547d4eae4be0406a31fafcd2df2bab2c996ca7c1d0c01d15b6b15e3afe553dc1cd675e21ce8effbeaa8b0aa38461e6bdfe42f47caf4dad6033e0e6eb09d18b32fba1d5a5fdd39fd6ff612950c1a7f178f1119adda695bae8d86bdb0c0ea853e1add3e044bbc8cc5fc1df87f0bdd5a9fd07b34daac5aab1dbcc51e9bbc1ed5fb9e2a542eea0fbd2450ac5bd9d0b904172fb3dfb58cd77ccccdfdba6d2c9e38cf0a2fee5ff53c3ab50b78bafc475e00ce7e5186fddcef4cd6a9b5c2decfcdc3cac26d6c6cc0a5b19560ab4c4baaebeee34eaa3e8e5b8811decf8347abcd025ba81063370598a7589b445ab79f41b20bcacaae5bf6cbffa7d72ffccb2cbbb0c56e4860aefbf19d3e6a2bd567abf399d0df95aacf8e7ffb3ba3d3bdbb2fe2d4bb7dc604d4fddc81ae01d9e4bfcf0dd45ee7008d71b719fff55b379a8df907c53bb43c561bbdbd1e452afa7ba3c1a4d911ac2ff9b259eb243f72b816af0079e88ad20fb2eeabc14bf9ff8e6b1bb25ac9b2dd1ea958cd50aeaf59161caaff06cbdf9a4ccba4e18ee8a9ab7caff67b4e3b7855e9b5a558fd06167c962c58868a919a070ba4fac9cbdbd4af24cccd58208921bacb8743f17ba776c1bdd0bbbcafcf7d0cdbcbd7b009ad7d1ae88fff006fa365c5b1dbeba9fa9a0e9dacee3b164cac609ff0e0aef68e8fc3f16cdf6fcdafdbfaabd8abba1fe75fc7bf34eeadf8c64cd02d1ded5724da2154e9cd542a1ea907c673ad7ae7e37a9b4fb92aa976b84a39d09feec11a266bd5eeb9bb5d9ad07ee309dddabdd4dde0eb8cf12bccbdddc285cd23c22626976cc5967ea301adebb6e6eec3598dc863faeedb1df05be55c69c20bc7dda588fe8ff2bffde6e6c080acb9f83cbeada2cec1052aeb53ed35459c2063c98aef9c8feb04ff6ffcab9fc0d8cbdc2dac67c6f7d66db74abedfa2a61cf9a9fb11c3d228f8c1ed6823e3ffaeabc540f9006a0df8d1fba73397ec5f7c681ad8f16abfa4249da7df2dd0c67ff7bfa389c1eaad6c322be154e40faf13aaee6ed9d2b9804a82af2ee6eb17eccbf7a54b4e53ccdc4e0f7fd28c048ddb74ea91d9cbacbcada3beb82deb95efc095e0e9fcb2f4218f4f106be47bcb5d3ceec38edcb17a3e5fade27ebfc3b54d23a0ccef2aaaab9438f8efce0bbef1dbad649987e4906fddcbd9231af63bddcbffe0160edd8b4a3fa56f6df5b0b1e8eef9164cd5cdd71fa3fcbd5769ecd911aafb782c4b75e0dfc3caa36ce14ad7c3d6cefe2a25a6a8ac6ce7b7eb44fedaeecede51dbf7368baba94aabfbfeadc2775710bb57aab6d35c2d5c4634d04bfbcdf47ca161b2eb922c2deccecca67cbcf55ed6ec8ffee94c6c2a127b46274ed32e6dcb83ec81b9cc184aee1fa6c367f34ad35dc4dbb26f7a597b8bf6b0f18a9d72bf5d1bb8deeacfa88c30dee92ab68a0dcacddf3fbabaec3142b6501d4b6bf2503b79df6e4f8b311e42db5c8dd6bc1dbf7db6ee56c2ababadd2d28de719f1dcb93c4ebc71fca1be4c572cca51c72bcaf1b0d7c05177ec7af67894eed2eb04fdedf0d217e9ebc7ef47ded9cf27dd6a4b67328e82aeea20fc7fddfdb9b56faea9abe10fcea6a8c339030d2b518968fa2878dd4e1b133e9ba8e090760bd72ae17ff0dd0325ad3deecf81fa7f1e952696ba7ecc9e5edab3b971940d80ab5114bf6098b4ee90c04bbfedd2aaaab2dc7beeb3ebd802fdf1caee1a0a0cedf2a5dfa0ff3c2c67c83ffe1867a311dbd62ecb3795dcf5baa1ee2a4e63f9724e72deb9ff1ea472fa1fbbbacbef85afe9bae7e85b5acbcaafdbacee0aa8790d6f390fc0e1567aa16c56dbbf1fad6fcbc90aeb74eb61d7c09ee57a54c209bfd217eced632464b46e4c52b27dcd9aaacf0abaf69185f9bda253cf6d28c20f46cefa3bbc45ed79adbc9effd460fad4304a561ef0ad14fcf0bbd930c3deb1bf9cab7c1d5b9da8077bfbfc11e3ffdee5a88fc7c7dce5cdf1ab5ea22fae25476db59f88971b7a6dd8f14e7cf13aed9aaefb73e2ebba2cfae7bbd4a0d7cb2c1622c159b8dd43a75ed85140bda0afbd79dbc0c37e49243f0f63fec9aa1b1ed0e293b8abace3c4edc67bd9dcc5d2fffe4fcccbbd97d093c44e14dd428e9eea563134d6aed0b698bbcfa01feca297abefa8da4eccd8a6a5ad8ae99ceecdde3054a56caf77cece6d62ffabecaedbfeb0340036b4df96df166d4cbce4672bdafaadfe126cf9bf0aca7c7f1df89bdf1a194decb17e898a44efaec234ec72799850280ffc93aabf0bdbcfa3b0def135ebce2e62d6cd52dff7c23cb35996a8a4ba85bb6811377e7bd3c15162eddcac337f99b4e1c535e1565f92905767da2cbfab5af020443beed376571ad736beeccf3afce3ef5950b1f9a0b8792b948c2498d0e427e62a1c2c8781e93aa29ad13ea4ba24cf0220a5165b597e1edcb9c2ddb3a54471dfbcbde5d5dec198cfbb94f9dde8f5c9be9dddd5ff4bede64360f28558bbe6dcc8ecdfdba0b551b04d3fdd11629dc36cabe39dd8d8ddef0e71b4df2fa2aef383f0a334153411bfa8b7e34b24686faa04a4f5dc8cbeb0fd646ef4bb2f67baca4f150e2a16befddf3ba1fb9ababc022e0baf6353c30c8fe5050b21cc19bf4bac5e03cb3daa2e4f28f3acf932beff34e1adc86dd2f1580120dbeafbec08b1b0ee8b3a60f2cf2ecddea8dcbb5efc8bde1e481ae5885abab2b89c52918fa67c53a0a731cc787c04c1db2aa9dbd25e09ddc38cbd9eff7bef31a4a5c50adf9c8fbeeaef17d6dcd58a6a4eb4daef9ece1264adeba5b81ac0fcfb66ee6eafe5b0e0d23cb8e4bdf2cda2a8ab213effa000dac44e130bea89fe82ffd63dfff95ceafa2c2ece8cf3adcff3eb0b76c93121794a94dbfcbdfae0a7fed33fd1bdddbfdf5a9befa0d611a3db0dcccafb75bdef8234ffb88fda822ac495b4d3cdd2ea3b2ddd0ceda5a9cdf64ebd8e50fb66706dff86eaab0b492f6720d61feaccfbd95c6ac8f9744e1a18c7ddcaa6ea32d0eacdbeb5be490e509de9b29be0ebb6d5e8af0b9be99cbbec91f7494a425f5a44d0a9c660d1d5770ae6b1c1ced9112db0e0d04af2cf47aa49c1dba65de9f3c6428da3ae6fed68dd8e986dc4c1f950e4aa2cac88bdbc9b63dacf9de13dc73a9c006f4d79eecdacc196b74cd8cd05d5c282c90dabb3c1df19efed0c535dc96d0b8cd2dede98718a439efa6a3da062a2b75e49cec2bbc4cbe9d2bcac4237acb619f46b5423cefbcdfd7970b3b04fda46f31ecb4e8fb6dcccaf8fdd7896a1b55abedad7f1a72c3a3d6dc38b8dd95d69fae1a03ecd5e94dda05b1cbe869d777ee1eb9cfe64f5a07deea07f8f7ecd8da18c7bddb57b9f6ac998c8e1cc02c2ec6f6ba7c0a89abb0be3662612b4ac91a363f03795ca2defea0cae4d3436dad0af1bb9edddd422fdf4a8cfe9d57eced5ed7ebdf6b6b500baf93d848fd35ee3d66aaa383aae47d44f5cc5c97cbd0cc9cade59fdcfeba5ed5b6abf0d2aa2bdaeee9ba8bddecba3ac025c25c9e1dd5e60de5ea0bf4ee47edb43291e40d04660e8d66ea3d38bbffc724f1fff1dbc8fd9f476cdb1a4cedeac2c697c35cd8bbcefda60ded2ec9dcaada46f2eb903aad72914c750707bfbfb2bfb7808b6c2afdbd7bcb8ecddcfb376f898a89dd9f85a4e051ecac4acb859a9deb60afeadfbb61d7b0ae11eae23a981109221435cab68edaabd3ea4d83604664ad883bcbe25dfd1956b1e1153cf12deb53de212f69f2b55dad976a696badf9cc4a4a2d76e8daa63eae6e6810bcee294fc2bd4a81cf99cee83eeafed6e87bad0683e17fa8f20d12dc8baafbaf14ad8c1a1393a2bcceff332ccdf0cddecdd01a5c90e5cabbfee3ab50a92bafcebadbf3f012daf0dd3c8b5b9e0ee4d6471a1ea07fd3ddd3a87d7bef38a629f334cda74cb9f2195a5d4fea09e5054bfa9afda2ed2feee014aa47effc3bb68c24ef2af3e4afe57b51e3bdbda709df7dc5a39ccfb74fff40eecd96bd09ee10270bed9e08606cc304ddbfce8f7b16f180614e4f6fde58ffc5d5efdcc283e1fe3dc28b4ca5ccd4c234bddc3f5a5eb6ebb01c7bb8fe03c99717b00f93cee37c9d5c69e31e2bda86f48380f2ec3b9cf095feda3c158e4bc2b3dbba37ded177e016cd05b7d185e0c912bcd7bbcda5160efdb3e3f9ca176bfd7df91dc5a066afedc4d5cb9d3fac0d9b9d30158c239ebec81dbad34ea33bdca3eb1104f9912ff7d8f7a5ff2eaf3f0be4ccad26dbf3ccad9e0cef9cad4db9abb2afa4606eea3e6bca41ca5a0da6b4f9e52ba78d6f558caada5f3fe84bed8a2ef8668c65dde3229a2afbdaec71fd00ccb5a9bf6f7f7cd2e228ded13ac98713c0c0fb75fcdb3eebfbe5039bf8a844cdfab3b223afdbef96045593abaccffbeaffbe4e7a324f8bdaf6b4f1ed443b77246bfdef5fa7ce3e79ea6af844cf7232fd01f0bbbfc2583400c0e0bdab18fa0f10ef2bdb0d67a426387cd8afdfccbb83dbe40466098959aa334cb12be8baa2e9bedd48552aa8fbc9aaaf5ee106adf54f82a18aaaced0a88daeabfe4e9b3c76a39ab570ce77cebcf3dbf4d55065ebfeeaf7635c04bb1b1b1fbdf00a042835db1703ebbf4a984dcf3accaee812ac18b94ae2d05dd4df219cca71fd2bcd2eb470812d613fd4245bf4a28a4d6d1a6bc2a74d9bc8b88de49b90fbe8dc9d1ace77b1dc6aac69e595dacd83d3fc66df7db8926baad08b0490dfd897f3f0f0fd04a615e32dbfbc2fb2bcb2bd388c989bafb3cbaadd6bbdeca1d17ebe6b38dccdaca9b4a4bb8aa79efae78554b2597acaaeccefdccafbeda87fea159b25bb8fc2b2efdf395923df142ca1d3b29fab4d9d28bc692bb1f8d2f9be133cafb5f3dfc36da8accfcfd443d5b2fed6e0e16fcbdbd3a221000e10ce2286eafa9cedea9dffa625cfdb21bf6eaee51d9bb4ee3c4f56ef1ecac7aaada45eb27ac6fbdbd4cb1806f1067eaa4cbaa0fdcac7fffcc19ba1d9d8186ae7e2c3efee24fd2f6d57cf1e491add5f47cbe4bff68113d672bb4a7f355d2de0e6ce7c0fc97e4bd13eacefd5ca7d8cfeef5eef3c43dafcc3eb37dde9cbae1323de4ee1be6dbdab7cddd6c1e2e5eb8ecc8eacced9d7bed9c6ebb4cbe9cd112f4cc61cace8e3859afefe6e140bd5e5f8ecaeddd6f53ac4b0acdacc5bfbbb251bac28ceefd9322e3cea0ec2a1f9dbbbaed7dafb70c61ed7da69dd0437ebf0e40de5855e80cce32f4d718f67fc7353b62a550fa7af48b8db65460d18ed01a7e3f5acbada8db9e6f9e5eaaaec88c555efbbba0ffaed0ebdcdde7df87efecc9d61e3c225c14afcde95c6f1ea374f83e2aa9beb89aa3c980c8052bb3e81d0d3ad5f2cc8af8f1eba69ac62f83ae088b3bebb19945dfefbb5e52a4260ca8d4f2ded26bf78fd5f0ad8a369affe6499c6510ac9f3bc8bfb1192a8fc7cb3eebefd87a468b47fd8d5acebd6f0febfbdeea40dc1ff3dfa9faded33f8da6ffdcd9d395c9178edfe126cd329ccb6aa956cfebc877ae5733ead0d1eafb612da3dd4869da5fa8b23eba063fdde0bdd764ed0cd4d69e3beb24c7fdfe26e0e2ebfb54706abeced452f95875bbaf814e661b588e7188dfafba3eac4d50e68fcf41fdbd5468f9802f46cedcd9d3ded3ebe072ed2ff9bfad51cb04dacf06ce7ffa2d43b4182a6b0afebac91cc65fbd4a35c4ab2dc38e5bf0ab5b3b4de54aa3eb08a5fd2f64d78b57665b0fa2ace7cce7ee7da4bbdf329eeb7d8e4b0c9583adaf340fa1ecebbf8c6045ee6b9de3b26e85a1c8583c13cf9dde06eefd067350eec8e86b91bb4aa1f3a75ca9c8faca5cb0cf85b9a2cb6aa66e22d0386a3fdeffdfa6a5aedea8d5d1fad1b6fdbdeeceadbdef781d2ded915acf1a5a35baee0feb9dce54b4f6a492639654fbb6f2eadc45d42bb2dccdc83bf8584647da5f4daeff54a95bcfbd6e1324af6cd0df1cebcdb7f0caea8813cb164a2ce3ddcff8ee6cfc6acbb5c669bdbbd0fe08c959f9ecf5f89dfefcafdadfdd0addaecb9c63dfa37dcb28840299caed58fdcbbcb2d77df23f598aeb1d7512bfbdbe5941fc1ebd6bccf459be236129ab7db60e5adf04bdaaadbbd0cc8fe43ed6fb5e895ca8aebd8afdf3bc5aaef4dedc71c5264a7dc9c7b8fe206d0de68fdfeb5c48cdec1bade8abca552eece752a0ae6fb0a9d7ad152cccfdbcc3868f4181e9c4ecbbad5cb48f728d3cd5e4ee2bba75f7f8e111279a41acc5bdc7ea9e376518ddfaef5102920628ae2ea66f5e4da6f7850d241e95da3bf3fd5bb3bbe905b3bb8fcf2bdbd508ba6e3a3d28369dd4ec26d947be15b0f6a6a82e9d3b6cd35e6ea9bdeb2160d23d9f0e5ca91def929ecfc6c3c18829bfc2d539ddde8dc36effed5cad110467bef2e6c063bc30c3ff5e560ae084fc1dcd2d2b6cf5c420b83d5e8510afdbfb5b2c3e6cd13bd8a690fe5bcea2250409c4da99ef3ee7bb48c9fdf029dabae97a13d2073ae9bab7ecd6b24644cd5f07c6af5de57ec2336d7dcfdb0dedf90393cd307a8596edb6b3dce434e5e7cea5f32df923c39aaaf7a1f0aad2fe8a5e69be02d0a2384ccc9bf6b44e10765cfd11d2cb07c40f0d4d4efe439c3b02e55af2ceaecf71cef2674e2bfb2badd5ddc9ecaf8c2dde042ab7d624ba9d3a56b3b0ef916d3f0b6d2afd83c6b9c7a5295bb3e8989ac1aaf7a279aa7f78ce9f07b5f6dc6fd4731af4d45fac39efd2e2cfcffdc4d7b7affafbf6dfd9cd2baf8e7e6efbf5bc137f5fcc2540e789e4f77a6eaec93cac28830d9b4a7266eafbfaf95ad4eb2e8ad6f918225dccc0dbfaee801c2ced9daf9dc715868ecb80a1843fbe5880e16a6e6f9b555630a1add7f1231fcde3d3ef10cdeebeb39dcdce70ddfecc908aee6ab47c0c401e85e05dde4e38b39f3b26cf48cfbeeaeeefe313e0ef0bb64b0d4adcf7bbbf1a00bcd8ac47ff10b0decfdd14d4c6dedfd0cbd9d1131deafc68e3fb1749c74c8a68bad34538c2fd6a13d75dabc89f060c85bbcc60364cf8dfcba9bcb55bcd062f34e3d851198e760ca0ea2880a3b8004f77e8dcfade8d8e7a868d74dfb97fbafde5cae0b7baebda98f003c9dbf0da5bd5709b5a5edacbf0d1f2ac71a6dd5ce0e20de1fd53aaa84c2ec2f8ae08927f958edfc77cab8ae47a210c3fb1bd4cb33aed6b6cacf2b4f5cd0f24750ddcbd2771b0c199bb0fee9abb13cdf1a4f97352b355205f1a77ab06533af5cbd508dff5eea094bbafff7dc9bcb29fcb9aced92c0eb9f88d66ff1520cedeb98edc1cc0eeea7a9fbe1dbed7bcd861fcbc9fa5b1f39fa211c8d3ba54ee7dfa0aac9ea2e46b23aacbaf8339af4c2e7c06ae7facab3e79a7df5ea1b752ce1db74fed02b8fd06ccc1ad05ef1aad26b6aa1352eeb767d43d263d82e0e4ed2c4a9d2baa6288b91dd024fa39b8cc912ab07b61961b5d702fec16cbea0058d68fde1b0e6d3ae6a3898ff1eb705cfa1b1dc4bdd31b1c1cddbac2eff8def7faff7fa18cb8b5cab2ddc6eaa89fc118efdc5b4b2ce2eccdf9f5a626c5bef9fbca8d8507d836b86b58f22cf1bd70cfaefb3fec6cb7f63afb29bf541c1d3830beb300127cfc76bc4af4fa8fca2cb72da1db0f0750afd4def0fd716c6753439ea4d1d0cb48a9fc025c2b48dab7e3e6fcfc49aae8a7fc3d3e913cffa598a803bca6bcea25635b5cb79e107b543c55dcc78cfef2ad6926e1caabacca849ef052eaaa31aa3bb9e5babfdf9b50b44cddfea0de7d2e68bb8d5ba76bd7699be75d44bfbbbcfd39fa3a2cb8f15aae24bcf5b0a58fb06a5a2fe28fb8f5eaadc8eedddf9eeabd8d04db9febeb8cff9a34c1f8aa3b53d37d27ddac025f4302fc34e468997d6f0de7b74312153f0c20c3fc31d09b744e7fe4ac79dd5293b24480ef1f5a11ee1bcedf3ca6b7bea4ee69a17a2a2a984e5ee67235e2b681d68bc1429e8bc88d02e329ebaae6ffc049e29ded65e4c09b42a15407aded8386a8d9d3b06c5b7ffe07750b13b1eb8b5a2022afa255e79fe328d8bb1dd861dbdd776bfa53f782cedbf6db93d06d056ced3cbb6e8feadaabd7d3bb4fc3acb0a0b9abdce1975b40414e37a052cadeebfb9af7c3ba4b1c4e04b09b112dedb13e2cf5c64f65bd4dfedd0e9ced63c1aeb3712af38579b627c31b69a7ed44e84bface3c5bccea84f8c6e99d375ce82deebca014369e29c9ef0a1ff9ecdea351c1dcd51ca31651fe61ede6c0e9a4ac3b805ded4cecd59d72afd9d9817f9b6c9fcfecb53b66daf398f2fc2c4add912634d9df2bbdaa555d92bc81cc2fa1a9a3bfeebddac1a94fb7bde5ad36f7822d5fdfe5a13572b0f545dc67b925b5ecd4f54b45fad26beed5dce3ac0d352a3a3bcefaaf018c8abcfadcff4f9db496daaf98f5b3e0a106b5efbf7cc98babaf09ceaf8e8fca57acdf81fa5f6aba2b8b6c0f0058c9db32baa6ebef84ed7efbe988ec930bc0dc73d63f9ba9efcb737ffb14fcfb91f11a1ec8bf5adc7daba9fe223a7ad2fbfbca60e4ed962a4c2feffcae98445c56afec573bf1fdfc4c7bd24ddea5abb26de74e22b251a1591dded73deeaabc6bc6c5aaec28eeb13f444acb0e66fb7a0b1bff77a1d0dddcc6a409ebeb36d85eae6fd6af1b6272fc97bfffe50eef60e1f3b7f7c8bf67a09b25def45f631ce8c256bce7bf6ac00fd94bee85aac5aecc9471f3ed11e307fddcc7490f28e68546ae6cde624aa35af0c5a6f5620efaddce62bf6d9ddc1bedbd5dec9d0debe0f2acef6c33dda26f8fe97aa6269e20cc346ce870eb11dbd0dce2da0ed7bb72af865e5faf1a2cad5dab88bcadd813d02e0ed3fc042b8c69fdceb29bfe5de3e3f91eb7f0ead270e952bcc29afdadbc5c3fcdea06ceeaeba8c0abcf1ea10bbc7b4c9fa7e722b6cbc4bd9be1366f63c249ccade33dca1be5ff5cb64b2feadcad030a3cfcf2ff60c6df106a029de8e3a1def7fcecfd65ba3a81cda70780561a08c98d1fa6aafd7babfbbad6f87ca82beea7dc96bf240c77bbc7dfdeaa6728986b40bf78118ee4b9d0a32d3296daff380a9d6f9ef1c2c939e515b8cf0fef7c3faf690ca8e955c2f4407971afefd9bdbd740fdceadfa0dfab8afddcafc21deabe1ca7f1acfc6f9aafebe4e7dbca427fdcc2ac5ddf23f0c9b4c53f31edfcbd0e39f284202b4cbc46744157ab85b9d1f954baacd5e3fddc69363a6ea6ca7fe9cafdcfcdbe9f7adbec288cc9fabfd7b4d4dcac8838eecb9820ee40e6c8c3a84d795661ab1d0bbba256fa984c058e0025eaf5db92c2cbcddda9f4c2f8a71c51336b1c8e6b0a50eabdad1bce8082bfadeed1e60a6f673a1d1de1badebdb9732efbc3cbd6fbf7cc2f1d7ec44e64fedb8cecee1c5ec88e1b6fdc28216d400ccc2cda15f920aaebafd1941bd8832b91104e962e1a477fc4be0b0cf0a2c5ab2ab7013c2bfe96ca8c6f75dce0b9efaca88efac9a5e3933ff25bae70bc7b8bbc7d17da2b81275cd20df80bb79abfbf466ff87a3ba6b7ef4e5efb7c66c56e2c5b7802fd8eecbd9b2d2cce751a3e1d5ad5bb9e10a646d203a5e94cd86ae7e2d60b58bcc3e0d9e9dc5d4c89eb6aed965eee8893f3c6d9fe844ebfbafc4bff2c1aacb18b254f8490f50de5acd841c5d4dcb9cb73f2faa227a9efd67dbd15a92e21fd0ab3214e62a2e2c9d87da19cbea4bbaef5d0cecfa7844ef657db8b6fa2fcaddfedfbc52e89626a707fe78d4aec6c0fcd1f36b5e875ba10da1545d9c7d55d7e8cf95fdcf0507d30bd5d2af16663866e4ddff2e5a8efeb8a300a8c7acdebacf988bc214bd42a0d3aa86f70900a0ebec328c223eb7ff2d5c22db9daa1e7fa9dd71d875b52f94fb6afafeeeea2dc9cfe671c80de3d9dcfba1a31e4de1fdf208fad81634c112080f7ed1b1dae2d8e1edfdb77f64ccec545ed8bcd59fd6dbc5cea3f582262a4480dd08509e533c1aec85cd549ccf0e52f645cde8ecdf90dc1ce2b3aafb3dcdd94abeceedba043d215fb7c934dddf4f5fdedf26fabed1cfb9dd04a7c79cab23c7383d8bb4bede1c932e7fccbbaceac7c96d3153bdfc09b1beb9c3ffeedd168f8c152aee98bd3a6289fea78c1c4efe8efeb448aba125ddf8ad8fdbbdaa69cccf198ab02beb950cdda58cfe66a77294badc9c9c8bbb32993ddeec24840a66efcffc47e396b51b1e7edaafbf77101ddeb4b53c7fbd4f4ef3648f37beb5d1ec29ec6a83d477fbdfcb401cf91eabebbdf9c0c71e8ebecbdab240910fabe437bd781d9f5ed4d9e96d989418bbc1ecc9db2be8b3e46afff9c9f7e9ae10a43bdb8eb0ccc8d66fff1bf514597ffacf30fef13e5f9cc84dcedd99cd55e8d4db7e2c7ad0c78bd786314fa3785af8157e1aafe2210cc3d151a1efafeaea5bd5ca6aceeba7a1dba1e8b89b17ecee208cd90be9da9cf8daf5a76a236facb8f53d2472c24785789ab04eaea6f5fc4873ec02f8aa985c52df4f2ededdf09a4f76c290f0c1fefb20e11681b05aa3850e725bcadd51def2b8e71ddb81e88f6f38ece8d5cd7fc6d3f3738f349db92f15e312f9acd248a768fb4096ccffa8bbeb15ad5954bd9d6db6dbff2d86ccaf3cfe437f98815e76544a55e49e6ac539153beefc8ead4dd1a46d1cd4acf9ec75c68d831aad9e2f0a0bee0dfca631efabced47459fd0bbadefe1ff1c8ba1b0cc0bcdbfe219aee9fb2ff19a53a8dbbd79ffe181c7ab3d50d7beea81bd95b9188df5ecab141d56da594b66cff6818a4d0c58ae0ec69ba7cb35a7698fdef6fbc1cbc61a5ce7ef27bdfed901b3861a63dc26e8a6e9d9bfb95554ba3be4f46dc5efcc979b8ab332dbc29b78f50abf07ecfcb95120357d096922772dde74a6942c3ae80ec8451fc90d5cf6be27c53df9ac0bafa2f0aaec1dfe7aa3b21d5ff34f8509496a2a5c2fd39754dcef8afbbff5ce2bcdca7ef1c1c7bcab9ce0dbecbfccf1e7baedaac24eacc9100e7361c8c035fdf2aebc039ab4a5df5d93dc6ba83ed9d8703b6f79c34f66acae23bb2d6fd80a0dad3f4155716a5cc04af2a34fdcee92d2a70cb468b72d8b4a0fceaa8bb17a9bcafacc04c647a1877bb46113646e500cdfb6ea7e1d0b2cf89bacca0927ac7dedcd2d71fad80cb6b42fdb0b3a7e8dc68d9edebfc6adc13b4a4dfd7b4bfa3c751d003151b27ed63a09680e5adf762dffba1d1eed7ce8b50de884e4b2fab7afceba190fe020ac8dc7fccac5c96fbb79fb4ae30bb9f5d0f9dc1a7a65d82052f039fd38bd2fea7d4477478e9fa015f41c25e0f3696a1e3de69dac2b3ddc6645c1ecb8ecbe5ece0c5aada72fdc5be1ebecef38bfaba6a1710a8e776bbe3d3b2adb3dc9e4d6db5c95e5fb12fd3562c2980b44bfaa0de47cc2bcb45fdccb7b9be58aa530dc0ecfb08fdcf16201bea15fd56d8027a4cbcbeeefeb2f4f2ce32c976f9891d6d0cb00ffd65acdd6c494554db4dface8cf5d001bdd7308a67dd34e38b6298cec14b1841da47bdaeab6cbae042fcbaeb769843fab9d1848b331f47e1afd5cf07c5bb93f36be72fab893f5dda18dbfaaca9affc63e5cbbf4a92ce352f3b3ab0a4ce6d90d1c59aeffdc606f49a32f76caeb4f5e923cebbc2f444ae27d5ce318c7026cc2631f33fa581ffc0ba2a2eac90abcc9bbc7f0e4ad05a9bec86c8b1bbbac335afb8cc0c38ddb327dcdb2af778b6c29bb8fa5224dab2f5f298da139a1ac3d1177852fb58313cbcc9edcbdedfeda2b3efbc3a0a49fa67dbadb25cc2b997873b3bed40749a0c7ef9c7b64f41abf6c1dc8483ba4baf6ab80cddbeb1baeab526050dfef8afb7cac7ad017a4cbe3e50b9b03b6e4e6bb4ebb3a1ad256951a86d7fc5bafd8d4f8d4fbc389de4b47bbfde33a2fa5d1e6bd6d3a85b5c423b3005ff7eef3fc1eecdca50f703b8a4ebaa3621eda6fbaca7c8d7cb0e4c3fc70c4d0cc963189cbaffac7438a1dde650e7baafad87be1d1f1f514d1bf72ba16ade89de134aa7fde6bd774daaf65bfb90bf0529e3af0a9bda6eddfe6cceae18e775ba11eceaeeeb9cbb23aff4bcea71f79f2d63efb707fbcd9f6ad38baaaf9ada2b0ccb8d5139d44a465a2c408b43346beff70eab6df006b2efcc3cde4748d26ed4aabfbf022377fababcfd2eb17a7181acbfca0dfe2ed1df080e2beb30d981f7a8914d9804a6e3cfbcb2ee8caaf2ffe9dd795fb253a6bcb5a0d6bc257e4bc8c5e0fbf12ad0e1bcbba4742b2fd6db46bbcfda3ef173a70ae02beb621eb2efe473c79a7af8d8fcc61b8fdfdd4cc88c7b35716edfcabeea6cad93651c66a0abc5d25aa0e1f1feee678845bfa2acdc5dc0eedbfeed07be2ef4b1af4fbdc9ed98c00cceeed8b951a9ddfded61ec3d75a5dc05bd6c4c0cb2e3c0618ddaba7ff185f8ac270ab59be19ab02a84286664094ceff6810e1e505a0aa5cc273ea2cd8ebcffb6bcee63e0b4b8fe9d440c2ff98b7bca7cdd17946a8fb6d4ee9f5f9ee8fca65188cfe2afb0cfdcfd4ee552f2fabd4d1cba7097adaaab0a63d8cf4cd21db6206d55fabddcefc0fd454dd0feaf6889854eec2c0bdd03aa8bf8ba3cd6da4ab59dc1bdf1bec9576ce9e4509cf04ceb2bcc9a70e2aacbbe1eb6aaa384d63b04afac6b55a7df12ff17d7e0ec46e41fcc93d5fb970d031a0fce7ffef1af6f32db4af15e0ddbf3e4ee27b71edffc924ad99d5d35f60abe7b697f46ebedfc38d06f418871cefba3cb477bf2e9abbd4d35a887ea7dc9d22ba42cae1a96f5e0e3da20deeefbd4fde40c657e89fc0a1391a3c59e356bcceba90d1f0afab1af5af91f0cc24fe6dfeece2d1dd7eff25b51681dc2cbe49cc04d39cf1f0d3620a59a2621a80986ba4f76dfcfa1205a3f09045c0c450afd1cbcd2cc13afda5b05df30f43afad6cfe9c9986be1b91c6ee9ad79e13b7471fb0ad03333a8c36a60d296b1be5653ba6e6aea8d27fabccb3c1d5dc0bf6a05f4657a070a23f0f28aababc74ec5e509cd0c4df19e1be302ef3e9ee26429bb7a5f625469f1f109bafa8b3cbaef33f2d992ffbd15c4abe7b92943ad187c40ceebdbcd9a6cacaa7af752a4aaf108cc7cdc214694d2fc87f6fd70b9ced3d31f0810bc2a0cafdaa6e0e1b2c0ec667e6bc026ffad0d5efece3dab4636bfd4fdac60c6fea8d96fb4be1ef8fe3f72f4a57e8cf985ee7eed2f5c4cdff3a47ff6dbbff014a4a9aa9c7ff7dca5b59f1ffd6bf58eca77c2bb478857e8eab9267dfdef63aa5bfcf84ea74fbefa421eef8af7a8c0c2ded21461a7ec441ef6bbf4d8dd64901d0f12f1c85e857149079b83fca8d11302ac6f712eead7f6c71b13358af1df2d271e688f2aaf3c8fba5b4b87b01cb49e6dcfc7cfceb9fddd6298afdd4afccc0fccdabbcbef20027269d6cd7448dd5bfedd743c021fce76b50826ff21469b24bdea3bd8d4692decc4f82ecbd5cef45e1eadca6bd9df88ebdd1fef2c82ee3ee1e23a1c49b6a26b898de0b81ec109d6a26edb24e3e5a5d20a79cd32cc9badd8bcfb83cba0ba29f6b31cc3ee423d541eaeb4e4f3caefeacf949ee018294e0bcbdf16eee6ebaf554db9c47b2edbdb8adea3eaca247a340c6a0cf7f31ae4323ccc1daf1a91c9cf1481e6fa12affcaca80555717e1b1f1a8c32aae8cdec7fbeb2d5fdaf7eead5ad92a7567f32e13c85edbee3b5b1acf75bbb8fb30ccfbac028bb9d2ca9aa6d6b6c346b4bd1cc8b56bbc234916ef453fb099aa9fd2e5adaeedef8f2201a86de1ef26e56aa2d48c91d4ee5deb10671f00f8be8a4d1bbd71ad8df2f0b675fac6ae4fc0ecea8fa7b823d3bb6e04e8fffa8dedce13befd7192ee7a948e271db52fb71c4aab81e96a72b04ca4cdb805a119cc76f1fdc5ae72b41456ba9f10adac7dbf78e76ee33556b7cc2d32303f265d33da51c2f4caccdea414fabecee3f41fab490e2968f44e7efeacb42bbebaf053a94819fe6bbca190d8b4fc3d1eabfc62a2aac14feedfafc1cbdaade76355b529412fcc2e4c98fb687aab44ce00ceeffc312fac0df06c0af9c8febfcb5fec6aa1767f1ed5f000f6a6fb2deb377e2fbb0e33fbbe7c68ab92a79ed0fda2ccfdfce2ebfd644cfec44db1641083b3e5eae961a049dd2ab4bf0f33c6c26268b5632a3eadd70c3bc6018e68ac9b1bcbab8572ffeb78a1185de5f0cbaf3bb1dadd217c0cfb0693ca3bcd4eedfa7ed87feef1e4e3f62a5ae0f9c3d5fb6e55c1a18ddef5b6a0f2ddfafcb1b8961871d0bc9617ba2eb7d07d8efedc10e947fbbc44ab7dcbcd9f0a8db39ece959bdfda505bbeb3ceba788d04964e4746f16aad227ff6b0d1ea99cda3fcf3bfbf666832f8a49518d4e60ebd8dbafc1eedd6e09d7e1cc4f7c9ea1e7bddcbabba3a96eb348f3addeb31e5df2f4bc52ab9fd7eaebeedfd1f33d990967cf01841eff1d6cdccaee4852f428c2adf5a172dfc2ce4f3ff23edeadcd501093c8b33fcf07cbcbeb1ffcacf3a380f5ff66559b6be8adddacefa6651dfc8e6fcc3f273c6a8b6dfa5ef8efab66cbe67efe0441753f0d713b82eefd182b0cd144169c342bccb0c3bb122b73bff89bfeff27fef797ea14ffef5815a6eed6b9b605da3ee74c39fea7edff0cb78bc7da225e8af73bddcf7f6cc7aa6b91c2cb117755fee024fed9b2abab96e1aabdca772fd5fa56dc5be0dd26fb5f5d305c63ab1bc1c9239fbded94cae0a7777b0aaeea5034bc405c01b69e3b597ef7ad1bca7facbc1e3b590ab8dc6bfb5c205ff72ba10edadc17d8cb2a55fad702bad30fbdddbdc5cee42be8af9cf6df43abd08ba89758da5b0157ceeca08ee2ac885f9fb09c77df14cbd8e5f10a2058bc5bc211a421f64754a8fcbf0ff68d372644e2b841aa4af6d79c4fd0bdc47c0d42f21b2b81fee93a22714fecdddb38d4aac9cad621ca9ea6fcaa67eed2dfec95d38d229ad7c37960f0d8dab16f768d03ee604f8dfb31d4ca42ae05acbfdb3efe3caafc3df74a18afb5f03c4ecc2fc34aaadbbc8d187eb0e4eeb2c744affb2f75f03c8da6525c9fbc4f0b477e295990d8570dbee425acdb4a6dba73aaf59be82bccb3d5ff2eab0ca5e9a810dc8f6bb58a8d3f25a27af1bce95a4eea2fde0430a88d55328bbc70c9a8cfce7dadb0e7c0e9e5561d1059cabbdb1aae5c2d7f2ede3e1cba0dfcbb6818dcaffbd36f7dce0386e0e6b0dfc8fb5b59f7e06e39eca3ee953dfa4a0c506ee6bc2faad1a9e1f1b320cc0201104a6f39cf3a27c6e455de4df1d2f3f3c3191ab7ccc1eacbad070b2d9da4d0d81f3ce5dbb0f94fc9cec0cd0d0b3f2c828e6342c7e715dfac0fb890c17a3bf31b5adaf5cc6e3fe45fa1015a39f53dfd9dfadb8af6500e95a1eeb9e5d23dccfc3026da71ae588b3cbd472d1b122e6ea05ad5e730cb482fdc37a368a2ef74baa8faafebfc7acabd0cd70ba1c7aecc2ffcf0690bbdf5ddf533d7da0a3601fbd39aab1aa86ad2bd70eb46ea43486fd7abf196131c7f813f718a3b0b9eac9eb84ecd5cdb7f4ec337849b04abb9cc08464bf7ba8dd3bb01d7eede5b6764b1cf5b93cb83ef6f6040695c27f3ecbcfd6fddc72c4c8c0f9388172db3d40abb8df374dc3d5cae8562a06abafcfe0dec03b72f60fffc6acbd1e787fc71aa6deadea8b2bfff6a5f06b44b001a911eccd56cb8e95a1aeef4cebc6c42a9ef442c1bde98e75ae031e5963bbbcf6996b45721acf7d36c4d8b73ab5e6b3805325d13aa83daf12dc2d1d6cbdfc9f4c91bc8bfa5b0aae69effc41d3aacfabb25b772c40a9af058bfbfbbd5f9b19ee5f79a4db9f2bebfc6099e4aaa08bd82dfcc2de36cf0ded3cca8cafceefcebfa893adeaab8c5d6760cafaa9b7f4f7ae8960d2a62de48ed8aacaca00eee9b0e9daf01e83943f8c3bc755f18a875cbab6d481877a05da33ac7d9bad8daffc7551ad09a0c5ccbffe8bc506c1b3c1715a04758be51fd4fb4b9cf9a61cb246ca6affab96ced5f57c97aeacc4d2bf4ab9d1dde4146dfc2cf4c4259b4e74d1dfee1cd1d2bc2b70e4fda2b7e14b1ad000fabc93b6ad73b63de85fce8fb5b0e1bdb161ba91defebe2dbfc7bb56192b7bfa29e1efe85a84b87a1c1f7fd1e7a094488fc344e959ecdb2e98f510e958c1d39faafe348a5fdce0a81cc481f02e33de030efd37c53c6c27c6edd8e022169e556f8e8dbb61a15e05eafa06d7be683af4f8cf9cb4bb6f2c52eda28f9cf8ce55f92996eae1013326ddc1ddf7d47f20efb7a98f2d008c8c882dd5a69b46e8db4a9e3a8f233babfabaab9591f6b38f5b320a6f97a4ed3dcb3fea4e46c2facc8f4c8f23ef93c40b0b97a0bc4f305bc71e8faad8affb8d8f491dfefbcb42b37b1dcfcf4a51cfde72e7ad4d3b0a42df75d2f9bd85dd7e332c0e0e59cf29cd8df570eba6ad054dfaec3869ef63eaa4ab2f779cb5c2cf9fab789f9f5e6927c571acbc2bbd4ef8ac48ef2c45f0ddc6a3f8dc3bf64de5dce3dad35ffc3bff77dd76ff80aacc921bbed21aecb6b20fdfeba37cf2edc8b249bf0e38c05eef58e6075c77a7ccd4efa4cbdf5cbc7fbdc7eb705cc75fdb1ff0b304fa3da997b4f696a43f6b7f58ee0dadc7e6deeee8da075249ac4b4cb86f4eaea67d6b7be50be1e2bcdad74efbfb6dcfaefe6aa0b40b27ca6a99cec98e34439a5309bebfceedad616f2f6ceaf28bcb6bdcc48e996b5f5448dcca5ca9ee8c21afcfa390f9bf2253fce5835f595ba0bf1f5fe2e7b41252e6fb9d210f48ffb46e5680a7afb55afed9c11bfdad1d2e6eca509efbf9aec18fdea7ecccbfb9daad9e77fe3fdfb4b0e3a69a234d0aefcbaaf3fcbb45a37845661aa3a17e2e1f5d7f4715fda7b56d14cfce6ac33f7e3f4f6ba7deaadbaffdce9c1a10eefcc7fed0a50df109b4a1fe6e4d297f65c74cc4a32323cbecf86416435caa6e8ba7efdae91ccbc579a53ba8d4dcc5e95df1a463ae4af9ceb428c80f0d753caa39a02fc6c07baed19c47af079ad8b6f4abb3dcdd07fd5de291a17d032eb09dabea6ae97babf7680dc22aeb6ffabc7ea744d6cbe65e0cb14edae1dbbb628cf6e4ff5b43302edb273c8df730f4091c343f7f4df98fb4f6d5afed6ca4f025709e6cb875d4685c7ce7ffcc3b9fb44d4f25ff6bbd3ed4b0b5fa6ad6b98d4ec1eb063c8becbd1b7f4a8afdfcf4caec88b0c8306fbfeadd0e62dd625eed22d85ff5cb1660ddb77d12bf4db53abdb7dfd6b4fb6abe66f0497d019dffb64f7df13cd277a2f5fbe88c5e65d57a1c5f8ecdf271aeedf1d48b657dbce412ea7f0be7b4c87b296ac66b084a47ea2d3d23cdb410cd94ecaa3af15cfd868d3f64eaceb04c72150741688bba935616a88efe625801df06f2f9c0c582feebc49f94d27eb6ce8121ebd9f52865f2fc21ef6e0a25b01d0d1efdcd306ecef2edced4cb3cdacc044bcfdee81cd7d7d617c99e6bc77b7d50b1da1f42dace1df516eefa77dbac8ba5c6d28fc537e37cfe1d20a9ac8dba11e60a5ffb4dabfda3ae6a36b5aaa15ac8f2fc02bf9b534b7caace0e938fef1dbd75dffbffc143b1abce29fe0dfa9fdea7eed22ef6fec7e09ab2c59d7cf2d911363a9a3bde9bd174dcb9f69a1b1ef19ef0aea516f8acfc5ac1083f048fe9761331cfc6eebbadab3a359c05bddc85e03a777cda2e5a5473c61a91241b1dbd8dc0bcd4c24a6a430db2bfb33c3a1b4e3cce8eeb76ead99d733caf6a55ebf42ab89698fc51a5e46aa4f24c3ccfcf78d4c58d9adbf9a81ffd8ffeec3f6a5ce1eb2118fcfae9f8f2adadf38a77a1bdd0bd34c97ffcc4ca81a17ae51d45bfe15f0facdeb0f95b8841fb90adafe1eef1fbcdada91aed2d98dea825df783172acdbf8cd3cd6cf924c933a4c95c028cf31be9fd6d23cfcd352e1c699ef1cc574cd9f419441f2c07652da974abbe9f638ad2c0bb8042a49f4ba66add2cbfbccbe2f79577cacdf49baedb3b7feac0ddcf4aeb33a1e98a0f09491fa6bcff5ddd5da99ddf10c485b513aad48a66a072b7ddee7c58cf973fada8a4a66eff816b0b6ee06b9c46bb04bea9b2ccafeaf01edeacdddd81fedb104a65bca7bbbf1eadda6b9da84fceac5ab0de34ac28aaefdeea7da626b3bc2a58ad8f2edfc20a1f0deea31bbae13ea2f79593d8eceb8c1af0f122274fcb6d56beff9f68b07fdd15cfa81208ddad89bcb033af8eba826f66d51b1fef2fcb0abcabe4c717abee6fe71e9bab0a80fc4dd337dc8eddb7ee3d05aac0e3e8fb0cdf3a6d951a8dbc5b4f9ba4f712af0d35ae25866caab76ddde931c0aa037dfcfa202defdbbcdd94af3bfdff6eac1c37e7cdeeaddadbd18b59ed8de85e2ee8bf2fdc63bef0cab71a66f5cd26b81dcd6cdb001ebb4fa204da0ddaeccc5aeb0cc7b18c9322a6ff3a400b1bb0efd1a07e782a7d7dbf747d1fb40a792b56f63cc78728e08baf5d24ca06ddcefeea2c88d11eb26c8e7dca5d5b7cdfb30dbeb50d6d7b8c75cd94dbeee8a588c4465b6cf62d2fc7fee82f896566afd04edf21d2b8bcdf40eedfba2e3b0b15bbc980b4d4bc16b0ecc5cac5cf8eedeb3c34ffdceef064ff534da6ff1aac7b6fd8992ab2fa1d9bc5cfb71da6cee3a2c49adefdd7f67ede1cbbeea7fb3aba19cbbf6e8eda74c115d7b09bb5d5cde2fe8a6d537adedfebadc7bef3cf6f16f76bf6faf00f3217a47669eb2949ff107ccd2f16bcf9c963090d711bf1bdffc55f0b9250c0a7f121cde228dca1a0c0ace0bfee7ace128b0aaf096e25fc6bb4b1a01abef9bdedd47d02245f6af722c3ab8c97e47dbeba79a9e3abd448f8e5f12a220c134ebcabeace61dcfebeaea4ed4a2f95ead3aaacc74f56fbd9557bf23a31b0c9d0adcfac82e78f402e115d6cd2b9a6e79d4463eb2c8ca04be44c1006eb57e4ad7f0c1dc79e6aae16464c1ed776204176d8efcbc0be1b3c4741cceebdf60e5411e42a3025543ee7784ceeba9b79bb709c5cf00fafc9e4fdeb5c6ab8c1a81fb5d734bc1e0b2a0936dc8c7fc03bd11df6feb92fb0b488394e84988d05df90cdb31c3d39ee7bc5f0a4ccaa82012f1a8fbf2a5cd1baabadc9c6fd9d779a4b285ccf889aa1ef9f1f4d6b1c69717e77df50e4dcaadcdccea2afa82dadf705e26e7d4e20a8b16ac68c51752f2c4c5f8baafacfce0ce8bc6fb9eba1bae433dc8bf27bdae2c9b69c2b61e514abc2961c02c38e8c35754faeac49135a8bdc6591cd2ed7fe640fa342b2aac12fc3b1fd32593ebd8be22fe1addbca8dfe0b3aac1ac943ef98f5ac86ef2fb9ec60ba4fd16cbf3aee8d8479a3ffe9fad9b60a5be6d8fd58c4c7edaebdefeec9b67f96caa34dbc3534bda2dba6daf2a49c3b13de67bd8707ae48ca1cbbeb60a60d34b3fbad943eea03c7cb60672a1d84034054f856dbc6ad506dacf1b61acd9cc632f33bc1b9f4066efdc6b2897973cc1ac7cce0d4e360466dafbca24abc58e737313b6c8aab7a3dbee50bdf4c774fcaacafcfb8a63b47de2e6e4a9adf093ddca35fe8baebba4c4a3e0c66834308b6b2ab8bc7792226987a9db6b1cd915aa91c1ab3ad1dad37cbeaf157b8deaec0d7e5ed4befaed02787cfcafc5eed9c61cccaad6ae650ecdfd74e91ba89bddfdfa7c0f28e4ad4e00a7ca31ab4bec1f9c5add8afefd4a64f8b57e1ffc70c2c8ed699be8c7668bb61f4cd481ea6d35f74da4cdf4d1af51bd15efc50def32fa27811ef83e8979f9934be286f0b0fbe118fa3c5e71ecbbbc22d1ea101afacb01f247a0c7dd3bb684a4a3b69b0f0c7eb5b5c6c648da0c9271775f86aee3e3b93ceb8921ab96cca16c2caff5150ab47a4ce52020be07ba95e425bc4d8d6fd3a8d8513c6ba0b06cd5d979ce53aa15d518d937cd0ddb2e1bd5faa84e6ecccaae78114071d7ddf4733187c4774efbb06beecc4ba788bdd694baac5cad6fb68a1b9ddc8e2aa198ce2ffdf9ab2080fdafea22209e0a71aec928951a81a4b3ad02bfcbfa2c0db01d7dc00abcc5c8daacafca661a56dc8178f1b9f2aacbbc5de4bffcbdcb1b03b22fabdb8fcd3a12af7dff9b50f1dd02d966a2bd9dedc5a99dbe441bb9615f801b822cd527b3aafebf331542ced74a7ccff4d4e06cee120ca1a8d57eaa7fde42affbfa86e089eff12b1ace39b32379103ff62ae6cd605c43cf6abda17bc0eeefbb5c5eefbb28f42d254ad70efe2b92ab1d4a5ae38d68ce85dfdd64ab0f1cc9ca024c33e363b0fae78c5abf6fdd1addccabc0310dfdaafdce06d689f4dcd47c4cadaffad9f3e5fb852c0cdfef8adf7a4ba59266c43fae9129439f8907a1963a603aaefaa8af99cfdf2712e4fbccef23fe9e8eca8ad02d281ab85bbbff66e54f2d47bf9cf51beacac9564c51622fd8be7a88b4fd472bf7c8f8e3c0663fe4f8f8983da1cb05e1df4f2ccdeaaa2fa2ef0e701bf4cb40940dd15195434dea41aea9199bd1c502ad0ce00aef63fa1f0a6b4adb145dd3cac5d1fa0d3bed20bfc4d6d7736aac0dfdccbea4336d5ac0beaeb0f9d2eef08161ee743fce9effad23eeafe7575ecdbb40ebbdbfbe86cf1e1f6afb2acb8edd237a615fee06ca1c532bceed6f1e3a7da2a2c90d24129cc0bcbaa86fad8c9b6f3c5d78c5d5cf04f6b70ec4e2bfb6eca58952aba0cfe558afed4fa6ffffc26922afd6e0ba2e5ea2ece8cb3faf3fbf4cc2ccb885d885c0c3bc786fbdec5dac7bc3aed0ddee33cdeed9acbb92ebdeca23b511d7040bcfdc7682cbce176dadbd87b0808def6ca1aefab93fd7bcd3fc5d88bdbcbe0bb763bba817ce6c2b5a0067be7f9eea2bccdaff1dabd16de5a6c7075b4ba1f0aa702be412ee78a9d95ccbce5b899efe7cb5ff31a0c57eab3aef23adc3dccba0ca24e7bc5b9757cacbda8b01aff12a3bb9a06e1d0fee0290fab8a3dd9acf29cff3cc337fd10ff054c9f5c861e1c4007ba2a06aeff882440c27ba69dcabc24c3572f622f6cf22a2fd65e8dafa12b6dabf638eeb2c4f9d34ad44a90ddd3b92fee60b48ec865a3fe2d63495eac94d5830eaa294cb34dfacc5fdece0b5e7cfb4dafdc3b8edebf68ffae260adf5e5d7430da7bdaa49959ee90d49fee2fc34f707accb8ef4dc0dec897234f4ceeeab5eac034332b760f9adef0cfdbf2ff82ff6ac3dd8f0e6b0eb9dcf6c757aff7c7e8dafd50f41d32cd37f3e970c7dea84fdc72fbb132cbb91c7ebe85039d89c5d49ee7fccafa91f6ece4ef31ccab37ba7b08652b8a577bfdccee631d8da190ce5bf9ad81a6eb4abaca34ce82d480d5a0c2e711215d9b9bea90f4c13470b1f983aca0fd2f7d6fce71eab7d03e0aeeeef8d42413de67be5a752e3cf08ebca9a0196f54abab5d2ee50eaffd2daee4f9696fb8a8ba5efb98386f651dc5efaed6c606b2f6fc5496e876d3d6f6bae61b23fc1d4fcab0bca53c65a343eabbb0a3cac08bc9eceef30bac4aef2ad38cbbef9ffb75ae6dcaa764aeee35e144bfbccacec8f0be9a233366f8bf3b968fcca0275d0e37fd2adbbd568d08108eebfdc51ef57fea3ce9fcde6e4cdc5188b3eccfc5e9a30c4aebbd2c5e06f5a34ce1820ea2b594573d61c9e7a369c8ddf1fc4edd56ebc13972b39d7f80dcad3a29e93ef4c93ac4441ff4aaf72d155d486df610e7baee5df0bde22d6dae1bad86e2c9e361fbfe38eee10a019e1a923b9eef2eeecb05e826b4c9bdf3f7bf67f1dfb24fb73fffd76ef6c0a7e2f36caddb5d130c74eeccc8af2edcd0fd3dd3beeb9808d84d3a8cf1b92f4e8a54ea63edbd5aa615e58ce3b9fba60dceecef1591bfeed7f4d63baefda1de2cb02bd508ab7f0768e253b91ccfb2a172bd6bd5be2c60841aaa079ad4ae9427ecfcbb9d30a8ebf4ae4ba3ee69c2fc008f7f2f9e3235dfff1720e675fedab8c727defadeb2afd923ddb12e8777fbabcbb026f771dc086ddcb56ed567eb2dd7c8851c71895a06d1f32ebcd0d8eafcab3d0c5aea0bdbb60ce1c1bffaadbbfa6bf65306fc396e587c333ad799a05d74e81c885c707d16def101bcfee1ab6ab5394f1d82ba9ed08aeab3a671dc4f3309e5daf554eb5455a7cecba68a3dfeeacde124ce1e7e0fbbb74cd59e907ed68feae6c0ea1decec8db3eeed273aedad0c2caffae1a0cd8fe0fe0baad9caf3aeeb12f20fd64fa1baf23e5ed3a35f49c7decadeab9f69598dfc6e7f7bd56ecf07ad3985c0faef18f5cbab2dfb067ad674339a7b03244edf6abadf2a42bfa8b80edc4edceaec2be6cfcc8ad455f0dfb901ce0a3c03bfeadfc4884fe70e385cfacde31ad28acfcd9dfa1fe4a2b9becedd6f777d3cbdb93daeb57bccefe3fecabe06fac40ff0acdda2ec0dbd4f1fcb3def5d7df7f7d30f3e1a0ecdbf75d7251fabf513edf1cfa2a423b217d325dcf9beeb5aee4bf647eb18f347fd7fb97e4cc5cda21e0b7b349ddacbbe7b8081dc7d26e6fb88b3e45fe93ced2a8dc009fec5df3ac23dcf3e5c910bb5f9cb3b57ef541ceb6fe3e7e00c425ff4caeaba96495cd9ca062b76aea40ec33cddbeacf2ff6fbefabe9cbde8ab8cfd9ef5cad692e114ca5dcb01ab3fdb68f33f8d337e2fb12a5b7ed4adbed12af4ccffbc8fa0bae4e8eee7a9a16bbd5d2ef5551dad1821db3c9c903dbfd2b2ef2c2b37eeddfef9d7a64a51b7c3c0d2cbaa6f2d8aec40a779e7fa66654d1dae1c858165f8d38fcf3fe6ed409166f6acc958d2edcb0cc56c5afecf2239662e648f2286a8f2f7eed95aa4dd3fbb3b8f5e5ec0bcdd9fd2db8d7822c11c27d0e74f5446ac64f84bdecdde71e9f92dbac88df844e74aac57f5de6324d412f7bad2cae2ac2b80b9dab56435d874bdd5e6aafe5a25af4d499c0afabc22c4cdae95caaade2a226b9ae028f1beabb6ac0b7756d8963e2a52fc7fd1f39eccaacc90947a0c7e5634d4b43bd0dc472aba281aa4cb935eb2fe5a9b5b6efe8aa7d1e0ae3be19c9cbed82b238dc0ffdab50990a74a960da8dab45cd168c85494faaeea079eedec2bf8e6f69942f86cf596caed8d6eaa8d7274c86b6ceff2acc0258b6ad8fcd6fb5ac854d7d88f3a9698d6641ea37baf3295be1cac4a4e5f48a7ec02dc2f47d3fcf92eecc2fcfc1fae1dbd6095db51ee1d2d4d984e270bfdfc574d3b2ee58a86e05f11df6ecdde958def8a2afcd3d6c354f7be2cf38fae5a79e4f5ca72d1ad1ad1aa6ab7a777df9a5e943c434ca8b56044cd4f5eff66b45fdeefe045903fe10cfaf9be4dee56a9ad4c9a4e7511af82de48e7f0ebea718df3ac44ab6c4b297b18899ea0b16cf62f764c0a5e9c9f44bb6acb9ac89c8d2b954a5b52ccdaaeeeb4c5032fb38aae1c5c6caef0ecfa7a5ccefba75c01727aea21bedfa1a63f4e64db4fd7ad1dc22cc174fada1472ab1ad54d56abb3cb8f3acb321cec46d72f8f6df65aaef2d078ce7ee51ef2f5f86c08dc39c93a20adfbde28c20fbdb3532ee114eae7c6f9c4557cc32ff10dbed3ccdb02d30caf4c5d2bfba699cd8beb58e0bfcec2139c97efde025abd03cadcb7a64c98ccf3b7ddde44bdee12bba0948ff014ac5e0ef5fbc99d61aba2f619cdca73fd51f0a98ab102a0f235ec4e2fbf552092dbe67d2bfc6cf6ed754acd38ebe426f763324c3d7dde410bbb8d6beabb376f2a5a5498fbdb4fdd7af47b2ee6ad2dec91091f119bda2cd5d2bf9848dfee78addedec8ba91900bacda4f1e2ef8b20a9a96683d4ef55c7bafdec1dca6c6faf65eeb8bce7de6bd0fe90e68ccae7bacfa4ecef9ab3c406fe0cf513e89399cb2a0c2357aecfe0ca3f1cc5aaff3d0ad9952b04ba1ec10846dd6c3eeaae3fedf87c731af12c25cb44d4ad13cbdd0c8fc10e4a43dbcbd82f462ba6fc5da36f346d17f37d7e165a73df3dba87b6d6e0ba57faed68a041bafa9936c4dbcf4582dfb2acabeaeacefa9c9d0a5b2fdfffa2081f9cceea236d4bd1c90ce7ddeedfd8dc85d4c5c07afabe80c0698ca3d6fac77d5eebc29a1ff9c59ff8dea8fb6a73d3636942f2fb1f563b53ed671664f181de6a226c6ebb28ab819ca4b6c6f55b7211f7dde5f466e6ebdcd3e5cd225cccebab2ec9c2cfcc0deae3939efbe46d7b35c8e76d4cfe0a6edd7dcfa2bbcdceb42e7c4ee0c4a9ef92c3ed321d456ae1ade9cbefabaec2a27b4ec9ababa1d9719e78bdf94bdbdcd44a9a5e1eaddbcecff26fcb6e2f5ad27ef05ef89c406eeead13e05e9efddd5b878a77cfe20adec5bdf0a73fff2ba44fd7cdb46b5cde5f44bddeabcc67f18d8cefead27bfa6ccd6079eaafce606e2dfbbe843f6fbffb3d17f1f96b4fdae3d4daa99471bf671fccd705adda3107fd8f3cfb658aacfb5eca6f8423eabfa1fdbed6acf34bc8c533cc2ecee43abe76438caf17fbade2ecd3fa0aac9a48cf5e38b6ef10d029c32fc2bcb7bbff932c924e9cd6dfa049fbb8eb0dbcf2cb8c3cdf63aa5cb0ccaadcc09accf5e5b6b965dbad6640e647cc6ebea50e28c1a1beadd4bad401b1b500e5a4cfef0e48b3bc4da3a0b24cb6d56acee0cbd2497aecd35cc3bca02bbdafcd91ef8777b5db1d99e810f0d86123af73427adfda303fffff42cead85ce1cd05eeecce67bf1f6314deb0ed53ee94f2dba9ba7eae9dfa24efadce3c1cc02dd21a3f3c4a4b9dbb2eaab942643dcfea091a10189ab760b3af8a81c748afa9c2aff55c84cfd3b5767dcea8e2da678e86dba19dc59603646a7d359052a4faddde4be3bab7715dfba0acf5bb3d017b9ce5f965df6b1dd4a2cf0bfebaa1a12611822a69a3fe0bc2db5183cb4cb1ef5ef3d8dae9fbbcfd7b43adade85d2df0f5fd0a6cefe4beca56c24e3a0ab89ce615aca99d7d71f46fc2cd9378eec70cfe6b3c8dedbb989dac7ef08c8fd8eecd11b42cdd9f9d14eaef31bbb08bb29b47badb0b3ecb4edc86ebebf3b9dbdde145dad1667c5af4de0f25ddd58f63efadfc7aa61ccbf874afa2a5aabe4faaccd4e9bb91eecde6017fdacf6caa22ec9a45070fa354e9107cdc478a76c3ccc0c8427f00a3cef30bf46cb272cb9bccef7ad4cd89dfaf12a428f37d0c1eaf7afacb75f00ae276df7a4aae9f34aceab3ae4a68c1348e2d4cbde0efd0d5abf8ae7dd3bc903875db7aabd3deecbfeee0228c06231ffdb6612c255dc4c3f4511da28b50fde56bac35f94eabf1aef9cdb9d7cc016bcbcaf2bd8eda8baf4afafc852878156c214dfb4e67457d7cbded0baeedd047b26cde5ac736c010d4fb82ed6ebebea5ffc3ebcda8e79364e93aaba15ce57c5f32fb37736b8abd8f273cf6bcd16181bd8c6f8fda5f18f32e0baad1c37f9cdbe4b99349bbadb5bd8afb9e8aee071fbae73ba3dfddf130ee0b971857d3fe2ff85f6de9f5d7bcb24faf9b12d87d7fbe92d0fa2a45bc64c2ed3ac188a11adfbf154fccb9f22c6fc881201bd0a5eefecaa07ed1bfa77dc8cb2e275a6b75cace71540d9443f2baffdbd9884c09c31feccf4abbdaaaa8bac2dc2fd14ac0ca392b8bb5ce858bb2e464abf42cabbaed8cdab30a838ec7c21157c3bfad2a05f733e07bbc8ff3cb6be9eea5fcc9e77c86cdafdbcadc4ae2cf1f452e2819f66cc0aa9efededf23ab87dc75ecfc0c3ddce3f674dada6b3e37e62a9b30966fdaa0967398fd20f43f7991bd7becacdf272feba25c878fa636a57a1ce0aee70d2ba934578b86f83ff7ae85b2f94abe3ecf17b8504cb0cd69dabe7b9bc5fb2f3edd8a1f200e2bb1fa5dffe29dffda2874fecd8efeaca4bc146bfe900ad7bbee435b116d25dcc801db28bfb5f7dac6cb882dafddb4acc24b6fee943527dac3375b9fee8a740709f87dfcbbebbd13cfb4fd243ddeaa4b440eb00498ca38c2ec7c1f86f28cb81b978acd242a50abdd0c3e39c736bf6e943078f38fc9bbaac113d8b5a43c1bf9d8ebd49d0ff2c7e186e05e0eea9108bf0a88c4dabb18dc053b283bcaa4b58c09f2fc0b1cb3bef677c2b128fc1fd93cfef88b7cf4ed0f18ac4ffed5f51502e89cf23ef421caafe26ee075ec1caecb18ecefceaa08fae15825c3d45e7bbcefbe7e5c35ff7ba94cce0bff3a5ca4f0bb597cd4ccb8de3baf9b44bd450b1a9e4f7dd874bce3985cc96ecde6fcb2e061efefac5a25bb38efa5699aa80d6affede86c1ed7794644cd30a7bad204303b87ba6f4d5ca9fc311fd77f9fbd0c5208affcd8089f30ecff3fe0a0cda6ec24ab444bcde7c7afe2badeaea39d6bcebd4d4efd8f54bb8ddc956208f1de9bd7d6921d3aadce53bc76eec9b74461afeecf7c09e3f3abd3bfcc9453eb17afa5d067f7728fbd7ca50f43fc11871b7f3d9c2e4642cdea1a0b8bdc00228ee2db71cef84d9194c0f9b1ebf54d02044ba9b9e8cd789c57ace8270bb61ddda87dcf222ec2ada3b7ac4b2a596daa1067b3448fac30f9db7a6bf9ba5cc7fdb2b491d331fdccfafb53df5dcf805dff6f2ac3178845ab2f9ca4b8ebbc3acdccb9da668deee5aa06216ebd342b7815ff8d6cef7fe34ddad84480c6696a1b4a31cfe7bfde03c0fc1c39fa3e37aa12fca9dc705579b898e7ad30a2ac7cef9bc2dadd432ff74b49dbfa42e22cdc21d0fb587f6ae7af9edb418aeeeb8c4a5d27f7549c81e6aa5495fe1acf1ab1adadadcbd186eba0a944edcceeeb4abd7bdba0eea3cb5ecd6e97bb43a9e52af99ece9eed20be67c9b8e376de2aa50941b57be0d8ffe9e4df8126b1bc67b79aec42aeb5cdbdbe006b7e3e9a79facff2bd07643c23b0ce4dcff1046ab88cbdd859179a5c565e4b3d1eb0bb3d3c854fdbe56a2d7af8ed1ee324c9f1fa66fee7ff1b1a90eb028cbd4fe9fd5adbb1e7251f0bd22e7e0a9cdb73b1ab01b847bbe4097eabea04ebdcb2cbadaceefbcfb1da5fdff6cae580a1714e95c1e3c103ccbfc2efec917d9bc3e3c26f399bedc5ca0fbce7c8e6fbeedcecd54ddbf9db8feb6d2bccc3018850cfbd7d2ab1dcae13aa2c6bd79cc74e7fac36d2d3839a01cece2d3bd53b9ec5f56e4e6eb8fca39d688b6b58feec3823c0788ddbdebff5afbfcee08dbcde9bd9ec2e0c371822ca6dbc5ec51324f486fa7b11fdfb1c99ffdcb77caafce1875cbdfcabf5fba7263a8c76ff0992cc83fd5cad43fefccf10b39e5a7cedec434547eeb3e48a07ca02f5cd57be8efdefda83acdbbafbdbd13aafced4aea4feba4df3a882dbf41de4a5f4bbbe6474ce691e3ee0e0e05ac2958dbdfd7cf7e16eb7e037edf47dacb2b3b06bb35feefa4ee3c73eb833de77fcff321fb41bcedada3f1aab6cd85da62823faac1bc73bd3b8721f2eabc8bcadc0d5bc2de2e05ec3904a875e2a2a35805ff70a8eb4ff13eb04e49b0783d62beebb3241b1d1dad63ebc56d9079c56cd3ab2aeafa7c4ee0cf5ff3ff86c3e4e6df11e0acecaf3beb04bcc3d7053227698aa3ddaea1de08ad8776cdab372cc7bda6cbce3f65c97d013acad0eaa7981aebb5b5c36dcaf5f7cdc384f0aa302b35920a9dc075c3c2b3dff2ab004d1efe5a6b4def6eec08dfe7fc0fe0d3c9a9be84d98dc4ee6d2cbb6bc1b3c4c5646e372a06ba2ada9e3dec09cb007aab1da0e0d0f0787bbbfaadf104c1bf5c0ef9298e14fadeafdc856edc1be403edfda4c4aaa5f4eee2f5b177ba1dafa14faaddbeab7dc8f528baa4add34ebfdad9fe887edfbb9ced900afeecc9ceebac50ad774dfff47f6fa45449c05da2e85188b641ff9dc1ea3fb71fa4bbc568e5e63fec961f2a68afcd121fdbbda3fea7fec4d04cce24c62e62ccae67e620ca1ab88c460e60e10159540e145ead922ffd9a8a76ac02bdac4f98bf4a7fe54b755b52e4add8ac79fd6cfe0dab24efadff0aa8b7f92bcccd9e1ceeaae7bed7ec2e0d71cdc66cf08526240cffb806d43c7df4a29c56b2f2c3d2affe0bdfbe2bf9b6efe05785ffaabc1f5ebc5abad9ce69a003fd0f3a7094f9af3efb8ad21e02ed38d04d4d50ce54a3e3100cbb66deaff5d448f8f284a69f84b08eb23ea795d4ceefcab22faafa4876e87c57dbc5eae173c1d3b1ce85ccfd373b3af89aaf1907ece4abe154c7dd530edfb3caaefe3e77d63e833499a3decbe0ecd9e7e837a7d37dfccefbf4a45bde3cf130bfbee741b3cb0f7c820cecbfdedbb97c6b628d6fb32eeea2ee6adab6b15025fcd2a3bb464ea8abaadcfbfddffeca93ba6ec2facfdd7a39cfc3c01ae4eb194eebc02a5efcdf16926e2b7fceead06bf912aab96ff45ca0208aef52d5cde4948a22b9dace24c53b2300b24f94d98ac3648e4c1abab319a9704ae038e5d5c29c0f4763026da2320aca7aa7cc932b3bbadbad3dacd6703a77cdc1cdaa8f410e98adda8bcff366ce2bd5a3f48cbef7cfa3ec7b4ae8fd3d8b846977bc9e2e6abd9a4b177ed10ce7da4accce3ebfecfbf4e5ba6ff3ec66538e1d23f2ef671bc02f66ae05fb42a2fe2b71a015e3e2054efb6bc083d68e7afda378a8de0a67baf2a8594b8150dead75beaddbcef7eed251a582df825af31adfe580d0bce73b3ee81cb42f1d4acced00c7beba6a5e4b2bdeeccf6fcb84a1dccddc736b45d3e85bbe7b71fcadda47e4fdcba2352aa21845b51db45baac3f7f4cfaf1eacbd8fc0f5b9878f09f1454d0bfb76abdd2efb73d7bbdb5f72eef42fc84bcddabbbe33a7c4b4ac179a3d0aba775dadcdc2aaecfce54501581c01cc7180f3f0b9aff2ca6e9ad3fad5c867c4ce298ff31a9cdc5fa6cf8c1bb98dbd742c7a97fac9fa8ff3bad5da4eca0b9d1e6edbef15c07bb5ce6a7bbbd0d7c4558744703055b9db759f6fdf26996d07aaecfe997dd1efed6b4692fbfccf0fc1ecc01da64303b2bdccee8812ac556798cf9e6077fd591f1353ca1b894b6d12fb86ddefefd03fefc04aebf2124aeabdc16afecabe4d0ff3fdcb3deb66ecbff31acdacd9b46a2fcaf1d3bcc8f80b8c5a6b91bfce8d5649dadd90eadc00f30a755f8bebb2f79799f9effda4f680d21ae8dc0d725a17dae3ef29a15ee0ce865edaae4130ce438e36b0912d7d13edcbd9c0b2fbbff66947f84b8c7985f45c7c363adb467deec13ed8ee3c0cee67222b074cec9bed0593ca35215bd1bcdcb30ffe509df0d2a0b98ce9f67d5fade6a6417dee7eb53efc4db8dafa8dde7257ded0cafadb5abdc6c1aedf85b1de4b9ba0b414e3f75aaf2a061cfa1e0b473feafaec6c0aad06f1de57af1b24a452cee64bd20f65cd9c20d800d987c45281b72fbbfffa552fb7ec60fdbee0b5af07ddcd4f11bdca2ae651ea7e8b335816ccc05ec2ab334fe4dafccb8a26bef4cbeec91bbaaccd0aed2cc7cf57984fb1fe713cc9783defd94fb62088fabc6a78bf2d922a139c9faddef06e3f9332d0a33696e3cefcfce8e871f1be8a0c710084a74cc7fd51eed4ff7bc0ab02a6b2267fe5ac8afdde8d8ec695dac3d40eaa2247db93d87fad8c14a7c4fedaebeb7db1c1938e56436dfbc3ddae38e7df2fb0cc9f9581bc7adfbebd20eab369865e12e4f9aa71a0baf95dcbc46c6cfee2edc9eb220a8e4bbe28faab6e78aacb719fbb0332cdb36fa11a85abbceb45b8faa70f5d1dc66e8abba541e6bc2ffe823fb4ccfd967eedba10cbc740c6ac98aef2e2d346dfd27eed90bdfcaee33af6ed582a3f1df8d10e9cefe391dc3990cb4bf8d6a7ad3cdfd2faf01af4bb27a5ec3dedc325b8cdbeacfefe9c3bfefb9e3db4ae1a48de084e28dedbbfe8e4cf17ea8eb8a1e1d42dae8f934588beb1db67eea39b1bd42efca62957f23efedc41fe4c1c6bc85c06f587f7fcdfd7c0ab26ce90c03faffe6ea9dd603dbcf295b2a1ec4e27ad68975a5af3fdcb90b4bac46de6d90f6a6f6abc83b0cf75956d78fd1360d66bdb5fbc436f79c3c6605b952e6684f659bb1f4ddb5eeb5dfe51bf84b1b9fdd430700ec1b99bfab5e8124574ec46ee6c10eb7583ccd5c6dddf72455fd12facabacbca6d180cd7fecf723abae81bcbab6f9eb76475fad45c2056cebdfd176a5a5eac5c7c6eeec41edae47c6b1102f86c3cecbba6d6b2cedcecfb9cd200fee97fdfefef3ba9abef31f4c0fc6fa8e24eecf75ffde2d582beca15fd1ca913928ab83fa4b4e6e28cb62aa6bf80adbfb65b0a704c3fdbb1f0a8ac8bb1b6b6dffa6df2bd6d3efa39ec0952f5c3fecf437cc55711cbcc6ede7c7898b6ed447c08c8ede0ecde7fad90f678aed85cb0346cb1088c25c4b7eeae0d1e438f9bc5cb45425c8fddf8ba56ead6af77dc6bcd3e0daf5b948e59fbdc36b73177f04a4afeb4e6bdad1cdaafb40df2e6f1deece30c6117c508fef3534c1fb1f3aaceb39cbb74979384ed055b72a85dbaa3189ef6eeab5ffefe996de18ebd40b6a21de4fde8cf2f5e75898adf318fd96b3e01e3d8d6c5aad06cd0afa0ba82fe0f8ce6bf71ff9d17fcc59c64c15d2a0eb8dcee16e5972e8c40f1bbfdca8bc8dac94c8b428e5be1c7e7fde50d106bc7e7cd09dfcfdbdad09ecb5d0bb79ecc6b785e27a4ddfafa9ceedbcdd38ec603ba1a1bccceca68a097ee218be5a6f63a41dc8fa3ccf3f2d6b1b79f4b7a638a7f5aa0bbbac0b0200aa96ae47ccf6c7c10b78ebbaaa822a0a6323ec72943c3294bec0cf08ff6c6d4bed4adaaeac5be0a6df35870fcabd1d393ae8c5bd7c3f3f7f3d6519333daca54bbcaef804cf1fbbf1d7a3e556cdce4b57a5c91fcd0a95ddaae543fa5493cefafdcafb63f9a7850bd4cce63dea2e63febaee42dd3bddd6eedceab304bbcb3cb5e3a58fa3aa704ba23afb1cd7ed8ff9909b70a1613c1fffdaaa130e89cb12b597befa680c6ccbbdf1d2b9abf9eaf2ba697fc9e1a6340bb33fd6be11c08c5eacafe991bffe926f4d6e4de7ba94fdff5b8bb3cee0aeb6187c68d8cabc8bed77ff54a8ed3ba87ed96dd1098ed8481bfad3219dd096e1140b3eefb6c07bccb6f5d2a9f4ffcbf57cb1831ddf0db3b346f0dc4232a9a0fdc4ea3bfbbbe94cb49b4ab6a01c116e9f1c3322d3121fe69cca90c0fee37dce6d4fec6e9c2d6d25ccd466bd909e9d97e5ddde0b96d8adbfd6f332ad3c293af5dd9dad3e8ef688c63eb28d3a6f83afbf4babbcd716405f6e7edc143d0bfa0effb0d6ab915c859de5d81f3e4cbd9adfdcb4dcb890f37bc1c1b7ae9d1f2cdd432e2d72264d9ff07f67ceabdeceab22c50748e622ecae1d09cd1abcfd5fafd6ac363deaaa4bbfaabd961abbd9d0c4ee96dcfc2d822e51c9a825b57421afbbd628320a5ca8f0cbbeccebc625faef878fa7eef12f6fff1abe57fae1683675a9efceaead868ea073111a64cd5eeadc22bc6fd3fcfca1fa3bf96e3ee5c1895ada074d137da81aacabe458e20f50bcad7802eaacfcb88fb45438bdbfb486dc65f030fd276e2707befcbb52e73731eac048a15ec4f80f7a27ecedb56ece7ffb32cec16d2a1e3f063fd75ae27abb39cd3d22989acaa95e71838374ca6d53a3ab7deab3d9aea4b9ef9e8ca74fffea033baa4b6fc0dd4489ca20661f2c0f28deefbfb2ec5fce3f4beaeb43f3aa4bd1b9faac40ddb40ebcead9605ffefb11b2c4da67742fa6579e98fbbc23a22096ccc51927c94d0a755f305cddc442c1ce45dca3d9c611950dc4fb546daafa8c0bfacfcc552cc3bac230b3ab026caae8605b7cff6f3d0ad8edc443ef9c6c4a875dc1a686ebcdecfcafe8fca0af3d2b479a5ad3c02eca591b82c216cfa77ec77a5c12e2f6d9af38cfc9e0dc7d6cb32e1d9fcc0ada8f87ed40a0d4b2aba8c4b0aede373f6ee4cd971ed58eabbe4fc8df5443c0ee6ca316ba7dcdb74bfd2d68800faf06fe0dff116435acbd7ca6f6443dd29daad8ecad53f9dbe739a6c1b22f68764aab7d95cbf29d4fdcec6f9ba68e90edd2fdc909a81dd70c6efdfe17d40f64a91d1b6ce5f7c3cacba0eb4f3b76041e0d1c83e4c7040e74dea76b47fff1ba937eaeabd23db6aeacff59b27b3bf866b5fbceb13f746b04ecb558d8fce4aa5ceae865027f0ee5e0a58b81ac800f3103cabd47dd9ece5066bb9bc7a35ba29bb5ae533ac8bfc4d55b2fe3ba625e18ffb4c9ba17becd16bad2fc3fe49fa3cf1dc1a5cafdff89edfada53a7a42da1677e1c7caafdfad6eadfcf82bf3babaeeb5fba82cef5302cbdc733afae5ab95ef2cf806c1e623f5f9a027ded2dea55bddbef07ea8c339af3ad555a9c2de41b100fdd51fa3b1ab619a6c1db0a948a81927caefd167de40dacfe10eb00e41bdd70810e46c187d42360edeae4acbdccd31b5cf193662a7d96d149ae32bdeb42ebbabd4401b3fc5eb8e8f0371b1baf04b0edc8eaebfb3ca9acbabdf9bcb49bcc19bdfb4cdce9d3ef6ffdc8e5e2a99b4e7fbabfaaea8edd15df5aa1baa64bfef64120bdb6ea46f20f420e80951cfe7eaa8474be0abcdf7f6d5cdfe38ffc15fcff33cbea93a9c2befe4ead1a50c9e985feffc9ebabdc4dda9629c8ef77b6d9eb31a5b4b0784df9f579e9ac7dfdf7a71ff180b2dff4bbccfc6fc5e8b0c1e628d9dd20fed1206c1caf21efacbb290bfbe63b4ba3ce6abfb6a78fd2f6ccda6245d6743b8eb479eba54aefe5feededd05d0deb37a1c01e49a683efb59ed8c614dca9ddededcee87bb44de12aa95a4d15e4b3f7beb5ab1993f4ffaf4d0af5bed4e48b0faa5ebadffa17b6805f922b321bdd90fdfbdfa252f0a38a33f7ffab488dcb77beaec6da837c5dced7dad0bafe5ff2a8adcca702dbb9a161da47a75b2dd28cafd552801ddd17dd3e81eb9eea248dd5ffd24bdf11e31f077b4a14f509f3506abfb1a0d0ba73c43019a5c9ec3c14d9c225db893dcbe90eec0da2a943618fc0f8c8bd4fab3c8e8f78db7cf0577a2cd277feab5e3615eacb1fdb19b6dc87dcd416eaee3ded0b1b1eae6c7ec6ceb5af78aa450c6ac5bc1968c8ac7ef2e3d8bebad8b9b3b7917a8ba21adf791a6b64fa6fd7ccb4dbfc1879ebbbef81f3ecc2a572eecab07aa69e3c149f214226acefb2a2ecc9e1edef14f3b8b16ea25ec3dedb444e3c4ffd6f400baaa359cb1dbc5a6a53fc6f0ada76b82ec5e548f4a931dccc6222afb4e80f136f94a3c060add59acacfdc4681669ad630a1e2dc6ad80aa39f66bbf792b815ab81b1dcc3dab56cd9e63adfb6ddd657463b646febdbe6a2dfc0eef6a48b15facaa916a67276bd80acba49a94cc3f0dddde8bd4c145c0aabdf6dfeacfea4c28d48dbaecc5cc57cbeee9dbeef3fea8c690cd3a1ab186cd408fdad3933cb0a09e538e9bdbe74ddde4ee2f9092c48f02e1696f63996d5026fa0c7779e5fbdef855ccfdead6adfd1a607a4e1a57c6f224c37f2fccb6f7bfec4683d4437b9b2cc79f36c9f46f2f5fcff4fcc4c1838bd239a841c8d55a0621e3deb40cebee39c0dbcf449e700be94dbaf9f4f05df2b03fe4dd1b685e66db7f3caf1cedecdd59ecfa4d962322cb22b7d8c03dfbd6f6cb81ab59bf6b244cf44ae62f6d5acc1b63edd0fabf3009fb1ef628b3d93b8ccb21abefc56c80ea4fd11baf9312f89ebed4fbde84adfaddbca67d7aaedef4ecd4aa183dfcb9bdecae95bdf53f8fc2249f0a46ebacc4aa97b38deba4babfcbc46aec62cbbbfd00c8b495ae08f35ebd7b9c15ea1eb891d86eddf6a5d5ed35cdf9ff927dace9ded8552afbbc2ed0dfa529e2eac4035cd1baaf30da5ccd2bac641c3e3b1949e7f43ee0b87dae4041bec27ccdc9de3ef0a6d1ffd3d0fb90a7d928f34f8ad4ba9bcaf06a235cbf2daee3ebb51bffda3f9fb3dddc5ebacba70f6fcab975caa3aa4734e2903d1e5e4366eedea4f7ffeac7bebfe4149cf40ff2cdc891effe0a3e04df0ae8c8fa3eec8a454eedcad054ce9d9b7a53aa7a6e7abe1aabbe0e5a9cebdfe84ce2aadb032a6cbeaf1eba9cfdc3edbfefd9e7e1ce03b5df6b6a2c51ffcb418e55a6ef20ef90633a6d28feddbcea97cd7dfdc1e6e93ef4ce31f6aee4c5cd6bb32b182ecdaba0d4e45cebb891b577ddfcd2ba0fbdbfd299a7bbc6d59e9c9c097aa1101de62b5ba3b89bf377ab6f70e6ab7cef299e8dafb3e330d6eeaca2b46db67dad437c243afd8afeb1a0ead24537e4a9e9d2dbeda9c908ac67426a0d4acd17b7bc11c6080d552dc16cbb67f0db4ccd68553ae912ac939e9deba4c69ca738dcb12a8bcdbfe95ffec9f5f4dabffda121f99dfcacecfcc17d2abea440ec17b6793cc081d3aabc89fb661a0e57ec58dfd5bd5d0fbf66acfbbf26beaf3daaf0baab9cd7df7f5e7afefcb4704d7fb60467dc061fc214fed4b1c08f6d21aa802c0bf3cfe457d6fc2edc0ed0aedb3760afa8beb805f2c51ffea55bacdb4e86a909afdfe4db9b20cafddaa65c3f13da4ed20c45f7e7d39ecf5eab2b760def3bf6aac965e7c72ffd5e4aa0fbfbd869b36febfd82bc97a7e9dfffcd7450aed29d87b4bed8cae3f1147ad2bbe705bc97dcbd8ac712e165bc13f3cdc8ffd693f335b3dc332adc9ef0c0a05c2d271da6da5cceb2f4af6978f21bf5dafbd8f2bcae8d302ac5bddab528aaf1f3eac5ad45bafcfa36d0d0f2adebbccf13c09a4bbf1edbf` + +var FuluBlockContents = ElectraBlockContents diff --git a/beacon-chain/rpc/eth/shared/testing/json_mainnet.go b/beacon-chain/rpc/eth/shared/testing/json_mainnet.go new file mode 100644 index 000000000000..965d0127134b --- /dev/null +++ b/beacon-chain/rpc/eth/shared/testing/json_mainnet.go @@ -0,0 +1,5 @@ +//go:build !minimal + +package testing + +const attestationCommitteeBits = "0x0100000000000000" diff --git a/beacon-chain/rpc/eth/shared/testing/json_minimal.go b/beacon-chain/rpc/eth/shared/testing/json_minimal.go new file mode 100644 index 000000000000..858dbeb3ae10 --- /dev/null +++ b/beacon-chain/rpc/eth/shared/testing/json_minimal.go @@ -0,0 +1,5 @@ +//go:build minimal + +package testing + +const attestationCommitteeBits = "0x01" diff --git a/beacon-chain/rpc/eth/validator/BUILD.bazel b/beacon-chain/rpc/eth/validator/BUILD.bazel index b4964a0570e0..3dda038b07ac 100644 --- a/beacon-chain/rpc/eth/validator/BUILD.bazel +++ b/beacon-chain/rpc/eth/validator/BUILD.bazel @@ -30,6 +30,7 @@ go_library( "//beacon-chain/rpc/lookup:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/sync:go_default_library", + "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types:go_default_library", @@ -37,14 +38,15 @@ go_library( "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//proto/prysm/v1alpha1/attestation/aggregation/attestations:go_default_library", "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//status:go_default_library", "@org_golang_google_protobuf//types/known/wrapperspb:go_default_library", @@ -82,17 +84,19 @@ go_test( "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//crypto/bls:go_default_library", + "//crypto/bls/common:go_default_library", "//encoding/bytesutil:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/mock:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", "@org_uber_go_mock//gomock:go_default_library", ], diff --git a/beacon-chain/rpc/eth/validator/handlers.go b/beacon-chain/rpc/eth/validator/handlers.go index f20ab9c5cc4d..fa1d3ba8f423 100644 --- a/beacon-chain/rpc/eth/validator/handlers.go +++ b/beacon-chain/rpc/eth/validator/handlers.go @@ -2,17 +2,20 @@ package validator import ( "bytes" + "cmp" "context" "encoding/json" "fmt" "io" "net/http" + "slices" "sort" "strconv" "time" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/builder" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" @@ -22,21 +25,25 @@ import ( rpchelpers "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/features" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" validator2 "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpbalpha "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation/aggregation/attestations" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +// Deprecated: use GetAggregateAttestationV2 instead // GetAggregateAttestation aggregates all attestations matching the given attestation data root and slot, returning the aggregated result. func (s *Server) GetAggregateAttestation(w http.ResponseWriter, r *http.Request) { _, span := trace.StartSpan(r.Context(), "validator.GetAggregateAttestation") @@ -46,71 +53,171 @@ func (s *Server) GetAggregateAttestation(w http.ResponseWriter, r *http.Request) if !ok { return } - _, slot, ok := shared.UintFromQuery(w, r, "slot", true) if !ok { return } - var match ethpbalpha.Att - var err error - - match, err = matchingAtt(s.AttestationsPool.AggregatedAttestations(), primitives.Slot(slot), attDataRoot) + agg := s.aggregatedAttestation(w, primitives.Slot(slot), attDataRoot, 0) + if agg == nil { + return + } + typedAgg, ok := agg.(*ethpbalpha.Attestation) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Attestation is not of type %T", ðpbalpha.Attestation{}), http.StatusInternalServerError) + return + } + data, err := json.Marshal(structs.AttFromConsensus(typedAgg)) if err != nil { - httputil.HandleError(w, "Could not get matching attestation: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not marshal attestation: "+err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteJson(w, &structs.AggregateAttestationResponse{Data: data}) +} + +// GetAggregateAttestationV2 aggregates all attestations matching the given attestation data root and slot, returning the aggregated result. +func (s *Server) GetAggregateAttestationV2(w http.ResponseWriter, r *http.Request) { + _, span := trace.StartSpan(r.Context(), "validator.GetAggregateAttestationV2") + defer span.End() + + _, attDataRoot, ok := shared.HexFromQuery(w, r, "attestation_data_root", fieldparams.RootLength, true) + if !ok { + return + } + _, slot, ok := shared.UintFromQuery(w, r, "slot", true) + if !ok { + return + } + _, index, ok := shared.UintFromQuery(w, r, "committee_index", true) + if !ok { + return + } + + v := slots.ToForkVersion(primitives.Slot(slot)) + agg := s.aggregatedAttestation(w, primitives.Slot(slot), attDataRoot, primitives.CommitteeIndex(index)) + if agg == nil { return } - if match == nil { - atts, err := s.AttestationsPool.UnaggregatedAttestations() + resp := &structs.AggregateAttestationResponse{ + Version: version.String(v), + } + if v >= version.Electra { + typedAgg, ok := agg.(*ethpbalpha.AttestationElectra) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Attestation is not of type %T", ðpbalpha.AttestationElectra{}), http.StatusInternalServerError) + return + } + data, err := json.Marshal(structs.AttElectraFromConsensus(typedAgg)) if err != nil { - httputil.HandleError(w, "Could not get unaggregated attestations: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not marshal attestation: "+err.Error(), http.StatusInternalServerError) + return + } + resp.Data = data + } else { + typedAgg, ok := agg.(*ethpbalpha.Attestation) + if !ok { + httputil.HandleError(w, fmt.Sprintf("Attestation is not of type %T", ðpbalpha.Attestation{}), http.StatusInternalServerError) return } - match, err = matchingAtt(atts, primitives.Slot(slot), attDataRoot) + data, err := json.Marshal(structs.AttFromConsensus(typedAgg)) if err != nil { - httputil.HandleError(w, "Could not get matching attestation: "+err.Error(), http.StatusInternalServerError) + httputil.HandleError(w, "Could not marshal attestation: "+err.Error(), http.StatusInternalServerError) return } + resp.Data = data } - if match == nil { - httputil.HandleError(w, "No matching attestation found", http.StatusNotFound) - return + w.Header().Set(api.VersionHeader, version.String(v)) + httputil.WriteJson(w, resp) +} + +func (s *Server) aggregatedAttestation(w http.ResponseWriter, slot primitives.Slot, attDataRoot []byte, index primitives.CommitteeIndex) ethpbalpha.Att { + var match []ethpbalpha.Att + var err error + + if features.Get().EnableExperimentalAttestationPool { + match, err = matchingAtts(s.AttestationCache.GetAll(), slot, attDataRoot, index) + if err != nil { + httputil.HandleError(w, "Could not get matching attestations: "+err.Error(), http.StatusInternalServerError) + return nil + } + } else { + match, err = matchingAtts(s.AttestationsPool.AggregatedAttestations(), slot, attDataRoot, index) + if err != nil { + httputil.HandleError(w, "Could not get matching attestations: "+err.Error(), http.StatusInternalServerError) + return nil + } } - response := &structs.AggregateAttestationResponse{ - Data: &structs.Attestation{ - AggregationBits: hexutil.Encode(match.GetAggregationBits()), - Data: &structs.AttestationData{ - Slot: strconv.FormatUint(uint64(match.GetData().Slot), 10), - CommitteeIndex: strconv.FormatUint(uint64(match.GetData().CommitteeIndex), 10), - BeaconBlockRoot: hexutil.Encode(match.GetData().BeaconBlockRoot), - Source: &structs.Checkpoint{ - Epoch: strconv.FormatUint(uint64(match.GetData().Source.Epoch), 10), - Root: hexutil.Encode(match.GetData().Source.Root), - }, - Target: &structs.Checkpoint{ - Epoch: strconv.FormatUint(uint64(match.GetData().Target.Epoch), 10), - Root: hexutil.Encode(match.GetData().Target.Root), - }, - }, - Signature: hexutil.Encode(match.GetSignature()), - }} - httputil.WriteJson(w, response) + if len(match) > 0 { + // If there are multiple matching aggregated attestations, + // then we return the one with the most aggregation bits. + slices.SortFunc(match, func(a, b ethpbalpha.Att) int { + return cmp.Compare(b.GetAggregationBits().Count(), a.GetAggregationBits().Count()) + }) + return match[0] + } + + // No match was found and the new pool doesn't store aggregated and unaggregated attestations separately. + if features.Get().EnableExperimentalAttestationPool { + return nil + } + + atts, err := s.AttestationsPool.UnaggregatedAttestations() + if err != nil { + httputil.HandleError(w, "Could not get unaggregated attestations: "+err.Error(), http.StatusInternalServerError) + return nil + } + match, err = matchingAtts(atts, slot, attDataRoot, index) + if err != nil { + httputil.HandleError(w, "Could not get matching attestations: "+err.Error(), http.StatusInternalServerError) + return nil + } + if len(match) == 0 { + httputil.HandleError(w, "No matching attestations found", http.StatusNotFound) + return nil + } + agg, err := attestations.Aggregate(match) + if err != nil { + httputil.HandleError(w, "Could not aggregate unaggregated attestations: "+err.Error(), http.StatusInternalServerError) + return nil + } + + // Aggregating unaggregated attestations will in theory always return just one aggregate, + // so we can take the first one and be done with it. + return agg[0] } -func matchingAtt(atts []ethpbalpha.Att, slot primitives.Slot, attDataRoot []byte) (ethpbalpha.Att, error) { +func matchingAtts(atts []ethpbalpha.Att, slot primitives.Slot, attDataRoot []byte, index primitives.CommitteeIndex) ([]ethpbalpha.Att, error) { + if len(atts) == 0 { + return []ethpbalpha.Att{}, nil + } + + postElectra := slots.ToForkVersion(slot) >= version.Electra + result := make([]ethpbalpha.Att, 0) for _, att := range atts { - if att.GetData().Slot == slot { - root, err := att.GetData().HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "could not get attestation data root") - } - if bytes.Equal(root[:], attDataRoot) { - return att, nil - } + if att.GetData().Slot != slot { + continue + } + + root, err := att.GetData().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not get attestation data root") + } + if !bytes.Equal(root[:], attDataRoot) { + continue + } + + // We ignore the committee index from the request before Electra. + // This is because before Electra the committee index is part of the attestation data, + // meaning that comparing the data root is sufficient. + // Post-Electra the committee index in the data root is always 0, so we need to + // compare the committee index separately. + if (!postElectra && att.Version() < version.Electra) || (postElectra && att.Version() >= version.Electra && att.GetCommitteeIndex() == index) { + result = append(result, att) } } - return nil, nil + + return result, nil } // SubmitContributionAndProofs publishes multiple signed sync committee contribution and proofs. @@ -118,34 +225,39 @@ func (s *Server) SubmitContributionAndProofs(w http.ResponseWriter, r *http.Requ ctx, span := trace.StartSpan(r.Context(), "validator.SubmitContributionAndProofs") defer span.End() - var req structs.SubmitContributionAndProofsRequest - err := json.NewDecoder(r.Body).Decode(&req.Data) - switch { - case errors.Is(err, io.EOF): - httputil.HandleError(w, "No data submitted", http.StatusBadRequest) - return - case err != nil: - httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest) + var reqData []json.RawMessage + if err := json.NewDecoder(r.Body).Decode(&reqData); err != nil { + if errors.Is(err, io.EOF) { + httputil.HandleError(w, "No data submitted", http.StatusBadRequest) + } else { + httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest) + } return } - if len(req.Data) == 0 { + if len(reqData) == 0 { httputil.HandleError(w, "No data submitted", http.StatusBadRequest) return } - for _, item := range req.Data { - consensusItem, err := item.ToConsensus() + for _, item := range reqData { + var contribution structs.SignedContributionAndProof + if err := json.Unmarshal(item, &contribution); err != nil { + httputil.HandleError(w, "Could not decode item: "+err.Error(), http.StatusBadRequest) + return + } + consensusItem, err := contribution.ToConsensus() if err != nil { - httputil.HandleError(w, "Could not convert request contribution to consensus contribution: "+err.Error(), http.StatusBadRequest) + httputil.HandleError(w, "Could not convert contribution to consensus format: "+err.Error(), http.StatusBadRequest) return } - rpcError := s.CoreService.SubmitSignedContributionAndProof(ctx, consensusItem) - if rpcError != nil { + if rpcError := s.CoreService.SubmitSignedContributionAndProof(ctx, consensusItem); rpcError != nil { httputil.HandleError(w, rpcError.Err.Error(), core.ErrorReasonToHTTP(rpcError.Reason)) + return } } } +// Deprecated: use SubmitAggregateAndProofsV2 instead // SubmitAggregateAndProofs verifies given aggregate and proofs and publishes them on appropriate gossipsub topic. func (s *Server) SubmitAggregateAndProofs(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "validator.SubmitAggregateAndProofs") @@ -168,7 +280,13 @@ func (s *Server) SubmitAggregateAndProofs(w http.ResponseWriter, r *http.Request broadcastFailed := false for _, item := range req.Data { - consensusItem, err := item.ToConsensus() + var signedAggregate structs.SignedAggregateAttestationAndProof + err := json.Unmarshal(item, &signedAggregate) + if err != nil { + httputil.HandleError(w, "Could not decode item: "+err.Error(), http.StatusBadRequest) + return + } + consensusItem, err := signedAggregate.ToConsensus() if err != nil { httputil.HandleError(w, "Could not convert request aggregate to consensus aggregate: "+err.Error(), http.StatusBadRequest) return @@ -191,6 +309,81 @@ func (s *Server) SubmitAggregateAndProofs(w http.ResponseWriter, r *http.Request } } +// SubmitAggregateAndProofsV2 verifies given aggregate and proofs and publishes them on appropriate gossipsub topic. +func (s *Server) SubmitAggregateAndProofsV2(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "validator.SubmitAggregateAndProofsV2") + defer span.End() + + var reqData []json.RawMessage + if err := json.NewDecoder(r.Body).Decode(&reqData); err != nil { + if errors.Is(err, io.EOF) { + httputil.HandleError(w, "No data submitted", http.StatusBadRequest) + } else { + httputil.HandleError(w, "Could not decode request body: "+err.Error(), http.StatusBadRequest) + } + return + } + if len(reqData) == 0 { + httputil.HandleError(w, "No data submitted", http.StatusBadRequest) + return + } + + versionHeader := r.Header.Get(api.VersionHeader) + if versionHeader == "" { + httputil.HandleError(w, api.VersionHeader+" header is required", http.StatusBadRequest) + } + v, err := version.FromString(versionHeader) + if err != nil { + httputil.HandleError(w, "Invalid version: "+err.Error(), http.StatusBadRequest) + return + } + + broadcastFailed := false + var rpcError *core.RpcError + for _, raw := range reqData { + if v >= version.Electra { + var signedAggregate structs.SignedAggregateAttestationAndProofElectra + err = json.Unmarshal(raw, &signedAggregate) + if err != nil { + httputil.HandleError(w, "Failed to parse aggregate attestation and proof: "+err.Error(), http.StatusBadRequest) + return + } + consensusItem, err := signedAggregate.ToConsensus() + if err != nil { + httputil.HandleError(w, "Could not convert request aggregate to consensus aggregate: "+err.Error(), http.StatusBadRequest) + return + } + rpcError = s.CoreService.SubmitSignedAggregateSelectionProof(ctx, consensusItem) + } else { + var signedAggregate structs.SignedAggregateAttestationAndProof + err = json.Unmarshal(raw, &signedAggregate) + if err != nil { + httputil.HandleError(w, "Failed to parse aggregate attestation and proof: "+err.Error(), http.StatusBadRequest) + return + } + consensusItem, err := signedAggregate.ToConsensus() + if err != nil { + httputil.HandleError(w, "Could not convert request aggregate to consensus aggregate: "+err.Error(), http.StatusBadRequest) + return + } + rpcError = s.CoreService.SubmitSignedAggregateSelectionProof(ctx, consensusItem) + } + + if rpcError != nil { + var aggregateBroadcastFailedError *core.AggregateBroadcastFailedError + if errors.As(rpcError.Err, &aggregateBroadcastFailedError) { + broadcastFailed = true + } else { + httputil.HandleError(w, rpcError.Err.Error(), core.ErrorReasonToHTTP(rpcError.Reason)) + return + } + } + } + if broadcastFailed { + httputil.HandleError(w, "Could not broadcast one or more signed aggregated attestations", http.StatusInternalServerError) + } +} + // SubmitSyncCommitteeSubscription subscribe to a number of sync committee subnets. // // Subscribing to sync committee subnets is an action performed by VC to enable diff --git a/beacon-chain/rpc/eth/validator/handlers_block.go b/beacon-chain/rpc/eth/validator/handlers_block.go index bf444aafa59c..1f229e1719d6 100644 --- a/beacon-chain/rpc/eth/validator/handlers_block.go +++ b/beacon-chain/rpc/eth/validator/handlers_block.go @@ -17,10 +17,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -287,6 +287,30 @@ func (s *Server) produceBlockV3(ctx context.Context, w http.ResponseWriter, r *h handleProduceDenebV3(w, isSSZ, denebBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue) return } + blindedElectraBlockContents, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedElectra) + if ok { + w.Header().Set(api.VersionHeader, version.String(version.Electra)) + handleProduceBlindedElectraV3(w, isSSZ, blindedElectraBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue) + return + } + electraBlockContents, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Electra) + if ok { + w.Header().Set(api.VersionHeader, version.String(version.Electra)) + handleProduceElectraV3(w, isSSZ, electraBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue) + return + } + blindedFuluBlockContents, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_BlindedFulu) + if ok { + w.Header().Set(api.VersionHeader, version.String(version.Fulu)) + handleProduceBlindedFuluV3(w, isSSZ, blindedFuluBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue) + return + } + fuluBlockContents, ok := v1alpha1resp.Block.(*eth.GenericBeaconBlock_Fulu) + if ok { + w.Header().Set(api.VersionHeader, version.String(version.Fulu)) + handleProduceFuluV3(w, isSSZ, fuluBlockContents, v1alpha1resp.PayloadValue, consensusBlockValue) + return + } } func getConsensusBlockValue(ctx context.Context, blockRewardsFetcher rewards.BlockRewardsFetcher, i interface{} /* block as argument */) (string, *httputil.DefaultJsonError) { @@ -587,3 +611,145 @@ func handleProduceDenebV3( Data: jsonBytes, }) } + +func handleProduceBlindedElectraV3( + w http.ResponseWriter, + isSSZ bool, + blk *eth.GenericBeaconBlock_BlindedElectra, + executionPayloadValue string, + consensusPayloadValue string, +) { + if isSSZ { + sszResp, err := blk.BlindedElectra.MarshalSSZ() + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteSsz(w, sszResp, "blindedElectraBlockContents.ssz") + return + } + blindedBlock, err := structs.BlindedBeaconBlockElectraFromConsensus(blk.BlindedElectra) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + jsonBytes, err := json.Marshal(blindedBlock) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteJson(w, &structs.ProduceBlockV3Response{ + Version: version.String(version.Electra), + ExecutionPayloadBlinded: true, + ExecutionPayloadValue: executionPayloadValue, + ConsensusBlockValue: consensusPayloadValue, + Data: jsonBytes, + }) +} + +func handleProduceElectraV3( + w http.ResponseWriter, + isSSZ bool, + blk *eth.GenericBeaconBlock_Electra, + executionPayloadValue string, + consensusBlockValue string, +) { + if isSSZ { + sszResp, err := blk.Electra.MarshalSSZ() + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteSsz(w, sszResp, "electraBlockContents.ssz") + return + } + + blockContents, err := structs.BeaconBlockContentsElectraFromConsensus(blk.Electra) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + jsonBytes, err := json.Marshal(blockContents) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteJson(w, &structs.ProduceBlockV3Response{ + Version: version.String(version.Electra), + ExecutionPayloadBlinded: false, + ExecutionPayloadValue: executionPayloadValue, // mev not available at this point + ConsensusBlockValue: consensusBlockValue, + Data: jsonBytes, + }) +} + +func handleProduceBlindedFuluV3( + w http.ResponseWriter, + isSSZ bool, + blk *eth.GenericBeaconBlock_BlindedFulu, + executionPayloadValue string, + consensusPayloadValue string, +) { + if isSSZ { + sszResp, err := blk.BlindedFulu.MarshalSSZ() + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteSsz(w, sszResp, "blindedFuluBlockContents.ssz") + return + } + blindedBlock, err := structs.BlindedBeaconBlockFuluFromConsensus(blk.BlindedFulu) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + jsonBytes, err := json.Marshal(blindedBlock) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteJson(w, &structs.ProduceBlockV3Response{ + Version: version.String(version.Fulu), + ExecutionPayloadBlinded: true, + ExecutionPayloadValue: executionPayloadValue, + ConsensusBlockValue: consensusPayloadValue, + Data: jsonBytes, + }) +} + +func handleProduceFuluV3( + w http.ResponseWriter, + isSSZ bool, + blk *eth.GenericBeaconBlock_Fulu, + executionPayloadValue string, + consensusBlockValue string, +) { + if isSSZ { + sszResp, err := blk.Fulu.MarshalSSZ() + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteSsz(w, sszResp, "fuluBlockContents.ssz") + return + } + + blockContents, err := structs.BeaconBlockContentsFuluFromConsensus(blk.Fulu) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + jsonBytes, err := json.Marshal(blockContents) + if err != nil { + httputil.HandleError(w, err.Error(), http.StatusInternalServerError) + return + } + httputil.WriteJson(w, &structs.ProduceBlockV3Response{ + Version: version.String(version.Fulu), + ExecutionPayloadBlinded: false, + ExecutionPayloadValue: executionPayloadValue, // mev not available at this point + ConsensusBlockValue: consensusBlockValue, + Data: jsonBytes, + }) +} diff --git a/beacon-chain/rpc/eth/validator/handlers_block_test.go b/beacon-chain/rpc/eth/validator/handlers_block_test.go index 9cfe0b485aa4..aa4e5b0b5c92 100644 --- a/beacon-chain/rpc/eth/validator/handlers_block_test.go +++ b/beacon-chain/rpc/eth/validator/handlers_block_test.go @@ -308,6 +308,75 @@ func TestProduceBlockV2(t *testing.T) { assert.Equal(t, http.StatusInternalServerError, e.Code) assert.StringContains(t, "Prepared block is blinded", e.Message) }) + t.Run("Electra", func(t *testing.T) { + var block *structs.SignedBeaconBlockContentsElectra + err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block) + require.NoError(t, err) + jsonBytes, err := json.Marshal(block.ToUnsigned()) + require.NoError(t, err) + + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: true, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + b, err := block.ToUnsigned().ToGeneric() + require.NoError(t, err) + b.PayloadValue = "2000" + return b, nil + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + want := fmt.Sprintf(`{"version":"electra","execution_payload_blinded":false,"execution_payload_value":"2000","consensus_block_value":"10000000000","data":%s}`, string(jsonBytes)) + body := strings.ReplaceAll(writer.Body.String(), "\n", "") + require.Equal(t, want, body) + require.Equal(t, "electra", writer.Header().Get(api.VersionHeader)) + }) + t.Run("Blinded Electra", func(t *testing.T) { + var block *structs.SignedBlindedBeaconBlockElectra + err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block) + require.NoError(t, err) + + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: true, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + return block.Message.ToGeneric() + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV2(writer, request) + assert.Equal(t, http.StatusInternalServerError, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusInternalServerError, e.Code) + assert.StringContains(t, "Prepared block is blinded", e.Message) + }) t.Run("invalid query parameter slot empty", func(t *testing.T) { v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) server := &Server{ @@ -650,6 +719,76 @@ func TestProduceBlockV2SSZ(t *testing.T) { BlockRewardFetcher: rewardFetcher, } + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + request.Header.Set("Accept", api.OctetStreamMediaType) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV2(writer, request) + assert.Equal(t, http.StatusInternalServerError, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusInternalServerError, e.Code) + assert.StringContains(t, "Prepared block is blinded", e.Message) + }) + t.Run("Electra", func(t *testing.T) { + var block *structs.SignedBeaconBlockContentsElectra + err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block) + require.NoError(t, err) + + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: true, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + return block.ToUnsigned().ToGeneric() + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + request.Header.Set("Accept", api.OctetStreamMediaType) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + g, err := block.ToUnsigned().ToGeneric() + require.NoError(t, err) + bl, ok := g.Block.(*eth.GenericBeaconBlock_Electra) + require.Equal(t, true, ok) + ssz, err := bl.Electra.MarshalSSZ() + require.NoError(t, err) + require.Equal(t, string(ssz), writer.Body.String()) + require.Equal(t, "electra", writer.Header().Get(api.VersionHeader)) + }) + t.Run("Blinded Electra", func(t *testing.T) { + var block *structs.SignedBlindedBeaconBlockElectra + err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block) + require.NoError(t, err) + + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: true, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + return block.Message.ToGeneric() + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v2/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) request.Header.Set("Accept", api.OctetStreamMediaType) writer := httptest.NewRecorder() @@ -944,6 +1083,75 @@ func TestProduceBlindedBlock(t *testing.T) { require.Equal(t, want, body) require.Equal(t, "deneb", writer.Header().Get(api.VersionHeader)) }) + t.Run("Electra", func(t *testing.T) { + var block *structs.SignedBeaconBlockContentsElectra + err = json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block) + require.NoError(t, err) + + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: false, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + return block.ToUnsigned().ToGeneric() + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v1/validator/blinded_blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlindedBlock(writer, request) + assert.Equal(t, http.StatusInternalServerError, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusInternalServerError, e.Code) + assert.StringContains(t, "Prepared block is not blinded", e.Message) + }) + t.Run("Blinded Electra", func(t *testing.T) { + var block *structs.SignedBlindedBeaconBlockElectra + err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block) + require.NoError(t, err) + jsonBytes, err := json.Marshal(block.Message) + require.NoError(t, err) + + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: false, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + b, err := block.Message.ToGeneric() + require.NoError(t, err) + b.PayloadValue = "2000" + return b, nil + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v1/validator/blinded_blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlindedBlock(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + want := fmt.Sprintf(`{"version":"electra","execution_payload_blinded":true,"execution_payload_value":"2000","consensus_block_value":"10000000000","data":%s}`, string(jsonBytes)) + body := strings.ReplaceAll(writer.Body.String(), "\n", "") + require.Equal(t, want, body) + require.Equal(t, "electra", writer.Header().Get(api.VersionHeader)) + }) t.Run("invalid query parameter slot empty", func(t *testing.T) { v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) server := &Server{ @@ -1309,6 +1517,82 @@ func TestProduceBlockV3(t *testing.T) { require.Equal(t, "deneb", writer.Header().Get(api.VersionHeader)) require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader)) }) + t.Run("Electra", func(t *testing.T) { + var block *structs.SignedBeaconBlockContentsElectra + err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block) + require.NoError(t, err) + jsonBytes, err := json.Marshal(block.ToUnsigned()) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: false, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + b, err := block.ToUnsigned().ToGeneric() + require.NoError(t, err) + b.PayloadValue = "2000" + return b, nil + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV3(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + want := fmt.Sprintf(`{"version":"electra","execution_payload_blinded":false,"execution_payload_value":"2000","consensus_block_value":"10000000000","data":%s}`, string(jsonBytes)) + body := strings.ReplaceAll(writer.Body.String(), "\n", "") + require.Equal(t, want, body) + require.Equal(t, "false", writer.Header().Get(api.ExecutionPayloadBlindedHeader)) + require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader)) + require.Equal(t, "electra", writer.Header().Get(api.VersionHeader)) + require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader)) + }) + t.Run("Blinded Electra", func(t *testing.T) { + var block *structs.SignedBlindedBeaconBlockElectra + err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block) + require.NoError(t, err) + jsonBytes, err := json.Marshal(block.Message) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: false, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + b, err := block.Message.ToGeneric() + require.NoError(t, err) + b.PayloadValue = "2000" + return b, nil + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV3(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + want := fmt.Sprintf(`{"version":"electra","execution_payload_blinded":true,"execution_payload_value":"2000","consensus_block_value":"10000000000","data":%s}`, string(jsonBytes)) + body := strings.ReplaceAll(writer.Body.String(), "\n", "") + require.Equal(t, want, body) + require.Equal(t, "true", writer.Header().Get(api.ExecutionPayloadBlindedHeader)) + require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader)) + require.Equal(t, "electra", writer.Header().Get(api.VersionHeader)) + require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader)) + }) t.Run("invalid query parameter slot empty", func(t *testing.T) { v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) server := &Server{ @@ -1697,4 +1981,168 @@ func TestProduceBlockV3SSZ(t *testing.T) { require.Equal(t, "deneb", writer.Header().Get(api.VersionHeader)) require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader)) }) + t.Run("Electra", func(t *testing.T) { + var block *structs.SignedBeaconBlockContentsElectra + err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &block) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: false, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + b, err := block.ToUnsigned().ToGeneric() + require.NoError(t, err) + b.PayloadValue = "2000" + return b, nil + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + request.Header.Set("Accept", api.OctetStreamMediaType) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV3(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + g, err := block.ToUnsigned().ToGeneric() + require.NoError(t, err) + bl, ok := g.Block.(*eth.GenericBeaconBlock_Electra) + require.Equal(t, true, ok) + ssz, err := bl.Electra.MarshalSSZ() + require.NoError(t, err) + require.Equal(t, string(ssz), writer.Body.String()) + require.Equal(t, "false", writer.Header().Get(api.ExecutionPayloadBlindedHeader)) + require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader)) + require.Equal(t, "electra", writer.Header().Get(api.VersionHeader)) + require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader)) + }) + t.Run("Blinded Electra", func(t *testing.T) { + var block *structs.SignedBlindedBeaconBlockElectra + err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: false, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + b, err := block.Message.ToGeneric() + require.NoError(t, err) + b.PayloadValue = "2000" + return b, nil + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + request.Header.Set("Accept", api.OctetStreamMediaType) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV3(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + g, err := block.Message.ToGeneric() + require.NoError(t, err) + bl, ok := g.Block.(*eth.GenericBeaconBlock_BlindedElectra) + require.Equal(t, true, ok) + ssz, err := bl.BlindedElectra.MarshalSSZ() + require.NoError(t, err) + require.Equal(t, string(ssz), writer.Body.String()) + require.Equal(t, "true", writer.Header().Get(api.ExecutionPayloadBlindedHeader)) + require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader)) + require.Equal(t, "electra", writer.Header().Get(api.VersionHeader)) + require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader)) + }) + t.Run("Fulu", func(t *testing.T) { + var block *structs.SignedBeaconBlockContentsFulu + err := json.Unmarshal([]byte(rpctesting.FuluBlockContents), &block) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: false, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + b, err := block.ToUnsigned().ToGeneric() + require.NoError(t, err) + b.PayloadValue = "2000" + return b, nil + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + request.Header.Set("Accept", api.OctetStreamMediaType) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV3(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + g, err := block.ToUnsigned().ToGeneric() + require.NoError(t, err) + bl, ok := g.Block.(*eth.GenericBeaconBlock_Fulu) + require.Equal(t, true, ok) + ssz, err := bl.Fulu.MarshalSSZ() + require.NoError(t, err) + require.Equal(t, string(ssz), writer.Body.String()) + require.Equal(t, "false", writer.Header().Get(api.ExecutionPayloadBlindedHeader)) + require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader)) + require.Equal(t, "fulu", writer.Header().Get(api.VersionHeader)) + require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader)) + }) + t.Run("Blinded Fulu", func(t *testing.T) { + var block *structs.SignedBlindedBeaconBlockFulu + err := json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &block) + require.NoError(t, err) + v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl) + v1alpha1Server.EXPECT().GetBeaconBlock(gomock.Any(), ð.BlockRequest{ + Slot: 1, + RandaoReveal: bRandao, + Graffiti: bGraffiti, + SkipMevBoost: false, + }).Return( + func() (*eth.GenericBeaconBlock, error) { + b, err := block.Message.ToGeneric() + require.NoError(t, err) + b.PayloadValue = "2000" + return b, nil + }()) + server := &Server{ + V1Alpha1Server: v1alpha1Server, + SyncChecker: syncChecker, + OptimisticModeFetcher: chainService, + BlockRewardFetcher: rewardFetcher, + } + request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://foo.example/eth/v3/validator/blocks/1?randao_reveal=%s&graffiti=%s", randao, graffiti), nil) + request.Header.Set("Accept", api.OctetStreamMediaType) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.ProduceBlockV3(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + g, err := block.Message.ToGeneric() + require.NoError(t, err) + bl, ok := g.Block.(*eth.GenericBeaconBlock_BlindedFulu) + require.Equal(t, true, ok) + ssz, err := bl.BlindedFulu.MarshalSSZ() + require.NoError(t, err) + require.Equal(t, string(ssz), writer.Body.String()) + require.Equal(t, "true", writer.Header().Get(api.ExecutionPayloadBlindedHeader)) + require.Equal(t, "2000", writer.Header().Get(api.ExecutionPayloadValueHeader)) + require.Equal(t, "fulu", writer.Header().Get(api.VersionHeader)) + require.Equal(t, "10000000000", writer.Header().Get(api.ConsensusBlockValueHeader)) + }) } diff --git a/beacon-chain/rpc/eth/validator/handlers_test.go b/beacon-chain/rpc/eth/validator/handlers_test.go index 47cfa9ba6cc0..a847a845d291 100644 --- a/beacon-chain/rpc/eth/validator/handlers_test.go +++ b/beacon-chain/rpc/eth/validator/handlers_test.go @@ -13,8 +13,9 @@ import ( "time" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/pkg/errors" + "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/api/server/structs" mockChain "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" builderTest "github.com/prysmaticlabs/prysm/v5/beacon-chain/builder/testing" @@ -35,9 +36,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" + "github.com/prysmaticlabs/prysm/v5/crypto/bls/common" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpbalpha "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -47,292 +50,465 @@ import ( func TestGetAggregateAttestation(t *testing.T) { root1 := bytesutil.PadTo([]byte("root1"), 32) - sig1 := bytesutil.PadTo([]byte("sig1"), fieldparams.BLSSignatureLength) - attSlot1 := ðpbalpha.Attestation{ - AggregationBits: []byte{0, 1}, - Data: ðpbalpha.AttestationData{ - Slot: 1, - CommitteeIndex: 1, - BeaconBlockRoot: root1, - Source: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root1, - }, - Target: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root1, - }, - }, - Signature: sig1, - } - root21 := bytesutil.PadTo([]byte("root2_1"), 32) - sig21 := bytesutil.PadTo([]byte("sig2_1"), fieldparams.BLSSignatureLength) - attslot21 := ðpbalpha.Attestation{ - AggregationBits: []byte{0, 1, 1}, - Data: ðpbalpha.AttestationData{ - Slot: 2, - CommitteeIndex: 1, - BeaconBlockRoot: root21, - Source: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root21, - }, - Target: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root21, - }, - }, - Signature: sig21, - } - root22 := bytesutil.PadTo([]byte("root2_2"), 32) - sig22 := bytesutil.PadTo([]byte("sig2_2"), fieldparams.BLSSignatureLength) - attslot22 := ðpbalpha.Attestation{ - AggregationBits: []byte{0, 1, 1, 1}, - Data: ðpbalpha.AttestationData{ - Slot: 2, - CommitteeIndex: 1, - BeaconBlockRoot: root22, - Source: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root22, - }, - Target: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root22, - }, - }, - Signature: sig22, - } - root31 := bytesutil.PadTo([]byte("root3_1"), 32) - sig31 := bls.NewAggregateSignature().Marshal() - attslot31 := ðpbalpha.Attestation{ - AggregationBits: []byte{1, 0}, - Data: ðpbalpha.AttestationData{ - Slot: 3, - CommitteeIndex: 1, - BeaconBlockRoot: root31, - Source: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root31, - }, - Target: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root31, - }, - }, - Signature: sig31, - } - root32 := bytesutil.PadTo([]byte("root3_2"), 32) - sig32 := bls.NewAggregateSignature().Marshal() - attslot32 := ðpbalpha.Attestation{ - AggregationBits: []byte{0, 1}, - Data: ðpbalpha.AttestationData{ - Slot: 3, - CommitteeIndex: 1, - BeaconBlockRoot: root32, - Source: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root32, - }, - Target: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root32, - }, - }, - Signature: sig32, + root2 := bytesutil.PadTo([]byte("root2"), 32) + key, err := bls.RandKey() + require.NoError(t, err) + sig := key.Sign([]byte("sig")) + + // It is important to use 0 as the index because that's the only way + // pre and post-Electra attestations can both match, + // which allows us to properly test that attestations from the + // wrong fork are ignored. + committeeIndex := uint64(0) + + createAttestation := func(slot primitives.Slot, aggregationBits bitfield.Bitlist, root []byte) *ethpbalpha.Attestation { + return ðpbalpha.Attestation{ + AggregationBits: aggregationBits, + Data: createAttestationData(slot, primitives.CommitteeIndex(committeeIndex), root), + Signature: sig.Marshal(), + } } - pool := attestations.NewPool() - err := pool.SaveAggregatedAttestations([]ethpbalpha.Att{attSlot1, attslot21, attslot22}) - assert.NoError(t, err) - err = pool.SaveUnaggregatedAttestations([]ethpbalpha.Att{attslot31, attslot32}) - assert.NoError(t, err) + createAttestationElectra := func(slot primitives.Slot, aggregationBits bitfield.Bitlist, root []byte) *ethpbalpha.AttestationElectra { + committeeBits := bitfield.NewBitvector64() + committeeBits.SetBitAt(committeeIndex, true) - s := &Server{ - AttestationsPool: pool, + return ðpbalpha.AttestationElectra{ + CommitteeBits: committeeBits, + AggregationBits: aggregationBits, + Data: createAttestationData(slot, primitives.CommitteeIndex(committeeIndex), root), + Signature: sig.Marshal(), + } } - t.Run("matching aggregated att", func(t *testing.T) { - reqRoot, err := attslot22.Data.HashTreeRoot() + t.Run("V1", func(t *testing.T) { + aggSlot1_Root1_1 := createAttestation(1, bitfield.Bitlist{0b11100}, root1) + aggSlot1_Root1_2 := createAttestation(1, bitfield.Bitlist{0b10111}, root1) + aggSlot1_Root2 := createAttestation(1, bitfield.Bitlist{0b11100}, root2) + aggSlot2 := createAttestation(2, bitfield.Bitlist{0b11100}, root1) + unaggSlot3_Root1_1 := createAttestation(3, bitfield.Bitlist{0b11000}, root1) + unaggSlot3_Root1_2 := createAttestation(3, bitfield.Bitlist{0b10100}, root1) + unaggSlot3_Root2 := createAttestation(3, bitfield.Bitlist{0b11000}, root2) + unaggSlot4 := createAttestation(4, bitfield.Bitlist{0b11000}, root1) + + compareResult := func( + t *testing.T, + attestation structs.Attestation, + expectedSlot string, + expectedAggregationBits string, + expectedRoot []byte, + expectedSig []byte, + ) { + assert.Equal(t, expectedAggregationBits, attestation.AggregationBits, "Unexpected aggregation bits in attestation") + assert.Equal(t, hexutil.Encode(expectedSig), attestation.Signature, "Signature mismatch") + assert.Equal(t, expectedSlot, attestation.Data.Slot, "Slot mismatch in attestation data") + assert.Equal(t, "0", attestation.Data.CommitteeIndex, "Committee index mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.BeaconBlockRoot, "Beacon block root mismatch") + + // Source checkpoint checks + require.NotNil(t, attestation.Data.Source, "Source checkpoint should not be nil") + assert.Equal(t, "1", attestation.Data.Source.Epoch, "Source epoch mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.Source.Root, "Source root mismatch") + + // Target checkpoint checks + require.NotNil(t, attestation.Data.Target, "Target checkpoint should not be nil") + assert.Equal(t, "1", attestation.Data.Target.Epoch, "Target epoch mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.Target.Root, "Target root mismatch") + } + + pool := attestations.NewPool() + require.NoError(t, pool.SaveUnaggregatedAttestations([]ethpbalpha.Att{unaggSlot3_Root1_1, unaggSlot3_Root1_2, unaggSlot3_Root2, unaggSlot4}), "Failed to save unaggregated attestations") + unagg, err := pool.UnaggregatedAttestations() require.NoError(t, err) - attDataRoot := hexutil.Encode(reqRoot[:]) - url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=2" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + require.Equal(t, 4, len(unagg), "Expected 4 unaggregated attestations") + require.NoError(t, pool.SaveAggregatedAttestations([]ethpbalpha.Att{aggSlot1_Root1_1, aggSlot1_Root1_2, aggSlot1_Root2, aggSlot2}), "Failed to save aggregated attestations") + agg := pool.AggregatedAttestations() + require.Equal(t, 4, len(agg), "Expected 4 aggregated attestations") + s := &Server{ + AttestationsPool: pool, + } - s.GetAggregateAttestation(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - resp := &structs.AggregateAttestationResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.NotNil(t, resp) - require.NotNil(t, resp.Data) - assert.DeepEqual(t, "0x00010101", resp.Data.AggregationBits) - assert.DeepEqual(t, hexutil.Encode(sig22), resp.Data.Signature) - assert.Equal(t, "2", resp.Data.Data.Slot) - assert.Equal(t, "1", resp.Data.Data.CommitteeIndex) - assert.DeepEqual(t, hexutil.Encode(root22), resp.Data.Data.BeaconBlockRoot) - require.NotNil(t, resp.Data.Data.Source) - assert.Equal(t, "1", resp.Data.Data.Source.Epoch) - assert.DeepEqual(t, hexutil.Encode(root22), resp.Data.Data.Source.Root) - require.NotNil(t, resp.Data.Data.Target) - assert.Equal(t, "1", resp.Data.Data.Target.Epoch) - assert.DeepEqual(t, hexutil.Encode(root22), resp.Data.Data.Target.Root) - }) - t.Run("matching unaggregated att", func(t *testing.T) { - reqRoot, err := attslot32.Data.HashTreeRoot() - require.NoError(t, err) - attDataRoot := hexutil.Encode(reqRoot[:]) - url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=3" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + t.Run("non-matching attestation request", func(t *testing.T) { + reqRoot, err := aggSlot2.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() - s.GetAggregateAttestation(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - resp := &structs.AggregateAttestationResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.NotNil(t, resp) - require.NotNil(t, resp.Data) - assert.DeepEqual(t, "0x0001", resp.Data.AggregationBits) - assert.DeepEqual(t, hexutil.Encode(sig32), resp.Data.Signature) - assert.Equal(t, "3", resp.Data.Data.Slot) - assert.Equal(t, "1", resp.Data.Data.CommitteeIndex) - assert.DeepEqual(t, hexutil.Encode(root32), resp.Data.Data.BeaconBlockRoot) - require.NotNil(t, resp.Data.Data.Source) - assert.Equal(t, "1", resp.Data.Data.Source.Epoch) - assert.DeepEqual(t, hexutil.Encode(root32), resp.Data.Data.Source.Root) - require.NotNil(t, resp.Data.Data.Target) - assert.Equal(t, "1", resp.Data.Data.Target.Epoch) - assert.DeepEqual(t, hexutil.Encode(root32), resp.Data.Data.Target.Root) - }) - t.Run("no matching attestation", func(t *testing.T) { - attDataRoot := hexutil.Encode(bytesutil.PadTo([]byte("foo"), 32)) - url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=2" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + s.GetAggregateAttestation(writer, request) + assert.Equal(t, http.StatusNotFound, writer.Code, "Expected HTTP status NotFound for non-matching request") + }) + t.Run("1 matching aggregated attestation", func(t *testing.T) { + reqRoot, err := aggSlot2.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=2" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() - s.GetAggregateAttestation(writer, request) - assert.Equal(t, http.StatusNotFound, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusNotFound, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "No matching attestation found")) - }) - t.Run("no attestation_data_root provided", func(t *testing.T) { - url := "http://example.com?slot=2" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + s.GetAggregateAttestation(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") - s.GetAggregateAttestation(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "attestation_data_root is required")) - }) - t.Run("invalid attestation_data_root provided", func(t *testing.T) { - url := "http://example.com?attestation_data_root=foo&slot=2" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") - s.GetAggregateAttestation(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "attestation_data_root is invalid")) - }) - t.Run("no slot provided", func(t *testing.T) { - attDataRoot := hexutil.Encode(bytesutil.PadTo([]byte("foo"), 32)) - url := "http://example.com?attestation_data_root=" + attDataRoot - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + var attestation structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") - s.GetAggregateAttestation(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "slot is required")) + compareResult(t, attestation, "2", hexutil.Encode(aggSlot2.AggregationBits), root1, sig.Marshal()) + }) + t.Run("multiple matching aggregated attestations - return the one with most bits", func(t *testing.T) { + reqRoot, err := aggSlot1_Root1_1.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestation(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + + compareResult(t, attestation, "1", hexutil.Encode(aggSlot1_Root1_2.AggregationBits), root1, sig.Marshal()) + }) + t.Run("1 matching unaggregated attestation", func(t *testing.T) { + reqRoot, err := unaggSlot4.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=4" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestation(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + compareResult(t, attestation, "4", hexutil.Encode(unaggSlot4.AggregationBits), root1, sig.Marshal()) + }) + t.Run("multiple matching unaggregated attestations - their aggregate is returned", func(t *testing.T) { + reqRoot, err := unaggSlot3_Root1_1.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=3" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestation(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + sig1, err := bls.SignatureFromBytes(unaggSlot3_Root1_1.Signature) + require.NoError(t, err) + sig2, err := bls.SignatureFromBytes(unaggSlot3_Root1_2.Signature) + require.NoError(t, err) + expectedSig := bls.AggregateSignatures([]common.Signature{sig1, sig2}) + compareResult(t, attestation, "3", hexutil.Encode(bitfield.Bitlist{0b11100}), root1, expectedSig.Marshal()) + }) }) - t.Run("invalid slot provided", func(t *testing.T) { - attDataRoot := hexutil.Encode(bytesutil.PadTo([]byte("foo"), 32)) - url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=foo" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + t.Run("V2", func(t *testing.T) { + t.Run("pre-electra", func(t *testing.T) { + committeeBits := bitfield.NewBitvector64() + committeeBits.SetBitAt(1, true) + + aggSlot1_Root1_1 := createAttestation(1, bitfield.Bitlist{0b11100}, root1) + aggSlot1_Root1_2 := createAttestation(1, bitfield.Bitlist{0b10111}, root1) + aggSlot1_Root2 := createAttestation(1, bitfield.Bitlist{0b11100}, root2) + aggSlot2 := createAttestation(2, bitfield.Bitlist{0b11100}, root1) + unaggSlot3_Root1_1 := createAttestation(3, bitfield.Bitlist{0b11000}, root1) + unaggSlot3_Root1_2 := createAttestation(3, bitfield.Bitlist{0b10100}, root1) + unaggSlot3_Root2 := createAttestation(3, bitfield.Bitlist{0b11000}, root2) + unaggSlot4 := createAttestation(4, bitfield.Bitlist{0b11000}, root1) + + // Add one post-electra attestation to ensure that it is being ignored. + // We choose slot 2 where we have one pre-electra attestation with less attestation bits. + postElectraAtt := createAttestationElectra(2, bitfield.Bitlist{0b11111}, root1) + + compareResult := func( + t *testing.T, + attestation structs.Attestation, + expectedSlot string, + expectedAggregationBits string, + expectedRoot []byte, + expectedSig []byte, + ) { + assert.Equal(t, expectedAggregationBits, attestation.AggregationBits, "Unexpected aggregation bits in attestation") + assert.Equal(t, hexutil.Encode(expectedSig), attestation.Signature, "Signature mismatch") + assert.Equal(t, expectedSlot, attestation.Data.Slot, "Slot mismatch in attestation data") + assert.Equal(t, "0", attestation.Data.CommitteeIndex, "Committee index mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.BeaconBlockRoot, "Beacon block root mismatch") + + // Source checkpoint checks + require.NotNil(t, attestation.Data.Source, "Source checkpoint should not be nil") + assert.Equal(t, "1", attestation.Data.Source.Epoch, "Source epoch mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.Source.Root, "Source root mismatch") + + // Target checkpoint checks + require.NotNil(t, attestation.Data.Target, "Target checkpoint should not be nil") + assert.Equal(t, "1", attestation.Data.Target.Epoch, "Target epoch mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.Target.Root, "Target root mismatch") + } - s.GetAggregateAttestation(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "slot is invalid")) + pool := attestations.NewPool() + require.NoError(t, pool.SaveUnaggregatedAttestations([]ethpbalpha.Att{unaggSlot3_Root1_1, unaggSlot3_Root1_2, unaggSlot3_Root2, unaggSlot4}), "Failed to save unaggregated attestations") + unagg, err := pool.UnaggregatedAttestations() + require.NoError(t, err) + require.Equal(t, 4, len(unagg), "Expected 4 unaggregated attestations") + require.NoError(t, pool.SaveAggregatedAttestations([]ethpbalpha.Att{aggSlot1_Root1_1, aggSlot1_Root1_2, aggSlot1_Root2, aggSlot2, postElectraAtt}), "Failed to save aggregated attestations") + agg := pool.AggregatedAttestations() + require.Equal(t, 5, len(agg), "Expected 5 aggregated attestations, 4 pre electra and 1 post electra") + s := &Server{ + AttestationsPool: pool, + } + + t.Run("non-matching attestation request", func(t *testing.T) { + reqRoot, err := aggSlot2.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=0" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestationV2(writer, request) + assert.Equal(t, http.StatusNotFound, writer.Code, "Expected HTTP status NotFound for non-matching request") + }) + t.Run("1 matching aggregated attestation", func(t *testing.T) { + reqRoot, err := aggSlot2.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=2" + "&committee_index=0" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestationV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + + compareResult(t, attestation, "2", hexutil.Encode(aggSlot2.AggregationBits), root1, sig.Marshal()) + }) + t.Run("multiple matching aggregated attestations - return the one with most bits", func(t *testing.T) { + reqRoot, err := aggSlot1_Root1_1.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=0" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestationV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.Attestation + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + + compareResult(t, attestation, "1", hexutil.Encode(aggSlot1_Root1_2.AggregationBits), root1, sig.Marshal()) + }) + }) + t.Run("post-electra", func(t *testing.T) { + aggSlot1_Root1_1 := createAttestationElectra(1, bitfield.Bitlist{0b11100}, root1) + aggSlot1_Root1_2 := createAttestationElectra(1, bitfield.Bitlist{0b10111}, root1) + aggSlot1_Root2 := createAttestationElectra(1, bitfield.Bitlist{0b11100}, root2) + aggSlot2 := createAttestationElectra(2, bitfield.Bitlist{0b11100}, root1) + unaggSlot3_Root1_1 := createAttestationElectra(3, bitfield.Bitlist{0b11000}, root1) + unaggSlot3_Root1_2 := createAttestationElectra(3, bitfield.Bitlist{0b10100}, root1) + unaggSlot3_Root2 := createAttestationElectra(3, bitfield.Bitlist{0b11000}, root2) + unaggSlot4 := createAttestationElectra(4, bitfield.Bitlist{0b11000}, root1) + + // Add one pre-electra attestation to ensure that it is being ignored. + // We choose slot 2 where we have one post-electra attestation with less attestation bits. + preElectraAtt := createAttestation(2, bitfield.Bitlist{0b11111}, root1) + + compareResult := func( + t *testing.T, + attestation structs.AttestationElectra, + expectedSlot string, + expectedAggregationBits string, + expectedRoot []byte, + expectedSig []byte, + expectedCommitteeBits string, + ) { + assert.Equal(t, expectedAggregationBits, attestation.AggregationBits, "Unexpected aggregation bits in attestation") + assert.Equal(t, expectedCommitteeBits, attestation.CommitteeBits) + assert.Equal(t, hexutil.Encode(expectedSig), attestation.Signature, "Signature mismatch") + assert.Equal(t, expectedSlot, attestation.Data.Slot, "Slot mismatch in attestation data") + assert.Equal(t, "0", attestation.Data.CommitteeIndex, "Committee index mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.BeaconBlockRoot, "Beacon block root mismatch") + + // Source checkpoint checks + require.NotNil(t, attestation.Data.Source, "Source checkpoint should not be nil") + assert.Equal(t, "1", attestation.Data.Source.Epoch, "Source epoch mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.Source.Root, "Source root mismatch") + + // Target checkpoint checks + require.NotNil(t, attestation.Data.Target, "Target checkpoint should not be nil") + assert.Equal(t, "1", attestation.Data.Target.Epoch, "Target epoch mismatch") + assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.Target.Root, "Target root mismatch") + } + + pool := attestations.NewPool() + require.NoError(t, pool.SaveUnaggregatedAttestations([]ethpbalpha.Att{unaggSlot3_Root1_1, unaggSlot3_Root1_2, unaggSlot3_Root2, unaggSlot4}), "Failed to save unaggregated attestations") + unagg, err := pool.UnaggregatedAttestations() + require.NoError(t, err) + require.Equal(t, 4, len(unagg), "Expected 4 unaggregated attestations") + require.NoError(t, pool.SaveAggregatedAttestations([]ethpbalpha.Att{aggSlot1_Root1_1, aggSlot1_Root1_2, aggSlot1_Root2, aggSlot2, preElectraAtt}), "Failed to save aggregated attestations") + agg := pool.AggregatedAttestations() + require.Equal(t, 5, len(agg), "Expected 5 aggregated attestations, 4 electra and 1 pre electra") + bs, err := util.NewBeaconState() + require.NoError(t, err) + + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.ElectraForkEpoch = 0 + params.OverrideBeaconConfig(config) + + chainService := &mockChain.ChainService{State: bs} + s := &Server{ + ChainInfoFetcher: chainService, + TimeFetcher: chainService, + AttestationsPool: pool, + } + t.Run("non-matching attestation request", func(t *testing.T) { + reqRoot, err := aggSlot2.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=0" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestationV2(writer, request) + assert.Equal(t, http.StatusNotFound, writer.Code, "Expected HTTP status NotFound for non-matching request") + }) + t.Run("1 matching aggregated attestation", func(t *testing.T) { + reqRoot, err := aggSlot2.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=2" + "&committee_index=0" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestationV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + + compareResult(t, attestation, "2", hexutil.Encode(aggSlot2.AggregationBits), root1, sig.Marshal(), hexutil.Encode(aggSlot2.CommitteeBits)) + }) + t.Run("multiple matching aggregated attestations - return the one with most bits", func(t *testing.T) { + reqRoot, err := aggSlot1_Root1_1.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=0" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestationV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + + compareResult(t, attestation, "1", hexutil.Encode(aggSlot1_Root1_2.AggregationBits), root1, sig.Marshal(), hexutil.Encode(aggSlot1_Root1_1.CommitteeBits)) + }) + t.Run("1 matching unaggregated attestation", func(t *testing.T) { + reqRoot, err := unaggSlot4.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=4" + "&committee_index=0" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestationV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + compareResult(t, attestation, "4", hexutil.Encode(unaggSlot4.AggregationBits), root1, sig.Marshal(), hexutil.Encode(unaggSlot4.CommitteeBits)) + }) + t.Run("multiple matching unaggregated attestations - their aggregate is returned", func(t *testing.T) { + reqRoot, err := unaggSlot3_Root1_1.Data.HashTreeRoot() + require.NoError(t, err, "Failed to generate attestation data hash tree root") + attDataRoot := hexutil.Encode(reqRoot[:]) + url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=3" + "&committee_index=0" + request := httptest.NewRequest(http.MethodGet, url, nil) + writer := httptest.NewRecorder() + + s.GetAggregateAttestationV2(writer, request) + require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK") + + var resp structs.AggregateAttestationResponse + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response") + require.NotNil(t, resp.Data, "Response data should not be nil") + + var attestation structs.AttestationElectra + require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data") + sig1, err := bls.SignatureFromBytes(unaggSlot3_Root1_1.Signature) + require.NoError(t, err) + sig2, err := bls.SignatureFromBytes(unaggSlot3_Root1_2.Signature) + require.NoError(t, err) + expectedSig := bls.AggregateSignatures([]common.Signature{sig1, sig2}) + compareResult(t, attestation, "3", hexutil.Encode(bitfield.Bitlist{0b11100}), root1, expectedSig.Marshal(), hexutil.Encode(unaggSlot3_Root1_1.CommitteeBits)) + }) + t.Run("pre-electra attestation is ignored", func(t *testing.T) { + + }) + }) }) + } -func TestGetAggregateAttestation_SameSlotAndRoot_ReturnMostAggregationBits(t *testing.T) { - root := bytesutil.PadTo([]byte("root"), 32) - sig := bytesutil.PadTo([]byte("sig"), fieldparams.BLSSignatureLength) - att1 := ðpbalpha.Attestation{ - AggregationBits: []byte{3, 0, 0, 1}, - Data: ðpbalpha.AttestationData{ - Slot: 1, - CommitteeIndex: 1, - BeaconBlockRoot: root, - Source: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root, - }, - Target: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root, - }, +func createAttestationData(slot primitives.Slot, committeeIndex primitives.CommitteeIndex, root []byte) *ethpbalpha.AttestationData { + return ðpbalpha.AttestationData{ + Slot: slot, + CommitteeIndex: committeeIndex, + BeaconBlockRoot: root, + Source: ðpbalpha.Checkpoint{ + Epoch: 1, + Root: root, }, - Signature: sig, - } - att2 := ðpbalpha.Attestation{ - AggregationBits: []byte{0, 3, 0, 1}, - Data: ðpbalpha.AttestationData{ - Slot: 1, - CommitteeIndex: 1, - BeaconBlockRoot: root, - Source: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root, - }, - Target: ðpbalpha.Checkpoint{ - Epoch: 1, - Root: root, - }, + Target: ðpbalpha.Checkpoint{ + Epoch: 1, + Root: root, }, - Signature: sig, - } - pool := attestations.NewPool() - err := pool.SaveAggregatedAttestations([]ethpbalpha.Att{att1, att2}) - assert.NoError(t, err) - s := &Server{ - AttestationsPool: pool, } - reqRoot, err := att1.Data.HashTreeRoot() - require.NoError(t, err) - attDataRoot := hexutil.Encode(reqRoot[:]) - url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" - request := httptest.NewRequest(http.MethodGet, url, nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} - - s.GetAggregateAttestation(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - resp := &structs.AggregateAttestationResponse{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), resp)) - require.NotNil(t, resp) - assert.DeepEqual(t, "0x03000001", resp.Data.AggregationBits) } func TestSubmitContributionAndProofs(t *testing.T) { @@ -428,85 +604,238 @@ func TestSubmitContributionAndProofs(t *testing.T) { } func TestSubmitAggregateAndProofs(t *testing.T) { - c := &core.Service{ - GenesisTimeFetcher: &mockChain.ChainService{}, - } - s := &Server{ - CoreService: c, + CoreService: &core.Service{GenesisTimeFetcher: &mockChain.ChainService{}}, } + t.Run("V1", func(t *testing.T) { + t.Run("single", func(t *testing.T) { + broadcaster := &p2pmock.MockBroadcaster{} + s.CoreService.Broadcaster = broadcaster - t.Run("single", func(t *testing.T) { - broadcaster := &p2pmock.MockBroadcaster{} - c.Broadcaster = broadcaster + var body bytes.Buffer + _, err := body.WriteString(singleAggregate) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} - var body bytes.Buffer - _, err := body.WriteString(singleAggregate) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + s.SubmitAggregateAndProofs(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, 1, len(broadcaster.BroadcastMessages)) + }) + t.Run("multiple", func(t *testing.T) { + broadcaster := &p2pmock.MockBroadcaster{} + s.CoreService.Broadcaster = broadcaster + s.CoreService.SyncCommitteePool = synccommittee.NewStore() - s.SubmitAggregateAndProofs(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - assert.Equal(t, 1, len(broadcaster.BroadcastMessages)) - }) - t.Run("multiple", func(t *testing.T) { - broadcaster := &p2pmock.MockBroadcaster{} - c.Broadcaster = broadcaster - c.SyncCommitteePool = synccommittee.NewStore() + var body bytes.Buffer + _, err := body.WriteString(multipleAggregates) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} - var body bytes.Buffer - _, err := body.WriteString(multipleAggregates) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + s.SubmitAggregateAndProofs(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, 2, len(broadcaster.BroadcastMessages)) + }) + t.Run("no body", func(t *testing.T) { + request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("empty", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString("[]") + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("invalid", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString(invalidAggregate) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} - s.SubmitAggregateAndProofs(writer, request) - assert.Equal(t, http.StatusOK, writer.Code) - assert.Equal(t, 2, len(broadcaster.BroadcastMessages)) + s.SubmitAggregateAndProofs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + }) }) - t.Run("no body", func(t *testing.T) { - request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + t.Run("V2", func(t *testing.T) { + t.Run("single", func(t *testing.T) { + broadcaster := &p2pmock.MockBroadcaster{} + s.CoreService.Broadcaster = broadcaster - s.SubmitAggregateAndProofs(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) - }) - t.Run("empty", func(t *testing.T) { - var body bytes.Buffer - _, err := body.WriteString("[]") - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + var body bytes.Buffer + _, err := body.WriteString(singleAggregateElectra) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} - s.SubmitAggregateAndProofs(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) - assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) - }) - t.Run("invalid", func(t *testing.T) { - var body bytes.Buffer - _, err := body.WriteString(invalidAggregate) - require.NoError(t, err) - request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) - writer := httptest.NewRecorder() - writer.Body = &bytes.Buffer{} + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, 1, len(broadcaster.BroadcastMessages)) + }) + t.Run("single-pre-electra", func(t *testing.T) { + broadcaster := &p2pmock.MockBroadcaster{} + s.CoreService.Broadcaster = broadcaster - s.SubmitAggregateAndProofs(writer, request) - assert.Equal(t, http.StatusBadRequest, writer.Code) - e := &httputil.DefaultJsonError{} - require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) - assert.Equal(t, http.StatusBadRequest, e.Code) + var body bytes.Buffer + _, err := body.WriteString(singleAggregate) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Phase0)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, 1, len(broadcaster.BroadcastMessages)) + }) + t.Run("multiple", func(t *testing.T) { + broadcaster := &p2pmock.MockBroadcaster{} + s.CoreService.Broadcaster = broadcaster + s.CoreService.SyncCommitteePool = synccommittee.NewStore() + + var body bytes.Buffer + _, err := body.WriteString(multipleAggregatesElectra) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, 2, len(broadcaster.BroadcastMessages)) + }) + t.Run("multiple-pre-electra", func(t *testing.T) { + broadcaster := &p2pmock.MockBroadcaster{} + s.CoreService.Broadcaster = broadcaster + s.CoreService.SyncCommitteePool = synccommittee.NewStore() + + var body bytes.Buffer + _, err := body.WriteString(multipleAggregates) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Phase0)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + assert.Equal(t, 2, len(broadcaster.BroadcastMessages)) + }) + t.Run("no body", func(t *testing.T) { + request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("no body-pre-electra", func(t *testing.T) { + request := httptest.NewRequest(http.MethodPost, "http://example.com", nil) + request.Header.Set(api.VersionHeader, version.String(version.Bellatrix)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("empty", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString("[]") + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("empty-pre-electra", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString("[]") + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Altair)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + assert.Equal(t, true, strings.Contains(e.Message, "No data submitted")) + }) + t.Run("invalid", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString(invalidAggregateElectra) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Electra)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + }) + t.Run("invalid-pre-electra", func(t *testing.T) { + var body bytes.Buffer + _, err := body.WriteString(invalidAggregate) + require.NoError(t, err) + request := httptest.NewRequest(http.MethodPost, "http://example.com", &body) + request.Header.Set(api.VersionHeader, version.String(version.Deneb)) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + + s.SubmitAggregateAndProofsV2(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + e := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(writer.Body.Bytes(), e)) + assert.Equal(t, http.StatusBadRequest, e.Code) + }) }) } @@ -865,7 +1194,7 @@ func TestGetAttestationData(t *testing.T) { HeadFetcher: chain, GenesisTimeFetcher: chain, FinalizedFetcher: chain, - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), OptimisticModeFetcher: chain, }, } @@ -946,7 +1275,7 @@ func TestGetAttestationData(t *testing.T) { TimeFetcher: chain, OptimisticModeFetcher: chain, CoreService: &core.Service{ - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), GenesisTimeFetcher: chain, HeadFetcher: chain, FinalizedFetcher: chain, @@ -1105,7 +1434,7 @@ func TestGetAttestationData(t *testing.T) { TimeFetcher: chain, OptimisticModeFetcher: chain, CoreService: &core.Service{ - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), OptimisticModeFetcher: chain, HeadFetcher: chain, GenesisTimeFetcher: chain, @@ -1199,7 +1528,7 @@ func TestGetAttestationData(t *testing.T) { TimeFetcher: chain, OptimisticModeFetcher: chain, CoreService: &core.Service{ - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), OptimisticModeFetcher: chain, HeadFetcher: chain, GenesisTimeFetcher: chain, @@ -1464,7 +1793,7 @@ func TestGetAttesterDuties(t *testing.T) { _, err = body.WriteString("[\"0\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1488,7 +1817,7 @@ func TestGetAttesterDuties(t *testing.T) { _, err = body.WriteString("[\"0\",\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1500,7 +1829,7 @@ func TestGetAttesterDuties(t *testing.T) { }) t.Run("no body", func(t *testing.T) { request := httptest.NewRequest(http.MethodPost, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1516,7 +1845,7 @@ func TestGetAttesterDuties(t *testing.T) { _, err := body.WriteString("[]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1532,7 +1861,7 @@ func TestGetAttesterDuties(t *testing.T) { _, err := body.WriteString("[\"foo\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1547,7 +1876,7 @@ func TestGetAttesterDuties(t *testing.T) { _, err = body.WriteString("[\"0\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": strconv.FormatUint(uint64(slots.ToEpoch(bs.Slot())+1), 10)}) + request.SetPathValue("epoch", strconv.FormatUint(uint64(slots.ToEpoch(bs.Slot())+1), 10)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1572,7 +1901,7 @@ func TestGetAttesterDuties(t *testing.T) { require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) currentEpoch := slots.ToEpoch(bs.Slot()) - request = mux.SetURLVars(request, map[string]string{"epoch": strconv.FormatUint(uint64(currentEpoch+2), 10)}) + request.SetPathValue("epoch", strconv.FormatUint(uint64(currentEpoch+2), 10)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1588,7 +1917,7 @@ func TestGetAttesterDuties(t *testing.T) { _, err = body.WriteString(fmt.Sprintf("[\"%d\"]", len(pubKeys))) require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1604,7 +1933,7 @@ func TestGetAttesterDuties(t *testing.T) { _, err = body.WriteString(fmt.Sprintf("[\"%d\"]", len(pubKeys)-1)) require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1642,7 +1971,7 @@ func TestGetAttesterDuties(t *testing.T) { _, err = body.WriteString("[\"0\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1664,7 +1993,7 @@ func TestGetAttesterDuties(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/attester/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1721,7 +2050,7 @@ func TestGetProposerDuties(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/proposer/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1763,7 +2092,7 @@ func TestGetProposerDuties(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/proposer/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "1"}) + request.SetPathValue("epoch", "1") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1807,7 +2136,7 @@ func TestGetProposerDuties(t *testing.T) { currentEpoch := slots.ToEpoch(bs.Slot()) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/proposer/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": strconv.FormatUint(uint64(currentEpoch+2), 10)}) + request.SetPathValue("epoch", strconv.FormatUint(uint64(currentEpoch+2), 10)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1845,7 +2174,7 @@ func TestGetProposerDuties(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/proposer/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1867,7 +2196,7 @@ func TestGetProposerDuties(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/proposer/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1923,7 +2252,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1946,7 +2275,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"1\",\"2\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1958,7 +2287,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { }) t.Run("no body", func(t *testing.T) { request := httptest.NewRequest(http.MethodPost, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1974,7 +2303,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -1990,7 +2319,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"foo\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2005,7 +2334,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"1\",\"10\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2021,7 +2350,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"0\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2038,7 +2367,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString(fmt.Sprintf("[\"%d\"]", numVals)) require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2054,7 +2383,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"5\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": strconv.FormatUint(uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod), 10)}) + request.SetPathValue("epoch", strconv.FormatUint(uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod), 10)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2111,7 +2440,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"8\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": strconv.FormatUint(uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod), 10)}) + request.SetPathValue("epoch", strconv.FormatUint(uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod), 10)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2131,7 +2460,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "1"}) + request.SetPathValue("epoch", "1") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2151,7 +2480,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err := body.WriteString("[\"5\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": strconv.FormatUint(uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod*2), 10)}) + request.SetPathValue("epoch", strconv.FormatUint(uint64(params.BeaconConfig().EpochsPerSyncCommitteePeriod*2), 10)) writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2207,7 +2536,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { _, err = body.WriteString("[\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "1"}) + request.SetPathValue("epoch", "1") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2229,7 +2558,7 @@ func TestGetSyncCommitteeDuties(t *testing.T) { } request := httptest.NewRequest(http.MethodGet, "http://www.example.com/eth/v1/validator/duties/sync/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "1"}) + request.SetPathValue("epoch", "1") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2453,7 +2782,7 @@ func TestGetLiveness(t *testing.T) { _, err := body.WriteString("[\"0\",\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://example.com/eth/v1/validator/liveness/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2472,7 +2801,7 @@ func TestGetLiveness(t *testing.T) { _, err := body.WriteString("[\"0\",\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://example.com/eth/v1/validator/liveness/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "1"}) + request.SetPathValue("epoch", "1") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2491,7 +2820,7 @@ func TestGetLiveness(t *testing.T) { _, err := body.WriteString("[\"0\",\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://example.com/eth/v1/validator/liveness/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "2"}) + request.SetPathValue("epoch", "2") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2510,7 +2839,7 @@ func TestGetLiveness(t *testing.T) { _, err := body.WriteString("[\"0\",\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://example.com/eth/v1/validator/liveness/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "3"}) + request.SetPathValue("epoch", "3") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2541,7 +2870,7 @@ func TestGetLiveness(t *testing.T) { _, err := body.WriteString("[\"0\",\"1\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://example.com/eth/v1/validator/liveness/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "foo"}) + request.SetPathValue("epoch", "foo") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2554,7 +2883,7 @@ func TestGetLiveness(t *testing.T) { }) t.Run("no body", func(t *testing.T) { request := httptest.NewRequest(http.MethodPost, "http://example.com/eth/v1/validator/liveness/{epoch}", nil) - request = mux.SetURLVars(request, map[string]string{"epoch": "3"}) + request.SetPathValue("epoch", "3") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2570,7 +2899,7 @@ func TestGetLiveness(t *testing.T) { _, err := body.WriteString("[]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://example.com/eth/v1/validator/liveness/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "3"}) + request.SetPathValue("epoch", "3") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2586,7 +2915,7 @@ func TestGetLiveness(t *testing.T) { _, err := body.WriteString("[\"0\",\"1\",\"2\"]") require.NoError(t, err) request := httptest.NewRequest(http.MethodPost, "http://example.com/eth/v1/validator/liveness/{epoch}", &body) - request = mux.SetURLVars(request, map[string]string{"epoch": "0"}) + request.SetPathValue("epoch", "0") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -2767,6 +3096,115 @@ var ( "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" } ]` + + singleAggregateElectra = `[ + { + "message": { + "aggregator_index": "1", + "aggregate": { + "aggregation_bits": "0x01", + "committee_bits": "0x01", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + }, + "selection_proof": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } +]` + multipleAggregatesElectra = `[ + { + "message": { + "aggregator_index": "1", + "aggregate": { + "aggregation_bits": "0x01", + "committee_bits": "0x01", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + }, + "selection_proof": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, +{ + "message": { + "aggregator_index": "1", + "aggregate": { + "aggregation_bits": "0x01", + "committee_bits": "0x01", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + }, + "selection_proof": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } +] +` + // aggregator_index is invalid + invalidAggregateElectra = `[ + { + "message": { + "aggregator_index": "foo", + "aggregate": { + "aggregation_bits": "0x01", + "committee_bits": "0x01", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + }, + "selection_proof": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } +]` singleSyncCommitteeSubscription = `[ { "validator_index": "1", diff --git a/beacon-chain/rpc/eth/validator/server.go b/beacon-chain/rpc/eth/validator/server.go index 5c0513c49370..d63553fd581f 100644 --- a/beacon-chain/rpc/eth/validator/server.go +++ b/beacon-chain/rpc/eth/validator/server.go @@ -22,6 +22,7 @@ type Server struct { HeadFetcher blockchain.HeadFetcher TimeFetcher blockchain.TimeFetcher SyncChecker sync.Checker + AttestationCache *cache.AttestationCache AttestationsPool attestations.Pool PeerManager p2p.PeerManager Broadcaster p2p.Broadcaster diff --git a/beacon-chain/rpc/lookup/BUILD.bazel b/beacon-chain/rpc/lookup/BUILD.bazel index 0a70a9991612..59ae22c64afa 100644 --- a/beacon-chain/rpc/lookup/BUILD.bazel +++ b/beacon-chain/rpc/lookup/BUILD.bazel @@ -21,11 +21,11 @@ go_library( "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/rpc/lookup/blocker.go b/beacon-chain/rpc/lookup/blocker.go index 39ec3aa91b46..9e22b577d323 100644 --- a/beacon-chain/rpc/lookup/blocker.go +++ b/beacon-chain/rpc/lookup/blocker.go @@ -235,16 +235,10 @@ func (p *BeaconDbBlocker) Blobs(ctx context.Context, id string, indices []uint64 return make([]*blocks.VerifiedROBlob, 0), nil } if len(indices) == 0 { - m, err := p.BlobStorage.Indices(bytesutil.ToBytes32(root)) - if err != nil { - log.WithFields(log.Fields{ - "blockRoot": hexutil.Encode(root), - }).Error(errors.Wrapf(err, "could not retrieve blob indices for root %#x", root)) - return nil, &core.RpcError{Err: fmt.Errorf("could not retrieve blob indices for root %#x", root), Reason: core.Internal} - } - for k, v := range m { - if v { - indices = append(indices, uint64(k)) + sum := p.BlobStorage.Summary(bytesutil.ToBytes32(root)) + for i := range commitments { + if sum.HasIndex(uint64(i)) { + indices = append(indices, uint64(i)) } } } diff --git a/beacon-chain/rpc/lookup/blocker_test.go b/beacon-chain/rpc/lookup/blocker_test.go index 93c404ca8cc4..cba5be916de3 100644 --- a/beacon-chain/rpc/lookup/blocker_test.go +++ b/beacon-chain/rpc/lookup/blocker_test.go @@ -166,9 +166,8 @@ func TestGetBlob(t *testing.T) { db := testDB.SetupDB(t) denebBlock, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 123, 4) require.NoError(t, db.SaveBlock(context.Background(), denebBlock)) - _, bs := filesystem.NewEphemeralBlobStorageWithFs(t) - testSidecars, err := verification.BlobSidecarSliceNoop(blobs) - require.NoError(t, err) + _, bs := filesystem.NewEphemeralBlobStorageAndFs(t) + testSidecars := verification.FakeVerifySliceForTest(t, blobs) for i := range testSidecars { require.NoError(t, bs.Save(testSidecars[i])) } diff --git a/beacon-chain/rpc/lookup/stater.go b/beacon-chain/rpc/lookup/stater.go index f993fe2d3324..101f46ecdcb0 100644 --- a/beacon-chain/rpc/lookup/stater.go +++ b/beacon-chain/rpc/lookup/stater.go @@ -17,8 +17,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // StateIdParseError represents an error scenario where a state ID could not be parsed. diff --git a/beacon-chain/rpc/metrics.go b/beacon-chain/rpc/metrics.go new file mode 100644 index 000000000000..7a20ab7446af --- /dev/null +++ b/beacon-chain/rpc/metrics.go @@ -0,0 +1,31 @@ +package rpc + +import ( + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" +) + +var ( + httpRequestLatency = promauto.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "http_request_latency_seconds", + Help: "Latency of HTTP requests in seconds", + Buckets: []float64{0.001, 0.01, 0.025, 0.1, 0.25, 1, 2.5, 10}, + }, + []string{"endpoint", "code", "method"}, + ) + httpRequestCount = promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "http_request_count", + Help: "Number of HTTP requests", + }, + []string{"endpoint", "code", "method"}, + ) + httpErrorCount = promauto.NewCounterVec( + prometheus.CounterOpts{ + Name: "http_error_count", + Help: "Total HTTP errors for beacon node requests", + }, + []string{"endpoint", "code", "method"}, + ) +) diff --git a/beacon-chain/rpc/prysm/beacon/BUILD.bazel b/beacon-chain/rpc/prysm/beacon/BUILD.bazel index d92fb3f9516b..d750ef3bbe2d 100644 --- a/beacon-chain/rpc/prysm/beacon/BUILD.bazel +++ b/beacon-chain/rpc/prysm/beacon/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//beacon-chain/blockchain:go_default_library", "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/db:go_default_library", + "//beacon-chain/p2p:go_default_library", "//beacon-chain/rpc/core:go_default_library", "//beacon-chain/rpc/eth/helpers:go_default_library", "//beacon-chain/rpc/eth/shared:go_default_library", @@ -22,16 +23,17 @@ go_library( "//beacon-chain/state/stategen:go_default_library", "//beacon-chain/sync:go_default_library", "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", + "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//proto/eth/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -48,13 +50,16 @@ go_test( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/db/testing:go_default_library", "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", + "//beacon-chain/p2p/testing:go_default_library", "//beacon-chain/rpc/core:go_default_library", "//beacon-chain/rpc/lookup:go_default_library", + "//beacon-chain/rpc/prysm/testing:go_default_library", "//beacon-chain/rpc/testutil:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//beacon-chain/state/stategen:go_default_library", "//beacon-chain/state/stategen/mock:go_default_library", + "//beacon-chain/sync/initial-sync/testing:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", @@ -67,7 +72,6 @@ go_test( "//testing/util:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], ) diff --git a/beacon-chain/rpc/prysm/beacon/handlers.go b/beacon-chain/rpc/prysm/beacon/handlers.go index c6189334fec5..81bc7203e2d9 100644 --- a/beacon-chain/rpc/prysm/beacon/handlers.go +++ b/beacon-chain/rpc/prysm/beacon/handlers.go @@ -15,11 +15,13 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // GetWeakSubjectivity computes the starting epoch of the current weak subjectivity period, and then also @@ -183,3 +185,52 @@ func (s *Server) GetChainHead(w http.ResponseWriter, r *http.Request) { } httputil.WriteJson(w, response) } + +func (s *Server) PublishBlobs(w http.ResponseWriter, r *http.Request) { + ctx, span := trace.StartSpan(r.Context(), "beacon.PublishBlobs") + defer span.End() + if shared.IsSyncing(r.Context(), w, s.SyncChecker, s.HeadFetcher, s.TimeFetcher, s.OptimisticModeFetcher) { + return + } + + var req structs.PublishBlobsRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + httputil.HandleError(w, "Could not decode JSON request body", http.StatusBadRequest) + return + } + if req.BlobSidecars == nil { + httputil.HandleError(w, "Missing blob sidecars", http.StatusBadRequest) + return + } + + root, err := bytesutil.DecodeHexWithLength(req.BlockRoot, 32) + if err != nil { + httputil.HandleError(w, "Could not decode block root: "+err.Error(), http.StatusBadRequest) + return + } + + for _, blobSidecar := range req.BlobSidecars.Sidecars { + sc, err := blobSidecar.ToConsensus() + if err != nil { + httputil.HandleError(w, "Could not decode blob sidecar: "+err.Error(), http.StatusBadRequest) + return + } + + readOnlySc, err := blocks.NewROBlobWithRoot(sc, bytesutil.ToBytes32(root)) + if err != nil { + httputil.HandleError(w, "Could not create read-only blob: "+err.Error(), http.StatusInternalServerError) + return + } + + verifiedBlob := blocks.NewVerifiedROBlob(readOnlySc) + if err := s.BlobReceiver.ReceiveBlob(ctx, verifiedBlob); err != nil { + httputil.HandleError(w, "Could not receive blob: "+err.Error(), http.StatusInternalServerError) + return + } + + if err := s.Broadcaster.BroadcastBlob(ctx, sc.Index, sc); err != nil { + httputil.HandleError(w, "Failed to broadcast blob: "+err.Error(), http.StatusInternalServerError) + return + } + } +} diff --git a/beacon-chain/rpc/prysm/beacon/handlers_test.go b/beacon-chain/rpc/prysm/beacon/handlers_test.go index ec8a66511141..54e471924972 100644 --- a/beacon-chain/rpc/prysm/beacon/handlers_test.go +++ b/beacon-chain/rpc/prysm/beacon/handlers_test.go @@ -18,10 +18,13 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" dbTest "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree" + mockp2p "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core" + rpctesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/prysm/testing" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen" mockstategen "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen/mock" + mockSync "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/initial-sync/testing" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" @@ -870,3 +873,163 @@ func TestServer_GetChainHead(t *testing.T) { assert.DeepEqual(t, hexutil.Encode(fRoot[:]), ch.FinalizedBlockRoot, "Unexpected FinalizedBlockRoot") assert.Equal(t, false, ch.OptimisticStatus) } + +func TestPublishBlobs_InvalidJson(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.InvalidJson))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + assert.StringContains(t, "Could not decode JSON request body", writer.Body.String()) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false) +} + +func TestPublishBlobs_MissingBlob(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestMissingBlob))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + assert.StringContains(t, "Could not decode blob sidecar", writer.Body.String()) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false) +} + +func TestPublishBlobs_MissingSignedBlockHeader(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestMissingSignedBlockHeader))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + assert.StringContains(t, "Could not decode blob sidecar", writer.Body.String()) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false) +} + +func TestPublishBlobs_MissingSidecars(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestMissingSidecars))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + assert.StringContains(t, "Missing blob sidecars", writer.Body.String()) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false) +} + +func TestPublishBlobs_EmptySidecarsList(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestEmptySidecarsList))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false) +} + +func TestPublishBlobs_NullSidecar(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestNullSidecar))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + assert.StringContains(t, "Could not decode blob sidecar", writer.Body.String()) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false) +} + +func TestPublishBlobs_SeveralFieldsMissing(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestSeveralFieldsMissing))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + assert.StringContains(t, "Could not decode blob sidecar", writer.Body.String()) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false) +} + +func TestPublishBlobs_BadBlockRoot(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequestBadBlockRoot))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusBadRequest, writer.Code) + assert.StringContains(t, "Could not decode block root", writer.Body.String()) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 0) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), false) +} + +func TestPublishBlobs(t *testing.T) { + server := &Server{ + BlobReceiver: &chainMock.ChainService{}, + Broadcaster: &mockp2p.MockBroadcaster{}, + SyncChecker: &mockSync.Sync{IsSyncing: false}, + } + + request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.PublishBlobsRequest))) + writer := httptest.NewRecorder() + writer.Body = &bytes.Buffer{} + server.PublishBlobs(writer, request) + assert.Equal(t, http.StatusOK, writer.Code) + + assert.Equal(t, len(server.BlobReceiver.(*chainMock.ChainService).Blobs), 1) + assert.Equal(t, server.Broadcaster.(*mockp2p.MockBroadcaster).BroadcastCalled.Load(), true) +} diff --git a/beacon-chain/rpc/prysm/beacon/server.go b/beacon-chain/rpc/prysm/beacon/server.go index 5af654712f69..d62c95dcad5e 100644 --- a/beacon-chain/rpc/prysm/beacon/server.go +++ b/beacon-chain/rpc/prysm/beacon/server.go @@ -3,6 +3,7 @@ package beacon import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" beacondb "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen" @@ -20,4 +21,6 @@ type Server struct { ChainInfoFetcher blockchain.ChainInfoFetcher FinalizationFetcher blockchain.FinalizationFetcher CoreService *core.Service + Broadcaster p2p.Broadcaster + BlobReceiver blockchain.BlobReceiver } diff --git a/beacon-chain/rpc/prysm/beacon/validator_count.go b/beacon-chain/rpc/prysm/beacon/validator_count.go index ba9b6f744f8a..94c0d45c5939 100644 --- a/beacon-chain/rpc/prysm/beacon/validator_count.go +++ b/beacon-chain/rpc/prysm/beacon/validator_count.go @@ -7,18 +7,17 @@ import ( "strconv" "strings" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" statenative "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // GetValidatorCount is a HTTP handler that serves the GET /eth/v1/beacon/states/{state_id}/validator_count endpoint. @@ -53,7 +52,7 @@ func (s *Server) GetValidatorCount(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "beacon.GetValidatorCount") defer span.End() - stateID := mux.Vars(r)["state_id"] + stateID := r.PathValue("state_id") isOptimistic, err := helpers.IsOptimistic(ctx, []byte(stateID), s.OptimisticModeFetcher, s.Stater, s.ChainInfoFetcher, s.BeaconDB) if err != nil { diff --git a/beacon-chain/rpc/prysm/beacon/validator_count_test.go b/beacon-chain/rpc/prysm/beacon/validator_count_test.go index 7d4f9b330186..0a6fe91ca221 100644 --- a/beacon-chain/rpc/prysm/beacon/validator_count_test.go +++ b/beacon-chain/rpc/prysm/beacon/validator_count_test.go @@ -12,7 +12,6 @@ import ( "strings" "testing" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" chainMock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/lookup" @@ -85,7 +84,7 @@ func TestGetValidatorCountInvalidRequest(t *testing.T) { Stater: test.stater, } - testRouter := mux.NewRouter() + testRouter := http.NewServeMux() testRouter.HandleFunc("/eth/v1/beacon/states/{state_id}/validator_count", server.GetValidatorCount) s := httptest.NewServer(testRouter) defer s.Close() @@ -465,7 +464,7 @@ func TestGetValidatorCount(t *testing.T) { }, } - testRouter := mux.NewRouter() + testRouter := http.NewServeMux() testRouter.HandleFunc("/eth/v1/beacon/states/{state_id}/validator_count", server.GetValidatorCount) s := httptest.NewServer(testRouter) defer s.Close() diff --git a/beacon-chain/rpc/prysm/node/BUILD.bazel b/beacon-chain/rpc/prysm/node/BUILD.bazel index 6911f88d1150..cea92902b96b 100644 --- a/beacon-chain/rpc/prysm/node/BUILD.bazel +++ b/beacon-chain/rpc/prysm/node/BUILD.bazel @@ -17,12 +17,12 @@ go_library( "//beacon-chain/p2p/peers:go_default_library", "//beacon-chain/p2p/peers/peerdata:go_default_library", "//beacon-chain/sync:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_libp2p_go_libp2p//core/network:go_default_library", "@com_github_libp2p_go_libp2p//core/peer:go_default_library", "@com_github_pkg_errors//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/beacon-chain/rpc/prysm/node/handlers.go b/beacon-chain/rpc/prysm/node/handlers.go index d0a8d00b9714..8fbe374937f1 100644 --- a/beacon-chain/rpc/prysm/node/handlers.go +++ b/beacon-chain/rpc/prysm/node/handlers.go @@ -13,9 +13,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers/peerdata" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // ListTrustedPeer retrieves data about the node's trusted peers. diff --git a/beacon-chain/rpc/prysm/node/handlers_test.go b/beacon-chain/rpc/prysm/node/handlers_test.go index 00532e9b7736..8b07eb4d058a 100644 --- a/beacon-chain/rpc/prysm/node/handlers_test.go +++ b/beacon-chain/rpc/prysm/node/handlers_test.go @@ -25,8 +25,8 @@ import ( type testIdentity enode.ID -func (_ testIdentity) Verify(_ *enr.Record, _ []byte) error { return nil } -func (id testIdentity) NodeAddr(_ *enr.Record) []byte { return id[:] } +func (testIdentity) Verify(*enr.Record, []byte) error { return nil } +func (id testIdentity) NodeAddr(*enr.Record) []byte { return id[:] } func TestListTrustedPeer(t *testing.T) { ids := libp2ptest.GeneratePeerIDs(9) @@ -62,13 +62,13 @@ func TestListTrustedPeer(t *testing.T) { switch i { case 0, 1: - peerStatus.SetConnectionState(id, peers.PeerConnecting) + peerStatus.SetConnectionState(id, peers.Connecting) case 2, 3: - peerStatus.SetConnectionState(id, peers.PeerConnected) + peerStatus.SetConnectionState(id, peers.Connected) case 4, 5: - peerStatus.SetConnectionState(id, peers.PeerDisconnecting) + peerStatus.SetConnectionState(id, peers.Disconnecting) case 6, 7: - peerStatus.SetConnectionState(id, peers.PeerDisconnected) + peerStatus.SetConnectionState(id, peers.Disconnected) default: t.Fatalf("Failed to set connection state for peer") } diff --git a/beacon-chain/rpc/prysm/testing/BUILD.bazel b/beacon-chain/rpc/prysm/testing/BUILD.bazel new file mode 100644 index 000000000000..bddcbe7c22f1 --- /dev/null +++ b/beacon-chain/rpc/prysm/testing/BUILD.bazel @@ -0,0 +1,9 @@ +load("@prysm//tools/go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + testonly = True, + srcs = ["json.go"], + importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/prysm/testing", + visibility = ["//visibility:public"], +) diff --git a/beacon-chain/rpc/prysm/testing/json.go b/beacon-chain/rpc/prysm/testing/json.go new file mode 100644 index 000000000000..549fc6b4fcd7 --- /dev/null +++ b/beacon-chain/rpc/prysm/testing/json.go @@ -0,0 +1,210 @@ +package testing + +import "fmt" + +var InvalidJson = `{ + "block_root" : "0x000000000000000 + ] + } + }` + +var PublishBlobsRequestMissingSidecars = `{ + "block_root" : "0x0000000000000000000000000000000000000000000000000000000000000000" + }` + +var PublishBlobsRequestMissingBlob = `{ + "block_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "blob_sidecars" : { + "sidecars" : [ + { + "index" : "0", + "kzg_commitment" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "kzg_commitment_inclusion_proof" : [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "kzg_proof" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "signed_block_header" : { + "message" : { + "body_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parent_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "proposer_index" : "0", + "slot" : "0", + "state_root" : "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "signature" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }` + +var PublishBlobsRequestBadBlockRoot = fmt.Sprintf(`{ + "block_root" : "0x0000000000000000000000000000", + "blob_sidecars" : { + "sidecars" : [ + { + "blob" : "%s", + "index" : "0", + "kzg_commitment" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "kzg_commitment_inclusion_proof" : [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "kzg_proof" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "signed_block_header" : { + "message" : { + "body_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parent_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "proposer_index" : "0", + "slot" : "0", + "state_root" : "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "signature" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }`, Blob) + +var PublishBlobsRequestEmptySidecarsList = `{ + "block_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "blob_sidecars" : { + "sidecars" : [ + ] + } + }` + +var PublishBlobsRequestNullSidecar = `{ + "block_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "blob_sidecars" : { + "sidecars" : [ + null + ] + } + }` + +var PublishBlobsRequestMissingSignedBlockHeader = fmt.Sprintf(`{ + "block_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "blob_sidecars" : { + "sidecars" : [ + { + "blob" : "%s", + "index" : "0", + "kzg_commitment" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "kzg_commitment_inclusion_proof" : [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "kzg_proof" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + ] + } + }`, Blob) + +var PublishBlobsRequestSeveralFieldsMissing = fmt.Sprintf(`{ + "block_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "blob_sidecars" : { + "sidecars" : [ + { + "blob" : "%s", + "index" : "0", + "kzg_commitment" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "kzg_proof" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "signed_block_header" : { + "signature" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } +}`, Blob) + +var PublishBlobsRequest = fmt.Sprintf(`{ + "block_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "blob_sidecars" : { + "sidecars" : [ + { + "blob" : "%s", + "index" : "0", + "kzg_commitment" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "kzg_commitment_inclusion_proof" : [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "kzg_proof" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "signed_block_header" : { + "message" : { + "body_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "parent_root" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "proposer_index" : "0", + "slot" : "0", + "state_root" : "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "signature" : "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + } + ] + } + }`, Blob) + +var Blob = `0xe3078ecee8c4625a862b8abab2e220be24d7bcbb6b72dbcf0a2afa6b6b5ea77afb84bfa2ec47e6fbce8f3d4fa8a46b70a1db8adaec6cb2bdd1c36cda64ecfc9128aecf2d1b73c7ffe75dbac4efb9e49a5f05bda1df6f7caad2ebcea7fe9919de9afefc6581f2b7bfeac8bcdbfbaec107fdcdaf3cbe765898c01ada724ebca0aaf356ba584aec7a9f2e44d07ae60ed29347dbe0930ee05ada11b861d24a7f1e5afbcca9eaea56e714eca0a54194e6da9e2a34dfa3d2cebe6c1c9eeed7fde1ce8af8ed66d9a63273df5240d20e0e2b3cdffcf6ae8aa1698fb2204adcdd1e79afc4a4fecc7e096edee38c9bb9980dfac02518ff88dc44b20a664dcbb34661da4df5af8f97ac41dfb7cdaec2acc91cb3bb7acceabb1db6f0cbe71fe2580ed83d056d7ebaf87e4a1dac19143d6b889782ae0c7aa65e4af3feb4c7da479a1a3b6f102cf7c1dfd26b6ee2baafc281297be1fcf5e032dbde78a67123a920bf5b6bfefdb8dd94a86b6eefde5e7f9d683acf6a0c3b1ea013a5dfdf54be6a6cb3ae262fecffeee90bff4f556bfc4e9dddffdd4756611f8facb8666637aa3dcefcf1bfca29dda307c349b0cef9f0ec40bfeb1cfd4aaa8a85570487c4f834ab12ecbbfe1bdf932abd1d484b7d9e7efdba6215d34c6201da6ed9f907a50197b5067f7cd7d01ba94b1af82efbc8e9ef5d781ff1efecececfff36fafb16957bbffad95fbafb14ccfe2a2bf570bf90a6f98fc660d80c712f13d0d630d4710eefcd27603bfb3cb1b2c1e3d6c7bcdc537d80f7eb31ed785de8b47a4119415c83b352cef30d23dad7f3c701162aa37db213da385785aacc79faa5f5f6ec4bff4cbf51e82f56ad33870ae74fdc7dd2dbd8d76ff92a8446f723a8e42c79bdfde1c6b61bdafa97a9cc25ae83a3d9b1e493f5fc5e5999fbfebe1c0879dbf4d64d14e0ca6abe8b0b7dda5b95fc65370aaded9086ab27d0e2fbdbe7eaebf0abfe0befb3aa844eec5c563275daae53daeefebf8ce92abec499becabcfdfc8dbbf60cebf00e45195dd8ba2e3bc1cfd80f1aabbcc0cd805e402addee1aaeb99d4dcef8b37d6767d96c671f1d9115fa5a69dc14603ea8db1aeee78cdccafcef8dc8e7dedc821dfd8a6ede6f15aa797dfb3f5ebb2bbff023eeddce3b3a2f4ea041aa07e513a928dbf7eed9184fb54fc12385c4e494cea1e6bf00bf6f1560edfd027f5c98bd1a4ee38a3b14e2f2ae07ebdcd663ae1aacd5b1aeba14bae9f14cbeb4bfed399e9b0285cf1efee8f2ab31dfdf33b5e3defbd6ae6ab5b18e9e19cc5a35a8b1d76f9f90ae38cb564fe386da0a586d0dde1c7c80f19a442c365aa1f1c10fdb1765f6bf21dac76aa1e8ecbc31f8909605456aa1bf5d10851cc6c6c9ecee8cce790e4fcaccaecdde7a4f5a40cc20d18de0978132cdc4e5aa53b97ac84d942dbcd23bf0c8bb3c02bc87d0f3ac518b482d87dfa411aa795aee85a5b55c3b4e136cfc43fed3dbdcf2def75309ddaf34bed3cfa1bed1ccf0b4c5b8dd14a69e3edfb5ec17a2affda52193c372cecfb1cceb8274edcc9e49576d629de561602880ebce92a68200a441bbd0c1556ccc2aeb16fcaa78db1fdd755acc6c762fecedba1f2b78e9b5bcbf494e6178b63ca8d4f40ffc7e3bd4a16dbfd7db2e4e6dfe10a47f0cd6196ca7a2f4b33efa514dee868d0a21c6dadb909aad1eeb05eb3fcc7d144b1eaabfadbe027e3cafb4e4c8d7e0d2cfbcfba535200478f33f6a04eaffdaaac1508ab6971ab84e6845a528bc91d5d9bbdd1c873589e896c300d069ffce5ceaad93e460d992ec6b1becff291aec8eed5dd9df92ff389dfecef3dedf41ddebfb7186cfaae9df2ba8eb9fb331cdfbfa5ca5040ade7cfbc6e6d9719e4626dbc66d9bc6ceb8cdf2cffff78fe2f077cfdd7320e6e2dfe44eabcbfedae887ecc8d55f7844983cf4ec54956aa6fcdb9cf0e37d9ecc77fe1f8e8cc5e568dcf5e2d83e1daea5cabf7fdd8bacc4996163a168bf28458eaaa39fecb4fae8cd0fcbdb09bc8f41fc5fe332ce455caddc4a8fa8594b5f0d0109acfadfaacacdca2c59fac1a20a414cfd9a4efeab415be18e9a18eaeeda0faceb64a2aaa58ddbbaafb29dbff8f4b52ced51bbac4ed67ccf4cb711ac14e8bf58f17d50e729bafc3be97bb4e6354f855feecb504fa2f35efb184abde5f29ee1ae2c394be8efa2cad872b624ac2de8febcc55da95aa5b3998de83dd4deb3acd3a9fa4aaac50fc6e7c15fba147f0cf0bb7c62d675559cc95e4abaedefe4e1cfeadfb71efb5deed5351c8c5f56e4b99b13de9ffe6fdb27f4e20fe325af01c8e5a949a0d9ddbbf9500506baab9b19a5fd7222dbe63cedcbbddcc6e8d66ab2b05273acb9bc04d48dae12d4fbca9ed26fdd93fa75e010dc5e388cf3d082ffe6bb3f55ac4703ec56fdd1700eef433bd601aff0f321aaf4d3cc6dff15c7c719a0e2f7fc6882c9d4b88b78f750cb7ba1ae67ccf19b61f55c3d236cd0c5dc0e9cfbe0bf903bbedb2bd9e2e88ee8ca61b3fedffb4bbeeba18a3eac0f4c087abfdcfa279e9b9672dea173ece706a1a1bb04e937d52ad3d2ed27c3be082dcca4eeac9a2adfafab1ccfb15b7ecefcbaaf6dfab4eedff1baa59be84eb1dca03d81f0c6befdeee1ef2bc4c343c1bcab0b6fa7481ae4d9db769bedbd5d94fdb41992c9cffeca918b6fbccefcec37d55a6efcc7c03cebf1180be704daf2d9bce12ab6e09acb84b8accec9d34ab83fa7281eddc2b6a3ddbca9eebbf535db14153faa7aca596c2daadef89ca3dcc8da4f96751a38235c83f6d87ab57c47e72be6d9aa410d4d7bcf9d6d563ce8cbeba7ad6827a1c71b5ce31c1ee2c80fce8ac7c9e6ec8fe5d6e1a1a81db61adaddbaae52d07db73cac7e5cbcab253ef1cc3b7494cca8beda70f6adff3c7b730ff00faa39d655fb447abe997fadcd298d9385ebcdba5cd9f97b53c0a0bdb7bddb5eecee609c8dfb12e001ce4aeada75e85e0ef8f6a1cea84bee6aaddca7876b79f1ebd639dfa3b9890fbe7d80f5cecadcf37daaaa5b6c5142f951eafd7c16c533ab826ae1ce236f7603b2bd23e6629de1dfcb17ddc52f42780eb333f04fd2149aaac49f258a0e4cbc97aae3943d8edbc646f3f4ec652a195ead95a3e1310cfa8dceddd187de4bbb369a7abae6e8d95333bee5a53e6e5ecff7b8849eace10e8cdfbf5a3e4fff70c4e638ef22c7bae4355caefa0fb7b36baca793ad5d1be0ce93ef35fec8eeb8fac83a5da4cea7ccbab2e5b1ed5acb22197b3a75eb1fcde1e3dcd0a51aaf655790e58fabdc3aadefebbaed828fdbfefa98baaabda5d5b203aca7fc5369b62364d4a57c7c3e3cd77ac0d3de428b5ce61e93c05d8f11db6e3b0adc9c1ffabaa998ca827d8d87b69fb12caf5c6b0f70c7f989044c3dc8c8baebaafe0ccacaebaaae6026e596bc92e1bd6dcdc524ab90f3ae0ff0d1d252bf37c777f3addd72dbdeb9e2a79b563110fc623bed79ade04aab96e319621e69fde576eef79cc0e6a7b292f8faadedd9fc720fcbccfb7fcec60f930e4fbee3b4a2f1a091894c5447666f15f8a2a3f2e2cff0d1630ab2e8cbce90b4ecd8eb18fe741e8abbca937b8a430afa8f1a18b2ccb966fb42fd7237b1a8ac23c085b9229c4ccd0589e7f7a636dbabb7b706afa1be145216caff4e56cbb04ed36005a65202e1fb8bf6d7d2065d2ab64fa45fdbfbda455aaa10ecf9a51fed69d784dac36833aabc47f9aa2a3e0c60d6cef59cacabde633735f5dba4d5b3aac7c8064d2a2adff84c2f9763c58cfe0c794ca5bfec7ec65e8e3930ed78bcdf8e2203b04ee8bdb69faf6ea94aea5496fcf8aadeb233da3ccd4bdeead54aeffd3f8cebf50fcaaf55ffadbae92ece813e3d83aecfcf0cfb9d16d4c9a2e7ad3f972fd69197b84e2915d8bd84d0ca98acb296da9dece7dac0b7f068e2aaaa6f1cdf8559fb57e09fdda81cb30ea8bbf58a4e6d42bd9bced5c32a0d1a834ef33d37a31e9d07febdfdfc211defa2c5d4deafcdd9efac0da96ac77f921f3f7eec06418f2c434c66cfa1242f21b247caf08bd33dc8f78ca9abbcafefbaf67ff7ae4bcb6924f1edc88761e70eba8dc2a97dc31cbde7932cffee930163f916db61bc2c793edddcaf4429857cee1be109cfbfaeadb0c49ba6c8dba6ff7a2f47c05d3c3c3bc5c434fb058a807b09b1a2e94fa9a8fa4e2fac6268665acbdcaeaf7ab05e5ec2ec0f48601150e7c7aefdbe97ddfc09eb2f1f22a50513d7dfefa60cbcd7e42dcce8bceb2feca4d0ee4143b8848df89ce121df5acda10fe45ef707aceaad6504edb2aaaf668aab4ed3f1a1bfc5f88a009c307dcc396f0e5ea51ef484fbdbccefd110fd85cafe5c78ec95b35d63d0fd9fbc4ccdee95055fb23accaa875bda9ffde534bb9dabeecaf3e90d7f5bc5dd15dffac15fd811300adfdc66573abe0869df8c3a495db6ddef7beda9d52c28f31a5afaee99c3f64ace76acd8812dce37be20d9f4cad7b56a6dfd1f0a1edab62b3eafd30aeaaa6cd02afe6bc04d3fa38ea79d5d8ecba5c04ffecfa13cde8e54ccffdd812c192fa9fdfaaadfaa2bafcc7b3debcc6d84bdcdae4b3aeda5bd0b9acbeb39fd7ebc2eff082ecde91e1eac63cfaf1d4efe94f6ad44acaf5fd3d5feaaab6ebace2cf5ced0c02bce1b933fd0aacdcc8eeee9fa60e2ad5991eac44cf86eaccdbcb5ede1bc89e346bddeaf6032197dac0ab0ce8cd1f2bbf19bcdc0eb6b098e3b62bbb3edb62a8aca92bb8d4d01aaf1fca82ea3a4efb927ac507cecb93ce14eda836cdd83bae1a4eab4cad9f6f975a56ab8ab0ada8faea40ffb9f1f4f2c6d574dc5f1e1defc5a9ab5e0deb735b49fb3b6d10fe8eb3f51f77fffffccc6a1c57b17bf10285bdac91abc9c993f403ece1b85e1df7ffcf7bddf486ea3e9ffb838dcecddb89afb85fe30874b0b8add794cf3344baf161b9baff96b08ea04ddfa7232a66e2a1decafcdeb4a26e3bbac8089c63bcc4fdf3d42ca5d6d454aebadddb7614c81f53f5eee7f6d82edb98e042afeabdedaf573de15bb0a25c48cb1cdd22e1517ffe370db7f6bb1d4eab8236ca466fede9cd3fbb88eb5e1dec8e994aef3cc80c346aafbaa25ccce5d9b5a4caceb5ea7fbf7e4d5bd16c21fb16ec7d7da21b3d7fdc31ec54be605eeb921fa6f5c998a4fc2ce1ec059c6a6faca7e10ec7dad9cccfc4c08c0dc69cae4b7aeec96e8d49becaba3f43dbfdd29a4dddf3bf0ecd2e4ea1a76f816f00c7cb12b51182420697fde6859b6a01aecbbfdb02fdc6cfcde4a6d1e98de70d5a6dbaf42f7a2ddf4d5412a8ed5f36c719bf22261d783abeec2ae6da933d04e4aace69194ad52654dc48a9bf49ab84d0a41c9dc6c6fde6647ef0e1cfe7e5cf05dc15ebd632bead5a385f6da2114faea1d88baaabb99f7adae24d3b0ecf1fc8c9d0b1fccec2d6b2ae4bfacedde489be4bca282a1a8cfafad7ff2eee628da39fcdcb34a123f66aa6cfc9efaabc3cd819d23c8abdfbab31adff1c5f7131ed6b8bbd5aec4bfbb9a2b8fce8aa7c70ceb7fa774b26dbaefa786e449aa3794f7b3558cc84b2fc2df1a2d311f9d429f4d91c2fcd9cd07c0dfd924cd5e495851ec7433353beddc94326dbadcef6e0ffde56b6351312b2a306d4f4eca6eb2bbd19980f3567c5b02ae822717adaeb90aa843bd90c6368157b2622fb1ae69baf7a1ee3dbbf9c5c295f825ddb25f1791b13a7dbd2cedbe1ceecfa0bcca3cf92b8c7f7f7ffce9e982dbe7ca9e6f4fdf3b852a1479fbfb263814ba75beebaa1af0ff4acdfbc225d4e281069acf20f03ddceada3b9ab42a92adeb72f52a0a2e2bbcca6ac35fc39e74e910fbf0dfeeafc3accbf2f4c3ff88ba31a469bec96daff2adf1232eb6fdeefa7b764793b46f291bc27669d57e5ff60ea4eb88dab8f2834c4d26b2940e60376f524b119fb9881c4ac9644fdfae5d6656d7cd25136714a94af50dffcfe9583143abe0ad3ac9ffe6b42c2a5ae2d3456e5bb9231ef6e15f0cf6ff413ec07bbacc26cbe7c8f33ddb7c1eeb407f382a44ed12cad18abbbbfb0add2bc81a078b54da80d90bdc50396a7171ee577efb9577caa460c1c8debcf669481f4bc67ca15888c94b8381cfad6beafcfac41eb7fc0a7eb521667dc80ef3fd0b10f6decd72af98dfeedbac2a7bde4b481da60bbd6e8ee09a9bfb59beee7900aefb2c89d7f0d2ef6f2706031d6e2da3dc95cde1caf4bcfc4fcba7071aecde8bf870aa67feeaf4a8caebaf7c31ee1afe69fcfa4ad66e9afd9434c0ff898a9d82ba8de1b7cfeeeadfaa0d5bf57ccdcdc3a5bcfb0ddfd14b14cd6ccaf94119ccb13c8ea02f6edf652ee0f8c8beeb496d5c1aaa5ba4aebd0eae4ba190e38bd80416ba4ace6e5ed1fee4bfd1cbcac618a3b2eaa9bcf6851c2400e2cf7ae2aa5e7dc1aa61badc0944d4aee7f2adaf7e87bd6d6abcae1ccfcfeb7ff75acfdbbdcbb5157d49b7bbba76b8aba0f4768cc0acb8c549777ed5caaa6263774fa1ceb5aab25a64a92cd0dc2e2ddb448c36c8bbcc2a5cce68ce9c17890538ccfefecdb58aefb3aeeaad745a80b8b0bf7e751c8bcee6d293ed1abafe46fec88fbaef4b28c220cb36dbb7fe01b856afa6d8b748bdbf5f13c6dbd0ac9f2fdc0bdbf8a1454cbefbf22761aaa4fb0564ab569c7f78a91ddbfcfca466e3de9a1d4c8d3b9fdf1eb352aef54bdbd03accbd8ab35cdfbde2abe80eafbf3f3e9d8c1b4deba76ddaaab8b6d486fa2b92817fdbaeb1ade398a7d6eae2349c04e8bdaca4a1410cdcb9277cbe3d414aa57f6d2bba4aef3f1c8564bae93b2b3cface3ddcf63c3dacd67bc4dbd6f9a2e09eec18723a5da60b47eaeaadaecdf4f48d6ccf9ad873cfbb3bf8a4d31abcf79ddac7f2bd8e55107e2ecea8c7fab1df7d1d5dcadcf62afff4cb7ceb32cdb6f319a55476cfeaf0d5e2301b4ccb4cf9d08ac909f42f0daff13b6f0a7b2a7eb9e0d4ff7e63819bfeb5e37d595f26abf92fdee8aa7a2ec674ee4ff9ec25e837b2e63aba21fbfc5eeaeaeef9906685b52bc4bdda5d2fd65957a0dde7c680ea5e6fb324da2fdd551ff2fbb9f911b84c5babafb7dbb032ed0b88ffb2cbd06eedbbdc9faf9fb8ce5afc19febcaeca9f99c448887b91dc55fd62768acfa81c5ecb5d1a0eeea963cd8cfa0f80dfe17c150ca0dea0c18130eeb1a88fdbd6a31123dcbcb015cfece7ed2f31f0aab6fbd2c82bf7f2c9b4e19ce613daf0e07b5bf37dcc9c3f4d09ae2fb55e212bdda94d1ead77aaf9ce4b0ff658fc1e5d69b97ae757bcbe4fcf85b984d92357b64bb21e6dd253e141be9441cdfb706cd7e7edf0d1d7a3defddb1ef27b1785a560fccb5cdbb26ad4ceaafe4bfc9471aeb2db61773f522fb5ebe17c5679bba785f7123a47b2babe2b45fbf4e1ec92c1400cb5c2d6b4b75c9cfa018bb1ad425ca1e5f1decab7dcec177450b952d84ed6d8e18a6844dc34eeaf30cdee4cbe0d4ec56c5dddf5fc36f2ba6bdbdf19a99eca8460feed3dcd9cbeb4cce7d1ed0d668ad8d86aa2d7fac046b0a51dbbdfeedacb56f0a5db7eeabcfad863e6ef1a4ce9219febff0cd9f9a5edcb5898addeec181f41faf7bc0e1c7aeb961473cc4eb8acac46b7db6c79cfbcecee17a01010697b1ca5380ce438c93fc4f0fd26cb114dadca528c32dabcbaebeb478e6cfd35dd95e67dd13dc2df6f8fdbd2d0f54edda6c73ea63cd7d9232ef760f40eb0895b14eb1d2b093f61908e5f2673d4bd7d9363aaddbea90f878fa7f9fdd6628f5e7adaec780f88e4cd4c8cd8fdea5c4cbd09caea7ebbaecae999aaec0ceffa6db6598720edb1145eb479fdacabfdfc58a8727ffd05a9515ac0dae0acdc082c1dddcbb6cba729d25f208b00bd03c7f36e44effbe6c1ca7c2b0daa46cdafad4c4d01afed1b4f2c2af6b3fcfccd33963de2e85a3ffe1cfefbc7b9dedc27fa153dabc462dad095fe800cf1e6990d03bf94deee2c0cfca5441f397c1bfbb6ffe90a13dbadaea22baf7878ee8ee6b9febcc9b95eac4a1dba1cc28a816bd1d37caff08bbffbee004b0bf200fa1c7f968fadbe49ab76fb0ebe475a7cadf943eb0cebf7df87bf9fbf8aee807d4bc9fc53d7fef5aff32f3eabfa5ddafcfeb4f4b0d9dc2e6fd50695f1fe3a0bba14cd2eb94b5d97c8bddf74e9a47208d21105e3ed92cd78afbd3ee13cbb1cfdbcda6bd8fe31ded1dd255d09cd8e9d616bfe3fc9ad2165e6d98571db8eb779d70bcdf3ab75cade3e7a4dcded77ca5a1ed77cd0b203f03755ee5fdec84f97af902ecefd2a122d0a0ea1ec267ce2be7f6bb331e632bddfcc1dc32a6ae8f5e6662afaf9f7ff430eb412c071fdce1bc8e908ee1e17bfc3e6ef1e6a77577efd302ea9bcc3b10e1ebf11eb2aa7bf663d2e8ea286daeedb1dad3115bd3edbaacfbf9deedecc28bedce2fbb19ec10df16d739b003efbadf50e94c5cb8ba8f5ae4b639b3f6bc7e7bdf416bee17d09b771bd9baea355d63c69fcb909af4d73de7b120c6dee5cfeabeeec2059fc69f06252caa9baef1c5d33bdc6334adac49dbb8f1fef2cdbf41c42f5ebcdfc54bbddf5841c8aeffb58a6f3db38f8c9ccf25d4e7f3fc89e177624c6b698d33af5eb3900efe830c94af8feacc7a2a363a58128fb9cbedf2b9b6bede41f6cdb70ff55e5bfbbae417c92fa6a84d4f30ffa83aa34796cb6ab1dffeef7df937dc490ea7c9ad34e5f70f67f1b3bfda319ca1ee65bdfd9aaa9f44b809bcbc09a4f3dc974dcdd87bd22a6acbaf0457b38d3add82be44748d7b00c9665bbf1aeef96e58e6d89f2c5d6ec3adab6a9fee16f29be5204a191bb3bfd5061fed19e5c69302be04d96e67bfffbf1dee44123fa6ad799cfd6955bceada21caafe9350e03a01704dd4f6ecd4ef9bbd35e6f3cad57c9db744dbc4ceaf5f0e5eebacc1f2d5b8ebec5d48aa39daffc9c7d1a3acaaa7d72d06c96441306bbdb81d9b951be4f1eda8f6fa1c0eacbedc71fd3d1439803ebba3b56e11ce2071ed6495a6fb69acc6dfcf1718afeabe6fbf7973f8e0acc117f220bd68fa0e7723cd4adc84eb7ba490cbed9eff0d0aeefe1a94ccf1dafdc8c65dcdadff8c1cf9ddecb9c09bada29caecdaee2cbedf8b780661ab4e696d1f69ff8cbefa9920e8cad924e8ba766bc8541cba6f7ca850d3f63e27e0ecb40bbdcb9b7cd7bfda9aa4d0efe1de4d06dac08606efc9c16accddc22aed4f2d53da35d8d241770c9b157d09216ec5e0f59edeef93c4bbf223e8b2c2c863ccc37ee2c2d07bfd964dfbfc66db44cc2a1cfbb5ba23aedca07c753b0a0cdb3be2e68c07b3546af624ad0f9d4f3d1fe0cda95c3de9db51f3aab1e90df5d1e2e30389fbf350eed613f3a1eac940bd77990975436f152abd7cdc0ae49642d0ca2958e8d8eee5a6cec4ab9d852b16a261a8af537fde21e59a970acd5d3c784efa2534056bd827df9aec046dbcc2ecccb5b0df9653ef4a7ad2c64ce3d4afcbeaf7fcfc1a8a6fef2a5afbdcd7f6dba58edc7168ef149a9bda5b2f9422deeeaace01db0eb4dc9c1fa8d5a89c3b8e92fd4c7b81e6e7df39e47617fdcebec9329d5bfd6078587b08a7d0890ac7a0f2a54b8e3e3f28f4ddbaaed0de2aaafc8f3e5e7f39ffbca28f5e1abfd9c5ffa1f7adc36a68edece08a66c1d3ecea56572b5c1abfd39709cb8decc0cddc54ff7dcb2eb93cfd7acccc5126cee21c3e4ea91cffb4e5182dee6bc11bd721dda301cf41e42d5abd8418e3e5af3df6d5acffd012faffbac88cf23d68ceafd3f0cceffd4809bcdad320211b7a032ee09e51da61d22448db0a590dfe3a97e892ebb3ab736d0aa6d6d96d6d2ad18b0fd6eae2d0ec374bad124aeb2b4a1adb0d7f3fbc740a0be9a12ef5da86ba5c3d40c9e203dc07f81a062c7acfd410a4e6bdfa19c8df1f1d8aa995679e7d493ce760edb1e8dad0c2adfcc62b0abaacbcd88ef90f5efa4e20adfe5fc7a1024b4eaf8d42e4cbd2dbbaa48e0bbd9a1761cb2e7ad119f3652da3181cb55f8ac9aff93cb8d23e361deeca4dae907acaf09dbaebcafacf4ae3ea78edfc3e1793dbcc0a8585b0352faa31c4cf60cef8483982afb0df1e7c5cbe270674c8ebcae667fea4cbd3ca8d7e112fdb96d7ff3ea3dedd909b1c28900a57a69bd5cbaccaff6bab2d8a7fbaaeda11f2ce6ff856ae51e029db6717bcadb79d73a99a56e5ef35dfc5af3af7f15f2f6fb7a91a08be9e8af979382337acab6d750638f0e9eabe5fe4820da5dce1bcbaefc3feefef2f6cbb664a5beda1bc702e7fc7c5f1fbf03236a8dab3fefbc05eababbbc97cb14bcaf7c8ba3a8de71639b9d4a9efb0f8f26dcc3bac5fc0b4497917e35eeae493ba6eb47fa1748c5e6aacd79940739fd11aaa91d9d9d3c17e1fddfe2cf1c14deae07545b71043be9ccc9deef6d4d947bc01ebb3dd9c09cafca4dea4f69f1e74bba0eda5e6c96ffc0f0b0a58bbfadff3ade7cecae0f1d419a3ad7e89e7bed01bccd3f449b0ef1fe4eb9ecb0fbdee65defaece4f1b1444842dcbaacdcffbaacb2c054aaa31f9dadd5ca22cfa367b5fae0c7fccb434c0a1ca4fa3eadd8f9ec0bccfeaeb94afb9eac9269df81cce3cef8424f8ee09afdf8bd346b9314b91ddf976cabaaff5d27ed4ffd9e4b53e63d68630d7e55afb8d6bcfc4c13bc89d2acefef68e82d5649a8cdcfd01baa129600511b3cf8ab0d94b68e98f42ffa60decb26720edaf50259afaaf4dedbe13e72e9fbea2e4943fbf777b72ac9a1caaca9eaf9267ab851dc44fa5a9add92e22ada4f0c6fcdff3eafbb842bf8d52d8cd57ee6def44b670eb46f08ad2f08fc9caeecbab6f928beb4aa4fcab5e6bcccda1e3c61aac6cd85a9b274dca9ebdafedd66dfd7bebabac13540a8cadd5c6b7c2bd0c043a625ba2d2ca6e7aa559e2aeebeedbe85b0d539679eb9df6fcc932d27984b25aaecba93f0c2c9cbed6419b56532d2e0c80ac4956da2bbe3bda939670c851a5cf55cd71b8cb810ae2d034ede81b9effaa4eab44bd0dc7c69ac96be4fa2d511fea982e6fce8aa9bb0fca304efff4c1261f2e0bc042bdbfe6299e1eeac2ba7400ebe8aecae85c5bdc24b6e102febcff721edcb2bef81f7cc1c8e2b4b4e544e2a37b081af96ef18eb6bbaa1dac3f73a53bf4aa8f68bf2f0bdbead885cfd25ac5bd53caa4ee4a433e528e8dd5eebcef375a7bcac7ddd4c4f9cfcb8f7a2aef0c5b66aeba577385e3a3ffcbf7d705cc4beaffedb0ccced0e0ccac5aef6c254f0ccc7d65ddedaa5a0d3cd7567c93f28a0e1c0af7ca738d7ab0d096dcdebbacefcc6bcc16ee1a1f224fd6a94e3b2c2d8b78f9ccccfde1edbf4fcbc065a3d08e1c19146ae556ee3e1d1b32daa5f1b4be2f80adfd06ee7ec24bd4dc8aa7cbae33bbfed50bbebe8603e474fde208cdb8bdcb93bc62c7bced97ebca1c01ac9bae23bfedc7d888b7fef3aa0c3949fcaf4b3ffea1b6e3da9defeb9ae99aafc94e97db56c704caebe845e5bdbc6faebda40fc206d48f09a339141fbbe6a38030dd52d2f0f5b9f09ddb12b8f0ecadfc545df243c028ada2a6c877f558deedabef2e4b97b3d2a36c6919bce4d8fbad0f5cb163bcabcaf6eb644665b0828d04acaba9be4c4dfdc4b59fbaa55f5d966a41884aa87f3f4af2ea27d8eca1781deeb44c32d3f5a833cfde73a9a0a75dfad0a5a2feded1bf075c0af3cb47f107f1ec347dbbbcd2e78dca630daa089c6c8eb69ce9adde2744b0dea5b3337db5abd1ddcbdffaed2fb0be24daf4714a8008189bd1c0a8e411e5b5eea346607ea60cead0289ac1bf334ac0afac94bfe762cde4aa21f2c5ff686a4a6dd9ecd8e27f00be2efe0801488cefdfc722599b1fa4ddfa94bbde8db9d5a430aee2a2bfda15fc86bcadead9679d41bff7f8fadbbcea3d9b829e8decde446f5efbfccbda815f4fbec66b3caab0bccbdd06a2aefecff4bddb2c9bf5898ae655cd4cbdd9ba9aedac7ec78b1fbffef51ec6db4ab28ae7e85b80bb7cfe586b8ec9abf6def036d78bacfabedd5aa2e1b1d9667f5aae46dadfd793a00bdeb7eeee164852064ad848761fc1bafcfaadc3c21dc7e57ee7fa844a8aa1d9ee32567cca3fd1a0e108f8f4cde3c50b6d80ddbebb493fa8d5ae324a6d229aaa8b81e7c5efb6ab3810dbbb30bfbbd6e4c3deb0c6cf8c5619c30c1dbfbac7c8925ac364e5d4f3066513912be3ad9aded8b1e73c95bffbea4bb2dcda7ebb5ce7bdbaae1d72e997ecf81f71bac1e3f6bfbaf51fddbfbcda79c02cbdfce0446efce69f72fd39ceba4af9cadadffee6cb52cb672ddfdfc0da4f46fdd6cdd0e68cc66e0a2de3f3d3afa1b70f42d49dbd3cf95f32eaeb936947f8de4a810eff41fcce901737cac73bee92db006b1735c0a0b919abea8f887322dcfed9e8ae6edde8e42e8da9a059c5eecdcad9caebffd9cbb916a21460eaf6eeb481ccc41377ffbeaeebf70833bfa2f9cc8f0dc3df4eab5eecd9d9d8ae66eacfa7c7bb2d51360ad7a7adccf7ac4401bc96a419bce85e98b0353ebe457cb6b228efb8dcfdfcceefea9d9ee485afc764af4baae67b88e8e9803bc7e6bed8c2ffcec4b210b9ac1b9a15fe6dccd63bcba0dc53e789d1b02acccb3d834b3bfd3d0cb8c80f4bf9da4ece4ff286e16c7a1d2eea31e82eedbd6fd3aae8c5031ea2914deebaefbf01fdf48d696a6ada8b13faf0bdd5126ea1bbc758bfcffd6d0fdc1fbadbcdfbbb5f7d947cbeaedfb3668ee788b631bca58c1db3c55e4de1ac571a6c1b9ce1af4d88f39c9abefba128e2ff40c48e7af841ebae6feb2eabe4fc5aef54a55fda0b94b1ad0ad9b6fc26e04a5c919cca9ba1aa5bfddc81deea0acf239164b55eccbdce674d467f2f3bebf05092daf6aac8a66dfe5efebce64e14dbbecdffdf645ae4aec2befec35f916ed9bb82b36a2ab5c1e8f266ddb1a70fef2a4bd3cf8f9e71cddc8c7be19a93ff8c6fc98a19f6a7c986d90f0d1ebc950497d8a0d6fd49dc9e6f237da1ed7cb4681b7305aeea80ffec7da2d4eed97ee8124caab90af7e0a3b0a0eaedbdc5efe5a89eeec22aedfc29ca1879e2ea813201cc7be594bfe9fdd7dabca37daf2cea9e3aa40ed2d22dd6653b63eabc5eedb2cbc6cceaeea49fadcc6aafa0837febce0d41ea4ff7befad7507a0f6afc92b8de1bcaecb3e11fc3266a60090ec342c3c0cc363d72e11a5eca95d4ef9b2badb813681af2e5bbf5aa1aa9bbbfed5dbfcee2adcec9abe161d4d6aec0ff743c7ef7d2fd95b7d27831ad863c48a0ce61ea801a7eb18e4ae454afef0d51ba55a719f0436aaaa8b26e1860ea5e4c8b11d1a258e5d4e9fc4f3c33e18b35fda7bdfddfebfe41c1ebdebd2bbedb34bffdccdecdcde6eaebc0cce76ec4a13c4a1c8ddcacd0adde2f4588aeef63f3fc33f613aa42831215cfde9c508a5cd2fee1e446cba942a19a2e8efc5adf6301aaf937301cbdaad38ab4ceac5bac7ae576f3aef98fcab97ffdf4fe81d2ffccd6bda2e28ce8e918dda98beb64fff100b1dc9a556133cac119c9ffeee4d4addeacafbbdabefe0db3cb48eb06f8d46526be73cfdd06607dfaba73a5ffaadddbf2ba23a14e6f2e2bbaf1a3bd4f5ceabcde119b7af89ed90e5c9ff88fb0a2f6f7d8eb1c3dafd3c8cfd52d7afbcbb1ce1debb84f9708eca3c37bcc14ab8b56ed62ed1a64decffffb69da0c09afacf2bbba2aaddcc0bcb51d274e8d2a5adfd367f0ba50ebdee7ecd07b4fadebd99dfbc7f1eca840a1d83b1f9b8cc6ac9f9b5f21eca2dd5cfb5af8a8b3dd9769e0ec7620f4cd23b2cd4fa0a8ec7cdfff8f451af1afa27f7fdf010a66a962f6fb015c32a6cd53ce7b35ebce4a6f6c7e868dbbbe21fa2ce8efb569d6b379bde7afb4bd6b4c5761d92ede1cbfe5af9bc42a114c21fde478d4c6d5a94edaf95efeec2d67d7f486b84f7b24eef5295eebcf3c3c1ece2cfd369cd4ccfeccb1edb04b162d899bdef35faee327ceece11b17cf3c3ec68e9dab88ffc9942efdce03bbfddd3e7421ed847d8577633c0fb8f0afd47c9b6eff791bde78c2f9bdb01d67aafbb861fae89ca2adfb51d8420db39101f16fed569a6edef3c92a4dbebf74fdc423a1dfdff13c5bcaa9a32c0dca986ca14ceb54dddaa40ea1b21d3bbf7a761aeadede77b6aba2cfb35eaadaa642edc03337c0eca213e8ae51c32ff61798378ca2ab370796daa38efa417860a740e27abce38c1ab8ce0bf0a1ab58cacd13330ff9c2fc74bf7de87b2103361c6d8dd09f5e45ce5edbbea819afbdda5f5782a1b8595feffcbf8e6cd10bdbd6a5dbcd486cbb99eab1c71bff7fadcfc78d31fba7efb15bb7f5e9e4391e4dc46fac8cecac692e97feeefbea85780dc834a8f9ddcb6a5ccc45f0ae5ee42914902d1c6916c78cf187cadd39fcba6a596e75fcd178607e3781beffacf76bf05d00cb70501fff494ebb0aa24c165e2ec8bd8fa91f8a8eac12b8e6aecfbb1418ca8713d0cfd0dc4f6ab1ab63ba39da63226cdcbac81cfca8f040dfbfdb6b1cdcf5e6a1335e56cbab72bbee3053f1f3a2bace8dfaeedc9daa6c9a2f8d77e35dcbd1fc29b61acfefba3dbce54cfc82ab881d6be35ac2bf5326fa6fefb2dbed80648e1b16bc0de51964f9bf5531c21aff09edca821fda33ba2c4ef179c87ace0b0b09bbabdf3f7e2d387e45a1cddf1a0f3853281f39b5cdde67a4eabbe6e38b800bca1faa8a3d545fdec553d62e57c0c3002f7b9c217edbbc4e6bb1f8bfea56c7ded8a7c981cfc4d6f9af03beaf5ddde4bff386ed5bb7eaa4218449bf3e5df2808b3a1dcaa8afaa3abe48b48b4044e1ed4c3c6cc5b1cfec50c5a22ba9dacd81140b6d374bdae09fff4aeaa0fcc7bd2b4b70bcbbf0dde3deaa4fc14bd17bfe0f5fdebe98a1e80d3c1a9ead8ac151fa8213269c3e67ebcfc6b115cfcdda44ad84ba9ecdab619f2831e4efdfacdc896aebf05fc5c4876c9bbbdd2eb61c2a502ca61eacb4d9a1a8ecf5fe6d4bd977cbccd91c97a7f4106d00dd1b4ed002477082722b26ab8a5caf316179422dda0c4af52efd6bd0ae9adf8f270432fde70ae5340a8d8022ed8f2bc5da7a7db667e85ddb2bf0dda0cdee42c8a91f6174e8f0dc9eb5d451fe5fd3b8aecf332cb204abb7afd90a150fe535d8ef4eb42b6fcee66a6e7a9e39d8e0b69ae8d4103ca6a3c2ae6cc28ffc5c4f1f40dafeedba0ca8f2daa8b7ca5e3da2c4dfb6fc44ca4a02dabff72acef98b1d031fb2c9ee421e722c064cec61bd92a4edc3b5d0e55d926a33dab2abce3fd31ed1c2009bb4b443c3753ca11edfaa4aa906fafe3c07ba12fa11fb44e3aabe131f7c95fdc3e20e27fbacbe3fbabfc1ac3a62d3e3d75b5bc8ff30001ecd3d23c80c3b4bb048d7e228ae10a7fcdaf9c3a4736cdd7bc57b2a612b7ec5e8d12b50abc4b2fd4ba8ba20b55cba48beecc0a6c8cd944202483faa9ac2605035bfb1fab98208d2a1908dcc3ce72d0d9c04ca6a8ce27cb0273e29bcf0cc4cf2ae79ff78ce64f6a4a047d788fac0fcf79406cbec24e7ad82b9bfed0d10119be2c23a1a9c02cc05591c99af789fcfc92be2eaf98faabaa058fda500afcab232600b3dacf1f17fcc45aff670b1deecfe9babb0552d46252d7edc794bbb0331d51fbc25e6a1a921b893baaae6575ae24d82cd527739feea0dfcf26ae9a4ed6644ac60f6108c7eb961c3acc5d007c0e2a0141b2da5b8f4e85fec3e2b7f275f47bf417e4bc5bbadd7632faeba32a0e481d7b8fed3ab9711cdd4c7dbdc716ffdb3af7a3e05ccc83564ca1fe5affdbf51a20fa7be4b85c8d9929d24bbfbe897cd67b1bf1fefbd9c7cbdbdf0a32fada822b7647a1c1510635cac979edf333164bfa2e7bc18e9eafcdaaabea4b95acc648eff2ffe45d352cf02a5a2e40cd2d2db5abb73e18fe16e4cf47c1b222dbb0848d5a5d12eff5bdf1aa52bff9f8aefaaff6ddaaceddac79bfd5eee7f2b18de2ad3deae8bb2245430ea2181fd49ee8419bda96eed1bcba93d30dde6b54ccaaa1c45de7cbcdbb977bad9fa42fda02ffe6c7aee7df14721b12a1eacb13dab90e18ceede8cc9ff6be49fd0e011ce467a5b5c9a49cc8f705fec8fd0284cad1ee1f1df34e8fb3e28de0631c6e7558a538af8eab7ad63b5e2bf009b73ac226c10a979b0d4ff47ccb71995523fd5cfe5bd96e94ec27a3da8dd8ccbea91fe5e8d4e8c9cbac75d01af11b8da4cfbcdd0fcbc515a4adfacbd2d6eefe7bde46f45892add4eccf8db4ac18bb6eeee7afb3ed5cd1b3c297ef34ba6b6ac8b1d1f117d56e2bb76c5b31f25ac0d4a0ddd46ac6dda8a5b8064ba1ca4cbeac1168f3a2a357bffe7eab9fdae7c3ca749cadbfdc8c965cd009f6ba3b6debaa4f16dfc006a4a76928affea2781cb2db7efcfadfabaee5b0f1596eaadc725fbe855d7069a5da0cf2c5b483f1ba4de1eb1fac7fda2dc70d84f17d47afa07968ab3b81dee22ecc0475ad7a061ac7193adea1a7df97eb28bba3d2342d6c3b4d0b3b0ad4c9afbb3dfc1850dd33ba6633ac5b8c34cfdf3dc317b77d02bdfdfa6e97d7fa184eaedb1948d62ab8cc35a1854499afd9161febd4a9b2f8cfec3ff9ad7f6faefa2ce65110d12cefaab7c462ba19d15a0acba85d4a9c79b1946fead2a580badd7dd0b00294a16cb2a4cde1e9f929796ba8333c45bfc2345b09bb0f4babc4dda29d971581da4ece8fa13962d9ffe9cefdfc5c8f3f62aabffe2cce9b1cc5cdf36defd055f5304bdce62bcf851a38209dbaf7ddaa07e4f4d0f445039fe8fff6ef6d1ae7ca48c62aaaad39afc9ddf6828b7428c684fe1b73465ebea95fed8d5ebd2dc7feafcde2b9ccd3e19bf5de98151efd60b93edfd1556dd7af3857bfc59bc37d029b2bea8a4a5a5efc0ddec401be106a5c9fd3abbafdb3ceb99c2b7b927212ec485d02e4af566a283cc5e7ac1b0a09cdea6e16edcd9be6f906d8e2e5ea5ed96d62eef84b5c95a710fea34b9bb693247bd5c27cded11e7bebcbdafd896a0ffc8cabb3ae8ccbbcbcd2f6c329e1df8fb7b7dcfbabd1daccf8a82dfecf707fb8d191ada048bb0fe7c8d90842e9d9eca1ed23aebfa812a7a89d51cd766cd6df8ecca7dc4dee178cb7de6e8efaafceaa77efcbec0b879de2ff56ecbfccbadad72d6d0dfa8eac1faf7bebb40d69bc47c4aed2e7aad7252a1ebff0eacf0b62718b605c9be9fabd0056086be5eebfdce5f6576f179deadda96dd8ae9fcb0dd5a80eed8bbbe2a07c5fd5a8e3ff6a0e4fa3bc285dba5cca3bd9bb84eebf3dff4e595fdaca57d97fae65b5e55f6dcf099ab33d5e6a57c43e9fb9dd5effef6fdf01e3e5d94d1a65dd64913fbf079ca4bfcff0fd7db64962911c9a0c9cf62a28fbe2b140f31c76bd85ab3d41b1d8f01c450dd4aaa39dd9cdb7dc0abe01e04eba3adbc43433cdbdcb9f1c0ce46aace9a2fdbc523f2c6ea7cdaa3dc475212adff2d3be0fcbec0e85ec41c1fae7a3accc6bce52e0d204f1622d94b37bafad7ddfe295bbd97ebf07ecc72f03b8aad80d709c72ac654fc4ba9f261dce83e4ec9fdd6a7eaecb4e2b64ccabd65a675c2ebaafea829fdbabcef881b1b2b0aeee16cbc722feb951dfecfc1da8f989fc5f14a829e2ed1fb1f21f8cb7d69031cfdc4d7a35c6fcf3f2fb4bbe5acedbaf5a701ad61b0c1662b3226b0ed7cd30228da85aec8dc096dab9dbfc9e39ef6016c75b328b50d032df87ebd8cda9cccb1e9f32d6bcdbecf2d8a679bc4b5c35bab3ebdbb9e86c133b8b185eb1fb3cafd20f558c8f27c15c6eb1f1fa7b2575b1fd3dd806c868d36bbba850065c18ee891bea9563dddfcba58dcbfbe3c4a86d9a4dfee92c7f1ba98fe1ea03c9deef2f5e2a95d740a00b525797b713bc05108293a1f55cb2adccd1cb375b7b50e5d8a5953fc3c7e0376cb36dffef0b1ab2cef57f6ca7f4db4d52eceedcdc1acc21c7da9efe2d79b7ebeb5abaeeaadbfba22dfdfdfc0d591cbcaeee480dfcaecfbc778c7ba8eb7faaf2fb067cf4c5a18ec51ec03aead9bd5ea20eedc6b062c2e7a8907d9cbc5a8a9cacd1aace7ecf255bad409d68b36564cf9bcf0ad0ce0be94d6bb6ead25cfcbcbe3d8711d6abac37d31fe20ec729ce20e6a54967b4d5d5c9739ca2ff7fd790eabd9ff4ce7df4ee4cded3ebcdcbbb9f2bbbc8bbdcf1b5df67e701059daecf8c4fedd0e63faed4bcbf0957e4b2f7f647efe79a5f7c6bab4b3a4f8af226dcbe4c37b37fbceb7fb4ace8d2adc4b6643a626cef76efbc653c4bd65dccdcbaac41dd48ae7aaeacddbcacf7d48e3b634bdbdbbcbccae8603becfd012c6e69dd63a9dea68c0389f91c0c4d8b2a05b9be57bb64d4ed7d5d6aae37b3aed5ab651e28b8dba7d3de68dcd7ae271fefd67b7632efbadcd73bdaaac3f93d913af2bf32791de8dee44c5cc2c863f1e5c7cafda2f1a9c9abeffd84fe0cb7fdd3af4512aaff9659e9d363caaf369ccaa98345f697c9fe650400a1e4538ccd1410d48d41a8178ad4a832f0c1f8cd1a41ef8110a5cee4a7045402a550bedc1df41d782fcbe562bf6ecfa163e97f34f712cfa9de08e831f3a7b6e888defb660081f47b1d7be4e9b2ff3e9ab9909e1acea7960c1fda0e295cf62acdf9adb02aef138bb0a0a998bfb61cf1611563d3a97e8bf9085dfaf8d84d86a81e89080d8ee6b6d6768bfde0aa9c7ceefc2accadc3eea5427bc276ab7edcaf6abd194f4cca9e57d20a748db2d8376ba30ce6daf0f1abcfa2cc3057532aefec0c78ec3dee2abaee5ff810fcbe701efc7cbe4dae6cdebba97bceb6a5f8e520f9e10bbefa5a9c1bff02802ed84faacde02aa0cdf926c314faed12ec9af1feacc3a59ccdab6d1cbc5edb78abcffebd7fa13fcc2caa959cc9c1adffd5c5dabfebafcfb6ef546d30077a5bcb0bad2b693e5b3152dd73ed9afc6bbc72faf63fe2fd39eff1ded9e5caefe2635707b03efe2eabc9bd8e5605faeaa2e9ef5dba2a2b659d2fbb0b8b4174fb22add0395b7f3b4a73b7e4d21ed6235a49f520790cc297f3cfb56abf19ffaea3f615ea11a086887f6bbf2d4fc2a4094cf9bcf5ecb1a35bb2f3055860ffefe9fcccc5bc6c4cfad10caaeda5fe85cfabd4ce66d3ab5c372243a6ab21ebcba9bb9ebab2cb86a7a4bf2ca0c82c05c0ed1bde4ee4f05812bf196870fe8d3ea0c417fd3973497dcbaccf1d661e0e8f05088837ba53fe54e1faa3e5bcc0ae5c6da613d3db3234eae6c90adbdfb9ffe56af0ad28cff7fbadadc7d7f589fa352ae18aab65f6cda97c5dba343c7cce4ce5be7c522c9b3fcce6ad10e04f95e2dcbf12bcdc292bdfcc6deda65c7cfea0112dfb2caaf8d54ee5ca4b5484db99ad7e71dee8d08b4fabbd14abc1a3f03541dde9f94efeaa6e1dfd90170cccacb69be7af2a7dbf86320ff5ab9ef5dd660ccaa9f261f96ca5f5e0e44f00b1fdb3083fc3aae6af65bcb71f3939b73a155aff8e2cfc7ebc02afa3fcf5965f3ba9f5ff3fcf7fcf2cf0e46b33cb0edbbf41cd6a94fddf3ba4be8bebca9b0efacbb8f2c5f59ca35befacc3f1b300da18b15abc9ef311b7c9b87cffc375072020525bb36bfbbefccf386fcc1b5feebd93cc713e544a9f3cc2005e5d4af971fba9b9ae1b74de70bf0cdedae5d6d22a825cd91bc63d2fafe5fb69ef9d3db9f412bd7f08adb5dc70ca56ce0ab6fd3fb2eea9c4b5b7d27cac3b8b4121a73e5eaf8f9eb5bef51eb7ddc87e19bfffadd87abadac2dea99ff0e6ca8af1db7ef0c048ce9f924fdb1def9f1bcea7e2deac0771cc0ccd7bfea3b3ea2fb98f03a4cdee954c6ee08acc033f5e08ba46f87eeb56f3c7349bff3e0cc7e54feb647beb4855713499bdffa2bfe4c6efaa1d6daf64dcb9e0495bb4b9fb0cf302ffe0ef92073cab9966bbfb7cbbabd95b5481e9d6d88b11d2efd3a25daaed08bc1cbfaceedca023ba7ffb102ffabdf878ee0fdcdecfa6ecaade06c29ae06036edde24a56ae1a28f22eda51b89ad6fdebf82f7075bbb5feae7bfc6a86e43fd974c5df6b07d5baae561f45fce35dd7bd8a308fefffb835ecb6d2044abd0f8ff3ba5dc80ffa45f26caecc2dff41ed0baf03f8325feace5b8cbaaed74c08386d14d77fc7eebe2a766b4c127c9ba412b6d6bae130a921cd3a2d9ec91fba1b4dcf24a82aeeb6a5cf479ccf46e75fa0ab514c4bef38fab6fd5f27a2ecbcefb9c87eaef2cd7cd01cfed9a72ed25a2eacfbed86e169d035b27cdadcce66e8cccbda1b83b5ab563f9b4a7adabede6bf5e92ed55d3eedc2a5ec3d4030a01cf0fff49c1bfcb9b5ba6013fec63ad2fcc18a8696ea7bbe9fcca8e18577b3bf4db546b2b039b416a13fc001ddcb19fbae5ccc4d6fec27f1f4cc1d77b271cbe5cbf5f0df595c1b12ca36ebbea3ad14dabb21368fa7a498fb9f2fdeaa5a4ae02ee34f0e292d8083dd00c22fedda603d05db8d291937fab444f9a5d2be0a8fc56cdf6daeea66d3fbb3a579a319f27ded0e7737c7c2f4e6fa8cce67119e9c03da176628f857ed0d7d5b09391b9be2fbcda45eb8bdefbbfcaab719a6babcbee8f7c13ad0e9d799ea514bacaecb37dfcfe0282b90ad90d4f85c8f5c2fc3ddee3f25aeeb74ad6abff8ef94073fa973f52e56c1fece3c9d7f32d2c30c31be3edd3a7a79ddbe0ee8eaf7fdcdef50d784c60ee115fa6bce8f6d3b0bf6a305e7df9406b6302538b55369bb900426dee2447ce9b00e9ba37ca91cc76f5d6a347edc82e11f348dfa971c5ad5bfc159f66e1b3abf03fc8c80b1ca7c173e87fa7ec1b5e32aebee07e0e817ddd6374dfcca4840ecf88c0acad4c25d3d35e3758eae98e386e3abc9fba3a46d4d094ed59ba9f75b9653d6bdacfffb2d394cecdb17e4e406592d33dfcaecce9af75bd9d4c674b9a7f2c4f9cdd6e67bcc1809fbde7fbcf40aeabfb853681b6332bbbfdce4c25f629ae2efa2376c3acedc0ebdd4cb03bdca881f64bee8c42eb9afa9b1e3bff67fa0d24fbf11fe0da152ab6befa4e3380f85b2ac4d0b6d1fbaa0f52b8feb4e41508a8892cf2e774d8cbcfa84931e7612e8bf1af167b627e9ada0d9d540bebb424b36bffffb9164ede7d19b28b46ace227d8d23a7e385d97dbd8e954dfdbbe046dc1735a3d946fcebaec41e977d3f8d4d996ca53fe588ecf7bd2fa7cbb5fdec788a4c0110feb67fea5befdd50c51eef50bd1ee84171671e49eefce10cd4fb38433a1167b8c60e3a503c50e2dd7ad2d0c8aaebef67b24f0f0e7d4cd8e3c9c25a25a82885f4aaebc4dd66cddcc36c6cd5b23147fa329af28fe9c8c974998ec4cd2abea72bbeafc8cabaa70db7e99dc3a28c7bfad2fdc4dcccee7fa8fff5dadfb31effc6a96ddcb60b4bfc0cc1fe96c3bef3dffd9a697e25ecadcbf9ea014ebdacaaed69b9a6bfaac043afac6d13cd11a0d2dfe36cdcc3569cd3d467bfc13edb4ccecf2fac8a2d81defba0629d767ce1e33f54de8ea17a2813b6e868fc9bddccca808cf101ed41c7a3b3fb05bbc0292fd6bacf031dda14cbb67ebd9fab292fddceffcafee49acbafb0d1d854b2ef5c9ad0ca5c57c3fac1cd7281affdb73e6418ba25efc3c8c721cacb0ad550fad8add55a2177bf536a0aab1cede6d36bd883da9db1c7adcbae540ebe9e7400b5e51f2eefec6fde68696d3d92b3eddeaf3b9d7aa5e2ee2bc1adf4c3746aac7f8ca6ed9dada76dcb5adca6e5dbc10eab4ad2eb4d903ce5d9adbaafb0bf554b27e54a8b2bdfa60090bc0238ea7c7d753341deedd4baecbb5accadc22dca9dad4fef3bec07c68192ad13f3f194d56c222e39b411b31ac4fcf7c0d8153d0c53ee857d93ec0e078e13754be6b7e9ff0ed966d0f1fc9bc63419d1cdfb0ab1a2f9f2ba13fe2ff71d8307b77fdb202fcb2bb6e4e3dafb8bd9e9de20be2decadf80294c5ec2e3e77ecce0a4ac9bd3dcd5a87a622e53b6a7cccddecad43acebdcbd4ad656d62ca7710a3a29e9430b09c9d5c7f437c41a3b486deeffbc7cfbf2bac16e7db5caaccc497f0c09d7b2f9c51ecacdfedddedda7f6eee0de4dc11afca8bffbd53371efccaff77e4aad9fab7fec58ddff6c4aba6ea214fadc6ced4e1047daaff4ab89a8f0aba4e6ea0f6b011023a5e53ef9e76c5f2f566ddfe4e2d62e1cf08e63baab61d9b5dea8c8d2ce3e18c2c3317d824a2a9cfb3c431d56e258dfafda81ee67a07ad80fb9af6916abece6d5c74fdcf2b8d10a61ab0c4eae03906fa610abc78a73adb7ea3cbfca035c00b64cd566d0367e5d85c05b1396fbb9adcb4fd81ae4197c9edd9c5b5cb6deac9afd6dab08decbed7ebdb03198ed234135338acd667db3e9d1e4403c0378136e21c81c0fbcf673f2851fcada0f128ad64c58ce8eb8dc713cb24ff1adbec4adbd40da2f5ebdcff4e1aeda7eede191d7fdeccdcce891ba3dc858be6a4cb22f3b9c09cbc4e28dde7c3d925fc5d31569b5a9c6ae85c41a8118daededce4b9a434ced2a311edb5955247c03b5f9be40d356ac0eda45588c8e027a1c4c1fe2f0f6beddafcaf3eab5e4faaa1a59fdacc0aefccafccbb03ca30eee36f220bbfadaaeed3cd5a8dc7b3f087e95de1d97f2efdb2dceaa0e6e02f689eed90a5abb8c934dad44f85123c21a1abd4e011f4dfd55839cceaa788419621fc082862501fddef8c54ffbdfea7b3d61b37e7dd9e7a18ad058e9edada1d8c0e8eeeae84ea6e938cfae4d7bcff42ce19b49badda1b45adcc80a73e0c38bc6cbe6bccf7aeeb65fe3ca8be8e7d8d84caceb27cbab4f1baccf5bf16fe0ca0a1b46ddbcebcdfb658ca9f92da4fc3cff201dca83ba3c971dc37bab15f44cf17ad7c4f0b72ba46bb169c1d8fdfd4f2f9e8c109d0dc14d29f39be60bfeacfa2fa473cd7c172afcddabb66cf089bccfefadef7c4e82a3f38db87ac7cad29bbb3bd02a0f57ddcac0c9b3bd80ba365bf976e08acbe3c5d8bfbdd320809b64dded39ac298a961e725fe5b13d8f496edcf6ab30e9fd4f94bfd97baf0fae02f81dba840efddd7d63fba91c7d7b6ac222ebeafd3ad1fbe6de5cfae0d1d08ac7b5fe435e5af9faa91c5d6b519cf3ad6bccad1cbb83ea52efc1d4fadcd1d906fdebcb35dd0df07ceabfd2e210a5bf60ad9c91cb9b18fc76a977bf4c9e2feacbe1c8fa98bfacaff4df61edeb9e1ebae3b3bf8d6dea5e9dc207bdf3f0e34ceeab41bbe00a7a3d56a5fff4feeb95b0effdbe4a8eb49c58b4ddcb0fbda2c4aaed35b066a44da5bfb7bd89bb70be33c6acac2bb1f65dcb3afc9da6bfbdacf7c8aef0d72fb900d4a6a0acd1c47393dafca1c5144f3bbebf6b228ee9e8ebd00e6e6c8af50fab33d0eaa7a60ed18507ed45ea88977461bdd8aa40faa889eab556dab7dedead49eac93cb50c89d7a6a97fcd4a17c5feb8ae6a42dcacde3305df43ab2e58c477baedd75d03bb2ccbc4d7edbfebbe3a3ead2ca4f3cfc850fcdfa2e84efc1e60c216abfeccb31a7dabc47ca6fbabb6f9ce559e7faf8bd9cebb88f0f296efcd6bd7bf0ddbbc9db9d8642abefa798b8e9988b9caa901f2d663acdcdb00efbe513cb9ab450bb50606efa1ea7ad21f3ad83cfdd0f2a6a271196a4642f712beb8be8bcebfb33d9ba8d133edbb9a5cbf92cce8a51fc8aefabbf47d2be91f5fdcdce76c6891fcf04d7fadfc9e709ac4cb6b7ff56529353bdd0fef1a150ff5d19b0db4d1a98a0be429c94fbf7ecc1a7ff0fffbb52bf9fffd7bfe7c1f7cd2c8f2e57063ebd7ebaed6b81d827dd3cdbe8a5e8805e44a3288301aebc83a555ac927be2fccceae74174a64467f4eaa91d2ac4fffa51d7ee4788a8fd6a10e8dc1b6e15b596a0476f449f9facc70ecec125aadca109ab8f66dbcdd7e856f3abdfcdd944edaa4bdd8fefe1ab5ecb6bb79fdeca5cf5190ba8da051ccba46ffddb7ff4ae695fefff8f8d2d0ec63b88e78ea7aebfbfef1fc5969df08700d0868175e27deeb270bbb1ab8fb6167fc32fadc5fb2b8ed3d0fd395e98afc81fdebe81bee01cb2ca385eca0d8f3afc5aacaefc9c1efbabdcecdc9ac3b62d893faef266de1edfe852b6da0ff6fa056e449dbdbfb3fb76fcd3c5c57eb2a26d79b1c5bfa6a39ed6bd8d975d534652e0dda60ddefaaadf0ea79f176ce0cef8aeffceb3d98cd51c8b9acc93cfa1fbe76db28ab6119f2d79bba1cc36010c1eda9549d2ab855d8ce1a9fa5e0faefb9eb408a7fec6176780b2d2e99450cc8dec1baddbaf9e2ef2a3ca4800de52dede2beaca2feccae663ecabffdd7cee1d5da5eeeada912d334a7ea3bc043c5cedecaaabfefedb0cd9a340a1e9c58d615b5a864ab3d0934b711ced0ebeb584163a48bca7f46aa8afd2480b5f8da39576facc9862e8716c20d43a5a8e92a13fc77b1ccadd2cfec6ee6a0388cbbaec6268dc11efff37ca3cffae90079fdfdd88bbe1bcd48e91577cfdec0512f8de4cd0ca5c3ce4ff56bb0ef9bdec88ab9e5cea18bcbcbb4bb4ffdf5e5a8da8fbfbb9eafb071da26feee46de7f6904236a13ceb796e66cf8ffb7e8b4fcba25b880e36db866ec709edbc84ff1288b0511e1bca2d078b8cf503877faad92f3ca02deab06a5cae0143b9b42d50b4af6b0d6f405bddea0035aba1614aa479eb810d8caceabaefbac2f769bf175ee4e9ab5f16d98d7d85c88d954e8d8810cbd13f3bbceef9b19bda0fbd9ca6be328fc2dd64bbe08922af37c32771fb83a628a1ae545ff8a4fa4b6f54bbbee5e612da18bdf21b1a5262f40d65fdb64ceb7e7cc4fef673ee3dfafe449d7355ac964148e61b08eb3ab71583b46fadbf48d8f0f4a9fd3b46a67ccffacfcbf7ee4aee9eae0dec3cd0fe7c7f8ddea140e9dfa86bddf39c5817cff6b3ddc2627c4df3dd83bce9bbd5d7880e99cb14cbbc079a2bc9e4eccdafb42c69315a8caa88055b691beabd2eaafadb9b8cf2cb240fb86be24d3de9f3df8fc7dd07e05bee2bed6eb757aff630464f604b0cf9a5d5db1e1bd7fb5bea897ba66809b7e2f4623f2d5a5df430b8aa3d23ee3514ba174bc95a0e343574fe5f4b11fb3f33d7443f1673e41180ad2bdbfdafefb3c9fbe232d9a6f16ca683c26203c5ed92aaf15b86eb1fdc2fbf84bde56e27ebddbf510aebf1cdd8be8caa9dff19ff72fd8ee7d3a8987efee2efcaf0cd80fbbb7cc3a2dad59b7bac6eccad7c1cbaefbfb9362141bbba8fbc2019ac6c5c6a6ccecff8acc359ea30d63f94c2bee5ca1450e47e0dcfeef526d6ecce580fca2bce9ecc755681de6748c50fa95b19531f1194b5c0ee1cdbb2afc6e604e5a03a910d7416c49c4d6eb128efcf2ac9ef4d015dedf044e54dfef007b5bfa1788c879410acbfd92e825dcab1e6a5acc0adacbcff1fd7b09cbc8f8ee3306559141ced65b913c9fea2d08c9da626dc1d4dd3edb8aa98eea527a5fc3ff936bfaf13cf289a5e3571f63fe75afabec6d1ad8e1d9133a0bcfc39f8b01ec281fca06ab61b23aeddbac5db8e4c51f6bbc7cef39bd0cedff0f2eb5cf244c00c6b80ff4f0ccf38e3e656ebbace5d0c4bde46c7f37b3b8ddf369ddcd4d8ead41d7dded53f803f25a1d84c925c25adcbdf78c25a6ef7e48bec7bbdeb2f5bfa6f8cee7d87d4383d161b1eabfac5e7cdcaf5ff92bbe37dff9f2bd0a6cc12b24343cdf3ea9f2c3f82fbe2bb18d31b997deeff386bec7ac727e9e9ff89dafacac4729cb6bb71878d639448cab52523bf81f0cdcd0d7af29df2deb5cbcbb44d1f6ca70eea7f32fe08a56d5dee46ecded5c03c61bdcc7cedc0ef0cbce142fde4998c4ef1414d0d8e3a913f0074c1ed73b1aa567f2ccba7da2bfec01ac8d9edba948962adcaf43205afddfb552bc0dfca42dbcbe676852da4daca619efbca48f298edeee8027ff58df6f3bb7f9fa5e9c8de688bcd31d7b77a978dacf5e31e8eca5e0cd2cbdc3df95d3ecde870ffcc7445bb3ee6f29bf4db19f65096fee9ac8ea4d1de50eb6ef15bfc01cceaad0064f656ef4c068a19a712dfcb64dcdde3442becb74475199d848af790c83c4dc45bfed3ec9c83cbb923ecef71c91c7dfbcbaf34daada3f9eacd322cfefc05c8000380c334c099aceec523dd8bd6bf6ce3105fdfcd7af9dedc50a8e7e1d10e0ff2f4a4f00ef8eb94fc35ed0cb9cdb3957af9a09bfaee30fbaec68aa1d50abdde5d2a6082cebb6f7bda1e377d618fd4cbf2b1a8ccbb4883f0a6ef87faaa8c4d57bea8bfd5e5fc3ce4cb4bca7bbeb9a03a9b725ebacda7d9991fe5c94dbe3a1647fdf1ecd9fffb2bdb0caa0b91ad760d837cc6bc69ca26d2ffb0165f4d73ca0f7e6889e9fc3fa5f36b56bfe75678e3db0cdacc3d577df0abd86a02e7dd8bd62f7f8b46f8cbfec2f250df025da3eca9397d83c73628afe769e74d0f8c88ca6b7eabf9c5f8bd4ffaeecfa94e04d36ae0f5decb4028ab1b954a4b4c33aa668c2efc3df320efffffa7b05deabe16be4afbb2ff612a66696a9ed929ca17ecaa7eeeef6ddea8445e5d1d0cdaba56e493cdfeca6dbbe12a8c056f0449cec5b4cebb45e6b2ba0eff80beb484d6fca94cbecd5f590c0782fecf87b4bed6ba2843ec6257de7f79dbd2b2edaa80d9d0ccceb924a59dfd9adbdc282f1a725d5dead258b2296d1adefdb3aa14e6542bfbfcd6af49490ce41bafd1d6ad6ffe9f0d70fccbba2541ed88938dff38ec5e57b856742bce12fdbea7f8a71a57653a3de397f6eb1294dcce2fd7f5c8d63ac3abea39b1adcd9abf6e432d4dad32eefd87bff88f2e78f546b1ce4c44b7ef2ef3d1afcd8e95dfde26b805bc36d85442e1aae65ea3c10e8d1d3db8bba0aedc4a229607dc5aba62da5294c6e1e52b132aa0acacd9a7eeee71a398a3eb1353d6a3f68b3f13cacd6dde33cc42d8f3febfec7df51b6beea4630e23ab2a5c93c106b9390f310e95b623535baaafb391d5cac87aa3cbc332e5ec8baeec343bdeca5bbc31ebe9d7bfad0ac8d4ef6e79302d94beeedcec5f12ed63dafe3fe0a3fc37f28b9ddd3315a9ab4b07f26e0ec4b4a5c2b7c55b6748e1efc585898c3e951af9dbf1821e0eab51187bbfb85c67ded1b9fcbcd4f8c1ceb87decaafb38bbc7aadfeab70e04fcc508f1d41dab6ad4ebffeadf0cdcece5c65a4edaca3fe372bedb0c3ebdb9b3cabd54fb93bdf5cdccf57476bbfe8f35df4f90ff16fd0eabead2b7a19d0f21107708a74df3b0dff55e4d928c8fcc55df73d8dbddacc77328d4df9ec59fc7ea576ce5cbb3e49bafd7159b3cef7fae2de0aaecdbce39d7faaf7cada1d7de988fbae416e3401209d0eb0e68ce11dba6de924faf1db0aefd2cff4eeb13601fbceedbbeedde2c5bddd7d4534dbfcddd09366bca6dfcfd0b3ddafaeccaefe953d18c85b05381f6dddc65381a81f51c89e2cad0a74d1e4de81588a9d27b1d2db4d3e245ae7271cc881aa5b8528b8acb9fc7814d71f766eb7fdb95c22ff3f2eaaece7bfbd112c115ddb369cdb20ee43e031d1a6b06cd1ad9a0e64bdd74bfddaeb6a8fb56082de6fcada2aff2bdb3af55cac6aed6bbfa3d33ea93d6ae4ddeb2d4e4e75bfa7cdcaedd1ffad2ab8a1ffacfdd7a9eecacafc82fefc6cbbaa8caaa60141ce4fccfa69a377d1522bbd55cbb1d071b2a7b1d5d5ff6d0d36d8b53924afb0c5bedf7eb14bd5fc169aefe5daf7b5f7b19af09e2f94682aab0ad4dbd3d68e0949e8fd4234adebb3299d309c3edd58abead53c3ba74791eddecea0a208c3da448f6052b21fee17e58633780fd654a1e9d8cd97fab5cbcb0fccd19ce94d872deac381b6ee7dbebec57aa3773ae1530376e7338a3baa2f1e8ebcb78a0f71dd37d04e77c3df497a5b5728cc7eade1e22c979708e904174b18b0be471c77df2a6ed4e0b99baffe5b1ddaec4ae4d1fb7d4cb7be6dd2ff4c57aa7cf659cf84ea7acb19816dcbb9a9fea8cbce5dea0a0c592dd0141ccab3cf12ee2bf45dbd64996736440632e46cf5eb1effa70fcc12a1aca0fc8ee05952c006f59a21755f94a1adcca46c292abeddeedec5c8c360fa9defe9a8dc6e1b2a625baafa81cb92f4aebef8af3afe2c1a686f3a19c307d5c112f0db99aadf2ad51d7b4c182cba4dcf768f9eb0b2fa0447a4b38fa9ae5358e6ebfadbb24754d70ea4bdafdaffefd22e723da5cb417ad9b9a19cab15b2e7b0254a3b24d1a71bc8d7b4ff6aaa5b4c6abdc85de065049268e7eaa2f0cabecf23fd540cdfcfa67faf46ff5bf062b1dcc3d370eaf70ddc7ccff407bd7e1dedeaecfcfffebd29d4c7a1ed2dd2c5869df28f1f33eca1ae0c5024a3dc7cd488e85e18f26275dfba76edbf0f82ace46c33b50bcb961eff3e8826a3bcfbdd85a2bc78e6debb50ac1401dcaed4dfdae7f161a9d841c69c35a58080781dbdbd93c1caf562a73fc44e8ca49cd8bce5bbcadc660e3da1a78d1a54dffdece5a76fbf4b292a0c58b3ba798ccc8eff4dfa4d73a4c3cf26499ad6181b5aa1ebdf8ccb2cec7ce030baee18aa3bcbccb16f574aa9f3a2b078ee8aea8f641dcfc40defe7c8a49b0af8d83542f0fcbfdb6c472a883ce457fef18eb4139cfe6403fbaefb88eaaaa3ed78dad23fcee71350b0d1b6c8b0e4287d3ff1edd22e81dc3d0e1e81e816ff0df0bbc3bfc3f250a7c55ee664f85cb3d040db8a7eac01a35667f2b2907e6ad85d279379d2af08a3af46c8af361eab5f7cdca6f93c71db1caf3067e8381cf4655a155bd60742b5aac8b09fc275fb0cbfc0ed6cfcd229dcacbe927796d20ef4efdb0ed4c4aee70e99cbfbbf624feac7cd0bf7edfd478ac1a509e4bd710bfdd2a4b1df2c8cf7ae86cd5e7f18a742c7dd2cdbeebff4c10be5e8bf8d0cafffb03548e65afdcac063c6c27d5e2e6dd6a40ce3aea32709cc999d8d8b31f1a65aacbc4daa8faaf68660e02efaddeaf9b6ac8bf9a61cade1ad10be6e552721aecfb599b8e61ff5c1f0fdb8f9de96212f5577cd1fe041762e6b7e3bb93d07a2c1ce1a8f4d333f9f62f9c9ee76052ff68efc7d4b46fa59a36dfa1cb1f871d8f0ad21f5ba9f8dcbafda38d2913837b6fcb944df83f9fcfdbeec6fa7e53d07b25ae0fe5dc64698af48c857df4038ecbc1bf3bf2a45b4da0c385c954f69c113e9b1dcfd59ce265cdf46cfef893cb3fcffaa04df3e08a80eb3c69a6d6bcaedeabe1ad9cc7d0dc5f880aff1ca1bcbcd16469efc4a9adc5b8077aa8adb1ec3a62216df650c8ae956a74f7c83bac1d871b1ada59a1d66ddd6c1e0ca8b923e4f3bc95b9eacdbe6ef9ccbeea2b3d2ffceccfa5dafb5ad37bb368d35db7d619a3380a773cc4bf5f625fad3dd0a3dd160bfbcb174aaf8b58f1dec2cf7137c55cbabf4e3c06bbbdaec3cd49dafdcd2bb9e1abcaab1dfd78fe4cdfa0feddeedaf0a27bfadf7d4d06ce7274f7f95ee50432deed16734cf0e049ed33f0ebfbfb2097bfeaa2cbfa35cb7bef55e72c3aea8aaf5f7e5c4cbcf62f5d2cf650da17784c49dffccf1d7aaab0b0616aadeca55beddcdb9eef714aa69cf6c8e3b6b5a4d4fdfc3c7dbf9ef0bf1ee8c88116255b71aeef98faaded31dded7e3db3e3ded6e0dd53d81c9658ee1d8279d2c4ff4eddcc5d94771e63fe44c45de96c2ea3393a17531bab6ef72bb9db1cdefcba1a8e62b04e62f5f3c553f3b6bb22f1ae5bffbb09b1aab3f0875efab62b3cad7c45fddebbb5b7fffdfb3e21ee2c53ca2cdc2c4baedcbbe5917e2b2d5b253bbaf5fbbf58cfde7eccd7db1ccc2dff91fc1de53aecfac87ace7cd16aed303cebbe8120cdc79071b98c1fdc0dfa7fca66124cf1be411e6f1bef8daed38ffb0b2100cc06e3351ae53b21ded32430d1c2046dfc3e4bdb1acf94f5cfc5cfa2a9c3a9bbd2fad5c8586fdae0ccbfdfbc7aafdf9c387b36ab3c1c5cd8042a6cb0e1cfa03dfeaceeaa9baae8df09c8fed13ccd1da15ee68f93c2c4acddc3efba62bf24aeed6db41920652cfb701dceee2aca659d5771e82efa9aef9bd9e31bcfc2f95dcc976c53079ec3dc481fc17b9cdedbaaacd6a5b7dd3c60964ac87560eb6a8ff2155eed39ec00e31b0d245bbf5952a31ffedc58ece4dc60ffc9cdaab8bda41b391b1c3a81badeb3db9fc437adbb8cfb2ceb8b0e2894ce369bd03aa96f8c4db11bb594aae65d6add9ad7ebab93c714ecb7eff2eb2b09d18de14f3da18bde2acbcccb95ba4cadbfb96effaae0cef013ae1897ac5ab4a94433f0be50ace8fc5c2ccd31f42b353a7b588f0befddad821250cf20acbf85effb9fe07c9fb6de77cfca68cf4ebab8b8df7adefeb0e59fb7f4afbc3f30e3af02ca5c1cec32cfdb4a5bcc30ddbb6ceecadb7ee595fbe4d3b60cad1aaaf318e440ebe44ebc83ecab729d0ddcf47ce1daf712c69d1e9afecc6d5c3538a34db0cef1ca0a51ede9e9f988dfbeb9afe63956ba6775e4ded809bdc3edafd1ddc9acfdcaf789fdbd1ded0bde966c2f34f600b3c959aaabcdb3f97ea2e94db92d87bd359e940df3a0334ecfa0dcf31d44d9cbb91fded625dcfe835e40e16aacb0b5be6fdca81dfdaad88fd8c86d09b1bc756d7e42cb50d5f390dc8005d166aa0036e3ac6cbb5a194140e7aa7792df7ef94c4db5c98ad0c2c99cf5cb43a7e7d25fba9b16a8be675bcfdbb9169fc78ddfc44cf85fc95ee21d9f0fde1bd2fd005c8dafca8401bd3847a433eefff5949f9fb4ffcef6da2fb5d3818acd70dccc4ee85dbeea9d2baf4343e412a42905449017b535a3e8eeee7c9d3fbcfa1e56cc9cffdef40eee40f33a8ea66d1abfe4addb1cd6adddb1ff8fa15ef34e05fdea2b3c4a6190d6efc3adfaf887d4e0d2fc1de7b22cd995bb63669ad2ebf32aa918a0cfd9da6b32ce9aa5f2fadec03dd02a03f3ff1c045d071ac0d1b6a2aeadddbc284ebea7f18345ffa3c2c2aecdbddac1ffcddfe788ee7af41498a631b84f1bd3fa8e9dfea5bafad439fa7eabe3b0f67f1e7f4aef2f0ec7dcaa6bffbe0b02bdac7bed83e4caeacad8e9b676bfe2bec80cea48a00b8aa599a1d1562494dea6ca2dacccdd8ae5fd55f8f4dca5ff6abec6cecf00a6cde4c26fdfac3cb3ce4bab290fffe10cf7ca6bd3dd45b07f4bceb7543fbf4ccb9a5b9a2bfe1f3dea5bfc23bf77c98caa4398e9818cbbbf2236f8142abdd682ba68e999cbc1bbfee79a5beace5b3815c0cd54b02040dfca8c99e8b6db6f98bfa6c7efcf3f6b5d5c3a722a3e3bdbfc277accd5bfa8c5873d489aedf5a3c93fe9a4c6a0c9eeead6ff3579fc422cdb55b02db715cbddbbcf5d0de6c2ac6da0f4fbb59b45e9acfeddf43edfddb03eb974e97adbed1db0cdaef657fc8e5a1abefee3f8bc670a0f8a5c790caba43529bcb7e2afdf283ab85af441fbbbd042a4eff8fb8568f75e5bbfab16de7d06d57a6b1208a1fa5a5da11ffb9f84be161ddd5ebe54e3dc0deb3b9ed1a430535188f23b65d53eda6faedb0bcdf4cfaab6adc11bec2c5c840f6323663bff0e46fca3eed7d8ac2c041cd4beb4a32678f33ecaaa21dc0d18fda5dbd2deee7bbf7dcbfe7ef5ed8e5ed2dfc6da17125d5bf6ab65a089aa63e7f9dccfddea9aad4eb31e7efdfc31a7ab6829ef1f11880c4ebbc8931bb727a6d5aaefbf65bce947c60ef37e6d50a9fbd4c93e8cee81e7a0f7ac04cd2fc0ec87cfe5cdbdaf1ef8f23c6e965d75a4528d5cdad89f1bffbbcc360da594f2c8ac3def9ae5fee9331fb3fe2983d02c9cb01e6a394fdd5e3ef5e0eef7addd3d0142bd8d3b60bc898de0cdc15bec9b794adc30f081aaeeb7e052663f793e7ade7fa024cf71ef92bfb2f8fc01dd93fbadb77ec07f2244b3dcbe095a24bdad5f10d51a99c4e246dddc2d2df8fffba34ded9f9fcf5dce0efd9cb9810c1a14e514cfbc7fadc923a601ed7ad191c76a3e9100bdcffc611bcf6adfdba9f2b591696e13a57ed7bef206a4ad8beee54fc03faa4a27b41f2d861dbb0dcff8ab9c12e762beca13874540ecb5d2767ebbeebbfeca8b32fe7aaf699b432c1792f82640bec6abdb87e3414505bc8db9708cc16fcfc19aaceae0fbcfcbe68e50a8b24b4dbff1d9dfecba7625e3445eecdade10adde3bf017ca68dd480efdaa7fbca1e7039f1e2f20ef061b02d08e5bf769e2ea23854d3a60f8074bea127d30e0ec39efcc53d1b4b10ac4d2aa4c56fe9f178fadba6b32bd79cfc6dcb482dda4bb15b3cd082bbee81b8bad4bbd4ab98ee679413d352cb221d7bd3a3e162a317b58df7e9cf5f10a1ef161fa54b9c0bb5b51efb1ca6846a000949a4f3ae0dea3badf1cacd763ffddeaf51f0bdde8ae3ce56f00b91a7d2bfc6eae142bbbedf0f4b2aade8f5e365ad29c753afa9c48e5fa6d77e6dd07aca9a922ba94fce8fb1122ffab3a744140a087b20edcab15e70599f677bb01aed9bdcc2ef10d5d2845b2a6d6c607cfe0dea4fefe1d3f96a280d2d4fcdc5d61bb5a7eb7f6dfa278bcddefba3c6f5a69738a0027b814bd84aee015a32fbdf5e267d62bfa31b809ae68fadd37dbf3bed6ddf71e999829bcf1fc7aeadad738c7ec02fefdd28f407c8cd498ed04d2bb1c5dbf18aefeae10da51be91afb7eda5f27eb7dedfbc32d70cb289ea0fbc8a4c2d26b8c0aa75ce355b26b6d7e3a2decf098ead7ec2ceae22c0ffea7b9a5a4246861d9e9ab1d9cfc9be31da595e7e0a1e5ccaaa574bbf3b5bff825264f18cc5bbeab317d6c6ac440efec6b80e8c74dc3a618bbc59bff1ea49a586afbec0fb6d9a0be61e72aabd4cbf3cea4c38ff7bbbbe7deaddcf28ec11a6a67efa823daf1bfd4ec9b4fc01e7a5ae58eefeba21c7c9ffc2eb675551cb6bb68d7fc9eef420b4e49dfaf4f6e714199751ccfb8218d169edc543c576a77ae8dbfbbb63a2cc7dc5cc95a1eae72f6ef2e42a8cc9a9f520ab8942ebde57b8cbc4285d5905e6adefb0bb3febd75003e0d584ee19b1121c1defbe2cacdcaefc78b0c6f35bda70cc31c24ebffdcbc1b6d68334ba02112b6dda8d226a565b45ae7cf6af45f8db31aa5ea3fbba699aabe9dbd1f2eb2bdded9f9d0d3cdffb92bbb5e42a80ddecc50c61ddfe80e670ea81bcef5cb87bceb3bf52cc064d0dacb565dbf26c2485abbbbda9baba4afb8de6efb5afdedce2e5bdb7d8be2076ed715fb485da8c0be420ebbf67f17bc2fb0caa23ad71ccfcbbee6ce8d2fa5eb1a86fa92edfb2c3636ce73b81a3326c1769b4ff5aea47efcd7fa2fbf8ecd0e15ae1dabd9873f7a2db18c44a780cb53bb811c5cf216f1b7a05ddc994c4bc4db7beebca6f0eaeaffeda50fadd047999e52df0b31d0fd6c7eee8fa653eef6bf8bcc27f7e6d1feec56bfc2b128bbf1cffced0a223ddc6acd3d8cbc1ee99cac922a8bcdaa72a51f4affcae18f7aaa7edfb41aae04f8daec40df6c5c2fbaa5ed5ae0ad8cb5ff015d985584a75ef6cabdb29385d6edfd96fdc6e9179454cf24beb4a2a0b063ccdcdeb4d2a9754ff8af7e5ea5a5f700dfacdcaab38ea48f4ddb94c3e929345a00c1caa76ceab040abc12e2e1c4ae905112959017fa07314f7bfc426452b2cab7d7e54d23acdcdeca564d6cf1b5effc4322be3b86bf05353facc5e040ac3cc5a911d606bcbccdce9feda748914eaece8cd0ba3a8df8bc36b81ab9cfd42aadd2394fcd6e62f9e75df50aaed2a1ddfb33b4dce982fadee1ade37a02fee36e8d19f7fdce7daddd4793fac5030c4d4a7abfcd0baaefadedea5a9e8dba95a8af26f3b693dae6c9caac0ba8bee62db4afef41b6bfd4a18cffffb94173bead55bfd84dacd2de2b0f15cbf3386bd6dfcd5da0cadab0befd278f4c39de66331e18c6daea1d3af5fca73ddfc7c642acea0433ebdf1c932e3e6db9da22866ee2dface2b0ffdcc7ce94accb413fdbf4206fe4d2c8d77af8b422bda45c46bcf2c3dfbd5ad20ef2abdc68dcd88e152ef884a32191ef5bca6de79ff8cd3a79c325ddbaabb561e8be555d6bbbf630982e9dedcfe84ffb5bf4d01a640baaba337a63ef7165b25e0bfb994ce8c7ddef6fceccc10adaebf73f3eeb9ea4173a696dad2c67e747ab2c9ca2573a41fb9a16c3cecffbb4913c3edb0daf71afa4becc53dfaef9fa1f2ecdb0b3fee46e34867f9a9c3fd7e9eea483a5bcdd7c401e8a2f0b35fc50e6afb6b84c5bb2dc0abff08aaad5efb9eb75e2b10f55e4a40c3d095bf19d89f4bf1808540aa833bff076667e445c0ec3de103bd156ca03cc1f02eac53c5a72aeb3b02e19b29c43ccbf8633a498bfbb80d61441ad92db9449d9b7114dacfdf3a46adadf19fabff8bc2a04b10cfbe14341ccb34c2c635ceb6dd2fabb5c6a0ebafc21f43fc5efdfe7665e157d29df6dccbba3dae73cfae01cc15d6945dfe5b18cc0a3a3bdccf30d7cda7e8c8c7cc66dab3931f35eccdcd7143b6182141c39ec45bb5d7f3ac0f7d88de7b1e6b37fab0a32bd4a456fe2c68fd0b113aaae5a08bdfaec4af9ec4be6d92a1463b4c4a44a4cd81d9e40d9a6ab5dddfdb4ef09c65a9cd67dbbf5c3ecceebff7e8a072fcfcac4d17cd256acc5bee307e5b69c88ed7fb7a6abb3dcedb67cd803b166ecd988fa67a9d1a0fd14e2fcae21324eeabcc8d9d4d03e8694e772e0b392bc66cc90dbc99416af0bf42ba50f6dfbacee8ebff5dcb7e118e8979b2e7e7cddcd4f64000d9ea8ff5a151f3b0d21ee970dc96e5fe8eae7eb181fbe3c8ece6deb3cbd3b3cf09cf12adaff2e22cbf2fce0bfdc99d25bff10ff21dab766d720c37edc8fa9bf6832fa790aacc85e3ebebf0eb8f00e14c2c35fed724fbb08ca6a05f8bb5c19684a90dab22f0cde34a4d0b7cc9cb4aa1f8bafea768ca4dbfafa7486ebca3bdfab46fd9cf13ad63c485e146b5fe2dfb84447ddefafb4cc4b2ae4bb5c995bed31cf0fd2dbeb3bea8f29629b3a71b10e8b428ce72ba642e1dbdc69c4b4ed02cd4d0fc7b72d4ece6c2ec8d8bf8ec7d65edd4573ac3aa6ee92dd166a1f4d5ebfdc4ecf915ecec2142ccfee4687d4b62acdc0d7c12fce1cf541c5fdebee2deecf3dfbd2bd231dead714cbe5df062523cd7abac3cceffbed5c14abfddc49d7fa9ec7b8fda9a63dfaef9dc137f0fa36958e286f5ca8f9ffe8304bfc3b71c06f704fd0ef59f863a5b4d01282a1cef7b0824dfd39c92379afe0acd9c7b9c5ed79cbf9b13ec78f5f7e86ba8e672cac6a0d70e3d5f9fcdddede59feddbecbdc64af3151dbb9bf6be15cdabda4deca957ba9afbe6ba68abbb2ff878fb8e30f10463c141f7baf253edceede72fc8b5b9f1d2ddb6eceb445ec0c013ab5c8c8af4bbe1d5422d0f7169a5d3aebe7a7380ea0d2d87decffdda94ef2b3346fdc718ba7214e0d3aadfc1b5f9a7b6023563d3fcecd01cf8fe52d867ff23dd6ee4ca72da3dfd1c1db01bf7766e3fae910c26d7ab4d32e4427d7b441cccafb4e1c8f70ce3286604caddebdadbbc3c99537e9df4ddb590c87b3c297f8deaa50ff5cebbffdcb28ad8dba6e7ec1a72b2a14bdbdec5da79af90e8befa72be518cffe2fcdf873e8e8ae1aafae8dab4854dca8210fce4f3c6b0ef86d8b5cbf2c584d7f9175c848eb157cd6e2bc64c62ebaa13ca1aa050027dc0abdb9f4c3e6a2d22c4bedda10e3d67bb0bffc9b8dfbf7ff4e0bbbdfabd00d7bfbeaafdce2b1087d2ac5221fd9b8da5f2c68884348daacafffc2a4075bcdbbcdebaab265befdceddfa8b27c43b49e12dfc786ef5eabc8abafa0c8dedaf9d60fdeaac7d8f0bbefadab673d5dcdaa2d0a735c5e3d69b3eb7ac2a3a70f441bce0d86bfdcac7db8df15aa5e5a5aae7fadbfaf7cf41a1aae6dbe2a26d73b570d60c51ba2befafe8bbaac0accd25f280ecedca06a2eea1b1ec1dd7975ccb516b91e3b68734badecd73daabbdfbbdfbceef85cbf0b58495c24fdfff81bfe880364fd841fe23dc8c1fafafd2dec2df68eae29acb9cee67daece5ed8f850d6ccc2ba0ae49df72df48d6d8caed6cd390df464be7c33ef2df7d7cfaa9d5f6a133f2ecef8afdbcaee34b1abcdbeda7f1dcfdb7af1dfdb4b9cecd7fc6c1bbd41604aa34302bb4b78ba3f170e6e510a01ae6f29edcd23065ebc13baec0efca3b65a4c32aa0d1ab6f0e0547cebedfd11897b5dda4edceb541db087141eb8c9d9dc2aa6facdd6ecb6c5df1be3bddbd429e2dddabdacc6495e63b3c4bed6c36bfc75f49fcdf44c9ddae0b1aecbe6ffebd0ed426d2bae3275bdbfee9a108efbe7eeccdd311daa3c685aafe9bc3cbe639de8cbc4dbff8780d1556677bbfedcc1a3d46629229fcaaa4bedba016eafaa4f91dcbe06e4129e0ca71e073d2aa9c3a6abc0ebb0ea40cc2c881ff8bafb6c161e21b7cfacc8bf5bdf6dffa2e0daa8eded8bccfce47dffddf39f99bd2d94cf5f1d6faf6a9d1cb654ba55d4bfdbbfdf56bde5ca9f19ab3c50e5dfd5edfe7ab1cdfa33b8c0dc4fd5b65e21d85e07d52eceb2747b11c21a64b5ce3cfabde9af4555e2a7c79c1538b31d2ed367a7c21fb7d27dcfbfc263c51f362e62fbb834de1d4e67c25116b4d39ea7bceadb95aad1c7c57adcf0aa6b3c5f1c8a0f4d9fa4fdf36ca894caccd3a2dacec7fc5b5961399c0bddecfbde4156aaf3b1c9f6a0c11affbbabdcfe1a93ed22aaa7cdbdfee4efbae7e8ad03cbcd7e0f7da8cbaebe4faa1abcfb029d82c0ab61daa5dce3930314ddeb31f58cf2bdf6c99afd6d89612bdf5aee4f9617b8ce7ec0fd08b42eca1dde36c4ebcd6295eddfdd81e9ac66eaaf5ef12d4c045a3a2873fcf946e9fb2bb45e30d4fb82efd97bf7d51ff8429d5445cf90e29c50ac4b2e7f0d960f8c9af23f7b61c3d3633e2e1dd8ab8a8aea7abbacbbe4b1dadaf9a0fea14ab9fde0dede3a07a28eafb9c0cbcbafada46bcdcc240aeb52dcca0ff98f6bcaa24ebca0e7208dfaeffcff4edbbe4a2dcd7184ba46c0ab0ab51ffc99fdf76d77b41fcdd7cff924b6d79fa6c315af7fe63dec5f0a1fa185323f1ba0c8ad523c0d34ddffeb1eee219a5e5caf05c9c4eabbda77aa3c8dd8aabdc7ebb4ebc7bdbf6dcab6294ccf9eb115afaa2ccca2c5fcdac4f1eef0aebcbfad427b9ebc26cba6ac91c449f3f106e0d55b088bffcaac5a6a2d9a3f9beec0d83db49beef02efadd8cb9df4bec8d14bba9fbfb89d85f43a2c1ebb100dfa97ef9fc3e3fe0dea5d5db1e79fdd4604dd0dc492a2509becc1d0cad7fb4c01daeb00f2d8518cf4ba23dfec5dc0defc0aec571decc9ede6bba5c3e36eb5a121a8faae6f21f6d41c49b4fabe806a5d174bf892f948ffaa35ede467c0eafacc9c884e165bd728e315b5cada2b20246bcec5de4a25ccfb17bddfbe2a3addd8ae34b6227f0f997de42fda5f5445fd4b2198aafc7b5b3681b80f3dbdbdcbe4b3f461e5f6a6838718acd4f3a5aefb5e0abdc2f2dba5eea97f5a702c4607fadd72befe75a1442bbba7dbdba5648ae5857b1bcfb243691be0d5a571cbb820f56ebbd0b87ee853c3e7b18a29c69b512abcef8acdc14d3fccc7bcc6ad7cbb2ef76d5fd8f6f031137868d9b25a41c535dd7bb83f84070ea6affbc0d9fbacee00402f0cbb0be18a5eaf76ee3baeccbbd7ecb1fd4a5d7cdca7eaa08901d955aaea26a5a7da9fd8deb5a3c7bebcb4b226a47f7efea4e15bacbbcb7ade0c9d4567b1ccf7fafbc11af4faef8db7a77e85a4be5e9bbfcde372decebd21ce0acd315ce0e3fe20cf2e54bdd407ec6c10983add9e38ea1cfb4d75fba90fdcfe5d6afcd1a568e9824a77a2830c3d87caca5aff818a36babde22adc38aedee0dda1b9e3bd253bcfdea08df97a7e03edd757ec0d2cbfaea01cbbe2da4d309df375ebab827e0bc2cab2e99b0d2d5b23afa8ad64ff19bcec32e36fcd66aaabba8980dab9cb1fe2943af57edab5f46affcb06cdb9ffd5a67e6feffb347dae9fdbd9f2b6a1001ea881fbabbff71a488fd4c4ced8f897bf08bff27c5c1adb7de6abeac1583bbeba7c02398abcccdd9b75cbadfc6565aeb0b580aed618ee896eacc7b1078a990dad5be017db207fc55bf31ae77edae07dcaadddc83aa746bae6d1ca4aff9effefc1ace18dc0ced2c6b3b3ec6ef85aed960d299df79ac97e1c3c3d3626c0b6fab33afeddfae21a6cd5ecbaa56c769d44f3d6b041a24a2af93e60d9d2270d848aeb4d1efa3b6fea42f5ba5e75cf27d993b490ae2cfcd65f0421b32d1db7ae5b99ccbc9eec9acaeec2e29f4171f844ecdedc9538eac0d65bfedd2bc3b3b9a4541b3e01f2af8f2266a004dc29ebdadffb9c866d5aa323cbbc7d6dbcceeca0dfd5e09dd5d82c88d5a09da5e8314bb79aadaf0e7b488abcdfbbdaa0b71de7c19d30215b6ddc4fbc0fb95fec129b04ae253a6bf5abc7df4b8d49ced8fcb19005a6deda1dfffd1f258a7f4ed16ebf27dd10dd83acafbd4e6f957e41cfbfe72aa417ab5f2cfeec61efc6c6cee9f6efb3ab79ca5dad5d8e48ffb9833f6d3166f2bf6bfefcd5addb7b4e1c60e9794ef7daa3fedaaba47b2c9ebd6ad67c2d6aa53752dcfda2c16a8ef28eda23c72c544fc1e4e7bad52a40a99fc7de0133af83959e360978ca5a41cec5c98a2f9bccd141daa8ccf682bcfc7366d2ab1ed9bbdac6a3811f3dcd4f43ccd273a278414131ed7b00fa7462eadb7ae3ba627a461daed8c8d49a4ff48adeff89ff6cbbddbe6883cddaf30414ca7fb7aaddf709dd6f667d7de02ccddebb5ebb14e3b7ed464e7bd6b01cf4bcddb694e2c725cd7fefacacf6e6cdb8efcfeabb5d4799f7277ef703c3d907c9eab3b0eec8ddf7cc264e583fb37ef4dace9734bfa7ef12cc51c53d238f0f1acfa8b4fcc90909ca43ae38f0f3c7daf3b58bc1cdb1f5abeb120dbecd90ce490c27bfab1220523bcc81f2a2ba3b7958d0fefc9af36faaa951873fbd0d487286d671a81974dbdcbddb8e8cc2fcc4c154f8f79ae2a9bc1ded7decdcacf89ea91bf6cddddcbeb6f174dceb4eb4df220aac298abf404d6be942ee7bbbf09ae21cbb34db23abaac228a895d072cece483ccf50f362eaf1f7488b0aca5dd0c5df5d5f0cdccb1db8ebeb84babd9b6d7133357cbf6a4b1f0cb89d02fe4172bd5755edaa03ff57af41ebe22f64c3bc2ddd935019eae27110c5e417bdd354c9d5daec2a29b04483f3fff36dc3c221f5d13e04f3fcadcffcefdadadcacada8abb93a63b6f5d328085f54c6bb4da6f5ceef3dea642adcb57efcfefafc3eed9d2babaa97c8acd80b083bcba6b0cbb2b0bbc6ffba2bde9dd60f533dbeabdeea16caf3a60f59fb5c0f068cf37e2d615713ae16a773e49a6d606cb2ae48d95bce6d16bb8cfe43e4286fb54cf6ed9fbd08a4a2b4119852daca099bebd99859e64bbdebb983c5bdbce07be5c996cfedfb688d24f1a25db333d1ff5e690ccbb0ad45a2ff26ffbbbe53dede918b220b4e3ef0adaad3c9aff04962dab1fbaf476c1b1c60b2eb7edd3c99fbebecb8fcac676a5350b9ebbafed40a4ebbd756bb99218a8b2dfbdcd55e6a71af128d8a2a443cee49e89defc60b1e8b8cb7a1acbf07ca3bcaca83dddf8f283eee9efc33db8c0da57d2bea6dc1d88ce03fc6fe4eeebcc7ab345e16c0115be0f8c3eabe598aafecbcfb71ef6032f509cda93edfb227ebfabef287cfb0c8239bca08dbd5d26cf65fe8380856538a1efbcbfd76e5fc6f8bd23bba43a8f6dd0cd408c9ec0820f9bbed2bc3b2640fabc51f3ce1dfc3bb6b3eefea5a5c5dbbccdb4d50fe2fb4febd2a15cdbcd0ae0edae6748bc9dd9e7883fd84eedcf4ccbf4ca6cba4af1a53b499bedbf8a32beddf1f48657c7674078b1b75b1dbf3af2e4aebbb5c24cfccd7cd651d84a5ab3a4c7bfbf206fe3bccad471e051eaf97aaf7dd7937f4089e3a72397ec4cf6ac32ea229b72ca4e761aec6dee10aecee7e3eea7a491aecfb2f89ebb2a2d2943a6ef10cef62dad58bdd48a27281abaeec15dbf4168cd481e0cbfd43cb45a8abf3965eee1986ada7e4ecd778ee000b3bdb02a2ef91ca5f455724aeac4dab4614e4aebdb5371effa4a285406d04c53db5f6faf1e0b7d7cb7becefbdcccdc09e2ddaccd34ed339fc0811a7572af47baeead5d47edbacecdf78d3cef99cd313cfaebd6b5b414dfbce6d4c3fbc5e95e508fff0fb5ac48c88eefac7aacd437d55bf975ca832fc50c1dbce7d7991f2eeb56c93a5ad7cebf94bad669730e084d1cbccbb47abea27b3dbc9d766aeee0f02682bd4c45b12a6f152e4ad04aba9b0a1bfd0cfd3d31fc7a684fcdfa48d341bf6dd8e3ac93e8737e77dbac6cbebeab1b8976f8ff4d2c22e692a7affcc730b706b69eacc0cdaa5efa76b3ae54ef8e24b988067abaecdc78882f6ca32f0bc1746abbd6c79f0e2dbcf7a9863f16a6bdb17c5fb85531744b36c6c6930d71a15ede1a2134a82c2e4f2fcf6aafb9c7dbcb768f3405a6c9eeffea9169cb6281c6fd52edb5a8bac8ae4839d8c7a09f2cecb7cbcc7fe37d1166acdbeafdddbdbaa1cdda9ce1c17e07fcda58bd9a8dfa87bf0ee8603e48fc5aeb0de0bdc872deedf7e50a14e1d99fb8a8e5e169ad17fccf34fdd4f44eb3e40ca3f96ceda4dc9dbcb423c1cb66b6f34f5bc029cbb9701999e81d9cf7d8fe34acefcaeb2ec92fd66ff2fb3873a48dbadf85dbcb5adf2a6edb904b3afebd67a2f63f33c2b5a998fa008fa8c8ccd64aeaf327dfe5cf5d8b5ec31c4c034c338016059f845d6333e4d2a71a12fea197baabdd3fbdc20c4cc8aa4e5d62ddeed1d46ffdbfd1a97f6ff56313cde61ce5e85738ddaa8fe4c26aabd8aaefd2cf26fccae9a7d5a4bbfee2fbecc87976425ce951af12ce4f8dcaa7ef4eb3ea040dfee294c52c1b5b57ed3813ea86aaf7cc8f4c2ef8f60c779ef949debdd2dbeec56aae2fa13be0e3a7a33ffe3bcbcbe67b01ca458ceeccd56e7849d8d44d2bff7daeedaead5ccde2d64985c2fb35a24af05fab1cb9c4e03ccd34c5bf6fb2f9df839e9baeac79c9cfef56d7bdbc4fb5eaca9eb9154e3ecf2dd6ef9b43c26f1f9b781af0c13a9fb996c949cc0e4acdf79dccc3a876daafb30892661354df158bbacff3b6fd2a3df0ec7357ae8d0332fabe39cecfd66733deadea0ad86e73fbaee9163f67edf75caeede1f8134bd2e456f8249a4d3efe5fcda62ee76afadb00ec5a6e9ea7ac5fef9e99fd8ccb4df88c8bb6a85c1cac6ef9acb9447eb6c9d9c3be438df3c4f87be93fc2efb67acbc9c3f16c7d8f84aff2c38a36b8c7f0efdb79f9a2af2230acfaaca9ef71ededf0ac53377f39f7b3102e11d928baaaabf513d2eff17db89b742bdcccbebda1a1f579abe45bf472ffaacbf25e6a6a0f0b98feafcfd39cba91a5de473b0ba6beb45c73ea59acba52ceed25dd68a0c64823ebed4b40edfe852baef23ffae21ea7b3c8d542cd7ed15e11fec1a1d9d2d6cfcbec8a625b1e5f1b4ebd6bf3e2e84bec9b78bef1bd7b8a0cacec4d852b2ccfa722ffdebbce9bc85ad68ae78ec0291ea2cbfdb9baafdd7fb54f9d4d03b12cedbedeec5c4a07baad005bbaa3ab575a1aff6a3ee5edecfea80fa522d31f23af24b6e4ebbff68d2c4f5e77e7e7dc4df1455fb0c05abe9eaf1edabe74e4ec84bf0f7861300f39bf9f8ab2b30d28e8fffd620aae06f9f2aba445ae8fb267bfed56ce97c5d83eac2a9c0d6cefafb53c45e82ecbb5f982038c05ff0f96f5ba31d9f4bb7e5fe8fe4a1bd8ddf194ad6dd1ef0121cd74eb6e8e3ed1e0d6ccccdb7043d1f505f7592f2aba19632aeb45bceedbdc74a8f5bda1de5dbfaf654b430deec051c0bdbc1dc0af74cd097fcab1e3dbfee671c274fd953afeb0aab63f5e53a3d5024ed814401cca6feda5ec1c3616cda9aacfd84d2ee1f54f240dc77b73194250648d08cb566cdaaa203aa75d2bffce43e5a70dc9e25ddf1a782714ecfbf2464c3ef63a71ddd4edacaf41d77ab6ea5ef98de5cfd5e52ffb0edc518d6cbbdb43076cf42ff4aadeebefd8d930709d21e2c26b2feb6fb5d908384ee5bcbfd34fcefed6a4571f90df1a1fd2cdf97db272378242f9f3205b7a2338a38a0cfeee8f26cb52a626b5c4c804b2bf50cbcecab1f916bad72372bbfefb9ee03fbefbaca4af83eec7b5ecca6e6ad55de7ab9a11edf5b8cad82781c0facbecad6f499c3ddfdd70002ea0d7cd8c561dcdcdf64d96750f92b7cc25df31d400ee4398831fbe536d4aeddccafce9ffdc9e4ba6ac7eabe439ebb64a45dfa09510041c86817bddebd48d6c5254fcbe0dfc893f53cf35a3bdb060d7a27c6dae1bbbf0bc8e7ddccc0bbe60be1fed361ca21e5e1df9cea1dc3ddeb4bad6fcadfccb77d8bf4ab6dfb7acaa8a1ecb1abec92ec7fe1afe86538be49db1e9ecadadd5d1eec5aa98513ce2f00b24213b39ce0a4dda27ef91b5ef630fa705fa2efbbeaca1670c26eeab1ec4149006a9f49a63e7da5aadd769dda7fe01d4ef62c78bef2aeabed234e5fa7f4deefe4a24b35a1cb6541ebad95efff3ecca7f49abb8fc9a9eacccac28c2f9ddd88aeeb8216d735afa8cf9ea1aed5c8cfeea4d5e79027eadcc963caa6c4abda89b11dea2224c6b34e7fb6e4ecfed67fbb75f06fb8c2e09eb2eccc716a526e1d63abe96effa4da10c0da6b2bdbb40826aa55149f625275b4dccfc8a9ff7ceaffb3ffde02bb663d32bf362c33cd94a6a1da977c8007adfab72fcdad7ec5c3aaeb5ef0fd5006fa831298d8df7cf1ffb620c98f38ca4d91c1e10c8f0ec6f7fc67e338acefacd9ddca8aafecc7aac05d4beed6fb35ef7bfdbe127795ddd78cd2a38c8d165bdfadb434c3cd4e0da4b24d2b8edca0d2cccc5f5c9ac081b4f0e06bb4bbcaf4c1c784c8e00b3a47dbc4ace4bd8c014ff402084a84cf94a1ec64feea15ebe8224a206eb3e2b7d2b4f72b069cda5fee46ddcf5013cc4a6e3f6addd8493533dae9cf3b97ba8ef8a58bdd599836bc7cdad0d3c1f3538022f43f3fc3dcacce045ebb5dabbbe8993acdd10409eb9fe3cd0c17729b77f8ecfa01dbdddf9bf18e827975a2aeeb09cb3eac2bce3d8a50ec6667a6688bf7aa0a52d3f32cf9f89d77bd414e7aa456fd90029a06b717d0b20eafd322bdbbef27af7d6722e9d20ce8c88eaa09c6eed3e17c769e7a9f05db1751e2cf03d37ddd3c8a6f8e752b527e64b73d432d39e18ca450ed53def9b8045be8d06a3be7af1dda36b1f8882a72b677fd29ae546bd2f98eafe26eb0a9f9072fd225d82b390f01e990a9f3f3de86c32bd7ad2dc16dc51eaa8dd3ede7390ec1691979bfbbfb530f8daaedaccdf003d753a8fb276dbcbef60baeebaf33db10a95fa61a7aa3eaafb86f5efbe1a417b45c405f55f25fcd48f6cfd1a0b3bbbaf43ac783d04838ef74ebd68c60fcd6cdcda7d9bf2b8bda835f88b96fffd8fdf5ffbf47bbc9a558a0af0d8a3d2320c2238e4d7dff4b00b39bf6d65ecb1dc5b295e5102ab1c75c1ce1edd3baeefc69c714be13645a5a6a4b43ec8df4a3bbdae57a2bae70d6c294cf4968e3bf74e59cf47af3e38b6f4ad5f83f9c3fd7adeee71def8c523e83de1aeee58d64ed11eef8aac1ed22dfffe369768de12bd3dc1baeadbf09dde7769e8d3d63a0fcc9b1aa5e47d0bccaab6d9e3ba68dabbc8cd1d4ddad0db6aec53d30f80d968e9b6deab4e9f4a3c1dff6c7aec62799cab772f993f2b9bc51da0adb07f5f330bddc470dfbfc021f6ec6e0a7b13cab9ad35c0ea29f6e05ae0adf2eafc1ffde233543cfcbd2c1f2db37df7acbdd5a3dfab13c0d251ebba5efc53b4893f4e53af4bd41d2340bccdffc0dd63bd5c2d1595314acd0a5dced8bc0b654dbdcea6e61d158daaa22bc3ea8ae3b547baba53e59dbd7c9f7e04a548da55322acb27cd584bcacafbebbb0609fbe5c7af5bfc0c1cdd33fdbefccc1aa6f453a6f56312c378eeac8adede3ce86cdaf440162abcba864cbfc27f5be07f5dbd50d4175eb1819783fbc231cb9f3ae1209bcef0c136fe21ed294a8495025f1c24f78dac55be00d1494dcc6d5dfeebf7f1ffbc2276dad3f8042cae73eba1e5cb135a06efff2a15a500456b36e190ce84a9daafdab570f9966dfbd0d6ee6fd5cc3e34cbeff5a81d000acce6f1bef0f0043c4ba7b55cbd972cab76698afd9b2edc0beacc42286fcdbfca90dfd6f693987d185efbea5bf860af4c4e95cdd97caba0ae7f699eea37f1f26f624feea96dc06fd8a1f6eef22f5c4d22d190be41ad03e8c049f74a042a1f452bdbafc1dbea9cc8bdcc2badd40d1c0f16daac3c2dc1cdec7e16fcae83adafdce8c6243ca5cb1d4d7da5cadf5d3741fcc032e824ddaa27bd23ee29506a24aabef432df5a4acfdb06a6038bd8501e427eaf2c87a7740a2fc7d9135f7ed171fbaad657c2d77dc5afbfc0a7acc37e575cb76aefa28abbf39c29cecea6bf1dddf0c4ee1bd7e503a3feb5233ea2cdbe05dbf1a7c1a29dfbe1b438bfddfa94b096a7a662d081cab540fc891d93b1cb8a09a0c3c2e7f8992fcc51adb20daf426956c6c8dc1774c96f80abe66eed32670ef0cc6e3cfd51eddbe49f14d8ac14ea4edc2dcb8ccea7beba8a88a76e53f65bddb282f54fad3f7a4badfe4c7865cf38de88760c0073f67c0ec4fe59f9ff4faf21a1facd4a6d2edfaa4e327185c17b0d97ebbb82ffa9818a83d0a438ec2d0edecd69134ea72ec73fab37a53acde2e8bbd0ceb7c5846d1ab4a139e2ff2f7de6e2c9c0b8e4daebfbcadf5e3bb6bb409adb5bdc5d966b4fea4fbfdcb71b5e02ac91fdc04cfebc396b5215fcaff2f3c8d651fe57df49cbdb0d979becf6b7c89693afc5c3ccefab36bd84d49c2e5aaf2cc9e75ded9e4da385c7afcacb728acafc26d6dbb2dcee18e626075fc2812aaa769d4fcfdeb3b74b28bfcc8ae3ec78cdac34f1fd80feacfbd858fbd6b6febeca51dffc36068fd47dea1c9f901ea2b5a0fff0ecfbcb25c0607c2b5d50550272d3ee6ae18b371eedeebddf2eab4221448edfa9a9c7c4ceaf732d1f7934051b59f3d2dca6e2a5a8151fde5f1c9bcc9ac585f7acefa9fc2dd9dd90eed1b092924d7882a1ca5fdeb0cf1cc0fd2b7aeeda4d6afe5dbd0782aed3d7bcdd7ba2e1f51b38befdae6dc76aacd3af6cd39c3fd920d7f950edf7aef3e4ea6fafbde4d8a1f88ff548d5e4fbefacbf95cc1f5ccbbde5e078da8c34f1ed9edad81f0da531adfc32444efc5bfb5e4ebadcfde2e2daaccf3ecd2deef5b0ee4dde15322c65bc52dca98c9c2a97f3c5dfd6da4cdb17b2b38b4b820e09e625ad03b0ca6fd85fdafdf1957afa16342fca26babac284c7c2ec0195b18fd594bc3d2ccdcaedbe5018ac3c9c434c81d853378add180caa7de953abf6efccfbbdbeaa0efccb996d9838c62a8d6e0eef98a538ffd295dfdeac71448f8ad5a7008325da56f2fc9dfcd9fd823eacc8fb1d00bb57df1b3bac10fe51c4be8df2fb5dee6b4f80be4ccc0bf17ad4aecf488d6d2dae0fd2e0aafff243fc717d0ab094aa1d620dd157acdbcacfdbc15f1c419cda295d94aeeed0f4adabe9e8532bac6b799f87dbfc1f7624b5bd74aa272f5efc2b395cdd187a5b36ceec1984cb16a2db4a7abfbb0c5afaa3ce4acabcf78afbfc9beab74faa4affbed6b74db11766a09dc2d33ad43a1d0f65b9ff0abeb86aa9e741b84abeabaf1badde5a077d9dd9502a39bde08bfea3b7f15f6def14482fdeb56eac528ab1ae866cbb1c0bb3d6f4bc9dad0f89faa3116d393ee9ffffbcadcb4dda200e599581c3c9b8e0f3275c3e7b9bca98abb0fa456d8e0dea8fa8f669a0901f1f50dda0356cbafbfee84486ddd4decf2bd54a7c4aa005db8dae6a6b8aab47dae598cab66cb2a9fa1ed6ba55fe345cac5f9a98abc6e4ae87559cd4c43f7f2edefcd88b0332ff7ec603e7986cdeacd28c95d1dad17d21b40e308ac4c550f353b3bb2d8ad84c4ee42975bfbcdad1dce5c5b28cbef3aff1e9bafce50cfeb76ffdc6d893fbec9c5f1fff7ea91fdf1bf1e7e20915c8eef2abfcdaae47c02aeb8f09aa5d63ea0dcf7cefd8c2d1bb63bfb1e9bea418ebe7ea0b5ac59a8ee23ef8adc49fe2a5439ec5efbdc28bd84be7e2d8b4cfb3e58839cc0aeb9b3409ae77f301a124472bfd6bcfd3eeecf8c9fc780ddd0d55efe35de4a04fb17d5d450cb24bd6106b75843fcc8573c3fdbea87dd7cc7b58eefa02aff1fc1bcdc957ac78ff31db760e1b040bad79c38b6fc07c9638beffc06f0bfbcce91737f0c9c6fd58bbfbdeaee9822d3bf65dfdeb7c6e5fca914b6cce008dbce2e6e2bd77aefdc0a3aecfaa28c4eb3afb3fb8aadd5699b7002a7265ef94c4bc7c76de3ba2aa0fddd9b87d9faa3e00a1e3ffefe8e819c88c1a36693c2f1cb4fe9a60a6cdc416cd62f7d3ab2b93735e6750eddfaf4bcafeecba7ace4f82c49e6fd2dd9b60fcfbf13fad7ac4c1bd4ed855add69444f664b58b16de6b3702a1fb54ae1e8c996cd739af71fb7c0f97d2452dabfd0faf1deb7ae1477041d8815957ae0a432b4ce0ec9acf0cdd5fec9c52b30adb4acbde4f8d6ce7aad2bab4c804c60aab1bcf8f7219eb3f2c5a247a81f9de26c8d6dbacf26bfbe74ac4b36cfe83849eab505efcca64a473c4dc5bfa5f35af295b2ca1fe39fcddc2e8d802b2eaee3539cfa15e1ee35c8cdef88bca55486762e2defcb1d8faa5e4142ec02f7c73dbfd484e7f3ae84fab4f4e2cdf0117d521cc65ffb2a3a61913be481ccccbd5d14283cab2e0c84e52e10836e61ccccfcacb384bef09fcc8ef80e80a84f0bfddeab14e1d6fd2e068b49bfd85eb663a5fbdada4cc54f77c1dffdfac3dfb69a21aa3c528ddf50e3ac34a7bcdc4aab0d1af5f35d22bf9ffb4a6cf38ae4a8d3bfc2d8ef5f43ac2f0beb46f5f89fb1aa7c0e1eb25c63df7ee04ca27d0fcc3ac6ebfba38becfbb3477fbd3d9fcc005ebfb5ea232caf1108a6591507fda282c407e5f04e5db6e0aca68d3fcdf8bf87cd1139f0bd30ab8a684b7a1ee37ba7e2de9ee5af328f0afb547aab1fdfbfef2fbf5bf7b5bd9d734e642dc4a784ab8af0a58b1e39323ae571a9f10baa6ab53054df3dde6def8f3bfad61ddd5ee3608137d7a6fadc64db0d8c67dccd099ad1e7c94acc895a096f37ec80dc64b19f0ab2b60cf4ec76fc941dd4deaf4f5f6d9adcfcecedc5aa46be759fc0aa4abdbaeb8a0b1b4c88f2b5ccd64cb19ffacf50dafcd4d4b3f60deaf4d1e7918df14ef6afa2b0fcc37d9c34c8fd0a0f81df320599dbd974dabfc1d217eabfb0dde14a9b8ddacf946dad46d2b12ebba7dfcbd8d2eb5abbd9d6ebd7110dbee0ea4a2c1d9ea194e96fc207abfe4f15cece67d4e3edb30200d0ee4b8f310daa2296aab0acbfab2f900298ea19390f7c2c30aa492e4e34db6cf7b4eeca02142eb3696ecad2dcdfb35107ba39d0caa2728bfa6656d3cb3edc8e5f6944c99edf8a0fd2daf08ba3edb0aad070dfac84e0adbb00ed375bc6f16d3ff173e71bab66af5020ddeb003e1f859070dca9d7cee57c63aebf68f7c3a3d3c82d3ceea5db3e6fb96e5ece2ecd05accac105aa88850f59ddd978ea3c8cd7e21dd2a09ff5bbdce8dca9db1bfb1dfc77bb1bce521dfebf91a9ffab91cc3daadf5237b49febc1ff6e4e316fbfceee9d4be9aaeef8f6a276bd73117df1c0aa0620d5d8d98be5dae10c8aaec72a8edfddada8ed75a5aa9ad55b4a29e9e0fdc7bcfa5ab026bb96a55aba4ed76d8aca87cac981fee42bbdfca8a3a5b9e7efbfcc00297c05dddcffcd19dffde6eaab9a3f2d2f8ccfd63345be1e792d3caaa68b6aae644cfb29d5e2b3e16bf3fa7d1bcb0f7a4da1ddf4a8db8594b9dda9bbbbc4abbdcdef8d7bfa37fe28d6aed917f1764d96b3e02a64ac6722fbebffce58ed7682c434fbff6adec73e4921d0aa67bb2e7b4afaff4fcec7facce5b638d0e647e25dff09ba0ed9f4edef4fe7e570ba50ec8b1bafdb19dde9cefebd6e20b127e57ecbecfb1dfc010e98ced25cfacce50d924263fe3931c65e44fe07ac673695d67dce58c26cecadc1b6f8eb8f4f6e74a26d4ffab614a8697f0f30dadcb263b0a4afbfe06c5d33adbcbd7cd0ee1fcf4ea69b2df6dddfdec42efafbb8bb8c7cadcfee8691c9e3564cbd8ce252e89bb5bcf927dc88a2d517caafd3714b1cbfcdcbef9ae383ea8abc83fdc93cba3aa72bcee257dbf8083a7582afddaf645f9c8d75df0b64eff05c1cfdafbecbe82aafaedddb7ed00490fa369f0ba2105bb4c86f76a8e0ffc77fb4918c60230bd4e69ae0f6fbcdadb3edb31b394b6aaf9cd98de3d3bcd416e9bc4b4ca715cf243e6adc7dadf477ad0ccdbdd9b11c049dcfa7f2afeaecfa8d75daa29a0c392dd1bc78abd5efb9faffa81aeef7dd77234f67d403e4cb5cde5fc44a284bc27f7c625bb31dd15aefacea675f2db0c29cd49d9caeb8dfad54c817deb732a2331386b3fe7ed9d1a61e23aaab23c6d86239bcb0e7d3e8b068426e5fcac1839ade17b2bfcf1e4151e4dcf20f64868ac62fd4fb2cf44d893991aebd3d29fc6072b0da10c349bcacab9acf68c9dbc3eee6c5cf9219c8acb67dfbec8dbff97fae99d2546b7babbbbf1bbcc2ca1ae0ea6deeedddd5a179a0ae76b7c6d8dbbdd6b5c400ebd34a1cfeefa9a244dadbadd88897b8785fbb9ecf02aa5b9c7baff9fae80eff5b65fb35abfd3abd41f65b656cc8ffafadfceb2d3bbc07a694cda81b83bccae96dba47ebcae3ba52f8f94bbe810466e29f9bbfdbc6bc730eebef226b08dbe00bf0e96031d848bd64d95cd39cee3b8b9df6a9fcf6b9e7a57b91f30aebcb655516e6bebdc92de2bd52e9fb9eb8df8d495edd14f1eab5a9ece6bcb9cbdefb54b54bc0f7c6f68d5ed1e9bd4dcbb873f1cb4e4caca3eef4aa12b068acfa0af99f37eb9abbfba4f1c9dcc1ee8c85da474a9f067d17459190f36be06accaa735da27fd9e21f0d073c2930cc9b51cddd81a12a46ef87eeee1f1aa94fb6a05eb8b7d8fdbf6da32cd62104fbaba68b3ec6f1b3c4ff9d3b2096cadd097124ffce3d0bb11cb3b102eeb55d58f416ccff4b10e32f64527bba1bd3594abf0775c283b93d4aace47dee1a040dba4e2411b36bca3f5cda62d1f7ab0b207ff3798de8dcfbb49f57073cdfeabcf5beeafbda781872583d6e9bfec143e1f3d962a4eb75f94abbff61289ebf0bbf4f6ebdeed64bd69a4a3fd83c2b4f211ad2c221aa946adf0e7ff0ad732bc3ca5be41ec12ec9a8a458fbe5956d3b6c72eb7dded5b32ff4eedcbc9c2ed4a6e4e7ea55bc0b328cdede49ac8593faea41bffaea7ae0ab7c2c6ae24f409accbe0e0fa82091f65eea6ffcbad85eff30d76d9f8c40bc8b0a9cf4c73cb879b3769f05a76c2bbb3eddeccb0efd787ac03dbaaba888a2c56abeaaace860df96b4fc81d8bac1d1ed18e8b30c6ed7cc83ed86a42a5e618a6a4beaf0341a66941fed10ec4bd7b40cef0cfb6f05deee39cb2029d0edf3aa961bee2fdcb9bab1e4faa62b4fc50a8abe2f6de3ded6bbcc612aafbc28b7b11f9dd7167ce91b7cfd2858a0db5e03ca2dd4fd4ce1b1a7ade5cfe2fd67070921587a76a6df54a2e589ae0b84a40dafb93d074ed3fdf5a1b2ace12d0a65ddcc5dc1891beeb1ab2dcfa6bee5aef2ab3a68224dad417023eebd3e4af66344c7ec0cde7bb5537f59caaeb2814fdafcd1cff8d745a9df36f5ebb9945f1dcfc7b1ee8bfeba17ecb87dacaebd6fcca1ff301bc0adea418d8fd2defb3bb43cf023d5cfddccf602ed7dd68e72da9e36f733ecd8fee8b66405abbad2edb3cadfeec9c98718343b7aaf53c71b7db55fb0cf1ff3fa0db7bbbfdc78bedad4f3ada02caf09e3a7dc2cced03e888e2ee20ab2a07a9a74a1afccdd84edefed40ad1abd62b7dedb954dc8e0d2dca88e31bd25aa2ba2c2bcddb0cfdef9ad614deb9eec159feab03392feb376b54e726adccd5666e8fdaf130b6f1e2e472de3ae16adfa205cd45e6c67776fbf6c75daddff6bdea24e3b7de7cf2afc54aa270d5a562480ac91fbaacbc7705eece6fc6116ec3b44ede8a1b261b1e4becdc594143f9cee740c599cec1ca81e2eecfcfee3aa0bcb72a8e7e3c6eed27e024d105ae7c5aaad45dc52e45dc0f253d77e47d9efaac6686fdca6ac9c52e0f32a9aefea089faaab0cb24a02ed3734ecbefe69ebee1e73a7e4f3cfe7f7cbfed33bd333fca5865ebeaa2bd8f7af0cd83b31e04f4ab6deecd56debce5aba93213e7f9cbd632cb7886bdb84eff7a0be63a857edd544ae9c3f89b4125c6cc3ebfe3cef3f7bcbb055a6ab22fe80c61ff96e0fcce0ec34ac1ec84d59689aff6f38cdacad66d7ab71c26d0b77ecc9576e5f4ea14f4c0dab7fd04d0da4eb7feb1fcc1c82f17e0f5bfaffb9b1a5104741f6f5cd6accada374a7cebe1859adc03cce17523e9beea0cc5541b0e0bc1ff7ee969abcc6a6299cafbca7606ef733d8b10676ddaa7d773cce6ec749df6a9359b4bdad99cfff931ff407edaa02733d1edffdc625db7002c21fdbb9e37e51a527c9cf93ad8d3d1f5244cf9b5b9fa58fd4a989ac6aaa4c5ed4b631eadbebfa3fa6b110deabccfdd7bf3cacba6b38b3c2d50ed33627dcc6eb576b15e13dee5dea5c3122b0bcfde7f5dce3bc12ea2fdbdd0ae2aaea6e3a2f3b9d1e4cf2bef0e5ffa12a66ee36384ffbdb15be5bcba1fedca17de8d60ebcd57cebb1ec4edcd7ff81c5aa5dc3bb721ab578ecbc234eaaba1b8aa7fec1db84ffab703ef207d4acdcdc0397a5dcea50bffae4cf5e2f55a0ba24afb1eafaabe0dedecba7fbe3b75b1df1caaaf384a57d94b0f9b1d4ccdbae72dcdca464a2ba26ae6cd1fcb7ebd6ba1dc6d01317fb25cb4ab419f059d956fdb26cdaa4db8a8383c91c0dd253887ca19aad7dfa2d29beba91b9122605b0134bb51484bc2db053cf1fe3f7ad5d7c4bf2b71bfb1bd35cfcc7a3ecce9c608fd3270cf8385f54e9a09cd7ced7b4f307ae9d4bcbcbcdf82c06c0cf8aba115e35fdacadb2e45f0bdb027afaed2af1efebd95bcecabda8efebd71e2be2c0d1f3c22d2cf91edc297592fec5fde8b038604baf25d5dd796c49d48d2e9f613bddced3baed86f48c9ac436cdda8f169cadbd06773cac934ded2cfbfeaccece39a50e09fcfc9cdd40a3c5f9483fe525e8b9d1d513dcc43cdac2ccccda79edb0c2e66abf94a8adafdcceadaaaabdc65fc1a88ac6dbebab0307dfbbd8d021f8dff58b9aa1e8b170b660ab5cee701a9c1eae505b623d065f30fcabceb41b69be1bcbecf051feea8f4f02c85fceaa4c0b2d77ffdeefe4ffb8eeaf6daa4f3d72bb6f6aed0ca1a32fbd03e5ae7cdb0ae3e60fee6e3dbd98c8a0afe9404f6adfc23c490f3ec473fc7ccbaedcecc15e6e243d94bf643a2fbd8e068d9e38898876116a4ead75f8693771cbbccf470b7e1eba9c4bc7eaeb37625c0e9ff6ef48d5fee72beddd8d0fae312dc6bb4b3e2b438cc11be4e88edd520cd252a45dbf0fa9b59fab9af14ee48deede7a41cc2151b51b30eca2ca1c5f7fdf0ba622d0d859c2dcc76b8a372a35adf6e2cca7a431ebb56379f9415be5ef8d37b1ac59ba95e6a5ddc82ba7ecbf1cbac1e47fcf32f3d9dfca331edeaeaacea846c8d666c8fa722320723b9ccf5abf0decbd5d1dbfdc63ef87e2b9e3faafe6311eeab031c6d5cfbd5e2fd4a4ecf2e7bc3aa35aa1fc13d9ece5ebbecf23ba66bed3deec69fab8ff857a7b46ccf89a2dadaf4935f7afaacbee46fc223f9c4f54af7eb5507fc1c45bddf97a18ff486aeb209602b92704e443fff5fe767cdfdfeadbbf3f2a421db7f331587cce7d175b1c94ae592f5db2ae1eba048cfb894c7b37bbd00ce2d1f0fa11abff5e00a4eb10eadf9f48bf91014e9a9edbabfebd035bca8be5e25c7c54f41bfed033ed6c063de4caeeb04be56acc109d14cbb5beac7e7b12febf39aba644b0f20460f57ed34cbab4f2d2db0dd5ab84af3600c1da1cc1c38a9a1c28d0fdcc9dc834bb899c5dfd656b15bf5a66f92da91692d4dce39c0b6f8ca5e8951af0ddb7da7fa8adcc9f7aca4bbc542fd87e348ad773fa51dc8b010aa459fbc77de433b38d8a99f7fd89a5b426d54eabbafc30d1bb8e73c25b6b8ef45bfcdf13d5c6dcb1d1dab8521cdf7ce6bbcba9d43d7392b62e18e3a6fdfef791971818b4ac2c61f1dd13dd780d3ebf82dd2814d4dababc379ffdfd4d1d5d1b5b892efaa9bebfaeca643ea36ff77e3f130831cbded1ff56ab6efa46e0b9af5c89dc9df2856850968d2b409a6444156e5827fda8d52efb1edd8b5dc0cc6b4358b1ccef13f3ffffeaa754fef89bbbb5f52285201cf948bccb741ac0cdbf0caa2e4cddffffdf352b15864836b5c0cb4ffeb9513255afcc55faccce9dd605118b899d38ce9bd8dff8e64a2bcdc7afbd380d2d3a9ddf3029a7a2157f6bc495d8bea93c7e17ab1ff28202cba2e8bfbe7c4982ffa7ca4d8fe62bb3d2b396fe83e7fbefefee62da9b6dd0a9fe5dec16b3cccfd7d6efdf0fce7f34efdaeae204bdcb611ccd1be4dd6f17b0afaf8ce323767b6de1e0aab3d88e862feee84afc1caeed5b591d9fde5a5cdc48481cbafa6ccfcd77c2b2e2d2bcedb9b04ec25eedaf79ae25c3f8608ffcf4cb7d2ec6a00bf94f2bfe4c9ac9ee36dfafdec929c3a29dde2b99f66abac702917de766e2f9637ec5bbfc3cb8cd631a3eddb08d8e31e6dd0ef6631cffb77f1fe3db1ec61da5626d9c2e76bdb6c1e3cc0488a79beeebd58ea545a284d4ee3d3c284d4eaef2deb7cdc971afaaaf8cbe39fe3e2aca0c1ef6dd0c53ca6bbbdf47dcbb57b36ac5543b103258ad867b22b790be343570b5fb39acc28b2cfc04c89efb46fecc4d236dbcfaead0c2341bd6c23c0ca741d6e6f868fb60ecabe04f8332d3c4c09c321596beeff5d6ae9d3e0079a9ec5e0eaf1aca1fc8534bc9d058ebb8c02c9b77c97976e71bb1eb9b68dfcf35a3941afaf9acccbdf40b7ddfd8ee78351e9539a3d2ed47c68f8c3946efecafe450d584fd5c123e6d27a123d80cad8adcf6eadf5fa09feacca4713fbafc285b4bfae8bafe4d28dfe7799d9faab7effcfcdd9f86e31ada737d4ced2786d37d0a5fe5b9651bcff3b131f7c7fae6385b0fa95d750d17f508189d115a4cc1f7cdcf0f5d7a01af59203a847ee422ed0e8cfc79a52adcdeafcee9f314db20a262cacfdeaba1bcebf37b9a9aa8bccabfdcdcb55086cafe1433e42aff35e70ff591282bd9d9e3dac7e8eecd399bab8adedce3ebedcd5ebcb96fdfd93c7c6073f57cf04efd83ce7c594e5fc0a0ba399fdfaa45513fc7dd32cc0cc2ecbaa98dddff646aeabad1c1a9a3eba964e5e4bb9c53ac9ea65af02dc7bfd3edbb97cf9eb0cffe531dfbf3eb5bd6b051c45d236ab24d5e8c2f8d8c89e3fcbb9d5110dd0ca1562b9dcbd809a2573b9abffabfd2d22a67a3a28f5e7849d2bb83a4fecdf83d06acfba0afe8b70f5e630baad1fbb9fa9b31dedb9bc5ffabebe7f4f36b0b7e05eba8cf4e121cd7b8ef4abdc22f0cfdcf1fe1bf1aaf39b68a788adf62cb1fca3c0fd975bc7918dfd98ed28ba143afbba6ace0baa7db29c25dddb0fe6a89e5dd43d8b2190c2a0f09fb2c25d729c2b16a8793e1b697cd4bbee879d446f4e87cd933faa0ced0dea7ec24bb9abd1edab58edd24c1ceacd771c7c5da7b20ec81c873a8eed4f5d5aeddd5cd043c41233bfbdfb1e0af0a663bdc06e2be9f02bb9bafde8cc9efac9b9478add0a92a87cc2d8bab313b24cfdcec2e8df6e9d5384d69ed40dc2dbc61736ac6df1f8dd1d7c9c4b3dec9aec7923fe73187c0a38bd5dfbb191bbc476eef3a8acf8b7dc22d8f27d7adfa8330b94cafbf1cafaf05bf936a5e887d246a8a4b9b568f777dd61feb886d76d9f06e0d83e6eba2d4eb4abd3eaa6acc81cbb89c7a09fac8bfbfc1da15c162f1deed7e0bfce2057200db2cfbdd9cfa00e839abdbfdbe2a5b3edee20b9c6cbad9ff5ac81c7259f5ccae5cd587cbd4ccdeabffccb4ffd7d10f0d0cdb6adca7d1302d1c39eaabba6c2cfbd5ec9a5e05ecac1d0eaabf97a29d5e8b00a415afc3a22d1fe0f375eafc6afa5da9c65bca27eee0d718fa2dcaecdadc0c6fb4cfaceaac19eabaebe6e2ce3a35747fa1fcf7eed0a3308c1ea8fefb00835ab10dc93a5bbe1bae99caec1c22c41fe9fd62bf400d91e07ebbebcaeeafeac902aaeac23fd516fd72bafd0c549eafaf5b70a978bb7aeab74cec0366ff8aa8e87a9f68eeedfc63f958d55e0dd0dfea421adaca729fddc4b2acdf8bbcd4267bd18a329d602bbc53a28c71da9ee1cf6eccefcf4aecec76ed64acbfcbbae3cefffe4cf8ddf6ad22f27fbdb39f23e8f73e3a3575dbaf76f45bf4dfbd5bbeb7c8b82f1d4ef50ef97d8dbaec38a3801bad96abeeec398b9da4f7a2b8a1b3ffbbfb50dfb0a6a4ba512eab0842ff05d9dd2104f3c208a09cdea09a5d74f9934d4e5dfadaacf4ab47baa828de7cdc6ce2ae28fe1faa9e30fdf5dea2520ae4ed6a653defc8c0bb56d6bbba2bf84482ecf573690aedc34ef2cebddf574b42b6ad6d44761ffa481f609ca42ebe493da2bebcac4dbc49a8ac1c3aea45c60fdca3b4acaaa219a53eb97bb7a3b6f1eb9cfdcdd8fd19846fc229b2bcb87df110d4030fc8bacdcffc64cdc285dafc498fb7ef4d2f1bdcf9ba9dfe137e4e3bbffffbe15fdefefaafdfbf3df8ec5cde99c3edd785f80a5a1eaa0f7fbf925e8a08e0dd111c8a9abc4e57ccc9dccbbdac15c0ebf609b46afa5d865bcfd01f6bcfdcc0a8eafb24f4b264ea63a2fed34f1dbb618cebbfaa22d8aefea7134cb804c6f5d693dfaeca6ef9a76b3eb2beeafc253b8230bbb8abfbd02c2cdfd5f6564efac9cfb6dec7e52848a1dc8dfcc400a190b6cddc1743255edb2dd0dcd3673bcbeaac0facfe941f59db2dce8ae180262062b69f1c69f77dd6a53256fe4ed75ae9bc06fddcadff024bc7ba1e832c2bd07e2f619afdd5bb0dcf37caabb0d3da0b2bd63cbf6dfb058c18df2aa5497daab75bf1ccd4657ca6e01ddfbe2c3f2f383ad3dbd3d4dfe82a7d0f92be5fabaeedfe9cbdf8d08fe4754f6eb48bee5a1c5cfd0cc1fe8dcbcffa5fd07509bd5803f50cddebaf1befcef4385d51e60f02aadcb85242ed55aaafa71bc4cfbcb28ac9112edffa0acbb29efefdc0e9ddb6d58aacabbaaa75e3fe0bf823ffff8a2d3755ea1aabf67e8a2ff1bcdbf4bffabfdb110b574448fecffb4fb08fa36c07fa0d5f2dda5bd9ab8d7ecaf4f6c540dfd76b8aefe81cdaa86f64dd406ad632311fde0feaa1d0fc2f3342d1de8dfbcf7b42a81aa6fa4edf493feb6cd237c3bb27b9a05badc40df0afa11797a737ff2f85bbe80dcacccfbbdca9df49c47bb5cd14dcff346d294b8fceb729686bbcfdabfb0d0eef57f592811cf7fcbac4ddff38bed58653d5d12cccbe6faacb03e2e88bc8db0fb1a8aa1c6e64cc09672caaefeea15cec89a0f4cf2158b2bd4cb01ef7c9a9733de4df1bde8271bdc4ba72ed8ffaaf2d1d255a4dcdc2b7eccbbcc22ef93edfd0b4c3edcc5dfbea1f5acecc8ea276a8c63f97d5dc46843c6d2d57a7ecdfd8d84d6beefc8e0f991ce39c70cef99b5ffbb86e6141bbccdba1837bcda43bd39fe3caa7d1eeccec8debcacb3a4a6df3fb6bbcc3866cfdbea514329b8e19bc0bb2efbee0bbb4a9eda7accfc1d55ffccceb0dda6ee8ded20fd9515bd53a4e525db6a2dce0092784560b17b710b9aa3ef2952bffec5a5dc99e3f52c0b5badfbd8acf4d5736ffe9995f4e3a3a4e6aec2bfcdbad9cbfdc51caf32befc6a15dc94a336debca3b410cafcb6e9abdcfbbfb837d953aaa07d2d6fe0e5dddaafde7cb696f5a8f3d0cbaf43bc5265fa3cf4e8cfe8d11afcb487dbdfccdfdc1511a3fff35b938df13ee9b5c9a6ad028a80600d4afecbbe0beba72aee4b0035ddca68d29c6c7a3fda9beb0f66b73e7cd3aa11d160d2b6471417e467e72abce0a1bf715fe9bcaa9faa0fa845414aebc2effcc17a6dfc1a06da2a8109b6da21aedacb8fff05974c25e6a6ac9f5ceaf1ddf28a32a75ab5a9df1afc01dac1f4b68cb2ebba2dc261e9a1d6fda3fbdb1b4b6bded2be1865f8c6cb5ce93e2cdfbfebb68eac9de60fbc503be7eff7afab362aee81cde7fb7556bcbba6ba9fe3bee5301fe342eac2a33ef0e4510de45182e3e3dbfbcbd953d5aeddda6fe0f51d5bdfb8b9d4f5ed4cdcb2a032ab02c5ce79a6d2cb7dbfeafd9dde4121f0357e1ddcb2daaa6b28d1fa65d5fa1db9e3bcefe1b0b795acb81acfdbddc6ea5626b3a3baa02a12df6fa74f1ecb42ce5c6f0eab6d4ff44601aa8bdf21fef6e21765dced297cebaadeeb2ebaaedec0caceea5ef0ab40d9002eeff4acac62f9dffee0b6ea4d53a2bc26cf38c714ea086a182099abb44d8ae3bfb4b4aba10a3e5a7bf179c3e22e437969ffd81aae83c6fece59afe97ff5beb5c4d3a7ed8b04fadbbedf004a2af07dfdaf5b7eccb825e5e1e6ab68cef1b95e0d3dca0b9b3386809e44cecdfdb50ef76c55125c6ad0a93bedac282f84efde455bf2bc94e26dcf2d1e5fdb7e40caad6bf01faea3fbffb315a588958e1dbfbb76fa1b4644af27a43ebf4607b3cb4cc01d8fa1d2db3d39e1eef1e3cacafdcdffad1887ac0e596e8ac8bdd0abfee1c4dbd5eef54f98d4575e42676eca83f1acd12af2abce9d4dcdbf1d31cd09b41deb577d265af3cddfe0397b5ab7f6dd9a1eb2c2fcbc5ecb36b0f05fa54838bdbd3e6e5cd96be09d9fbcf73ec964e6c19ad3949209be9b193df97fcb78bce9c8df790f41eca7e7d04b7b8422af2a34b27d87b51fcfcba1f2ad88d57b5dc525febda4beaffae63ee24c3767b3f22ba007bb3494ebfb15cbbf90bc090cd6d5bc951e1db607a533148d8c4d5aef4ce3a8841cb9ec6c459255ef00fb4167735070da5dffa5bdb8b85cd8cd0bffe99bc617d40152c9e74cdd3eac11e8072dcb5cf5e5ed7ef8a7f2e25020db8a82a59a362b599a1e3e63d9b845da3afcb1160bf227bfdabff2248602d1522c5fe993460cd1220de1dee42879dde457462051cb6c5a5dbbbade008ac9bb8f713fadfd92d13eaeae8cfde8cc4cfceed577ba31fff8aeb2aaeb02a5ce45c8adaaef7664548e088ddbc422d1c46cad2af5647df071060bfe95fc565ff744f2dcae5baec2b7dddfc1ccb06ce8f1d6e596bdc9ce51418a812a0359bcc4c16be6beb60cbf3876d42c91db3800e24aecb58a5a3e2e2edb4d7fe587d4848f53eace3cc0bc96be4fbbd0d13c63bebe198b0cfbcbf935cbded5a5ceacbf6994db248d04abed42688adbe83a3fcbfc4faeffcfc26a558baab9390db9fb68ac1df8721486c77c0fe375a25ebf9ccb44feacecf19c9b350fedbd7a4e77a2caacef4243b7b1f0b2effc18942ac4d7edbacf6aacedcdb389ebfcec63035c44ab09b3acefd0dcedaad37aceb92debf1fcda5afadf997d874ffc4b8bf3ac2bcf4effaca0daefe2ff2a496bf5a8dc4da4eeb93f08bdc9507b6128ed0c8751ed465cd653ded6ab7dfebbbb73edb69ae024d868f57a1f227d60568a9eacd39c4caef072f6b3c05eadf015fc06dff465bdca65ede49c3d30fcebadd0c9af7a0e177f81510ccc975470abf9a1a44693e798156b0c63efb3ddc744f457ea2be7d31eb5282db6298d4e6904029bbf9aecb43fb1f464aae391efe7cee6ceae7685d50503b9fcc7146b4befabab24cfb2b164aa3ec1e046b88e54dfadfdc86dfeaecfeab72fecc44fb6acd3f07cc9065c3afab0fbc6a0dc8bad5d4651c9adbfeb36e2b42ca60cbd4f30f4ee4770f1dfdcacab6f8eac52df6ac6649dabcb8de9c5ee5af6ea520debccc0f1b7ed599c96bed32d0ffc5d1e0862d79ba1d5d531bad85bbed588ffebfcf6b0ee0ba169df02ec1b6d6bc8bdb1fedb2abd0ae964fefbb5e3700ebf91d01bcef09cdfffc20e612ebd721017e6494d0a1dcf241cca2a43fc234c04b6bef7be779db6e6cafbf623eeffb776adff483c13ee2550fee6f874bf1bebb9843be55babbedc0bf0c5daa39bfc7429b07f675c707cb83d419c83d6f02d32531ddf23708fb68fdc61c96ac99eaa828de3d0cb02dd5fcaa9518adafbfa052fc6b9e8fe94a9e0eb420dcb320e6c5eea7faab2ea372cb1f90908f2d8c4d3d8a99a5dd6abbf90bbe610b5bebcb85d59d3b4184f474d86ed4ff7f1b9ee4ecbcff3eca267cb1adab3b00cb2e831cc283cefcf797ed8d3286b8b2241dc012e89c8ffeeea7c8e11bf9e9cabe6d1da00d5f5fac52cdc07a8028bbfaf911f0162e0aed492cb33ede16e59f0092b730d1b2c1b1cd63ead3e3a62e3eb1d5eced5a1e842da5df3bfdf5a12eabcd44c5968fbdee7c8b669d5fd7f7c3f44dd413e1f4c3b18d75aaccba743c1fd95fea324a25f2cdff8fbea9faee42c56aa42c56dd5989e625dff5075e87cf8ff626361cfce86faef41e0d7dcfed59aaec566f9be1c05cbfb74c6f3a3fac83dfacc74d9c91a02ef7aef08dff5e6ee95e5afed9b14ac7ad76f31afc2efeb632aada7524fdfe1aef8dcbf39aee3bc6fe553bb74adf4e03c1fdcc2a024a53ed08aadbefa8bf62803d52cbad6bfc97b2e9bf80fbd151b9161307e310efa6098a6f9bccb44d82d117c3ebfe6bbdcd6c4ef2fc1abe905c8cb87d5cd7dcc7bd32ca6dcdb44fcf78fac63df27afeefb23baaf665fe87a5135c05ca419ad028d2dcafa05bcdcdf5a0d451104876b4bae4ae3d60b4abb0cece374846a8bef74ddba62c788fccb63b7a9bbea5bff539bfcc6983e7fe55de49a81eceb3df786a9093bacedcb7f43a36aaa7acf57e7fe38153b4fb03dead5d3a9bac9b541da2dbbd15eab67192ed0bd135ad6cf58d8cbf661d63182c332bf25b1f95c13afa6bd7b6abc41d54e0fbf32e07717d7cb440e61cf671d1d64b066df1320757e73088fcfa22f863d0a8fcfdfbd0e670deecedd3f0085f16e6b55ca25dc0ef65c1adfaf5169a12dd0b96cafbdf956edaf7ab76fa35beb6e3d349c9fd3f8bba7f6eadeb1a5eb9f9b572f4afa06fd3ca2493f22d77ebad578ab184b96fffffb4a7b1f1aab05eb414f4d0aad5cb64b05f15e1d94b6b25afa42b76de2f9308ce0feebd810193e52b0acfdadebf16f04ab28d6eef27ac9bfb44bb72ac6d91f6b4b8ee2d96123af5b8ef191bcefedbebabaa2ccacedac0860ddeedcda6b5cc69b9fbcd2a16ff6cccbc10e1ecab1ca7622ccdd054b9cd7a3b7d400a38ff2a85ec5cd3ccd8ebf9bacefb1f351fc0dadeb271d44d946a01a85b6b3a0fd9d85245e7b67dff32fb1efcac7e70d8934eccd0a17b3c2a8764b2e7150efdfeed7f91b64c623b36f0bc67256fddf0cb2ac5de80342f2fee33dbac16f5a091c11bed1f28decbefefdbdb326ccd7b6a2e92a1b9dcd9245bdce72cb3bef2cebae3bd3adbce12ece60cfd2bff4acd61d93bbae5fe77cc3ae9dae6c24e46062df8c6d8fac39499403d52d0e6052d2402cac1aefcc3a5bff476fab60dda2bafaa3dd88d692cde151ec13dc2dd69d0285d9c439817cff3dc6d030c973cba7a7da475d2ed99f9bcced21faffcffebaa82bae4afba14f3727ca4b487cfa8eedb2bd4f81c3fa9de9359dcdb9b580faefc6f7e080baefce6c7fcb72ca12829fcf70ff7b691b17601ba7d2f9699fde7312b52cf80cef8ce247bef6b85fb0ee1a45db5d29af810acbe519adfb5abedeb8dedb400f299d6c6f6efe165940fbffafb852deba608b1d9fe76f4fda2cc053aba30c399d7dcb8344295eefddc99b7e9fc5ceead2ae1e0d071cdab5c5c7672cc6a690897d29110c6e67bc850546b5a16ef4f7dfab05bcefea207ca645bb70d95dff947c78ebf037082c743542ceedaeb6aeedfe2cabf9e0bd2dfff60ebe7a83dca3d307b2b92de270e415d7cca5d5d49c1b17c22a98b29493dde20c881c1c83d67ead3fdf6d8f0ca3cfbadd975cdf3aefa519cfe6d8b9997dec5afff36cdde81bbfc27d25fcaed0ef6edae22f05dabebbbffc8f839ccadac7aeb88ba1f0b951e0aac192bf0ce4879cae25d3d6ca7204fec273ac4fd66e66fbdba0c50ad44b1cd6dddd4b61d6e42c3bd2bab90dbbfa0b4ce849aeca95f1a032a1ec7606d52d446f1da8f6bf3bfcbf1e16f9f8668c27d2912947a6be4cd10495aea222532aa8ccaecded4fdafcef4d7c62d9b661211efd09bf1fd6c70cc76e986bbeeec4dfb80ea54dfefc0f3ab9e0d0e84713a8d716dd528f4e0fd67aadecd0ce6eabeed4eeef3a873c9fdaa8a7e280bfb96e6948c1ecea24405e45076fc4aa3c31dd449eef8aa1e3aea53ffa70353efdefd7eb670f39c38fafbabdc6d1d941fede5c42eccbac68ffc2d9fb34a50947d987e5e8cf90a7cf3a5f9f6ffb6cf5ad387ea7eb1b9bcccec8ed9acae8e4a0e51a5b3e2641fdf9f5bbeb523c56a735ece68ded252a0aaffc05bd2344d78e5cb8b5661fb0bb91aa32dca92ca7b9eb37c7e52f6e56f2bcbdba90daf01ebaaf3bafb2abfa8e5c6fac372861c42ce4d76fb4c2e5179d1b770e8a595b24b04d7d31e2ffcfbd0be0cdebfd72e81a66ef915ad757b42eb809ded69e718f4b31cdddfc7ad3586767f9936fabdcefcdbbd8bedc8d6dcb0bcd2ffceccce39fdfac276be263eaefc603a0ca5af1c2eba3b6b3c82fbb0badec90edbe7fab4aeddb35fb9eaafeffcd40c3e078df5a6e7abde4bb3d4cd3b894f560c59ffedb1fb9c67c4c534af9011294deca5ac1b9cd63a50224acc44194fd0ae7fbbcb8f4c8e7d43f6cb7aa2c821b17fea0560a4ad0c2b42d6cd8ff33cdcb4df5a6f88af5cff65ed81e5cf7c8bf57f536cb07a8fd78fee314f6f8b712a5efb4c75a0cae48a6759199036c3ddedcfde88a967f8eb9f2fb3bf52ebffdccf41bf2dba3afcca0b66ab3b6eec7dcd2fe0b194d53e6ed92b3adc22afaebaaccbdb6b81428cc56dcfc1f25b76cdcfbe2e4fca04831fe2acbd96da6afd1f5fadb3bd9e1bcf3a1bc02a63fefdc4369a4ecdf24f9707f81e0b1adbbbbbf6cdbb3dfbe8f2f2f21f5bd391ccddaa98af8ab8caa3e2a8af5ee91c39b2a4ff04ddd01684838df9eff7e422bf3070c9f3d83d0e32bab6d48c376f68348c40aa5cacbcec17ef3a3b9d4f6fe5aaecfddea602616bbaf2f1d1dd1ecc9dbcaea943c4faa55fa703dfd00e678ff279ec7b9be04adeebcbfcb3fbd2ea476dbd0b1e9b604ab4f3fc1fe4343adaa5aa1e9a5cf994eed6afeda5ccf5662dd4a11f6c3d42ea9fc6d7a1df6b974dcba5bf34ffb1f7bdf70adeb763ab40b5be3abed45dd4fad86bcebdd3dbaedd2ce0ba854e880737d93b24d7e8b2dc369cbfe0dffff86f7f83d4dcc4da4cba9a446344f10bad8faec7bbfd391e1b70e3dfc5e58ccb5f2009ce0a9cedfcbf24f917aa381f86f53fe8ad0f597b2dc8af24fc1511a7162fa68bee6d39faabbdf3cd9e5f2e2d7e8ac6fef9a8ec64d6c3c5cafb1dc4ebcab9cc1aab297a3ebfcffb0fe1bf2731f02a6bf64ab70a89345cbe45dd3b2aa68c0f2adf415abffbb72bd2f95b1bb26efca5d1ff5bdacad9db8dd8d77e9e787bb7a88ebedcac8cd0603f0187eac2ebcdad36bef9ba0e718a03bdda00fe0ad2bd3b1fb3a24fb6935645217b5edcf6b0f67f1b4ddd0a44aabf2e5cafd58aa4fb65cabe90bbf9d8ae68a4d3dc1cdbedf5ac42a3a1f994e4fa2290653bc9d18e0cb63145efb4cca20fc418b8ce8ff65fdcd326e5bbe1f02e8388c2af5aef14dfeb16283c2f3d82cfcdc6afb93f96e8ebec7a54da9f1cc9922ed25b8da19bbab3c8358f6fbb2fa675c2e07fd53a1b14bed6ba31ab54f5dd53d629fc6e754e24e8f67d5f73ec3a884becaa5f4ed85f2afd8afbdede830cb0ff1ec6ab1efaca4bafdacdefd310a4be3d193f9c8ac27b78abca1ccbff5849cea3ff500b9f4f4bea7d64dcff2de6cb1f8afbcdbfcabaaf667e817acc1ba5de80374ae1e9f62eba2e5b7ca153c2d3cbb58f4bdc8acdec5bcf33f1dbe5e10f5904ac850dbf8feee147efe15cfadef43def10393355da1bec348b570eada01cbeeae6ac0fc5ae20870df5afba1ba7b7c2cd7dbbbc248e36deae8e9e7ba36ebedefd45f81ef42413f9d4c7b1c246fb4db57e66e8dea4efce6d45ed1bfdef25cc0cc7a8a80b5270ec3d85bd8e9dcca5b6ed3efaf0c1eea1537ef1f4f3272e2ab03c9d382b14bcc945718cee341be34a0753e2f32dba7d3a35ccc5c452cc74d86d9342b73a5b033f0257222dcf9d2bf75a431c5d92bd8e5584d4aa8d642f366c7aa65bec5122ff9bd59c7cfaebac669bdced61fd5e04b24eecf4ff7f55ebb1bab01aa56d3a1327d43b593cffa5f2ec9fab8918aeacb34347a6f47ca95b427bdad7cf1cda2f3e358ffad12f26c18dbbb315c2d5ccaceab294ea118f9cece5cbafc1c53fafbae4faddd1dafe0d2e507af4b10eaf49d4c3baaa13eecf68d88fecdf37c0a4dec43daddce7e998bb4cc15cd8dd5c360b1e02b60a9dab3ed3c8feaafde6e18c0e17c38d3acb7ffa3d1350b0fd772430e9cc282ea7fcdb1cfc61d6cdc41fc0f33b2bf1dbed6ab42d559abaeeda38f2efd15a0aedbe73c13c46555fc1208de24c3c8ef20c9dc1cefd959c8305dfbbd7624c3bfa904c5889cc9cffa69d4eb7c5c4d9552293c1dbc5b4dab04063042eb7e6c25ecce02e3ae1fff1712656a5aa16ff62eadf61afbf56ddd9b72badb7d0c07cf38c338ec58eb4ffae2d0ad5dd9a31c664d5cacd06935339df476b9db9ee8dc9d8cf6d7532df2891b51a32dcba7c3c24a5dc4de9bec99fe24999c2fbef16cb3e9cbefbefea6eaaa0838534a09aba02ebec1bf319bef71c6de3bdf5ff4fdc9c93abc96a4b9b5341cab109db83ac4e07a2ee16bbb4f82b65e3ebcce7681fcbdc4b9d756fb09dae23b56b2d1ca261ead6972b5681f20b879f9b1db7ce559e2ac306633fa98c5fb9bdd24a6a0c54f4739ef7e462c2abde8fd047a78408ebc5c0a6dfe2fad8dd4da85f019d2f5fd4b3e57ff1e896dce2bfbbef0ffee7eabc117bfec2e0c0db639a5386bd74a0adfef759a1e0a9aa7644ae792e8d1ae40c6d3c2f6e7213c56a19d1ee8cf20acdefefd4fd8fdba20b44ab4a1ce3f0674e0f9dd231071efde77baa12ebeefafec5cc977cfcf5b9a4ac9e09bb39e77cff10ecfc722f5c1a69ec584aa4e4f3243c25ffbc1ee456c96e90efddb78155ec723d8b77ddc2f279eac4adbad030c9ef1c3aaa74e5efa6bfee6076a6cf8c2ccbd0c4a767eabc8ad3def8862eebd23ea401ff9625f20e4dcbf9482a006cc8fab7bfcacded3dde17ffdbfdaecfc2aaa64d0dcba201acc3fdfbe9b3c814cfcfbeefd3e071a9f5ab9bc93e91ea130234621b1dad19c946325b04a76d2a1d09de9b4ec5cc6c49ecbfacbba7fd4ecbc07ebcfce5bf8bb5615cace5b17ef09f04f8db9eb78c0b23c4eb1cbd3ca96bcbfff63da2f5fc5ee4bb37cacf5d29415eba5f2d9bcd9c095b16cfbdd08fedd6add82bf00eca2f9e8e902db8cc8ea6c32a171337e6e54276d3faa8ea8daacec316a71e037a52c0402bc90fddacf3e4dea6fa0edf9167cbd2b8bb0b2c99e964ec5cb9fe430ce4b953de6aff78eff328bcb1ccd48f7d5f0ba0aea36bde44b3aed023176bec2e49f36cebeafbb0bb9f0fcfbaef390bca2b1bdf012dffd6fa4c8fab91290ceea28965af132a08858c05e6eb20c5f1410cdae9d49b95ca113c74df6e4f09251bf9e1ec75eab3d6acf207ddd8fd7f6a5d793468c2b9f7fdd9d67c29c98dcc51566b5b42addec93cfca4d34c27df88f0d9abcb3bc4a0d3bc8f1adc9b27be28abf7dff2eeddd5825dfabccfcbc2f9e8c8bbfa09dbc7979330078d77c4effbdbbb4cdfccc0fbc8536b8eabf9f94acd8fb4d517b4b0eb5f17beb6b8fdaf2b3d9abe9becaadaaa080d06e2f332be85b4cf1ed73e8f55deb0ca3eab0b5c8beb5917a465e38bba23f6fb92cac4eeaaebc73993ebe9a14c9009f79b50ce178de1edbee612f39ee9b5d8ab1cfae783cbfee2daa86f7d5b5abafae7ae7c0ee7fb5e1129f28bce3e28ffadb8f3a0c03bdeb576bf497a6f66f61027bef1eab1bef346cfb5cc505ab2c2d0b356ffe4e1a1f0fabdd6f2d7c34474eac6a92e52c0dd82c14badd3db637d72f9bc7c3ede5cbebff76a92f36efcbbeab1e3be93db5edaafc3ac63b0893e6935ffb3b32fed183ef50c6162bb422fb69eaf9a856b1cc6a6b4e05a11484a2696b2ab3de1dfbfd6f6537ca129a522d6c1fb8c3dcfc0ae1bfbcbebb708dcecfaa717a36eec9f66a68ac2e7cdfdb7eff9d5033a58e9765efa0dbb9f8d4b0a28af72db8f0e3bf6bb180c3e190cead5abeedcfb067c3b78d018cb2e4abdf6d6ccd62818eca99d3fbedf628bed8ddaaceec8e65ebb566f41aeec83e5c7d7801d3ed0d073bdf3d52b1dc37536a161d52775e37c3dbc12e6e12dad8b31c5b69aeb0af3ea2bb164f4c9afa93dea6eaa9d652eb149a407583bdada35c1dca39a85ec1fcd3c69a7982324eeccc8d3cb92a5ebdeca7027a3f646bef7727faf4e3de3c668bd2edc86ca5b4c1fe87d4b5fe4e1afdbfc66dbeed9ce2f4d50aaadeeeed38baecf1fcfcfd7484c5eadd059c3caba457dbfc1ad58e1cbcded98e76aebcaff9c240eccdbaf7bb1cebadd7b67c95f260beacd5aebc2eef6f9dcaadaef6ebf67a01f90b8a54ee2fcd6f7e0256d1fca4e70f3913abbae674d2afe3bacebebe57efdbd3d2a4bb8f1ce6c0ef7cc6f673d20db99cbdd4b1c77d0b98fc92aac3b389dd8602aaa5df95bdf1646b1d70d07d81ef059cdb2af477ec02f5caa1bfe48f9baac14defdcc9bd337df9a2fc7c1addeb4ca44fa75dd0a7adba343eadb9f8ded3a89dbd010b5eb119eba9ded7b4bd8ec1e39bc7fcbaa0f5bdbb0c6f4ff780cfa67ab7a12e1e06e4e7ff9c8a113cc52ce5eaef2acbe8fa90483c5ba0f31fc15ace8a2d19b1dcef1dd0a2fadab8edc6b4cbe629bda98fa0be3b65aab6bb1e9f5dbde14def7cbd54e5affa5e45acb28a32bbefcde7c6d8012fb0f02b3ce0e0ea3ea9f5a3ba0f0fd1c2220b69dead21f6debee01b7fa6e73586fe83bf662e63088dfc65eace06ce34d01bbaa7d0e4caad9aee5ae9d08d32a5e9a023f0ac17a7efb3becf7f47287c6d7d8ba5019f726e2c7a09fb0fadccc76e6bebb56eccc3ae2c07c99a94edcceeb5384a60ed0bdc95dfb89e27209ef4bdc0d25cecdbba3bc83b5d7bce103da2f68dcd17a480fe6b0efa6f1c0caaabe316d3cbdf309f7c5e07d94fc65dc6c7a3b9763ce8452081acada2b8e20e37edcbbccafd0ffa3ea2121c62b5ba82f8b87b7ee5dd614a74acd6b867ce1ebeb9cd6c15f761ea6a2be83d3c18f98a899322debb666cbe1ddecdc8bfedce51e2fd2669436a058f081fb7f2ad53b3caabc9ecce5e7f3dcd9ab73ecc295b2720e38bf3f3b9a9ca20b6faf3c5161e45f0e5c0ebf8b0fb04fec61d54477fd3bbcd8c4e4bdd65a5cfd5e74cef02c17ffacdaa5d486f7e5a55cc2cf1d6e842eefaf7f27cae270ca30adf024deb81c8aedd86904deef543ef92eddff90f94acd1189ff8fda08ffff26c6ab292dc1be148ae0ed27eebd3aafde764a01521fb5428cbbeabacdcae18c841665ffbc1bf99f7ae98e66f3d0d8afa50f08c4bcc5ade311550f7a74c61adc70f4feac4ffdf24970ce6f7f2cf5a065c2eb3468fbdbf0f2aeacbb2bf33cefdc0dc9c6df37fe1369baf0d5b7a434fdd8da492e9e4434acebf9fb8de77cfe40fdb6fa6fe647ef1a393afc66fcf62ca8b8fccfeac0bfbf37b20d1d07bbd7cf0f730d2cb0d985d6ec5bfe04ca30c0d107ed0a382df9e1e2273aadcc3dc0dd5b6a0e59ad2f3e3eb6b74f074ddcf6fde9a2ecb99ed39a1bcaffea2bef46eaca1d7a8358dc7d8e3fdaa5abbfcd99b6114025a07d67fe9fe11ee783cdd309437d581358ccdda598fef581bbddd90f155a8af8b04efac2bd4b7728bdbbbadb2f17e4cc72f071c43da9c6ae691b1abc8c7ba8ba078db6dba25ff05cb41aa6befce5ae420a4d67ecffe5fadee749d5eef0ca8d1ffc1ec877caafad104abc32def2c8d0abad0eaecbe4afafc3d2bbe66cfe1e0a2aadb76db8647f9fba8a2fae3fcaa87cecbb12e05aef01dbfeccf0a9ad23596beafb1ffddbad084d93c1fccbbf37eadfb4b4ee57bdb634708cd11e99866e0bd1d78af79acabfbf7dabde55f15dc83c9cdec73f7bf50f4fa64be45aa7a19fcd1c3a499eaadeee8bc5d2284eff7882c2a5ecabbc5edcb18fc9cbcdaa6ad9dd391cbfeecc02ee68ee9ae0bceff42d17a62bed3faffecf63bfee3fc35e89d5915fc71a20fdfe9a7adc1a9adfeafadf1ff563fef8aa98751eeaccd0fce2bf239ec3e8abfef5ffe54bfd7a6f5bdb3b3349af68f629c38fedee5524de9e8abb646b60d8ebcee8c6dbd9543af8a55d0b1d5b0cce2405dcc49b9846da1a0ee60b5afdc6cc8fb1a2dcb592cf81905343ae69e57f556c551dad4ccc9b269ddd0bf171a03cd3d3f74eb75653dedac0fb5fa48e72cc40b5e11cd6eac66fae51393e80eabd89dabbf01d27dbf1d2c2ee5d1fba77deafe2effeabad8c9ffdcfabb2b7c969affdf0825dea7efb16a69b36d4f51cbbbfd7e1ce8b8a9f7ae210cb248aada0cf2e1880b5e2def03d4fcdac91f2a8da0ed63fdfa71afdeeacafa2fccbbde0ffdd6baefc60340f869140bebbaebef4ff55c1403746077df3e9e708e86b5d0b0fcfbcceea4dead13bdff874830b81beab92ddaad41e5d8bfae36ed7a8aab01eb615fce99bc2e1b84d32236cd2b8edc87b2f7ec4cc9fc8059eaaa763b0c939b3519bb1d3ddcfc39adf3dfe8717fd685bf3d02e3f8d458f5c0a88acefb2efee4e050ae14eef1cfe6180dbfcf6383dbf97edfed27729d0dbf06bbd69ecdaa0f5e03bc23ce99edacaa3d9e9fca97e4a8562c61d30f5abce1ffb95e2703781dad7b3388b7213ce32ff406ffdfdff98eeca14c51d3629bbb4243ca8e572ef24c346cacfa7904a2bd2aa4632e02235b4c626bd4cfdcf2874fcb78ec5778eba0da9af40dfffbb31ac2ecabea2ff707bbf91541c929d8daf0ced3ac489efcfb3caff8f82ba3b81dfbb9107a53c685aed9bdd86ddb4aba0e42ec02ee5ed3a4cecb032af062bfbb6db43de3bb4df763530ccacf9edcf2cdeb2ace05fc48769bed1f3354d4eb4adfdb5c3aa4c0e2cda638c126061303fac09deffde7d64d3934cca27c75ddfed7d6c90ffb5f3f2c5fab5724e7faffce693d983eb6dc7dfdd6d5fa11b1ecce15489a4cb5c4b01ffe667e1430906d3706e777dd7bbae95cc11be77debea8911af585aeb98c83acad0acf2b4add5ed9d4cddd9fbdcfdd8bf9e1accabcdd311248a3db3ca84ededeb5c7dc380aeae89ef8787a80ce2e82bba1a52a4a0ce4f43a30fa0bbaae3daa4e7a6c561205ca7f68bcee3eabbcb2328f54bd147ec7622bbafbd2eb527bd9dce8ccff94fc125b3cc509d3cfffc689c0fbee0ef0afc7164bf3f6baa676a9caafbc741fecca40ec47a1ae9150fd21777baacdf84cacd342d5f25a9bb7ccdcaeaedabeb54d26b337329bd1734bddbf2e4e6b5daec7e5bccb2ea77bf00b360a1ec131e5b8e93ac1b7f6b517481ec45ab7ceb88aec2c8e9d6afb65bd034a9faeb62391bad1cb5ddd921dc66de229b63cdb7dc5f36447162cdfeeafb123ebf5c3ceccc583b6d13e6e766bd78a7ab3cceefbff237c20329d196adfa43caaee2cd8e1fafefd8244fe7349d1e96c90dcfbafbc8d32aaeebaad04e8fe3f86f8cfe661ef7f153095a1e46ef2da5ea119c0537eb7b43f4728a4e8cba08da45373db482d9ce7b921da97e6c9e5fdbd9ecdfd9abced783b5f3cce034e7bed7be9e0277b82b9f7d7db7da7f25f998d4e1eb526d739a867d60293f6afe00bc74ac9cdbac62e7d3ad865f793cf0f0bb7c70a7bf48a78cd83c3ee5c1b66aed0c66ef7b0dacacb5abe5de549593601ebdca1ac76e04fcbccad43707cb3d9acacbfdbd9ae8de715fc20403bc402ca4e5e07f56edafee5fe5dbc0aff9cbbe91474cde7d3920f8a5c2b198f95e0badba508a7ef59d52ef8b41f9be70ecc30dcbcbf2f3db866d0f3ef7af1facadaef92e633efb4ba6a1f9b9e54031d5a0efec1bae8aadaea56d408e903c60e4e4fd83fb2debe4afcba236df92ccc639210068b4a19c64e83ec9a9d3c0c0addefec408fcb845bcdb5dc6e42d9feac1c26b0a4f1395bde69caee2f9faa28039d847ddeb6bd9f03fcac1a79e8efb88dbdee424e2ab1193aaa876c16fdc4bdd4caa9bee437b1ec60fcbe41ab9cbd04c1cede1f5ebdba9e70d68fbb97410da6d324f6b55442e12be6f5658fc54dafdfa8b3193cea845aaf784dfd925d61f1bb71dff2f4a5cd3aff3bd8d06e8717dd35dfc84203b7bbb8bde9c3d1e278fde76cbef6511048d8024f31f6be55be1d1effc51641cfabbaaadffae395218ec0facb1d25face54f2d17bbb597fe2dda8b644715cfd6b6e2f616978466feff76cf4ac44fddbeef5caa6ad7de28334dbff1a6bac5a9262aacfa10bd29c6f7ac1aeef138ee5fff82ffa6bd5a2bf9323c18b81df7c4bfead867dac2b3b064cef33e7ac7b05dfcc65d8c7c0ced21cb4d3aaeeff6f7d8033d2e5180dfbbcf6d8c2beddd7ff8aefc1cfce27cc7e8a8d5fa8a1596d5a655b3afc1281f6e65c0a0a4c91bc0ac6d546eeaaebccdf599aa29cfa06fa33fcb7cbfdfe87c8d4e0aacb13a71ec62deeccece7aeeaabbf5ccf3e8ee7cda1ba0c45ddf99cabfdf9da1c7c4aed86f9fbea2ca7caadfcc78c109cf6994a01f5aeefba25e8e614d67bca2fc550ae7edbfbd3d9deccf87dd10557a201f9a67b4acdadfd3ae43fa42d106cf8cda5fa4efd5cfff6f70eba48af7b89ef5f18044cf43adb21fd3ef9c3eaa70aa06e4efa07dbfebb29a8adf7aabbcb24bbe04152ca4cc920cafed6fa1f2eaddd2cfad3bbcef8f5a8bbba520c1d62dddc5e2b2f62aaa94d4f8cba4400bf2ff5c5fea7b6541aa6ca0afeb325cbd1bdab8db5a30d0fe46b62f242c2db17db28ade9f7bc3aad5e8c5d7f19cddbfdc7dba0abdfdb5336db5a6ed7db9107dcdba1e0df2ef3ae13cec69bedbec92fac984e4b09556e5c78beef5c6905f62fdbeed4b4f61a55a4aa86530eaa181aa4fac1c2cc84adc0a17dcc8e08a40d0df3862de7dfe93943aa2da1363ebfa1180f3cddc0af9fbf81ba4c0d4bcdc1ac8ccc1f770cc07c65b9a30fcabd9d4202ea0d7d831a0bdb9e97abbd7e19c1f66d0eaffdc66ea2b6fa1c11fb8ee6a00bde8add7f5a785a8cdcbaff0a55e902622cbbf33bbfff9bd6033aeafc8ecfbde0c5aaeeefe321c89b2e77fec88ed814b96178a5c5af3f9f60ef3c70bb5d8eafa4dd6ef940fbdccdaa1ee5eaa557c94fdc58af99d154333cba62e5da8ad90c37e7afdc5d3f8f573a84a2defbdf5dae490fbae4b5573a1916dde804b2be2af59f74cc6296b150bf4eaebbad8e2f1fdbb5bb19aaf460ae5d5ae7df49fd8fbd73debb6fcddabb1d60c3bd9f2f4b81c92ebcf7d15441ac96cddedcfece4ea997e43afbfc9e5d7c7819a0700a8acf5e83bb0e6915830a767a634e87beabdde3afbd56db740c36a24ddc5bba559cffc5cae5ad5a0b6abfadc5c7cdddaae109eaac69c1bd8cf0fb7573e22c5999ec2e18f66ab81bb3acd6d995bb5bc8cc20bff6fb23a5e1bc4cd9aa5fe3ef49f3fd4cec8fdd785be49b5b1b14c1bc309de4ad55beee34ff7c8ba2112ff7129cc638c09b6d8bfaac53e8783bd11e427e4e55ef81c9cfd5bfc4fa463ac8bdad90aa29fa1addbc29bcfb5f7f98bf2737cfa4caabbd6fbe68b92cf8a98ebae9ed8ee82feebe7f8e518fae0c6edf20ed315e743ec5ad17196aa0aff37839be1bedfe0cadebb2d309bbac0ce38c7c63dcd7cd4cb77ac9e5620fffccde589dda8eddac1cda1d5d895dbfb6bd1efd78676cde80c52ef59ad22ee3d42635bdddffa2b2d777bdcafae3d7476c14e7e2a08ebeaebd5f7ca8544c8dd61c5b5c2d11f0ec45ee56c701d0cfa404fdbee4d58cf6e4dcab8529ceabd2bddb5b0ad67a631310c401a987b0be5d7a26ce5ec7a894a42e1eb1fe6c5128aef2b779169efa2fc7d9f4adbb0bae1c2eff9ff8a4e11ebbc1ae28f8bcadcbf6657de18842bbb4abdd0ce1a6acf9357cfaaec47a4e8d5de9f04ccb33e75f3c719208edd92ccf4314ea2c58fa9f988fd2d3ec0cadf9b8be99cb5ad952893c3fa27c8c8a87d1e8d89e5002ddb686782cec4f492deff7b06dffe0cbda6d311bc9f63e118c2ff0eb894128fb7b8b9ea5360b9f05e4e750a9ecbf44eae76adaad064a6c06d5048cf99e603e1946e2b75cca0bfcc240bb2ed7dab8074eaa4d5c0cbc5ad53ca4642d2bcf0e62ba77aee9b6dc8be84dccfecdcd6ed1b0bcb8ac5ef2c6fdb7b18c1a0ed8c1dd6fb647f59d5dd07d2bf3116bb47bc752d144b1a4bafbdd2e6181dead3f2e6d2bdbf3fcae57aacaa9e188253cccf354c2b6efc2edf7208c5bb5294dbdedfadad1fd31f9cb4eb5c9eb19ebef8edebc1aebb73fbcad9bdb2dbdbca3431ba590df5122c33edc3f6ad2a557e3ced1a64f389bcf84d8abaee439e2d56d829bd9d63fba73f95fbdcfedea1b12eef08ec23c3c2fad4c0ecf9d1fe7e6b8c5aca8dabab4edece32596dde79f2bb78f30f3ce4f3f76adb8acafb1f8520f48b5c22348efb2ace3becd9ffd33f6cb1ab39976cec3281cd1dbf6fede6a3bdc2dd53e4a1d4b88e5be975be30122ed3611facc31c3eccfc4799c0eac595de390bc0c8f6de656eabd78929caab6bfcfc4ee25ec1badc2cebeaea8e3bee916ef2fc592cabefa7a5e227302fb6cdaff513bb3c2feb0e5182be6f35bf8fb0ccc3f0772dd7ee99d3acaea2d7fac3637ef5e3eb0eccc1ddffb068109882f36eeed1cc3ebe3acfcefc17b8bb5b312fbc67ee8dadee337f58fbdac4bada18aadfecfe2ed2fef051deccf2fd7ae3ee3fcfd793feb4fd3bd9c8fd19dded2fb1e96dafc9936d7c195b2d1ebeecdeb58dfd71cd7438dc91464c3d9a582bcbdccae52ac70c8a67baf346ecbfa1a9a8d662abba8baca4342efacd9a00bdc629cd49b91c4ea2883749b9b08be4497c4fbf83066fcb1eff606e6bfa2bd94c69c82dbd95374bf8dfdad46defc6f1b695ef5a5147ecafab1d6b8cffacfcd2c6343feefe6ddaff6ac5ecde4416bf2d279a66a7594ab3ef8dcf22efad52faf9de934c80387d9e5b0f35aead187770064da0dfedeee7d4289d56fe5f5cb106d4776705dac0c4fd6bb9eccaf5cc38750fc2c3e062dcb1bb835cd7c8ac0cfac3c2e5cb02ca3c7bbc3a7636eeabbceb45be5b52d20d6fa6fcc5daedbbd69a31a116cf8abaccbab3bda7fccffcdcd484f7fc39cdbf782db4760a57459e296245ebca63f51c2dccb7ad8caecff749efa51dbeca02dfaf6cffa49f4c8afb1b0ddabccc4cc3f99cacc68ec34a72bcb0cf6afea83f06fdfef5fcddcb3a5d3b2f4515edfffd26d58dd5bff5b823fbedf40b14afcaab09ba47d20f6caa010be294bcbc0c811ec1b87badb6a2be488b9c2f9a3e1bbe9b924b1aac2f962d7ecbd6c7cb1916aaf2d40fa6cc063dfcf5ad16edcd53ae63cc81bdbb6aeadb0dfeced3cf80a8de9e128c2f7fa61ebd608e26b3ec87490a76ca986768bbb9decedd8daa803c9b0d65608fd0dcc38e7a67de97d9ca6ce6d15cefe4aabdfb00d596acddafacce1ace22aaa6dfeced1c6acabdc3da20523b1d2e2ffffc71cc73c0e70ec531bc3eec8e6117add64ae4e1fcbebaacaf6af2e1cbbaac470e2ecfdcdcd04acec92cdefabbf143acccb3c8dd0b6aaa953da556d4f2eccdc4acc9fea1d95ab6ca1e8b8efc87e2e21b2df8f00af6654fd7dafb7f1c21cd550c9ce36d7b540fc37588bde64b242fec58cba11ca8efa2ab1f5bdcf8566e756e2b438f929ddc1bdc187aba83aceef15557efdbdbe51fbe71cf7ee747bedd34ff9eae68db79cfdeda98dcbaa8f6fd262cd0bb5e62b91bcfd8ffcfdc3ddacbf0f79566bcaaea0fc776cdc62babfa6340dfcd21a7ff354bff77c928ee2fffcf870bb9435374a08c203e391ebba6ed2bbbbfc08efba09abeafe5fa2a7da5a88d8093ee7ce0cdcd31bdb97acdfda88aebee7f6eecf434faead8c03516e3e141d0870b8ad6382dc5d358fedb12ed4d636d001bc87fea47825a6da588628d9fd5cd0a0fa15fef25cc7e7b50448c67571efcf1bf823b58241eaa816da415f8fc4e0ee1ade554d419aa6b01ccdee0d96a0b9ceeabed8bd55f0caee5d1adff12c44385d231abec8c8dbfa69fc7bddbc2fedbbf66cd9ef95c2c428461081fca89eddaedc8f83cbf5733154d2700f8c35f4be7dcf538b308b5349119baf24c248eb3b81db78524ca6d7cfcdc57acebfde03dfdae606cfd0e0baee8870decc22218f32db17bdbbe688ae4f65682dd12a9eb2dcf6f456652b2f38c99cf01606551f8ab4afcb0664d6ac66a9c34582d6cff71f0da32073caeefca7da63db39aafb0ab3ec70ba8bf34fdcdfa64975045b862768ed59a8c4ced5f97ffafacafa4850adefe4faa3e4ae3cd0b6714e15e1da5204eafe6c3e7fadc7adc12de3fad25aeb8796e6b70b8f0bf14f481daead7b53c825fea35d3ace4c4f28e2ad4dccb29680f9fd0c4c8aad6958ebfebe0c79aafceafdab355127d2a0c1d23cd2bc1ac9cedc483907ea808bf0e22baa6bffdcedf95dadabceb3f9aadafeb326ad84ea582dfc5e66aaea0e77d3dfbba0eb1e7bdd1452ffd8beaaacbaeca3521a84fdcefba1e3c24fc39c41e743be8de2caaf1f7ca1dc481eceb8ebdbe71a5e5f21b0ab4e48160d0e2f8b76cead0aa5fa77e14f6e8c92e36883a5d8bad3efdb832006589a48273b06f36eabdfa5bcb10ef2d0c77dbefed1add6abacea2b55db15c1eefbb548407d8c0c89ae70baf9c0c4fb02c124ad6bfb62171cafdc096cb0fbb3d4fdceae6adf61a163a3fae5a7cf21e5fd02dae96aa37dccbf8e10cd927daedfa0bc7bcbd7ee0aba6eefd69bd7bd8fbf67dc8f4b2e9395c020e1f46c7897fb1cf62c7c33f133f9264cffc70baa81c6bdfe272d9d3b4ecdda70ef1f8aebd0eeaac1ee04cceb1e8bbfc1266c9ccfc20fe1496b4faeefdfedfd15c49e178c4f04fcf5c160a0d5fccbff5192c4c45e6678fcd8fa27cef4efebbd5ade0eaaf27906d8b737acef5f32def9e1b0ea0141bae4aa6c32baa1d98fac2e1decabffcacd9ced63310f454e0ed47ced55dad98cb4eafcc4cedcc7dfaa08db075de937c1cee4addf74e74f28c7cd95f8db70efffebe23baa1aebebd7e37b9a60ae5960be698be8d3aec233cedbcb5a8acadaa6d17bcfeddb92c754aadfbbf5e611b3a4bb024108b17a600ee62cddde25bdebfd5ebedcecc8b74afbec0bec096fde1766c7a36bbffa9e95ef0355ba6a1cad9af405e8f8fd53fd072ad381befa8ede8c2fa3b1920619f1f93bacbb0b4aef7555bcce35d5b7de83b99c7b7e5db8cbc8afcfce0183eba1abc38379e7833e36c60cccc090f0feb2f9cdbefb479f4c62f06c501b0fbecbdc6d94ecbacdc1cf4cc83fa15ec38df9a0db13bc9b043e3718b21d8c1c05674f4c4ef5e1d6794d52f83cc1919a33de91a9c72fdbc8c6e4faa00a83be25bfafc96edaecd1e0f8adfbe83383f7a52a51ccbd3ea4e0f9ab39ee07fc1edf32adf2f8486d0efcf17bd26aeabb9f5d0d6bca988bebd2a95e07aeced2f27b36a12bcaf6bc7cef4fadcdb765e0a1b8aad3f47a8ae1ff3c0bdca14c1dbaf81d3a66daf7b9a0ba07ae5c64326eaf7108367ad0ecca5e6358a593f6221cb84dfecc05b9834a4db23dcf0a5ce0b1dfb321ddf8ab03f5a6aa7d15ec231b3adcacd7b8219ff899d58c73ad2dd0be2e0167f9fcade23904b2f7586a45f1bbaac037cf5cdf018fab812bf8aeda4fcdd2cfe3c38af9e85106efa5b2ca5cacde5486bea5fb5f2a2ce4a1ed1d69bd5e4bef83d4f14cba5de40acca62da2f492dcd7beebf201266cca9fa8f119e9b5edeb6eadfc74ab1aadfdcffbaa6a8cae4f59befdc5122ba7ce3a0f3a75ccbf5a4257edf73dc94cd0f2488fadef0c3545849ee12e9b506a62319c4a6ec608acd014edc01e9ac2c70dd1bfd6de16fed3f5c5b9eff6fcc9ddfcbd9137d9abdcffdeed5b622d1dadf2e588e65fd438d7857c6b6e4a75fd84ae9f96ca3d449d69f7f0bfa4dc808a4cb3dd1abff26bc71dc9a748bbe2ffb32eaf8946aa90fcceadd54a787fde34b1cc2627d88b9bb9aec03045e6f772fba805207ba99dcbfd1b0f6ae3b36cd655e6f7e3acc6ebd9e4cbacc35afb0b153ff4b404da73c127dd5e6a7cdf0ca2359e95ba32ddba568c6ba5f1bd4cf90951b6c3e45fc4abc84aeffbebda5e41adf03fba1ad1faa7cacb8cbd3de99a5e793bfbd257a34dd9bb3bc03ec8cfcd820fa87ba994214eb2ccacf8df4d2efbc9bafab565a33d02d11e3f9fb0a5dd4ec5affff7bebc020abcdf78753ffc08cef5fb41c339a590578c06b77bee7c5cb4ea453cef8b14db2f821839ebed31b39e837bbd3c4e5a22acefec9fbab6ae5ebf13bffe7a7f713a0dbf4ce1d7cc2fdf2111b7c11e6014c5d8938adee41e0caefe55d77bfeee12388d08344f3b21cd67b851975b1153a9cb1fe1af09daf28ebdf13bf547a1037bcc21ea49ac0e2725a981d23acc02da384726023cda8fadd82edd2dfe962e43ffd97eef4b3aa3b5be6c81cfc0caa9b0c6d6c39e8df12b84df11986dd661a0cad34cb745ef5aed8c913d63eeffd7b997f50dab1eedfbf2b4c3b0828daaaefe96aba24cd5d2573a632c2f57fd2a00ce65b6127afe1a9eebccdb8dffec1eeb62cf7f5d6dbfffdbd9c23bfc29917a5f3bbdf181771b6bc9e3fb0483abde0c0308afdebab9ce8e508f37507dfcebf3c3f2af7a2cce0df2f6bb71fafa1e2a17afaab6beacd5e9cd4feae7dfafd8d5286cbaa03155ee5d30c1d0addf2eb1c06cbfdc57f41ebfded4aae70b4a629f797ca7c2ff93b98ceaaf6ddfbdd1e10a14141ba9fc4bce7fa6e678f6a088bdbdeacbd897ceef8a7f1f0c59519b50cbaec2cda3f38349e95da28bed3af47beeda7a4ec6b8fbc0e7785aabc6df2edb435357a1ae0282acf04f1ff2e7f4ca809e76f0a69ea9f5a2b7ecdd3aeabfcf9f381ebb48a857a19daa19b4def106ebffaf7dadecfccab37ca45fdce899a6b56bd3e63fafdeee6cf396b1779fbfe95aed42c8fadadc0e31fc1cf51c2ac633fd73fe0d7cb17cbc6e8fb9e8bc3c8e44b9933cb2286f43e2d4e7bdba27aa8d5acbbf47d284c26ecfdefb6aeea1f27dda938ebe48ce39f7edf18bed5dbafc3bfffc3cb21166afe27e2a9fbcf4ab9353d080f36bc34e540fe720fdef339abafcc10dbc1ffb16ce5d7a2d416cb84ef636a3a40115522fd75ecf48f3b1f0582eb8b5ffca9fbeb9f93f2cac8ee8ddb62b56e826490abe4d8d3ba43f54a49fa670ea9bb0d7ee4c006c3eb9a3ec3a1dd72a2d8adac1c1cfa08bebe797aad5548c226adebbbb960dc4edbec9efaef18837a93c6dd6b8dcf2672ff5f1bd2fd89ac7cdd534fd2a3ae743863b855ceeeef0d2bd5c42369d8fa23ccafbed1453d790f95ac1af5df761a5784770e5e33aacc0ddbf57bd107b692dbbd33ddddcf7ebf7de24cebcc287f80eeae5e2c5f0bb06b6e7d3adcd6dedba252484dbcd56af6df1afa7cc2a92dfb43e935bacfbfbdeb3f7cc4e14d0bfb02baafddfccf578260bc3e73da1aafdf34bbd6e8bbb01ee8ccce491ceff4ca0bb5525fc34b9fceb1abb3f7fec33a6a8bc352fbb47e74e3aaa80cca0cbbe4d7b125f090feb095b6ebbe1bc7663e0576da63870aa3b31a2adfb416bdbd99cf3a6e933db3bf182c1c17d830a6efeaf1dc1aca7fe1b376fda2cae11ad095a7804a96b958fc065d7554ad65cfe7b572c50b71ee9569efede1698e55e2dd4efe0d8bda7fafe3fac2ab86edfa4c1cde7dee3b9e2decec8e4ce7a2b8408aaec521189977484b684a986ba17d71f111c91ebb1cbb1afd6ee6c8e649945bf748cacbc4cbf0dd4b0da1ed4ab35f21bdb05aee2dbbdc2b4f6a80ebc58d6432d171f6be3acbb7b3ba349408eba0e4ba14f63f7d908bfbe1c3f3fa03aeaa51d38ef7ffc7a97dadad45a65deef8031ea5d6ad97c0ec1fccbd4ea8ee6be78b7f8b8cfdc9c6d4536aeec3dd8beade1ce3bbeb6edf6eae9aff3bb6d2ed6cef22194cf6bbc1bea650f8fb06230ecef54ccf02f627cc72b6ace2a8536b0dd58821e963bdba6bfde51e8b551bdbcde27adfe03efa4ab33fceb2473df07e817442db37c62e1d6cdc8134e41bd5faecb730d3bfb9adb14060172eab1b8190375f5275b71a88d2913bc4ae2bee8aecce7eebaa88e7a8cb1272ba432c3efad3b3f0d3fa75569f754b2eb4a5e5afdbb560b7929e5f858acf3dd3eca3b6d374727a68eea5c5db7beb8f1ae9d8e2f1c25cfb74456e8d60dffb8cc2fa9acefb6cb141a13dfded6143e0288a78acbaebb1055d6b1a5eaf1e1cfdfc83f65cc2882f8cda58be0efacb200cd77d9b2e6e6b02cf47acc2b665eb4cebcc003a1ad947be5e6e2c9ba8ad73a22bbca7f3bdeb31c35a7c700006bfdfde2ca7f328eb1e3ccfabf3bec5dc33a45b83f9f6da1df346fcb53362ce8ad9115f2df7e49f07b09bd6ae85c04cbac8bea75fdd2ed40eccaf0bb3d6eb81292c169e1f99905ca3b3f843e04c8fdee57fdb072b4ecc976d64e1dbab7142c1d4b11aace50b1ec895ad78dfbabadc3418afd9bda37f8752b539e2d6e91e59af36227b77b468c5f6c47d53a51ba6ac97e9a5a2adc9f0bec65bf7eaebaf70bdd31108db31bce4ac9a0eacff5ebb2dfadeaacce059837d7bec8bd6f08a2bbcead1ae7dfd2ec1af744b1ed56f62d72e4adcb2dbbfbc304dc0e0b2b02afca0f8cef6be9b3d76a812dde6fcd8bf7a30aa1ad2acdfb8fd1bb7af7feb90ac03ebc3e534b25dc57d948b9b43eda1fef333fc1fa0608d0f31f74904fd15e8fa44cfbc7c282a8da97cb61d89c6e5dc9f40bc7c185dabeec0ffb8b2a296bed406ef09bcbbdeadaedaa2cdab9bf5e1fb2b1bc3beeea819c10cc5469510eeacca012bf1913ac88aec4abca7a93eaaee6363e2eada239fe6aa05c13cb7ebb0dc91a464bc9ea0e4ff461c51a5bfb47fc307c7fafc89feb8fad8c67aaa78dcbbaebbe95dedf0edaa7d113e805deaf049ddbe819e6b0a79d2245eac8c7f25a04eea3db5de7af814267e0f121e0b20c1eeee515bce8e7d23bc2b02ac94bf45bfbbc1adfa7de82c5cbadc27c62dda30f430bae4a1c761eaafc954b5bddc54dffdeba6718a1d17603c9f32c1b13ff4cdaa48e90a15caf42dd1dfddfdad4f54ce5bed7c07eab985c56e8e250d3bb50298ac52b0eddbf4deedfe7035e6fd41cf47c7ef7e01ed2ce889be7cdfa5d4eccaa7eabb3dcdcc1da68cfca1d3fcfb977bba497c517f95397d4dbe52dc00cf50e52c734ecab3ab948de4dbec238cc01bcca9d1bbd8f4eadbfceba2eb8e602374f7bcfcfcebfccfb12dcee69fcd24ec8549f5f0d92b5eadebea5dad077ad292c87aef16ebc14cd7377a0fdbedfe6fc15eebe07eea71bfde01601be36febaadb3ae2dca0acde6ca39b55fde11811959bbb69db19523b846b4b8d5d89e9cf94bc0b130cf7f12bbfc6aeadee99c2c4e44b66a6b1addfe136a9caca2cb4ebd7c8a8499d0581d1c5d13a9c50ddde1d76bf24ce407fecfcfd6b2c3afdd82ae1ac03bd2dbf8edecfd3f3c1afe4add4dcb2ea58df0cb8efdc07bf5baba2ddc4ca2730cc3e8dda2ecd712fcdac302f9f5bdebb00a783b9f7e2affbb12da52086ed9e66ee3fafd7100be224dd03c1e6ec5ce8c66ca440d4f2803ebbbae63dee4faf4da06bbca3f5d386cef9c1afe8fbad7c1ad5eea85eaeff21e8d4daa6bef5ea2d12fd94c54bb5e3dff3cb50bca988dc405e2fd2030dcf7afca9bc86bab364eed6acda2bd52ff1aac04d6ecaea77bad6ef854fb9923ad9dec11e88a6f0ff80228cb2d982514d5c223ddfb4a8a8450ebd2cf544a3bdedaba6a422faf78ca3c766dc8f6a7d69d9d79ddc19fdd8a145accb307cd1eef372dc0dd95dc75eec1d6db2efc34ab357ddd7aacf4de9b1adb4aa5d1f441ec107beefada59dbb70abdbfce2fcbf2f22dbad60c440eb2928dbdb0c63bdbbe866ced7dab7fb1f5b0485f4bdf69fa06ffe46cea14aefc7a9966afcc6b9c0d8afcf828e3b5afd5f6dffafbceaabf09e8e0f51ff0b4b100caeadffbdcd5666fccc3c28196d430ea15f9c6feadaecea47a1d92c36ec67aed7adcf2e1ca85dc64acb9a2d9a6d3015f4e8ff364d5ad1adfeb608145c9be926fe147ce92befddcbfc3ea016e1558f3e2baecf0af7c5cf6af55b934ffaeb5d9e1c8ddfd35cbbf77df6c2bdda10f42522e6fad9bfcbb51fb6fc98cf9c52d5fbe17a3ef7c2326cd6143b342daeed22ccf883d0fbcddbb81c4fed2d4cd36ebfecfeaccb1da648ebafc6944fccc8d7fbfdd152c4da527c3dc6e0ff200cbbd7c2d3e51758ddb03b66ae3eef6d7ddf888990770ffb92cf33efeaffb6b8de6948fd7cbcfa7b8cdeb3cb1a9dc3bcdff16a233809e70ae0e5d8073dfef14e21578bba77d4dcbb9704a4e74f98d40f2c4fdba6622a55d0ffcf538cff77b29f0abbf72db0c40ed6dcc0ce4f1cfb2941c183fdaabc93acc8ccecdfc2c9b73f9ac5b6adac316aaa0be45aaff08d8beefc8cb4eefc7ed707a6670d6ce02dfbfefa38e7a5d1a666b1b9eecc951f1e15bb5bbaeba5f4500d204d00055ebce66ab1c3a3cfc7001fd6df5fea2dedddcc0dec15f88a13dbf34bae60b2cd5cd449f8ade66fd5b9ab79c4174ec81b0b942cfab1861aea4b752b943be5bdeba02ff2d16c91fba3cbee04bca0ff7bb1ff3947d2d0d12fcdf7f96c048aedb33bce0addd3768ebcaeef4d5aee5ba46e87fd48aff3cb0eaeeaae8d7dc1d9bafa326b93d81df61a078b73bbdcf6b7eff382efa0eab9eb5dd6eafc9391ec99e245291674f82ae59943bfd5a48f4f775f8cf76b67ff6dd17a21d3679e1df1dc2dcbbc6484bafa5882191a1eb5eb3e7cb4ea3c8ab30c0463f630758d2bacc95d6d0acaaafcbd5c67c22a13db9a3a5e84b5aeea62ba6e0d0bdd0527ddcf0c4219f8138ed1c8c8d6b6f9d10b78f06f94a33790bfeb4b7112588792f01e9bbf549f35afffcc9cbf7a63b3ef5cf31d7f9e8fcc70aeb4d8ab61ee214929fb5c895f68cfb277dfc6a1eea0b1cdb89d914da9ebb34e6af54535a4b622f4daebad33ccff8ef1606dfffe8d82f2a40a65a9e90e58f65e0ce1e6b0976fdbcbb4ea05f37fda5ff4acc907bec9dd5a103ff0afce24daec68c9b8cadcb4c0ef98a5c8a4d5ff97cd0cdac6a1b7ee1fc78e8d70ad5209e3bc10af2046f4235a7b483c5cece6d1aedfada063d7d3df35fd4c4c3bfc58d84dc69a3bb3dfb0cf09bbf195beec088af73e1d2b7a3cbeaf5e78af5752031dd0feef4d6e262fff2fda6d772e1c7d9144877caa56ddfa93aa2272e6aa974d18dcde012a9ab2cc2cf47d23aaeed5b5bef5d34cab67b744c739d6ab0409fbaa878bebbdccd3446a0fd0ec51e1efbddfab82aeedf1ed885adafb49acbf8fa3cdb77419cda3db6d695b5be3c11f79502f14a94de45074dce9cb1130e8e8bec6ce8fa6c5d6e1abee081dd674ff407ce3b754bc8caacce449bab9abf9c7c5d3f9ebeef6f4ac16c98824ba2fa92bcc280ccf703afce8d634c5fc0b6e22fb96feadf9afa6ff4f33a63e3be45f3ff1bbf6d6c027faef7fe4eaf6e94fb5cdf30cbeacc2927d0e23e4abecdea1db8edccaccf76a0e8dbbe6fd013ee7fa5069e64cf3fb97faa7fe9ddcf76edaa51d4317242b437d273bffbe452897a0c7ed3bd0b2caffe3b94a1a3d5cb3a524baf119a9d8ba0b4b94a909fcb22a3efe7e4cf3ad0512d6ddfaaa942c984cbf91dd7ae1d3b336f377b2dcd9fe9c9c5654ccdc56aa9592fe3b9d338df8cd9db5eed7a50d3e48a1adfc41e0ba3f0053a5aaa504a8df43c8cdeab264d1159bcc3a5e5eb6647cb1917ef50b14aeead28ff6f9feca14301ce9fc4ee103ce328e0e0a9ef563325edd7ca5ece66c85affe200490fad170d8029b78dc722d9e1f6cf3cdbb1dc5ed3acba41fcb7cc4d66fe611fefedc95389e41181ffb33dab62ef7ddb6e51aae5d5ddf4e3bafabbd966daebda3dc56d54bddb67064cee3d8b998e4f031d41e3b5aeb30babffdac53f8fdceccd4c0ac829b5b0524f887c4e3ae22db06c1bfb75ca162b949f85d6060c35d3e48c3a4b32b0f52fa58dce4a5aae2a5bd1beb6b3135abf71ef476cfd5308c801face9f1cb7084fdabc63116d1abfabdcbd0eb0da5c364bcab8c1153e80dcf7a7bffddfbf867e5cfed1318be0fdcaedad0169faeea2cefc81724f8fb94888fbbc6d677cb4c2305dea7dceafc423e24dedfcc0cfa1339bb18b119f75e8109aeef70f8ff023da9856a710aef6aa884af54d9537b4ab04a1f4ff8f5b0adcc2ae5cef2ed5c6baa342edbf8ecf5cb5ea9ecfb176e5c3313d0e6eaa9d2fe198140fa92d571dbc04bc454bba18dad3bd90cf26118ffe020ce2bb0e1f3ec7d6bbba13fbab316de4bdc2fee20ea6958fc46531417e7e8e8eca7a7dcacf0d15ef0be9cd70f06fdc1ada3c1a3fd0590fcf704b8f1ecd5b38dbdedfaaaf4abeebefaebc4efaf90ccd3bce206bea9612d2e9acd5ac2c10ebca3710170ef32a82392c4b67e62edba3fe6e675e13513405ae1fadfff4f58f305b3104cc382ab4a38fbeddc3e9dceefa6be23cedb41eb22eecff193d8fefa3bfa4e5e3c69aab3e982ae9c016fed81e66bfe53aeeddf34053bd82385b6d1fd4378bcefea13017f9b76c73a2f507bfb7dcba264d5b6e8bc962ca52a991ff8bdbebda59e77fe9c62fcef1415a993ffe4cad9fa3a96984489bd9edcb1a4bb134735cbe7d6bbbc1df6dec8809a45aaecab1bcaebaf06fbfe90cbd8dab61f50bca34156b47f4de94cb3075d37e9c7ae8f7f540ed6cdd9ed7dcffb90d24add5dbfefd06ca1e6ebcc4ba52dd7dabc8106acccc7ad0a4dfff94d9ccc1b104bccfcdccb8e3d6c1dc3f88acc4e3fbcf5df561fd7a0b1eba7dd58f7c9b05d9eae7c5da7d5dbd4df7ffa1dfcb34f9fe0ef3bbaaba9cbabee477cdbc9f0f1064ee1c1fc1ebce136995bfb7c8cd22dee5fdcbdeb1f457dd7302caac50dc5d9ea07fe01cecc5a7cfebc915e8c7eedd68dc1178dbef71c9771f3c7e1febee6ddedf6cdcceccf2a3af1a93a3bb4eaa508f72adfa6d33b9b358cfca16d4f7dbe3ea07bb331dc552be2145932b6bf94deabf7aeb0efd59b7be6ca30ddcdad948a87b1044bad23cddd45abb2bae5bda00d4eededcfebc38525f58aab0c5c7dcafe8c6fcf0f44dfa44d38f4fd1faae2e6bff4cc205def25be1d1db0b50f2a57d9af0caddb95eee0ba96c435d2cb737b7aeb6d43ffa29882eaaf2ba84f9fe1a7bc10ef0ec856257a8a58d9dca1c47a6e214dcfedbfb2e4e5d8a5729fa2db9e61b2abdb5aa39addebc3e7a6ed4d24fdfbdd5edf21cb770df102c4edea8b6b0dedbe1e8aabe8cfb8cee5820e6bae44dd4d22a1e65fce8bbec9ebf7bab8db20e4e690068168732ade64edbfaa4164abcb5202dedc8e1fbae9551ac8c2f01a1ddda29fedbf45de5cff09b8bdcdc21bfa660ae5ad6deacbc0cabda1d63abfd5be47bf8e47babffd0ecfabbcdc99bef9f1d5c5a4ea0fbac9fc3c49e9f56640fa5afe6ede1d03ab98dc417adbf06aaafda17f4f5babc83e12cdedcdc92fc1bddc6007efaecf38a7ee3a231ab7e3fea538305e1d0aee81ad84b188fc4515da14ace9ae82471f2ee50cca0bad2f324e1eb88df5a55d8fb4faef71b9cbb50f8611d43cb9f83e40d562ddde15fbecdc0ead901df4f8aa25ad1dbba35ee4ff37da9d46eccbd51a4c03df52d42c1c2fe82f930c9dbbcace5c86d38a79b5fda30aca8c46ef7ba95cbacf11ae39e0d200de44c5ac6adf350eaeedc82d4cc8b7c37a67a3bacac95dab3eb4ac3dd83e5237ddea307ebebc9bfeb8d3b8c2a4020a67e19dfba305555f2c22f4db7c0707008257ead57d0fb9d01ed6bb5a84ee1afd86f1ceedf8cf2d59251c21222c67c86dcfdc92a21daeea401fa9cb7a165adb0e9cd739aa3ca7a145ddbfdfe8c5e2f2b1bbdf1cc3ffdae9e49f15f7cbc3bebdbb49acbaeb5abbcbbae7b891a5fe7a4b0b5c1d7ac26ec6ccce3bdb822cb5c41ea5ea06586f49fe08bfce04edb2306bcaf5f6ef1e987b343ef5dc10b6ad45bcd219cce26adff0d12bbae7c15b5bc5d5ad11b573b931beac50ac53f4ddfeed5de1dd5aeba82f7ffbd6dd5aaa6b7a1f3ded71c8b2a1ad9f337bbbf447ab2f4c7bf04ecb88b37b1c44efc3c12ce9daee28ffca447f388ddb5f9c0fcd4042d08241be3aea1e6dedb02fded70aab5c7c7843e990dcd2a93b3a9f208c9be3ffefc241a6daa9e6effc7d9d1ccd4ad11abb82dce281afbde2bfc3faef4500ae10e36fc90b6ee231f42e4de8d1bb67a5cb6502f26d2ad2fdcd379f0f0cfc29c0dcb33fba67ced17dbcb5ecf5afe7a4f505f5ecfb2e20e11adafd51dbb70dc63effbe81cbc67d5a38dfabfe66da42e8e09f420e4ef21d54ed112b6c51f9e6de590b4bea72581ddcafbcd2062a693addea977d8c6f42e44508cbf57e8d9b0bec9b5ed482c392d1d6b7bcbef16a3f89b446ea3dc90650dc3b0cfeb6f3edbcdd3c76fd694a268a4e15c6ec8c137cf9a9e76caa9c7edfb5203ced03ecff2cb7caaaa2abd5f77ee874ff7d4d7fc2cbc2875952c358bd4a1b1facae59ee83bfcebc5be7b6038b4d67794de3d4abc4cdacadfb0dc19e3daa42e4cfe26bdfa64a70a39f0e2eed5f7ca86fcea7ad4ab1d6faefbc24a9a3fdebf7ebabf0ca5ceb9270e4f7cbbe23b2fdfb0ec93dbf6f1daf5fc4cbcdeaadd8ced3032eb785cfed83605618cfeb20b74dbd9dbede9ddcdcbf6f1efc5d0e529ff24e3ffdd5ad0aab7b3bbd9a2f8c05bbee448a8ee8fb46afb3ea1905eabfdff3cc1c7ae65ba0ba2390160de6d9f75cc7daab2acd6659af93e291bb7a4e02853fad4adc0aeaedcb77fd672a65efdfc0aa57aaa2f15aaf6cd34fc60b1bba8f1d2bc96de82d7ee2a31b24bf7eae80430d7af2f0d883a0c8b3bc28bec8cc3ac6efe3c5353e211475cef82d2f1e7c53ef0ace6e0939ba59baf718b719f4e967cda08d0cbece3a60fbd9effb75cb52fcc0dad5bbefe4d1f7cfbfc0cca9c06f53fbaba19ac382f5a18bea27cd9d0cc1dece7dac3bc7ae63ce71aed6caa5a5ef6a4edb9e66dc6c3d489e17dab6f942566bf3f65fb45adb0f77f2cca8dd3b8cc5dde7196e193f2dc8fca15e272e2d0dae1a0c17fad5fa296f1a27a0eae8bfabc38c28c2d6dc0361f6bcec4f0bed6cab5726def4b564ecaa8b80dcc9e3c21c7839d54ccad2abdc88ea47f2127ae96e8f41d4674f46b04a6ff7eef3e5dcb4b7078cb6706bf8edec2f30bba58c96fc8e7b3dcf6dcb6acca40a42afaff3ea73dcd8ce2bddb55c65eef6c4f8b2c676b7e32e6f8d6fabcb5afcfe5c978c17091381911d4ffcdba7315abbed1f4dbf72dabd76053faeca562a2c9dc96fdf3a3a54adeeefbec36e2b1b4f4984ecc5ba7f1d34ba376ab4f0fcc4c72e887d6c33cbae1cc90f31b7d99d7f096f62f3ed9fbba88eef2cdb5feac0fd30c3be5efdfbade0eb4bcbab3f38cf42bb89dc4fbd0f8a7caf39f0dae4edededea17669bbaeae2fdfc231df5fa87dbf6deb41ad67ae813a1416b549050ed02acbfed8acb7cbeabf2a7a3c18602fa0dfadaedcf2bcfaa5dd0fdb9b39dfbd56ecc801ce078af6924f5ab76c1ac4b7daf34a6fd1aec4f9ffd13f8ec89f9f47c7dffc575d7ddaafff6ed18513a4d070776eccd33afb3b9ebd46ae7f3fde0821c8afa8de5eebafa7e55b85fac023ea3ccad1dcbdbb0e1d869707517c8fc0c45ce21dcdbfb1fc2757886739adbfacdc2bf7bd8d980996c05e17d87113c72e56a1eb2c1dabdf76549f2ffb882e5c6928ede090fad1abaf784ad28ad6ad292e98900ff982409ea707ebc6304ed79444c3ee059cb3e1ceeeacbd1e4ac23d5ae5a237bae75a8ddb11acc4d32e7af2bfa3382fbb921e6617f5ed4c3e9e3bf79def807efebdcfddbacda6bf4c0b76ccc28efe7aaf8cc4dcc4f1e00f8f96c05254fe86bbebbacde28ebdc0ef0c4c973469834b1a1e27dbdb5b9ed7dec79e187cfdc9fabcada8e7e3dfcc0cfdd2381e4ef2981a4c2975add70c2cfac327a09aef0fa7256bef58aa314cdfed5ad1bf8cec6fd48dee9a993e7cff4aff08bcaeda3dce8ff43cb2e54224317fcdebed4cfffe9e8acd4ee6bedfc4eb5755e375b9ed49ed4e9e00c7a2e931bcf90b1bbda4ebc73020c5c1367125b6aaaacb14aa3d6f210ab4c0baf89ea6f33e230be6eed9482debfbaad9cabeda3db6ce154dd9734adfb64c3d9defa84be5b35c01cdaab6c4eb782b4cbbbbabc61a7fbc1cb25ec46bb2affb50e3b536feafe6ea7eabd69fcd0e1fcacb14bfd7e1deb52c3fe6a61d78bce4e8ebdef6bbb210a5dee6fcba66bbca5fdffacea7dbece63ab42af9afeea3c2c9b1580fe2dec9c9606eababa2a7bafabbd6eccd34b0ece0d5efeb210288ceceadffe3c75dccda6a3983c8041ecb1fc65ae8edec9e63febe295dfadf6e4ffde29b31ff89ffec4de8fac4e9f260e1264a79f9628db94b419c69a4afeeb9ebadcf4cff5ed4ecbe5eaee4c2acb0fdc4a077e07aee9f92121f2a70234301ac7a733acd682749f83f13ed8537a21eb18bcfb65a28d44d5b5caa80c5c1d4deeaccabf6dda448b4bbf68c61bcc651a5ccc7aab9ecfcfc5acf8e12adee00efcce66a94099f05f9c3dfb0c9b0a89714c3d7e0bea874a2fdd0922fb0cbbbb9f0aa95a0caa0dacc0e497cb41fc41addfeac307bff7dadab0fbbdf4edad28ceffef943dc7a95f3b2f542b7ce0abda38df85db9828ac03c9d830f72ecddf6eed5d2dab0aabf82a12b32e9b9e8ccf9524dcf86eca50d7acbd9f2db07cb77d1bafe7bdcde9c2b6ebf78dd7cdc358bc5b712bbd8fb37ffc7fd4eaafefdb0bfdc1ee2f4da98ba7cfa0cae9cde79c5dc11e40dcb344a618bef5d0fddd938dac92493c5dc6ba1b6bf51c48bc0bd3c2a0eaeaf095c06e3f06ffaa9762ec5c3cfdfebe9e69fd6acae3f72cabc02c75b4bbef9fc4fb13abb9acd88fd5f3a5f7baee24beab3a6aebdfacafd9c7395fddd1484cbcadf68fcdcfc9c3757a1ba8a892ed5ab8646bb5c368b7661dd048a45fd2112679a28a058e2ebde8ecb4ce38bfdf4b740e72acdcd9ab6fcae4f8eef44adcbecc2ad91fd4c2aecbdee314bdfcb061b646daad0c3cc9a91370d22a00d66fb2892bab7bdcecfac6632d238fed80b6fee96513cc660ce1bf34b93bdb91af3e1d19f2cebabf5d5bbbaadb54cc269edefee4d4ddfcbecb5dafb588dd6cac3f2589eb3bfdbd0b99fed5aabfc9dbffa17f94cddadb505adca2012eede7560b2ccb264a8aacd2faaafb86abc44c77ec47e18e8c7bb1fc58f578bca6cc05be0ceedfbbd76b5d7a65fcc84bfceacb8dfcb3b0afffe97e63ba72bcdeac4790faba71179c6be75f018b0afb48db60750b41b596eb3d77e9adcbdef8eba5cdd1b8f2d4696073fbaf84eac07db07cedabff0e9d7fdd882f97f44ce77a8fa83ce34326dc7bf9e19bc7211d1e0fe5bcaea3385b22f09e1cfcaa01fd51dbcf9a8f35be67e2021a5a25a6eb9120deb0a0cac668e3545ff10bcbcdfe7ce641ddc7b2ed8cb0fe332c4dc73e7cbe63060ede4d7da3dfacc6b1ad70da4c58c70bc5b679c11e4bcac9e8fc7bb96af23eaeacc5469bfb3588abcc41de26a6740d8ae5aceb5e0d3c3e63362d6088aaa4fdc6e87bfe32a49e0ce78dcea26d9dbc2ab1c2255f8a094d86fcfc2fd4b7ad6a4232eecf870be3bdd9b5ded600d8443c73efbf21bcc1ec6d3e3ccc1b5b39babdfef125d225e31df8881dcfcbc12e0d7f5d7fbd1a29ce0effc61bdbbcd1e0d8ea44fe29fad05cfca4a67c9e24d59ba44def1f3f349130f2a66827c8a7020a3fdfe956bdda9fadfdabd2ea29cfb65d867f088dad8bb88f9a1c8ffeaa1689d7d4f8cce1439ff53b76eccbe1b2b655e3b8c9b3655964ce2b07cd76eeabab2ffcccbfdfe6f6bf92ca1c0bcc0ab1f8083bccef4bf52edcf34bc4b80dca3bdf7ba6cccdcb4f2d41dd554f9674a3fb8a4e4a643bc4b49bf2cda0abd20747c7dc8eb5f4ab0f7f7a0a1f9cfcb653ac34da8dfb88d485bf3f1021b853ffed4dcc9eba3bc8448b06d0fe8d3fe7b4fb7f20e21c8fbf45f2631e33c7dbfb8feaba089e4dbbecdca5277b2c89be7a1e9fbc750671ec2f4fe32b32de4a2465ddeeaacaace43d3ab74ccc6266d21bdbbd515f6edae53ebdf855f9dec0150f92e4cbc2d9e6bdbf77fe3e46facb2fa33acbf2cb3ab8bc8b2eab42323c6659d9bcfddf9ea87a5dd23339b02d9ab35ef84fdc42e22bd481d81ea4d33ae0561b6eadbdb6a130c49c5c1f6d7faddf6cd25b87baf49fffb9769b8adc316fced6fa8aa2edfa399adc7fbcea41544f7a8add3d023ecca3f17cae1977fefc23220f1f9a2ecb56c91ea625b9ee03cecfe58e4282520eeb91cfbdb18dce012bb7efacee73abaaa5ddc75beaabbb33ca2fb9eaaaec9d3e960eb88feee485cdfb9ffdac16bbbbf9c7b7a1ebc9b07fcefb88d6f6a47fe7c2a342d645f1acfec5c794c1cf36aeff35febfddb8eecf000ca81fbbdcb55b53a661ae5dcdabda28f3d04aaab37f279d37a1e82adf686a5b0bfcab3ec6b9fb0c484badfdea2ac9fbcaa9c3da53dddbcaba2d5bb9a15a7f4cf58673d29ce68899f87ee9dfddc0fddeecbbeb600f941f4ba6b1f8dcecc6bd9a5759cfdf688ada6c01df78d32aa6dbcd8145f5528e793f07fdd97ec777ec28ccb36de6edfeba35cce1358eeea17996795783c2ce5c2c23fca60171ac89b8c18ae4aa7fece5141a3bc34e2383932ffc73ecaaeecb05c617db2aaf4077f62cfdb4b9e05346fa9cb82ffde6d9f6a4e9fbb1e49dacffd94597e393bdf9efaf848fcfd3441bbd1a9dfe9e8bbd29a7efb9bbca9dcd1c7dc32fc026a9de74df70b8cacbbcbd5e4054a9dec5e80d0d9d7bcddacbacaefb9dcbf47cbbfbb503abc8411d6a7e7ccdc6fa90cfe8f8ad05cdca8ffa4e75fb9b81be08757c1dfb43dddf3ebcaf1bd4dd4f0c8962ec3c5bdca4c9bb0e4a951addce9d1ed87c0e39ffc3a7a189fd8a62dcb7bbe10d9248efb3de2758ab2ca0ab668fc8cc8cbbd5639aa7f2f3b802f3c699aea8e91ed8a58df11f2c4be4eb8a8eed5bd5ca9a225e8e8af37c2aec7d714be7ad0ac7ed64dbdc50251cf9ddb0c23af834ffe0892a8ebfbceea6f471cefecb3afe87f21debcd5010fd3bf79d3ee2af252f2612a2d78ce5d6e7cb0ad9b10edbaf07fa4c1caef66add93a0bfeedce38b17e6b2db88676c2c5cbaeb67f2d4facc925cb7b0efacddfe35ded7defe5e977e15c71997ef0479d97dacdffcbf2c0c06b3fe8d0bc9a71d7fdebbb2e910b1e3004b5ca88288f1a2bf84ceda3e5e1a66672cec6bb759db7faf6fffea4da7fa462f8b418157a90c14d8c1c75beadca0919043baea22dfc6b6d32aecebf7fdc1cf2ed5f7f58fc7c0c0ec55faf0da4ecdce7d1e97faf6af180412f5be6a44d9c64928ab33b6a2cac30def3389db95f7f32eb56ade3232dcab0c7b6a850d2afd70ed2bcfc0db9e0dbd46fbaf5d5bf31d97c6b26e3fa9908cd9aced2833ead9c2e4ec870d1e9b7fbf2233d1ec64aafde62ac0f8dc6b216afdd2b47b6caeeee40376ecbec0369aaca715dfdb77b99b0f7de8cc1cd6111ccc9e7ba81dfa16d36ad9cfbc8bd0b5df3b23dbfd91bc0a0debea0c1b7feef77eefbc1fa2f8eedb5f746f652c1f8639cbe67d30d9ba729dfebe41ddcc3ca1ff6cc4e7bba7c4fb2028b291b880f6aff9db3fbe8fc27f0150c408fa0eceef5ea736f8ade2b7d5fba43f487ae4980efacbcbd80dea9b2aa04ce4b8746ecc2fadfcbbc4122ab49f6d7a86341eedeae55c31748cafc29bbd4558949eff8724abf99ee54be6da344fecc8cf27ede8225a05fc5dafee1a131f060e92a2fbe83faf595bcebb6ba51eb2f6b2aa76a1f4cbcfa4c8ebdaa98a0a56151ad13ddda5aebfb2bbed57daab66a61ac77cbbed19ddc8a6537eafb4c86ca6dc2fd584a2ecd76abcafaa9866e81a8e5f5ecefd9bb5787f9d4aabefb83bef7abf597cbbfca8a932a6be19a28fb0a88eadfda2cdc342d14327506d094589eb95f4b6bba54e46741106f7211ef4c77df0ccfdcfadfa4995ea973f5f13ec1f9cdadbc1b6b48d2a11767d9ba5e7c807b0af2fa2fbbd03d69337ff17ccd63b0ac17d24a0de4dfe9aaee86bc7d0fdea34b52ca9ea66fdfde50e4d47bd71e10661ccbef40788d0e7d03eea42768a73f2ccc6badef6f6eb753eb6c03bd6acc1a420eb3c300afbfe8a3edceb02f6ebdfa7cabeafce6c0cad46dbea3a29587f0b068e389ae869b5ae47fafebfced6dea3a8b66dd4e6bca24cc3ffd1acec7a7fae6132dacbd9ec97f7d4b9f9cbdfefce60a9b6ffcfeb2effd62354b8f20c2b2dadbf0eec119edc74bed3aff645f51fd90621af8abb55d9cdc37e52dc90b3054bbc23a5fbc19dddd6c1e8f2d3fe57ad4cae2dae9fac15caa2ead9ee7e33be6c47ec516bce5fb6cf10e5ee4232ba8cebf5e7401f6c0b5bfe9b2804c9b92942e1fc8bba31bb26c404002284a2c58f583d8085cb97cce17e20ad7feeccceb478fec56c7aea01e8580eadbe8a65f5737cfb4d4d6d7ce30b16b6a2eb5fc5cfb36eff87fa1ddae6b8cfafcdb88d8de57e8e4c458af9df33ac57195af0bd40dfd4e09be761fd60faeb68d73fdbcf9edb1c27af0eb0e4993e4ed61bebcdc483eebb27aa36f2ecd2accb2d9d7edcd717be1cfe732fd7aedb4db28fa7ae12f1caae3c3f81aaf7dd6b0ed3566641aafc5be96e1304ddb48abb63e4ee0a316b699b66e6bbf2fcfde85dc9046c234edc8a9a987c687fa7a94e354f2f3c0230e109afbabe78d013cb015af289c49de59b8087eacb83ce50995eedc4b96d8e11c97c22d2f130b2afeb6f9d4dcedee4fc3fbcdb98165e11ccd6d5ddbe0f4cedcc8ce1ef012c3ddb3d17119a7bff8b1e9cffbafd0ab6bc5db68d5a2f50bebf92cf8df4cec32df1daf6f391b1bedfbd8f6cdddb5ae8a4afdbf05eba3f7f1b887a9994703edacf454d7bd6674baec2a0be83faf9862be5cacc8f6eab8d4323bf45d1fde09f4bce66b37c77763bd583f9a1e7cd3ddcee9adbabc58f304dce1aebccceaa24c23d9d09cbcd2ae3ad2ace95ab2adea70a9cfe5d5ce55d2cf1ccaeef7d371dfd75670cb9d4f3661ef2c5bb03946dc7cef49ebfb65df1ebdfafe26a82cfff1bc962fe277cfdbeb2d2fce36fa7c7ee1a6e75e0db68d6ae984abd55d0b80c2a3b3840c85a754819f56172da86ffffb6727bc5e1e832eaccf9082d5d903bb03ea96fab94c57cdafa9c9e4614a46adba4f09326eff20d63fc1f8fc5beec0f9f2ecdc3e7ed53deebb926df74abf1c50d82dd74a177cc271ea511af6363f8bd9bf9d4f08022029eba76acf7b617efbfb8ffa61a2663ce74c81956fb14f3a61dc6f8b80513ca9da0fa45ecde0ff980c83b5e8e8372dfbe50af0a6d26ebcde2cda6d7d0bc7bed0bd2184b8599ca626cc6170653e1e5f5cec15ac382e51bf61d21fcf7cbc9c8d49f66394332ec0ff2d80814f8aa5d06fbeddc31ef8b30ecbf74caa8b58fc8e49952ecedfa8675fac9ad5082cdb6dde939aaab7cf8bed96cbd4f1fe14916a79fbdfe5be6dd78f8a2ebfa6fcfe3de0b0b8bb4fb8f5dfc6ce8aedfecf7a5c9022f37aa98f08dc2e372b32ea18482b3def8a8ba8ae24aa1e63eea5174925982aa1b7d96e453bcd2e6370f9bfda23f1e1b2eea46bffcd97a47ae307d8da9ee8baf1b2eab8565da4dbefeaaa180bfcdbb580cf2002de1fe3c87b8ae6adccef1ca2f542bfdf8c8b1cfaefc4cbf9bbf0ccbadbf9f12b345cada0d98518daa4ddea459adbec72b07f9493bcee7fdf5a069eebb9f9dba86ed49fbd65e4faa04cd0696121609fe68e23ffe98f59b28b52a3263c57acbe5ccbeeed4a20df9aba219dba8fa5c72a7f478f61a1bbe51a7afd3bbf3a1cfe49ffa2ef285bcda6bf5e3f89657050e93a5648bac02ef8c3eec8250bb686a8f7895df53b4bf77d6f20649abc7b49ee9d3f4ddb696e04e36a2ce91abd907fc97eae5ff0baa9ee68eaa8cc4cd08fdcccc77c72d2b28f7cef4efde2a4538fca8cdc34fc77df7fe801add213c034fddab2c3c3bcdd55f7c046bf7d4f2f0df24a2bbed0fac12abaeeb23ebfaf5615eeca18cca7c52e43cef40b0fc5d3ecff55e9bcaa71cbd0aab6395183cbfdd4ef9b33dbbe3dce8bab3c0adf6a6ebcaaaf26c4bc8ce5cc183b6f0d620c3ebaad3ef3a5d3c2522d70fb50cafcbc744c3c3793aca5562b9edde573224afbc2abbba677131cfd5742ffb79b21c7b19f91703fd3bc5b4ce042619696d5c73d38e734c2bd37f8abca8c3c9cdcc842f57cb1aade81bd8f5caf5c767dd8b0dd74e5c3bf310e910fa6e69e9775ffc3373cb3ed6617fdb29f4deff3bfb02ecfe93cebdea82d7273d14fbaae400ba302fe3e0bea9b27ccbecc8de15acfd9b45c2d275e380acbdfa0c42199753346e38bbbdfacdbb5c63394e88c71ee1ee58496f7a7e3afda6e1f4e02e0ae70bbf0beb8de13ecdf0aabcf5fbc739ce088ad544cfa5c3aef3bffd4da900fb02672f32caddcbbf44e7cd0a4fed8f1bb3c37aef0b43df0d7e308e50bc9e2d1b6ebd5e5412f8cc325edf64a509c9a4deaefd580bda502c0e657f76edc8fa93967e0384acecddf9cf2918fbbffadddec7843cc4aeeb0e232ed7c9d0a5d6fec7bae7a09d6db9abeda3dff7e4764f456fcc194d2d23eecd29bb3ef2d1f6d1d99bcf09ef57dc89df82ee65ab5c1cb9e5fa30aad709087e15d9c95fb266fdfbfc9c625ac77ca4d3ca385cadecbdccee3fe6caf69ef8a5065a7ea25acb653ad5f98f2dbaefd9cad462b5141f5cf5df6b9fca0ebb79f50d9f9c818de557abbc7bd3baaada8abb4eb4a7a47eaeebe2d30ebec5ecfc75a49edcace722765da6daeaedd18dbfd3a4bebadcfade577beea1782b41f64e7a7ac878b6a356cae9ecb28af236bbef8dc79bbf6127f0abc657ed5b79ef93ecee98bf5705b5f92efc9a0ec847ddbc9b4668056861ef477b86cdae87289ab8dfb01fa03be29c4b7a1e600c444e96e888bb1eb46ff9abdafebac5a09a544eaaa427d654bfdd99e658aea82b8c7e3ebfe9284e49e1e8e9e8bbff199988e96ec4bf8bbe96ffeefa6d2849d5f0d4cacf7fae9dfb2ccc23d83caa3f1bb1aabdce8ebf4edcdecab7467bc3d0b2bf3baa40bbceabb9cbea5abbcf5bd03b2e8aebd3fcc7aabd5bcfed83da787c5ad57dd6f6d51be75dc5d5dcfc6d12206b0cbcabf6f82f0ecd9a355bc0a16fed9ee479c252931ea45be3becfd814ce6eaf536cbb9ba12ac42dbb7ac0f4327cf8e7afbe56dea9beb24cd6ae43dc21f5aed611dca9fbcd3dcf2e7d979cab801ae973d1dfdfdbf9cdaf9ac6198557b7a1c0cdcf46a03e022410e28d2abc0a71ce1329df61ee4cd3d19ed049cbb7a8d70bbefb617b633ff134ceeac2c667b53445c4a5df3a4ccd34b4efeebf921ffe7601aad3b0c04cffad3a8bbfaa5edacea6a7ede7ac7a8decdd917cbc9b59e2fea17e3c1fabf11d023d82edde8fbdf1e4fbeb221f1d7ca42835faf313dd9189dcf1212e4adba3b62b1e0d663e8d60c40ac02ed33fc8f063f8afb8beaa82eaab2fb6cfc43bdcda8902525cf11e7afca82c03b0e5bcdac4cd9c6fed46deddfd6b92ecddb21cc52a1d45fcb9faad3d7cddead6cd95bd52cf6031664cda0a715cf6c0bcebcf3fa41f3f0ac25ebbe8fc8af88f7afea2fcbbec4fbb2beb27f170e860b3ee1eae60e9fe43961af4f5a5cabfe3c15b49b74f28dcbf9ceed3dc27bb18da8e96b558a3b481ab2fd75ac084b102aa593ea32b80aefe4e3d3ac09fc5e7b09d84bf1e9ec81b4a1faa8ce0dbffeea0cf8833dacdf3020e3c9d07a693c62014e8bd37340cafabfde63f9b6275a3dbc1ac9cceebdd75bbbfba3e0b5c4cefbd60dfcba08c70dfe3ceeacc73f1cc7d70ecc9aab6faf3bfd574be8ac81cee7373512aa1a2fa36baadb8e08da0ab58dd92a1431da223454e4ccedad45881365b73c82cb789d7ec5c0a93dccb2d4aeb3692be46bfad952bbf4ec27c97c39e709b20330a169b7d5b90021e24e122bbadee24ca2a161f21a523dddef45bb3e13638a54ac7ade56b8f14b7bdcaad28efebac66b0ffed1e2eadd1ebc9b2ed6da78f610cc65faa75cedeabc4f614fbdfd070f52345f5b5c00af32fd2bee7c4a0b3025984d1892c0a72f36df7e1eeb1bd0b0fd448c9d99da65eb047dc772101efbe7e0da96ef1a9ee30a32863cfb8bc5c4e8eddfdbad4f4cad08facb1e6e08f3d9d4dacd73c41def737edcfda4cc5fb19980f667e107ca9cffbbe699d9efcdbaeeeff8d7f01dafba08af99fdfa36d7054e82094e09ade0b14cf238c6dfec95ad897a9dbbb2c859c829ecc8cf4d7d5c3a05805aafac51a95dbdfccd870a2c15bea1fb70fd408fddbddfbf05d3ad7e7cdbfb7c3c20a71a411ef3cf8abfbdf50fdab66cccfaf15fe20abcc8fae2b34f270e0202b1bbc91ccadafeec8c209edb35ccfb9469ca5d9adcfdfc9acb1c6defaf35a7fd8c54b1f9fffbbaebb294c089a70e9fbd5eb0b4eab7dd830c28a6d840bd7ba74719c5bc951dafbfe09c72d55fce7de4ea8a08fcb09276baf7cbefff6f0d043df03baecd7ba68f5bc3d9a0bc09f02fcef9e0abdd5a4184741ff1f8b5ed8d3eae388b9f9462e4371a8c680cba41f81f9dce07ecddd684ee5d532de00c5e9b58ab8cbc5cffcc6922756a0d064e84ea55a5baafcf29e272bd98bc4ae5d3eea799fda0e55e722b7c42bfca4cb2a0471e1ecdbbca0fe32ada9047c60d9ff5235cca6e8eb6ada43963cbcafdff2eb0e9c34e8b2dd3a4067ac65fe4acabfcb9d3aa5aad28cea0ee9bf2f603e5dfff47510ff3a796a3df2f3da0ebdffb87aeda03cce8febcc4ba13e8386fe30b1cebacc338b1aa52dba7bb880c72cf7ffd757097c6428dfeaf4134baf27bb5ea28dfbe39d31b64597d9cf462a2b860f2d3fed0167dee3f1ebb8f21bff9dcf6f9799265d9804dca3e4e1d36f7b5b02f95afa6f8cae923d82369f5d2fcacd33bbdbafeac5c26754baf14a04f046b8ac1e907a8fba0e0d80c0fc6bc768beadd41f39c1d111d2b6b2fe5d7dbbcdcabfbfacb04ebafdc0d7eb5e2fed249d8561f3cd6c1d5c57722ab2bc4af19efddafcfdf8fedfcbce06ba4d82e41fcb3bb9b70cc30b6accaab54aa912bdece76eeca6a2032ebbdf0aa9acbcace80bfeb2d9aaad0aabd3aaaec0fb5eea38eb7bddde50aaed84f439babab1de4c6b60b84965a23bb058edd5dcb0e4ba2dca3dce5afcc9fc11adcf18ac682aacdc8f575a53d3e6240794ebd59c10639ba7adf3322352d9ab9578bfc88d0cddbfba1ccbfc1dd88b78cc3e734ccde327cc14a2227b19aaa1af8bc9bacfd29c5eaf924cf8df6f60f87073fa0bb388a05f6e9b860ba5adaa3a62ced21d23cded375c939ec9c374e2c81cf0b4fb5ade8ca0b1ce0d7000edfe1bbfaf13cfe8fffbb64d1efcf41e3af85ccafc3bebb13ff8f48b3d0dcc3cfc5b5adbef8fbde5db73bcfdedccee7916d4acaa1a693edc81794a249c7ea9435efca5fba3e9ccfc839aeeead2c38c853796dc13ecbae8af00fc7fffeca4368cc1bcdc2e75f4fe88845c7db6cda266620cb9b1ae8abdadda4de8f221cfbd5d3cde76cce9ecaf93cc6dcb0ae3caea76da97dc876b8dd01fc8a703c6b2146c032e5be26df0dca0c5d0a953667c3ea67a08e6c4633878330d2caaca3e4e8b8e07efc67bfcf3945acfaffe011eabdbb2af5feb3da681a09041e8ccabb2abe094db6b0171ddedafe9cdea72a3ecae34c6f8e97b77f8961eaeb16bff9117946cbddfb236b7c066a4bbbcabc7cef13493b9bb828f5e7f34ce0387fb6e15ade89ddf8feffcb45476f20c21db85ab957fe98a2a8bb2f78266e48a91eb5f6a1079d9f1de9b726ba8ebb5f61ee5ded3e338c3b19ca1fb97f3d371acb9898fd6bae6cad3aaba2fce0aaa5cf7b44fd1054e0dfb26992ddb4220afb167463dc73aadbeffab58ef6ea33d4aab47e1ddefa7ddefaf744bd9638fc77a6abe39efac7a5a1ad9c30cf453668e8a15e8b02296ce6693abaff0d251084af3d3bafdaebfb1f1e0f617ca41ee0ea7c79f5c1b0e245efd81d16acd9f2bc7ebcfb3bbfac28908f7ad44b0de2a97dddad6398b1d31fece1dfca2b3f519334dd01c8a9f34a2cb9a4c7e493eae9e11a8ffc2e7747c56341b9c45bac253bcdfe8f28af1d5daeae19bbf8afcba7ca1c20eedefc1de223e6a8fbeda11af36ab10b08ceeb3223fc415a8aefba2c2e4ccb789b15ef5e31a823e3cbeaf04c48b98ab32e390da577fec2fa8bfb7d8a3efa5f90c68ffbcbc64e8fccefd4db75e9dff78baa6c8c6ac15bfe9e7bca8b2ef14a48dfaed511dd4a0ca1c4f74c1706e7ceb9edb584536cccdddf22a2dabf54f62dc5afdab64fcc1ebcde199fb4fcb4bae0d6daee54b3a3f4ae4af2fd33b13c27f3f97bbef0f6ee8218ef778c3bee130cfdd4ba33bd0a8db1659d69b0c741dcc3761330dacea70e4b6583bbcbbb4cdd13fd6c97d44543d9cbaca08fffe98df09ffffb732dcac6b4dcdafac0daeee0b6ab7b47a738a8df5d769fce9b4bac33135f793d9a476feaa65727b121a1d37cff8f370c5af086bc6b46e65aadcb9bbcbc066e4af1eb79c14c1b0c2c45a75f8ddb666c3967a299d0c5ac6e941cad0f01fd5bfecaa1be2fefcf19bba5d9331c54ea6bb1cdc051ecd762b876b775ef5bbc4ff6ec6ed09ba0ff386d4ef7f77aeceecc6dafdaf36cbab57ef0b3eb8a3aaffd72fa0bccdafaadbfc0bf90cffab9b02b094f0e8fc354d8caef66bbfebcd9eb03ec3dc1cbfecffad6edcb376f2e39c0dcdcbb08983aecb7bcdba61d7a43fcdaeeca2d45a4fdcc502a3ed19d7c8de028dd918874aef509adfd113afc7630900deca93de023bfaaacafb13fc28c35aadc9cc6c4cc85f02bbbd5bcb181cbdeecdc20be26fdd8c6acbfbfb1ba0b1f21e5ef1a8acb1b9c41eb4c8a4a2ecd8296dd62a0cc6c00e8cf124fd6e0c31ee63a7c068cd73db676f69d63652d9e8fdb7abdda6e6b6bbe635e5c9d5dbd8f93c6d2e1dfcd6494f5aefdb0608a6b3eecec11af63da9feacc77277bdedf4cc2f04908fa2e33aa3efcea30f94a63c3bb56bb494a6e5ecb17bd3ddbc76ba3db8ecf0feebdc5be94b0a79b8c85cc5d5ddaffdbae1edea1bfe1addfc5ca87ac7efd2a7d1db150acbee21f555de8cdac19bcaccde8bb3bbb7035e5a0d1c7edfea089e328ef8b0d614fe7f57d5cef094a97b9fc6fd211e97b7aa0beaccefdde1e80db9f18a59d4761bdaac34eca6c4bd7dcadf4c9c937c13cfbfe24ebfe82bef5b10f123bedb761a3ee96d247c2532bec66536fde332b0d62a0d13c3def3ab51e3e5e18f53ee06c48ebaa9302c274afe021caa1260b15ade3ecda6263ce37b5e2ede0c3eb043debff57212a2db2647bd4d6bc4027d2af3a488cf6d34df741b0ba448b36a8a6dfb9b3095bc7f13efcb42c92b5dc5e6ef2ca5b01acc0017b67ec7cfa8fee2b2bde0cb3baa1c18159edfd654977ae6afcff372e752fd032ba8e44e0b7be17ceaaabc7bdbbfe9f808daefc2d3db685e5ff7c50bf8289f2665da8409a4b312769629b8d19c02a7d379b260b3ecd771e6a7206caf5d5c9cd7fd4c8a1bed5db0b2fda8c9fe2734ecf656d0b92c87a5abadcb8f0ce8d559f7ae29efcc6d095f4aaff7a5ec7dbd5f73c84ec65aaf4fa5ebd3f7e5cacf7631867c1aea3ec4fe2ab47daf30c250b2f27c0de3753ca1cc0f9b8f38bafc4dd20dcef665aa3330a116744828da88eb5dfbbe2458b4dfdb77f07e1ddb2bc2ab88afa2d8f0dec6ebfe8ba45da27866d66b7ec2df85f4986742d82f2c302aa22ed722fba0cda3105b8ad84a3553c0dacd6d6f06efa0bbfe1bbcaca84c8adc047217aebb1e7f350aef9b5b71ac5f2f0ab2df0fc8baa04371c5ed363f5814adeac6efda6cfce0cdbd35acffbfbbb50ed181cb4bcecbf86bcac5e26d4bdcf13bfa97a4bcc1ed4eecdbe3bda42f24ec6beaa451ae66629bd3d162bea8a32aae81ff78c6d8d4a5a8ff6babbd1a0eaddeb2dfc4ce485335f27bc4a8f72e2681cd84fb37dca79bedc0fcf7dfafc6cd9b19afcd11c2d74f9de0ebdefd112cd0550d6143f4211c41e0e0552aafcf6cedfe3bee36eb37d40b75f3e2bf96adddbfdfaabcff2fd42de7df6f1dcc446d8ceff7b0ba0cd0ca7fcabfeddddbccbfa02faef728af4b23abe626fbc8c7d8a8dca5e5dfb0dfcf28af6a3e1d2baa4ba17bca54d901cbedcbd457cfefb4fa98d6d52c63addaaef9aaa670f78ecf28bf8f8ad64bd7fb88f3ceed27ff5b541ed0c6faa485bedefbb979cd16ae8a4d27222ac14dcce14a85bcbef1c8d28fefc760aa8a0ffdfedc5e32fc6aabcfeacdf3cf3f2a2dabb47e3ec6af9f4cbe399ad9e6df5a561d9dfd9e9835bc9ded628e85a0a2fe0e1dff5f5ad43e8cac01337dbd6e0cf619b886a73d487d770d107ab9e9eb2abb4c84f6ded10cdbdedd4dae27eaf2cb18c4847f8c3371c523f97dbd2efc3d65ebe619135b77ea7d13087b349f76e9deab9dd11ac46dd9bad419cef641535a112443efa3e0eecfef726cbefc5efad482cbcbcbea50fe72f053ddf686fbcd7ed2fcfe1dc015fb458a5ae2ec7f2caf783d23ffe116fe59a1cdbcaef68beeac2dc33abec19cb47c740cde8ebf230dfd9258e6adfef94c7668045ddbc0c8da1004ca9a10a773e3bfe6f19acae67ccbc0294fdfbc9cfef3337f6a48350b376ae56d73da8fe3a04b2d61b901e7dc3eff31bfce5db7ebaf87aecbaf2a6acfd21cbda520aacc4cdb47b4ff50ff344a52a5be31a61bccffdf4aca5c2a244bedd4ff02cfcf5d3156380a82fc0efd8504f94bdef2bddd71baeaeced03a52ecdea1bdbde2de4a2cece69d48edf2bee3a7f9ad66fe8eac3f12ddbcdcc7423f85495754d7dab41eaca58bb4ebdacdb1fafe46eaaf0fd1eddb4cfca39fdbf5d6d9babd3ed2b6138cf99a9eed8b48aa08cd48ad5dcea2aac1e7c7baf171dcecfcfa1dbe0dec877b10e2f530be8eaceea205c0490bbfcad6b0ddfaab776e18fcde0e895301b645ed6ccf0cfeee9ec5b86ea1baedbbadbd8133eb25fd71dbbbc7fb8ceffb2ebe2d4514ca0372eda63e70543daaeb9e806aacfef0bafe3d18dbbdf6f75f5dbeae3da2f8dbc7ec9a6aea855d42a0f5fe93aaabce77422a51cfefe31a40ff3ecbdb40ea2c9deed4b0ab4ba05f93b7cdb2618ebd9e64ed879cffbcc62cfddd5acdc1421adef7d044da9fdbdb03ca6704b6bee4fd267f2dbc5acfc87054dd74ee02fbc5b4ccaf90698cc2619c54239c2fd668d1a12bcc9eaeb0efc9b8c7d4d1adfbefa8ca5ee40ecaeb7afab52338037fd6fec1c74a68ef0e74efbbe7ae1efaea19f4aec79dabdb472ae0ea87ef2fa59e4b2bb4ace7f4a0ce8a7dcbc7bdef43ac2c8d74a76dfc20f4a5c7be8c38b9f7c9d9d1e1a95a0bff6dd2213d3f1f898bfbe7be2b5f2c6ddba884ca24a60ffedd0e9cefcfac4ffef89babf3aede783c565cdafcd6cf8ef17ad0ddd434ec8bfdbefcacf6aaec3f2fff1bf4bc26f42bb3d91cbed60a9fdedfcd91a2e3fdd3bbebaeeffad86edd6492d7cd1adbea47451d7fd270ea50c80ea6812112bc5bb1f9711be7a53ab32607b2bafaf564b1c5f1de0d4039f20c6fc67a5efac367a4dfa3e45edfe7561ddeb5ef7ecfcabccbe681ca62cb48faaea2c98f526ba15ef51aaecb2edaaac28ec5e8eb0cbfaacccc87bfc1433dee045ac2bd55bfb6cccccd236e722d5ac75ce3f682f7f87bd892e4edfbabef748bda9148ecac3bedff2bb023e76d03f9d507019ed06499eed0d353d2b4496bae4e41c92818fcfcdb1ed0bfb9f28bb49b6ebb5ac9ff8a46b694912f00cbc92266ba58a55968d5d404e058fdaf2efebccf4da6e1e1deabd910dfd5aa99f83501fbbb2fc145bc4aeefebb1afbdbd2b0b23dffd6db14fcf6a98160fa2ca69944428bde5cfa01b0d17fddfeb23116886ce3fea37868f5ba944f7ecc0d7d7df50ec6efb6efbf4edea0abd9940ad4c3af4afa568e50b3a2b4c24dbf1f81dd06221eec86aad2cafdc2aed2f2ca18310f7ace0adaec8da05124874095a1da54d6d2fde6e6fdd9c930fac9f71fae95a57bcf52e25a48f985dc2170ebbff76fd5c1bbc728f3dc2da27de173cee77db7f7adec0b9dce4c9ebef02097d6cc8da300d14caacac659dafdcee845fd0eb3e8deb895d7dd3abdfce3caf3656f0dcde0ebe47daa1ea593475a9edcc31583ae2e9c4356b357de1cfb8ba0d78f23caea5dffd664f117c8433064fb99eccd7be0cfb89adbfecc6d0e3ff0a2dda42daf11a363a43eff9c34a8ecbbeaa3c69b98dbf6b3fbcb68a5076e2a76ab46a00ffc0e07025fc4cef8b4b21f21f23610f909dccbaa61ad0af03cfb0cee9d0fedfcf02748fb2bdedf13b4da5ed3c0fabadddbb7f6f178004cd2f9096166d1ad3add4f8dcae646b7bfee74fa8cb7a2b94be1ffd52721ae23bb4571adebba99d5aa5b89f437cacc5040bcadcbedc14f2464dcb01345ac8fcfc7abfacd9afd0dc3719fab4cbbae4ceec6fe5e6e84cf1a6adee72cf131ad7eafd1f4c1f5e0e6cab4aeb7bd0607f6e0e5baae01c62d7c85cc644fb05f0f2e7bfc14d4361eb96e832bcaefec9ccccbbbb2effa87dbeeba7ecb2ddd49c71bbe119afed3c4d7cacf214297eacd58440a98633a6afd35fa6d7cfe292568dbb5db5ba55b48cdfa6ae9ef6c1d41024d8a4b1a0faa29a2ff613a10fd50bad1d3e968b40fb0aa388790098b9e24c26ebce9cec4a2baf9e1724b10ddd36b0492c9e8b0ccfa4c2ffde781ff4aa498ad7775c48e89660ced6dbbd9a4bed9f5a472fa5c0be019f5a1daae87c6f9dcaddba2582e3f6fabfdb67dbd3a0fce94f1ceaac333ae7ef5fc0a8a84ac36de6b3ed9caf46fce01ab3bd5c47e56ea5fb6ec3f1eb82dab9dffee24ad3a45a0debedd1dbdbfaadbaa0f5777eeebd44b89bdba45177abe7f6b99bab6b3b0fb1ef316369667ddbc5d0e67beea73775fe1bd8febb67dbd9edd6cdff43c3ca7645aba5d86e11db117a61ffab1e6d6c35c502eff35d58dbeb7a1c051fa00db8d237dddcaeffae31255c2fbbabca2fb541da6f9a3fbe0e1a354a74a5fec1d4aecbcffa86dd8c3a6b068fcf0ffcefc4a0191db69ca1c9aebbb5abe7c4f4eb8bc54e692bcdf93e8f4d181eefade07c976aa95a7387c6d7bb971ec96eb633cad97189e2aacedacf2207ee3a4c6e94a848c09af17dbcbdbe3bb8c4baa8287abf1b08d42c4868e5bf6ddc33feba308e4aa1e9abc3fd7cfc75fad65eb59b1da08db33cf05d5ede1bfb98bd8de88e37fc6653ef43cca9bcfa8c3b1cdecfb74d4c0e4b4cc69d6df3e0adeade4e2eb4c39f1cf4f2a1bffa27f3b1debda7c7231abc6aec5d389ae68ad1f1a9bcc73daaa1e5c6bdf14b6c2f3dbeafc2be73caeb0fca4c48538bf47039aa1a9d1a64105fea9fd7bdfdda767163dc4aa7fa47cdbfecf3bd1c8c84aef13fd8ff6d5e4353eb91e02ba129d7f8362ddbeade0fcc7838c60dce964ebdaa9b376bab23b39901b32da6837e7145cd025eeb61a304fce1da8d5ec90faf2f8c6b86b51be82161db91efe90bf2fff8bddf64681c3fcc61f2d4833b85ebbc4c8bd8b2aae61bfd21411235d71730967ae762bde90ac9f68dc0c7fbba28fd9e1a6dc7a67ffabce7ec57db8242eecaea79b00e8abbe2f7cb88f8c2ed71af0bcfeed279e8d94de582044e39ec87dca337cce68fbec558a6caf9366a2cd02aed1a1723b6caff6defedb006a00375e77fe205fe90ef73e6b18dcfafe645f5e9915ff4fb17ccdfca2f58291f5ffc258f66fdb5585e79222ddba6ce77ddf58114e85d0c66ddcabda5dd197ded01a3f6352def0f4ddabe0fa95e0d4bdfccdaccda3a948dfb19bfbcbcf9e9bccc003db64ef7dddd2253b239ebf2bed4ed580bd033c0fc55c6aa56ccd1651ec056e7e7bddb2ec42ca9da039cc0a397b2adaf0d9b13bc4ca5bcf26ab6a3ab5944fc563ba6d493eca8cdcbd1cc0eae45f1cafb57d059e7accd7cf49cd9efbffbd0ff431cab5baafb2714be5bc9ad622dcac0fac3abed804ee6f3051d35d6a58ae0dbcbe359bad67d5c9feba9efcfeadd51bafe1c3a3c541aa7bba51de4cba6e74aecf40ee07f509acef85db5dad6be0e3ad9c43ec19badf1fb879eb0cc0e8979c06f0ad40f1bdecc7720afee5c5258f10ddc0365504e66e9bded1facbabddfdc6abe0add1a31daaebeaed8ecedcd2fcef5fcc4c34dbdf387aad365dec0087cb0c987fa3543e25eccf7bec46a1cae24b66cfc987de2ceff2fe3d0bda1cadd4fb64610d3fb9e5ba345dd3337affa324d93c68eebf19de69ce5db4fd3aa95960fffc0dceecd96d04291c898ddd6a1eab388b9cd762cb0dacfaef83734bfbe0a3e5eb69cd63d834d4c92b00761fbebdd8c8e7281ad7ccf409aee7ccecbf3d1ac856115f1ada932547ef9ce85bcacad02dabf95ce4d4bbddaf8eb1f210f7b2c9e67daa0d81acefdd641a3ab0ecb1fdbc46488aee2bd582b831fe4dadeee4f6bf5fa6bac55454cca3e06edca197fcc8bb8e49dfdde1fcddd574f9e0fee1e66dfdc3f91f844ddefcdb3a9f452deeedc71f9dbbe4d19d0f1b9fcedf9a26cff71b05b942b24ddcfb178a1be3beba1d1e3010afd0f6cf8004eb5dbaa2b04d6aaceae505bdfa7504fddfec5ad6e48f8dce6e1003efd40dafefc1dee6ab9043cfb2f238bdf61e84adff9d6fbc68d9eca6bff7badb430af62e7fbf18b64f3a355affe9d28ffad0560305ebaaaf49e242567a2b47741dfffdda1dfcbccb790deaba3f30b4e447bf2703131dfd887bed1c6f3bcd0f4a2f807d17f89dd4130ed76aaecff700d6cb9cedb55b9fa0c8b86aeac804d88dc0ea42a9111efb9937d70fabe6ebd928893bbda6f7fcbe14db74cc07897b3605fec3459d2fa8fe13995cef09650a90e8ee14a8fcc2ef63f4ebdfffc372aed4847d684ad79dcec3ce2f8b3230e927c2dfe1ee01d987986f8bd48fda890cecadc4cbfc4565cd984dbcd21b3d44e8100a63d346632c7bc433b3eadf4bffc14b95be4f8fdfaaba31d010ed14df496167bbd5bc5abcec9551f38bb0ebbea126fed3a6ad31abbc98ce196d2a693cdd79c44909c406cfe8bccdcdeaa9fcdbb5b1f9ce7545a15f55f1fbcb35cbda56cae493f2daec8dea33ada56c4a6aa6ccf96f4db7fb6b35eeafcd2190fd1cddffc4c40194e0adff928ab89b1026ffce4c6aebc2e7fa5be19dc6d9ad3ef1f68d6bc22d46ed8aef60768f7b90a3234dc174c5c3b7694adcbfb273bdcfc5fad609dfaf7a99a9337defb0fa36cf09ccbd8de3f099dc07110ca2f8a74d7e2cdc67cbfe7ccfdaec7c2cebc66179f98ca793c8fddaaebce58edb1f8cbfa07bda6bf5f2d5bade395d6fbcd897dbefeebcb521ed4da90ce551dce57b552cdab0193ea1fc3b3ff1666db80b226d1e5c90ad2e4bff1cfed9a240c1188cae6627b889baeef2bbbdae72ab3adcbea16a14afb95acaaa8d304acb16c7bdc9e10addaae81f0fbf3005dfa02effbc72ce0e2c597803c9ddc64a18c0b6fb5b2be63cbbc8540bd5c56278fca7a4c017c89f57658bcd0089daac8ec84a499a6cb1f3cfec874f22b46057e773e24da1ead9cefbda9e9d08f8b7db9c45fa5ccd0ee956bcabce52dae07b9f7b9f7aaceb3971207ada3e4350ce7813b8ee3fc7dde2b4a62b911aa2bf25f1c2f4c7ad7a2be34c9b0a06a7daed124c4e2b22cdc115ffa91c3eff25d2ab6f61d3776bcc81ffbbe04aeb96175cb1dddfa9c84a7a9eef3ff7edcebb1e12afae66a85eaba5b9ef15bfd0cbdd60fe8dbf7dbf17df906caad7fc6a9cedafb8f2bd11f4eb37f88e07f8da43fffab03fba7dfce0d452ead84fdcdd4dacc28ca246a0d0fcdd1c7d85db8a36086aaeee2edb9b4ab9cabe14ede716deaef6c4f0e701b4ba85fe0b6769e52bbbdec72a3afd6e6fe040474b15a5dcfb38eafb69cb7e9caeec3bdc9deabd4f5aadf1603bc1adafee097cb9b3f4dfd540ac7ef6f1ca46aecdca942fc0c9e775f39a5f75fb7f1c0fcfeb7ea0d17bc180c355cfd2ecffad8ed0d0423a462b3cd6edbdf3f19fed4ad05999fc92f27bb0f1908878a3f5acac1aaf56ac3e3f233fbc75ff0fb0d6e81e22c4bdee4ba0ce9dc83334c4c9c9ee8650984c68df2af0d15fd6cde11aa85d9d55de0d0b446dfccbdf4dfce71aac4fafb9d0ee236d858928f28cfe4558c77c0a34f0fcd1ebdeeefe3034cbada5edadaab77f57b823bf7c23ea4afcbb9e9ed86aabdc985c967aa0026fea9df87ac3c99fce87bd9aaa5ea993d7d50b9af4c132caad98adb244b3c2df00cfdcba551c2a09df4efbab7cef3f264e49ea6ac5645dffc4077fdf854747bbcd7108638faaf198a7fca2bc24ef2abef429b0abdf592f1ee0ab3e92bd316b84f0c20f8fb33fe7ee7bb25dfea0d5f2bf440fbcaf4edaefcd6caf87faffeccedcac1faf7c6de7da0f56c314fabbdaa6acf1967b397ac509b33645b76ece1ea9ca41c68ae59a84b7be515fceefbd0cfbdb3ed7ed5ede4c7e79b1b2c7a7131cbef73ed8c5702ebbd241abea2afb8ce5fd4a435babaae81a74a23b1f545858aeceff66e7ccd7e49f0d31ffc2b92a4b8cb4aff5f290c25b8f0d8b7871af7b5e34e02b89aabe9ecd00dcaebcb6bbdc1e7adaa895527aa47c5a2a1dc0a27ba4ba4cedaa50fdecbbc0ee730ff30e78c44c5fdcfeccb6b2e25e9ebac07e32283addbabe41dcd1e4ebdff041a34b7c031dd9e1cdbbedfbeceb571959e40ebf204dcc54429daba62ccaf800b598e8d0064df6b5849e6cfcd22d3aefc38fadc07cf7e9d7031cf8ae11bfadd1e18beaeacb55ff161f26ee41ce3a6cda461c3bcc2b0c163a0b2ec927b795039aeaeaab9be1e2ca9ce2a532f5cfbc2b13ddf00fbbf4ef87c075c99eb96cf45fac35ac88e1b22f6ecbfeced7efb8ac26a3eecfe76a13ebd5d4086b571c53174c6a89255c4baff22aee409f26ef27981c27b4b67ce267ceaeab31b7eab8adf0bba24f5eb2192a5bef0a8522ef6e1c66f2fce2fc4aff2f5b1ee4a7abbf3ebc09ccc06c231ead4b4b04f8ef8ddf59a34acafcc42b3a99bf1bd33e3ffed458bccb79736dcbd2e15e0bcad23c3dcdeeebdffcefbccaead2cafaafa188463ca5f8cebdfe0c505c0cc4ebedd8caffcff1abed174c61dfab59ab3ed0067ba2ad39d7def88a53bc8dccbbba7a4ba8ce1fcb822edcdf224fd586da537a442281a23a6f1baa4b21873aa5344b3aea20d782543aeaedd1cb9a680cfe1c208a48a17eac9cbabcff6807f4948324afaf2cbfa19e0ee1edddca279a9e0a0aa5d99a1bd5b128c9baf0f83d7400a13dd5c268c2ac3aadedd67f7fa59256b7edd4386ece0ec1d1f2983adb25e0a9b0b1aa3d32ddb9dcb26d58ceec2f02d39fb4e232cad0fcce37ebfbc922dc11519cf9925c1b0de1152546c8d714e40dd4b1c1e3fadbd5fec452bad5b2fe362d6d358faf5e9afb666dee831dbfae690c1ab76ec6f6eaff7e3ffc225cfb426aedafd6fbb37dfe371b84a8e60d55ed1d8c64ef4f96d832d3fa69fb4cabf6fcaf8fe66fbcbbc3fffae6a39647be37c8a1bd3e946afdf17b644b2dc34928c98aa4d50ec70acdbf5ec041ab5fe389ed6877f274dddbade41e7eb1d5d7998e7a6e1ea7aaffeb42a44aaf0ce7f9bfcb6b9ddfd2c34f7cbb75331afd751bb2a8ebcebeaae394b388cf1f70cffe97f131dbcd3ccf419a63acaec620e4be7aa8db8df33e928f45f5b942c1ba0bf2fd0a6de9b36c947b05efda13cffd94a5c8b1b2c8ab1adfbb44d7affbacaf5f9d6f6e15b2df90ce3c0f9f53be10e69fe627a4d3ab4d79c99cf75fecdb3cc2f7cbdaa24c84cc07db5a21cbad482a2faffe24bdd2f0ace504436bb68edc30ae60efb3534baafed9ecd4112f1128c4216ae2551df29ba7158fcc278b19609cbcff0ae6daccd1b8cd1ccc3761ed8a6facd1dbf2cc72fb991afe70adbadf419ee1aedebc93b24bd28e2fefe2a2cfac38e78ac582cd60ed83e8f2de54dfadb3a52d4aaafaf3d3addbe13fa337a4d0f050eec96ce103aec5babdece9090e70d2b059da2aecabf9b79fb55ab65aab0bcd0d6aca7acdb665f04551b85ab14a080dbb40fffb69ace5ff0dfe3e5a79b3fadac524e910eadc1eca51459d6da1cef8d131fa95baead63af5e754ece737ec3d29e49d1becce4d62e9cc9ddcd753db0aacff5a9a4dd5b0ae8ce8c14bcfbce75a3be2d0f902cc3afd7b76db65bf4aab463643bff99dfb225dcceb71ed400de2d2eea4b7ddf5f5fadfff4742d9ccb81c4ab2b38f8fe3ad5abb8e3a31e28e6e691b74b51dfb40b99c8dccb3a63d3b21f1ab307354eebb0abe5cf45d2cd6eacb13f3c63a6aeab38f21ceeb78b85ae2c8f3f140336bc5eef6e62f4b55aaae9c6852d31739d8af9eed12a76387aa0826d9641eb1ccdb99cbec3dc3db4bfa69ab64713ce640e2db9524dd33ff6d2b82fc57a36f372ff6a637f3db1b7aad8aef38e8a2d4adb25df3c951dce141bee729ded992efb173ac25916be3cca2df3a05c4d0cf0bd5b05d1b0cf768addce3732e25b1e87ec79077e4bd6ea055e5c0f1c46d4dfa521afc7cd2fab9aa926d4fd60dfe5b79df25f7afff9b8d65bdac73ffdec4e0a69f66156bd51fdf42ecfdbcd67b5eba9dc433ed7dba89be4c3fe4fdd61ceebefe8278dfc16e7beb0820c1fbfed6c52ae23dcb736ee0982328b722464cd3b4d1e9906a27afa28b455eeb2b006e7fdff28e2e6cd9ff355f0dadc6e62ebfb6d35f2adbffab0dfc20be860c3ab70dccde11a801fe1cc9aac73b6d2abaf2c67fa265adfe3cc2bb7dac79aaa20f3df49b199db58abdf14e58ca7ab7ac07317d2fcf20f1d7bf8a2cbd3de6c9caf49e6f9e445abefc92d6b3edb6fbac9f75b6c0975bf9afdade5acbbeadbabd4aa017dc9de9d0d6ee7e5bc091924428bec8a6bcca2409b1afb68d2db804ce7a1eb9ef52bf0a6bab8e5bfbdcbeaaff68e5fdd2e3c4a04a542eafbcddda63eaf27d22b1b87b8b03ade75a7feeb2335cbbc77cacfcbf7a6ef4fef2db3eed8b697e5e06aca8d6a597ceef00acab7aaeaeac39c6bddd856b570eb62cb9103f2fadc5f2f31fdaefccdb57d5f36edacfbcbafbc9fb3c750ca95e882a5dfb9b00cddfcfbc54f5f9acf2f05f9c96baf3338d9fecc6fdeed239088f96390b91c1b44d6cd30beea87e429c432cb59fa1c3cac7c33f5f4d03bad2d5e27b2dba18bc37d9d687e650e4abbb4bd08307f06762a89a37a16ceba722cabe6fcfecc424acee6f8c2ef4b027010cdcfdb85afc8f41fdddfbdf9cf515cda3f7e9ccb1afba946f5267b0fcfa1d2eb12e4d1af40d661eac4cabdfba61b755c1cc0cbcda6e5cfde791fcb4b92e029ddc29abd6cc1ab955bfbdbc1cd04df5576810948eb4d76aaffd47ceae811ddb8dca2aa45c310ed9c25162c8ba0b7ab4f62b8c9edfac521e62bc8b4af88efc81be2facbdc438be8cfccde557ce3ab6adfeee56d6ac629cca87dafb2dd3cd8d6ededfbbef5e7533211afdad36d4faff3e0bd3bd97b41667fcfaf5fe8bdcfe93190d31e0abd6eec052c92520a962118e2ebc6017cd87fdaaa2ed8792cec40cb5608cf40fa8ba09dcec23d0d8ecdd08d7a8c1d2bc697dac9fc0513b30c585fffcfd77c3e6fbbad5c64cd38ee42cccf530edc3f0bb7fa7efb7d5a1d1cb5c497f4a4986febcfbaeef69b3ae05c282a45fe0ff1ca4dffc1a3b1dddd1a53cfd5a79b9ae62ddaebecc995ef5ade23691f8312a1c9f2176abda4ae8edba49e1e48caa31d7962bdda7ed2c7ff4bf58ce57ccd9f3bcbf5ebe211fb8b1f0cbd2e5b1343b7a1e2e34fad6dfadfb84417b13f993e91daadbb8f0dca76aff40e94be5acd294c7ffb1d77ebc4caa704fe0bf5868ba80bc5c7dc1fc260635c96ceea6beeea8d4ff0c1ddd6fe24fded9cadcca5db8e223bc7ca4ac1bb80dd6edd2aa4b0a20257ac5d9d5e1c3ffbf87d2e8c1744ea6061e3ef9aecdf55c48fdefc2bcff6319cebbcdabe751157be74abe66ecd3f3c939cdcd0cb88fca910a74df6c8fc6b48807eef5a2a34be217b5988f0da6df5114fcd52c6576eb7f3b0d9b8d4a8847deefbfcf4ec3cf2eff3fb6b0cc08d7db87ef9e9a7b8d76b2fbfebd546a26fc15dea6dc0cb6feaad34b0bc9bf8496adeefbaf2c0a86cd3f02b11a65f60acee041d87abef2f3bcfa01a06ae2295bbc02e7bbb9369d3fbbe147d0dfcbca367efbf4955cbf3b5d5ebe6b7f09d93e17ad8dce54e16e9ce8b95f9de0dd6582a9a35d5e9e00cbd7debdcafaf34ff7a25d18bf188dab605060d74e70cfb1ceedd18dafdf3a987e1278f0deff19bddab31e747b32ebf5d10ccaecc9a1bc4930dfaa76e6eccbc97c3defeb3ebd5240bd5aa86bd0a8a5d28b5fbece1a8b7d8e2e2fb8cc75cfc05fd97eafdaa61daea9d66bb7e089a2b2fdbeca04b1d1d9bdddfe0d0e0b7cff2bc12c2b9fd1615c80e3bca55e5dbcedca2f1ea65ebb7cdad1a69634b4c5c7ee752893e7545af2daa4c428a1ddc433516bad7914bf74a3a2f677802fdea38afdb77bb0dcfb4ddedaaaec80d9ea2ca3a7fd90deeeecafdffbb0cb77acce761ffe8bb4ff95bb7fdfd9eb31daea4ebfebd9a1aacaaadcef9d2bbf76e9bbe9e8198180eee0fa8abcdabd0375e7aded743b4035de8661068aa6fc13fcd1be7edf6f83d2d98f3804c553926cbcfef63daf131dea5c76dffa1e2c941ee27182d55cc10eb2df3acdbd33e41c2168ff5e3ebf1c7c4d2bd72311e2eb8087c57bdfbaacf5efc53bb9e6ebcfca5ccabdf8fdcbc946c7accb57c3be33b7fdb4fed4b2b81ca0abde6a2557c79aafedb4de59259b3c0f9779eaa9646a96d5808f6389fa3fb4a4169aeaccbbedb803673d35e6d3fbc1b66346bcc894e8beecbbfb88f5be05ab11dfbe6da7be2e271d190e47c36f56db1fa39fff5db44d9cdbad7e2f9406bf9a43cbeb9a7cfb162c2bad7f77c2d9bfed6307d2afada1402cdb0df6a5bc0e2af655fb102cff34afabd3a11c4cd9f015125ff04bcd1ea06bcddaedbb1fed6ba69c2aaf4634c0e8adfa02d73d04af849bfed278f1eadb6ec9fe26cbc4a8e69f44e4eefa4d8eeea4b3b8d94b241e3960c909a6ba1d8f4abb31cbeaf1321beafafaa8c126da47e6ad2a2ae6c79dffaf9dbf2c6f0f0e395afd0248c1bdb9f3bbbe4841c1f3589d906fa82deceef62ae8fb9952cac1b4eac99f5e1dbfdbdca21c9b6b7f7e25ccc8a2b7ce9dc2cde6607dabcb82e5dbfdf064de8b2b93ab785cc6bbdcafbe2ee7fb41066d8ef8a7d6e61bba979f36befe433afcadfdc85be0f526d980bbd9cf0bbbb40faeabdeac5f9b0decb1ec51da5e72d89290a5933bcb8b92cd738309bc9ef2effb643b54de300fc1ccfa7ffc13ff6ce8f87cfc246126c8f97d7fc1a0db572dee2eea377806bf08c2dec05cbe0d3c340e7dccae9796de6b7163ddac7efe5eec62ca8ebdd8bad5041cd8ed5aec1fa1ae48ae7db1ea37bbb2ddb7aedae0f4caaa4c48f22ae3957f2dec91b5ff6c1fa0feaa45e17eadbfc46bbd0cb9a77da0a1f2f4e7b2bec3a4d00c3c0c55dfb6deedba254406d27e1fb7faba1acbe6cc6dfe3d0ddb0b1e6edcd50ecbe56da59e9bd75befb76facbefa0dcde72acdef194a6c1b3aea4e9f5d2347aafe12fe4baf5318c3a9fd5f27f014cf0ccfedcd3d32f4a3af0fc784c2fcabddb0e9ecae3e0b48ee574e55e3e6a17d92b12ebdcc1b6cbfe71ae0cd02e9fd6a2d77c2a245eb0cef90dee0ac2aa6b422f69a87cbab5edc12db8a48df734a96b0b3e0c6772feaea12f87befe5ca5aea9e7a23df73c3073845c11ac5595cfa81ff9d2f4babe1fc82fa3ab6a20fe6643441397de2d4edee4838a812c63dfff9f7bdcefbf40c20e0e026d3f7b4befcc86a99f2a1ad6a73dffef4a74d124f3970fa78af5e19e690acfb7595b690fbb1d83a3e0f2feeccaed47451a99bde504c1abf8d0a36bffd0a2d7b051fc05dfeec82ed7fccb2dcbfffbabd9f9cfef5bfa2e2c5b7fbe1af8ee8b32ad3b8a7e7b0598b8dda06949d8f3dd9aa1fd5fa865cfbc0b1c2bedeb250df3f09deecc5ee65367df8f7c9eeee5bdaf251fffb05e10f3fd3bde3fd462dca3c8ce0a8fdae34ebe9812c4db23e51bcbbd1b9f53cd8d72e4b9cc15e79cacefa3ee4effd8ecfffbaaa141749ecadfccbe276aa9fa6dd6b1ab87ab4837bccfb2a4fcf4bfe9c3f0780c6f9f8b7bd6d812fe68d6aeac7dffaf8db8a85a45a2efc03b0eba8c3ab7edd9d191caa6b34ea7d45e9bebff43c18f868e71acdaff6be2be3c54b98ee47a16c10e4fcd5ba050ce9aaa50c57ec3ea592aaaf544ec6c2c8fdeccb3eb9bcb7cfea493cadaa5a7c44e061c58f8eb17bfa08a4dcc947d245ca09d43ce5f9f0a1c853ed3b5257cfcfb29dd5116ece5fc60baadbb9b37a55dec16ddfe2b9e11eee778bdaddbacbbcddb1fd0dec4dceccdaddc8b52ddbab92c2b73b8c6c4bb0c3df18ed9cfe03e169cb3bf90e7acada801bcae9ae84c913afa912851de811cae53cb5ecca2bdf11bf4ba8a82d10c653e2cfb3c50fe5ec25ed934156dbed11f37ed8bc3e6fed5c0f9540dcdfc1effb3cffc43ddbc394fc858bdbede4b9f431dc88f5dced31d14fbb902f9adaab02c219663fa8ebef97bd2fbe4e59b0fca3ddd8d988def23de6453f660a2eed74436d0a65dff2fbf6d3ab3a2fa7c7bbd8ce76cafc5a93686df1ccf3d30c1aecab544a0c25bea5bd8fdfcf72dba7e8cbea0af75fb39674ccf7eecc57e97894bcc0fea0f8c62b954bbb292d9c6ebc18a8f2d25cf4c645a2bc9eedbd68bdf90328cde89bd795a4b2c713b966dbb3164a59ef9c2e7c7fdce1fde1d258cb0cf27b0dce8ed4ef52ecffcb5fa2fcf354c8dfa6aa2e9ecc3aa3ea63dcd52a06a3732978a72a38d28d842c4bd9be06af9cdedf8218e7efed37ae38fc4572eac7d6eb2fdc8fd3520cbfaa845bb3d7fd715ff2d9c5fedfe9ba3dfca2aa41bcdabc18acc6d0eb50f22ac23ccd8911aa9750e26732da730c7ca9b8ebe440f77493aa09764c1bc156b5cefb8d7f2228dea0ee3edf5ec886a81cad57ec00be23fed3c4784d4bc0cdcf0ff8b0a27cdee0980eced60cfade29eebefd3f8ac25ee75d6cc37e499df3ef8a177e183fac1bebcbab3596c2fe87f3b5f8fbfec2657fc5f3ceb2850c772dad0bde75195949b770d03abffdae0ebcec369ab49ca1c1860e79f2e7c41e3dc8c71a601a37abfb932c11622cdebdb5fd3d4a5a31e60afb54def28f518d5fb9b5180602e20f3affbebfcb85ce60f3dcdaacdf5adfab167eedf3cbbd3d5caed8a83e4fe64d80adef39951e7bdf85ae6ab3e3d8a2cdb7cfb6f4e8cf9feacc4226e0667ec4bebae01d7b8d4c77f2ce396c6e19c4ecac58337948c3adff8cf0495b7bdb0bbbaaafaac9f90d6c207e8c65c15f6cda9d5f79dfea4ddb175f6bdfbbd1ac8bb4aba1c10c85f946f54e42c62dee4a2eaf2dc10b29ce60a6a46ebf4e8f1362bf3b1d445f32447866eddb695ac1ecaa6e49058d0fa70cabf77d1e5135f2ae198bd3fa040dedafe1b6ce4be4c0bd5ac6fb89c1552b076aac9cf9ed7ccfc28f0df009de130db5ed6018f733bd5ddcce88b8aa524e6dbcc905c796449e088cece75f11bbf0f240fbdcedffd1cc22a72de24ec60eacf7989a7dabf505939e3a0ae915e22ddcc05d2be031ccfaf3cab4f1ef1f95efc6bfc422b77be6dbade2e3da86ec137dc72bd9fcadf7ddf683c62bfd2c0fc35eebeb6aba6c8a2a1cf48a4f942c4a8ff2aea1a4c65facdfb904efce8dd4b7fbd08f3f487fecf9fcfb5d2eceb15ff1de11d21ce64cbae7a2c919e60c8fea9ad1bb79b6fc2dae5e6a5beb2dd677fcdd81f7be7cacafdfac318a4fccd61b5e0a4b1cb027cbfaedacab15f4b3d296b48f4cb8afbfbdd3e5899cfaf38acfe5e7e6d1f0f647358a57f3c7c410cb5e35cacf75ea0cfe9e82ffd2839edcfa7df6a0c7c38cbbc7e93e5be4f9d8c1ca2b87863eafefe4da342d1472faa1dbfdb0cbf741ca617da2f89df1df6ddadeee10d38e09e1bfa71db74adcfcd9ed644ba50fb153dca4dced46ecd5d2dd2a825d0e877edee7ae8c43a0197facd6fdad0c3fface83aadb4fe9e6cfc2f70a6972a76edebbed61bf8498ba081e7f7edcf64e4638341aa8c2bffe0f64e789ee4fb547b2eefe786a8025dffbb9ef1fcdcab20ccd91c6c1d99ca6accb1ae0d168fe7def12072fbdaeaf91b68e4d47b1dcaebeb7cb7f9754b8d742a3cfb73b4f520e6ddeda40ecfbd03513fcd53daeb4f782df72ea5ac8c9abe5b33cfb344b607ddff0c91bd088109c5e77aadeff68cc3144eb506e466f5bede4b90cbcef70baaebafb8cebcffc8cbddd309f3db424edf0eb5aa38e9a9722a3d4ebac1fa9cdd7c2f3f8dc0142fa2269a82ea3f7e1bf0c6abef10dbfff5bee9f0dd83d0dd6bf7fd4c8ff2c1a193beb5b4ec3ffc3a00afcff0ebcb5fdbf8a9eae5442a946efc9e0287ae52b5ca96d1bcf305eb22deb9662041aab35aaa91f5dba98c7ecd82ffc1f2a3459213f7cab23759fefa7e8f7dafeca18d0cb6b10a77bb3bcaffd7a7be3fa67e828eb1b1b5229e02dae56159a6b80fba0fc3f7c1bed9c8f53e7a2fe9bffaf6dd6043ccbdec7bab66aac25e6b8fa3fdb5eb18ef9aa6e04a3c8b4cd504e0bf9ad10ad118e0a0efcdfa052a8a0c7bf5be6a21b981b70e0daa9ae35abf2fce418ca3e9ffac8d4bae8df6215d3eb0fea1facebfee1d6cba54bd61236ce3b0b82bd614decc6904a36a4a3cce1e0da4fd4cfd44fee743d41ce433b027258aa8eaaae9cf4fc3e5544cbea4dcede808dd729db39cab725bbb60a42f3e4ff0f7ad51e260af41cff59422cb164390ccaa9ebdced979adb17cbc8c27deb8ea144e14935bfee1cfe8ef3f3c85ede816f5e4ff4b37d3a8bf93bc34b0ce027e4ddcea959bebcdaaec6bd540cf2b5ffc3deae0a49fafa2ad3aaba8b5c3d2ea1ca1c2b3d9df344b650edeaed7439415472c05dfca3e96ac64b0cc3ac3cf4bf3e697a35eedb0abebf15dbaea37b8ef4a5c4ca5dbcc1a17aade50fbd83bdb531ee16516dbc6ca3cfaab1deaaaffcb68afdea29e44f210b67fe2068a02f2212eaca9c1cdc129a98bcbe7df1cb070e50ef0e425ee6a5face2aeacab73ab2cdb2f6ef0ba21bb490add5abfbfb99fa32a7cca9efdfdeee9aabe229884fccf2838cd96a9fe7ba199da7bde1bdabad552dba4adf48655ac3df52eda1df119f2dc3a9fefa3cb61d7dc0665c4b2bfcebdd5fc67dcc1b03e5f8ae10d96feff41b2d9dd0b691733cecbc9e71075800e77fa7ceaef401a1a836a6a75582a19579ef44d0c9cf1eedf6dab35eea41bbed8eedf8d6ad08ddfeb4cafdcb1a96b838f12f7e4fdaff4df48feefc0c0bf3c79179dbd3ed7de1dd55ccb55de906b11854b19bc8e6d1c8b0d0c8c20fdc2e62bc5e96dbf76ca3386cd1e8f99b8a5a4ea240e6aa77008bade3a118dcaca7dfc5d435e9fc9dd7fa1ce2cdfacd7cc57d07adbb0b6c9b9817581d987c0fc7b1d6d0a7a52baa9b18c39114fcc2e71a9583143a60d63ab1e32c0f96c0aa44ad9190de9120d2ad3bb2f41ab422c9bfe11df049aeafee11e8a7b87faed87ad21d8e21bcd90dc8acaabf8e3eebfdab8ca15d9f8729f11c00b66bbfddbd741b85bfaadf9d3d8affd4ea44be7f10faeb67dedccbd1e8b7b8122c7aedac8e74fba4caeac0bf58aca0abc4247fd3ade7edddfadbe0ea328214eb5d25b8fe8d65dff90ec7b45f6ccd9e7fd4dcfce2d5009f6b5b845cabcfa3b7a6fe5d0f9be4dcdd4b8de60ea7ed540b1e5039ccf31ab14d9bfaedbfc14bccf94c4aedf6a13a7b2c7bc320ee60a99c755c7f0dd1d1151d8ab4cbdd76e2e610fefd2ffe16c2db11fccc96cf8cacae7ce8c96bddb5a48a84123581431afc84dffefbbbd621c96a58fde0afcdcf2f187fee518a53e5847ab2dab5757e756b1a3e8f1aadb77fedd6b4ad201601b0fcbc5b41e7dfe7e5d4a668df6482dea4f9c6ad0c01eb02e9c580defa98afaf74c9d69e15bbbb20f89086decadfaaffd6ebd7c41cd1af1412b5a914a4b2d2d1b37d1f6996cbdccdce472fded28bcdbded48acf1e3eb42d7eaade8fdcda88adaca5f9317cbbd42caf2fcffc1adaa8f22a897b6bbefebecb2e718aad4f2d0c8f7ea6e1f3ed1faabd253dc6e2ceb2d11a214f5d1dbc44dc234a3ffff9ede3b9adc57d0ddc8ff0dd2d38cfeb00ebfd57d3d54b4add9fd1b8e4e4f0c15c7e8a08deef5bc02b3accfdeee84c9a6205d38d6d7eebeed10fe8999ebf4dbcc77ba6bc718319cfd20b48feb9b05fc3c0dc56ac03f8a2ef90aed0fa3d7bd2678cc17bd8f0ef57b6a332c3da7b335b90b0d507bff4ca6ffbbff4ab58df0d83de64d71b5ede09ebafa7e0bc5b43611bbffa2eaa38adc648d6e98cbdd3cefaf40abfc865e6ac42befdfa1df41deb5eaead7014aedabcb54a620ad6db3f6c2a3cb3dfaebac6f9ee2cf5dfc4a7ccde270ebca77be3aa2ccea0b980aa96a07851f30be7e53729bbac8ef7db7aabef93dbcfe24752b8e1cb4db285a25fa0ba2aeadb2eb0333f7ebe0bc103206d965a0dbfeadacdc7a26b8cb487ca6ee77abd7f011dc2de2fcdeb3eb2dd6ade6b4fbd79e25fd6b84dbbc0e926a9e42d35dc6f9071ae0e1984adbc20012c1bebb4abaaf91f24ed24d5ddc02523ccd9ca4c0cdc5bcfdf85a972fd6b23a9c0270e1244a9cfbd7b6b81db55a5da92efba1a2ac9185fe5ed5e7bdbe1eedadf2d129f7ce98c2dc59fab7906e2baea57ad1952dcdd18beddec34e2aa575aea508cb3bba9e17762c81cfccd53b9dabde3a4aeadcb2aee5e9bf55b8f752ace04e929fdfd3d1ccc96dd9a45196e1b6b2dfe2082abb8eae545ee6a2ae3e77a70ea9dd5cc3fad6e0503b9acaa945afdc85afc62f40e77ebdf5a6c6de35df6eb15e65a47cfecf3a1fffce5e59adc328cbd25267a3594d0f0558aace9236a4bd1caa5109d7b5c3590a01cbddb527ddb469deb3dd4d88ac1c8ab39f6d6762def2e7ab193edb7c1ccaaf6aadcded2f1ecf92c5f16a94fb160ffa1c8a4f6aeaed799db2379ded0c6b56a54af6dbe4b6aa91343ace9ef8a36ac71cefbda4aa14769fdc0d3befeecab36dd08abb3836afebcadbe35fc0eba0d2beae44dc7ee48fc52a19932e0b84f97ea49aa0a257eb7cbabdef29937eeeab91fc9f8184a1d0eca34aeaebccbb6cfdda3df4af9eebcaa0a539feafdbcab3dbdceabda676aeefed8cffad6bfbf05dfafcade32954dfde24a0646fcfde0bbceb1fa6edfffbfef56871caa0467f52e65edb8b9ee7b4678f14ac2e0e28f9dac9e89dc708a24854084ceb6bf58dcc121a7adce1fd1fedfbc01fc9dfddc3dba47ab9eceffc6df2220e2b0eada9efc8e40fabcd25f0dbcc767deac43289e152ffe24b643c7aa9ff7be67724daaa299cf7df094b6cbb6abf55eade33dd2e23f76fe9235fef562333aeb7f158ed2aefe019584d32c8711ccdcdb7a925c695ca6ec35d0c23892dcc8cf69290b22cea1ac697dc9ec86a35ffca907ed48ec03b1ef5f73dca6de4f92191e3ed1edf2728dbbc85b3676f2b2afdb0cdec17e4dfede300166ba620c06cfa31ebfd3b8ca13b6337f6058e98b31ebf0b2bcf2ba9cf2d6fdb44e0f1e9e7e9aa7f3f5ebf0aa434aaddcda30f46dab4e9324c61bd76e88dead4024fe68c6872f3ff7bbc1b9eeca6723ee45dd4eef91de61df0fe4eee1fa385ec869ae7e5f6c8d8ead668ae67eceb03a4dd701bf1ca56bcae4478adee966eab2bbedf751d7b8f04d7edffadbc62fbdcb9ca353feabed9eddeb0c6db5a10eeee1d8aeafa340d1df7278a2d1dbeaf9666ed1ee4ae5f4bbddd7f8cb311bcfb32ac80e46b7b9567752abffad506c95b9c1badea1e597bdadd45a8ff1add93ddeee6fbe15caa230a9eaaa4d57e8bbbe37cee1ab4ac3f4feda5a08bdb9dacced1f4abdd8caa8affa9e00b4efc6bf4c94c22dcfb6d4e5fdad9f142a9d78ea9f0fbddc5de3720b131aec918e3aaea9cdc2f1daed79ee3bb0dd3e434cb17f78f56dbaf7996f8c4e7f37a5f298b5fdcaff2a659d51fa36fbe6fb5f3c69c24cc5b74b2ec0b8ceaddfb8cdfcc8229844088acc88e65a7f2daaebe224ad96d2fa6cd6ad2afddf53a023e2eebf63ddaefdeff5a696cf3b1c04e3ed79da5e24db7f956d87ebd68f2e815844dd54b3b2a181738dfbe6ae3d8f16c3d76a75c30b33083aa81654a0e695a41a3fbdfef98a86b47daecbe7fca7bf50d57b1dbbee7ed7d3c6debe9d1e3eeb967c9bc7f25f583339fadfc51d526f8469bea633eac9dc241da5e6dbc5d9dd6f7ba50267c2a734773809cde16f1fee7079afafbb1459bbd20ebcb554a23f8584ab8b3ab013cd8bd0ccca3f1066d018404ffc0a76c7dffb3faa16b3aaf6419af89ef69ee6cbaa6a9d9cf9850b9ab67b773a56ba16fa258b9e4aa0adce4921e5cfedfb9f146891dc47cdab2e3246f0daa47fbd70d963e29bd0b5b6fa3ffa9e87cbb8ccea5fe04b457903c9fd610bcff87d91fcc53b4f414ffca8d26d2f7ba75cb1aa2353b304a902fea6e856fafcaee09ef0456cb87eef7887d09a2472dbcfcf6bf75bad2dfd7948ec23e7cacbb070ac1cc6ac91845dbc6aadc8f4ffe1e31a6c1fe63f0bc0d7dc43061b8daedae2fdd315185cc4080738c53bae55f827f188b8ef9e0ff84aafbffcab25231ebfc0dcb2ecceb7aed44c75aabcb32488ffd5c5d1d9bc9f433f3e6c3eabbfd111ed5d4eef9fabf341d571a71d6c70cf69f2cec01ff345d1cbcf7cbed38f3ce59a13ac6cd1efbe65f711cba24b3a5f190b21ee37e5e9ca9b5ce0863dd59d8b9199feeb6d3db8dbd58eacb87ea288fff22791d6b892b124066bb88fb563535850cfb19bceeb1d9bdae139bbfeb85d0b279874228aaa25c9b9914bd98eefb6ee83eab666df2dffcca6abee58b5e4b37711a98bcf4db4a5563be13e4dcade7e7f38171eccf4a96a6510b9d3123a73ddf1c42dbcffa6498ecb3abf9facfced271ff6dc3b78dcdeece1ef3310fe199e02ede32fdafb3e0cb9d0ba06a542e6c3b71a4a209e23f1dcfca9bbfa5ffcf82b16bedeaf3cbdcaecb887eee8ecd08f132e57ebde3cf82f875b4013fee0aec399549177601bac38837e5ffcf35bcd1fe373cffc1c4679a60610cd4dd69e5a09b12fa3effe6ef67c923bfa7c2bceecfef9f190328a4d54b601bd3aa060cd21cd8c385da2bafeb9bbbaba74eced25ffa9cadd0d2ad5d32fb9ece569badacfeb595f1cbce2dc11fba389caca7aeedffed014f49f7c5dfed35eba9ea25dbb54dad3bcf1ac6dfc71d6415f35de1512b09cf1cb0273e3c4054410d8daa4bb93d8aa9cf6791e0a4eba803db270775d8519123b639fccef201dd0c3beccff0d3ae72abeabd5e95f52dfaf9a3bdec7e17ee921fc6935fa7555fbc2e7a05bff8bdcf5063d7b5edc3b8ffee39efa8ba6cc91e584dd098b8833f2dce3e4dfbbce7d0c31f9e70c1bcd8a3cb19d5ce8fce7542d6ce1756919c0b9bed46fa93caccbecbed8ed501cf0dfbefaab80f8bc0fa6eef1e4951fdb31463d82d48cbfbc929abc02ce13ca1cf8d0ec1fc88d8f1bbc94c0b9e3ed6e20e6c80d6bf06c2c8ce37a30920d1b96740889f72b0f26b2296af44383fedf26a7d0e639c8e5d7cac962f166d336c8c3ddd2ddefafc4ff8a73fc4da11daebbca2fcac86bac1f3870260b1a520d4d297ac22df60729e06ea2d03fd8f5b0d6649fa7ae2bb5c5cd2ef3aedfcc99ec5ed7acedc30b14af0beaacee58e28cefd3cb975da7df4207b278df3f767ff8927b3cd23783ad2bec11acedc1a6cb7b921751ba1f0eeb9c4160c39cbded3aaef77aef50d184835dcc5ad9d565a3eddaa0ac5fa1e8d34aadc9fff7e7fefd10c7f3c8caa0cae4220b5cef5ce5c59de3fb4483b2e0422afdea4fe6b622309ccef85dae5d9cb4bcfbcfe54d0311c5d90999cadc9bcdf61be0bdd479529b2c1eacd02f6b2f4f62c82ae2d1e2b3d9eac7cd00747ff8ceaf8bd077fcf1afdcfed05ae98b6be05f9acf1abf2da00ff7e7eec12b3c8dbb7a4cc55aefcfdc2e0adf2eabdb4ee47bbdbeefd8f19add88d4ce3fbb8eaef90d906acffdd5d394afe910870fe56ca6bb2dec361ffd50e2a280df38139cd122c8dadca2c3a9ebacd30bf3f1ed0ffe87baeeccab4d851d6fe2a6261e2ed3f0bac1c8833986e1cb28d4a2e3c81bf3cce4ba7bffafbd9d9db7ad04bed4a2da5c91dba8734990dbb2d3a194e324cf1f743ec1db0c5dacdda0a31af2b19dbbed8a8dcc0f7c5ccce9abffcfd9c0837e1c4da8facb19ecf62d0ed0d93be4e647eae8f39ba8fa693afacdcfdea4f46ee3b1fb05312eb52cda561ae9bf601fe1d562efdbb0cadfbd8baaaeacad8433cceeebead05ad53b32fef5e327dee5a34aa861ebaa9dc2a3a1ebb340ff9762f5ed7bf1fccc5b8d5535da5c5a4e3aa2dec9b59beeea90fbcc08db87df06dd4cdc7d582f0c0eba66e0c8d1afaf7c6bc4bc4cc9f08c30e662add5d3cf4d2ff41fdba8109d468cda5d8caae8567cfe313ebe721e9ec7c3b5333b0e6b6cffafa0c50fcec756ecd42e082e09a20fadb0703ae7d317488cfddacdfbd533e36a00cc89c1bd3724cec85637d5c1bb30ae52d878ef65ee5dd9cb46bbdedadfbecef8defee0583d64aeae32eccba5dd67bebbd93ea232075f625e984facdaaaeb0a3bd1edb5ee6afd5abaa4ef2b893ced39e948fd91e176548d6fdb0b01bdaa27bd7acb0e344fcb3e63a33e87e2edb3bd07414005ced37a3bd952aee5ce5dcddf9caaeebced344b4cd6cdf4cc3c33a679b67bd539c2108b25f5deaea964e3dcb3fcd9aaabbefd1bfe1de7a4b05dd9f5b63bf7bcceacdd766aef142a720a9c663cc839ade15401b72ea1908c37e7b6bcb168dcd2cfc3dadadcfe2cded8fcfb8de9cc1eff73eedfc29b63ca45471efccde89fbedff158bffab38d201ee4ceda6fe8cc5f76ca203c7de9a4ebca76f6eaf5a40f0ebeebefa05bda2a347e1451f4be0dc0d526abbcdcbeca5e873ade2faa5e54a09eaa43e203d77eadeba3cf8fd161fadf2c26b493c5d04ba4be6a307c6172a27ecf3aa09ea0e28bc53a8c55afb08bcff638cebdeecf48a88c1c8c2a352b9bfb53d2e28cd70c051fffbcf433e28067f63bbdafd7bbf129273ffd90e08ba2828ffad7ff8a5a1fae03252da8cd7ffa4fa46db5ba0b2796acdd4c5fdf311f0d7ad3140f732b4d0c583faffa72a3bbb5b91cb442c15fdae8d7f823fbbe384dbcea14c83efcc6ccebecd68af0c27e0829ddcb0a53b0811aedcec60d08ea7ea4ec88429bccf31677b4fcf73b2db6f4ea6de5d3aab79a782b414a11bbf54da2d412bbccf7fdb0f21f9b9aa0e4e1aeabf36ecc61fa4bfed1cb07e46612de1bf73cdac97d98e33eaad8488d610d852dd7ddb092ffddeb19f9de397add5deddbd77eefc3d6ba63c6fc7fb5df85fcb0a5decfca6fe1a1ce1ec9d8ebcffefc5d3a87c0acfc54c16389ea57ea857a6e8e8bbbbba7dff57fefa9e2b547f66106c28ec9d120de94b4aaac5116bc333cbd2b6fd345c30a2ec5f0bd0e344fa7f2e50faab8f4a941bd0cb09475312c21f26a8dd46ba86dcdedfbf3b76a86b4dee13e5e84ace0f15178c3c81cd0c100a537b2cf26ff6beffbbae36f0aadde36cfea0f5a9daed8d38f7facee9aac3d559ba0acdba3b053fefd31ab54154aaae71b6b6c7c5e4cb0aaa9e3ec299ba1ddda4e28d36faa8e7caa5ce4eec4b5d3cb38d83a94b0c75af6efff02292cdabfc7abdeb4e9cd511cb4bd486080e40c4cfebf1ced3a0de5cedab96c91cbf97faebddffdfa44a7f19f84bcd09018ae8ecedd02f3f0ab20818e3b4a08f71cfccce5bef15384be17eb65d0c4dd6cbb6acaf0f2efb58cc8cb1cee93bdb6d962bccaaceb6abea0c2a2a26debafbc1d8c83ededb5ca5455f10efe31735ba7cb88ecf46f4dc77dfbdfe58dacb994ea2d4bb74d06d1afcab8ebc5790f8ec9d9cbc8ccadd961dbd23b10f982fe1a52b9a6cc8bfeabc7b3c34f2dc8f7ed508d8fab44d3f89aa436942b4efde5b3f67dbac506a5b54d9a69fd1bad9ebe83acc4a666569ee3e4a82c0a921befc70b59cb78be00f31fda4a6ba89ab52cbab5befe3e56deaca58692a23dbcedee73175e6bbee72e6a6c3776cb81be4fb336bfd5ffe721660a58bbf81dde56e475a85c87eb97f165dc4ce5bbae6ee099f11daf43d8d35e1cf4bc30b2b5bccae1d533c580ecf1b7bb2eefb6ca8f5b405d3ef95ecccf5a054ac5c0d3dbabc987eea7575ebb1f000cce17258e5fdaf38afb98fd5ffddd14ca9f67b62c811e42c118bb7cce0bd0adcd5a3cfe7aeceadd6c5c5aa5a0f7d8dd3e37f939fdef8c1dc33ca14a5ed669bf53eab5dea64eefed1ec9cea6b5255c773bad3de3db42ee661deea90fdaf37a0dfdf6b55d15d82c98157be7edaa1baccfda5a1daba6fed5e0e05f556845384e9ac5f6a19ff1e2c8461ae11bbe1832efcdf92cdd5da3cddfe004d7287d389a2e2de52b9fbf926ee41f6fc116fcc5d2d6f078ac4bb1a31b6b6ceed98e26aab4f2875e07535419d28a5e3dd5d2cd104edd7685cf62dee3dfe2aebf097f76f938dfb6e1f84f99dacad7d84c1bc4a8491dcb99cdff8ff05edef9b6253f36298a705df4eee7ca6e52dfe5c81dfc3173fb9f969bfa56b4ae26dda7f3bbefc1cfdab9abacedc8dfc4ebafbf0fefbf07c8e3939feb4ed299e18b57fddbd9f8aa3ae5f28be5c0cc0cb8a2250ad2afd5a0fca411834eba3dbccbb4c17e2ebcdda1bd1d7da13cc7ec6289cec7bcc5d02d50d5e9a8abd3b87dd19d3def615ae1febaff132992bdcdac834aa6f79baf7df677bd8f3fa0ccf81cfd2f55204efea9dca829b80cb2bf4aa419fac1d998f20f70eadad3a4c5c7ab7fd4fed4cdf24d6912d7c9ba54c5aaed7ae3b4e1d85a6a9bf0aab5a6cf4aab17a1bdccfaddd552bb13aa674e69e93962e0dd6eaa1098a67a1939783aaacf6cce9feac6e62cf3c2dbdd1bc54f0eeca20dcde4fb651e1dac82eec3326de4410c7cddbceba2f42d6387838e69fef6c216ff9fcb6ee67cb9d6fdead79ecfddbaa6f6553e312de58ca6db83fa2b2fdadee8d9afeb0d4d179c640c626e9f38bddbf0cb50fe7ea02da34caed4e1dbf3a54aa9f1bb8e8d8f7dedcda546f5cff92ff00a50fff1a761e7b05a54eaeb4cdcbc014aadfbd0e5a5e722ccb3e385bca5ef54fa6a617722d5b8c783bef6c039f39d1db794b94dd87ee53adf6e30ea3ac64a10a08eecd64d2ff55c11c15bbaaf97d16c5d1a815c16eaa1a5ead84fddade697f5d50572637b09c3abe4400ab22e7f7cae55958f6c77f1b0e50aabde4f5c9d5966cfa572fcca64bb7e4dbc6e33e6fbb2fd4aafc6dd613a359efd1497f0a1bb5ddcac8baaeb25fc04cd4bb7bafe91deceb255b2f0f23fad924f86c4b29bcfdac793cbc7a2edce2cfeeaad255cfb6a653c6c95bede55ca51356bed0c63fc9bac31225b99cd699e0f4bcbe1fa3bf33dbd5d64e7f1aafddebffd1fad8efb5cd6b797b9fdde7fcbfa8e23eb90c6adc30af7291f054cee00fc8dcf9dd3e8c1bfbbdbac6d61ededf4f71bfdf330aec9df40484bb3038b1a1ea097e8f2dff1242b8afe039ddcad25e38406fef0a7e70a2f7d3d12fe82cb5a54ae8ca456ee51bcee3850d55ff64962f4cddeae7ee6d8a73a20065ff7eaa9ffbc28b35df8d0786bcf9bbf6e987b64edfb83b863471ffd3c6e028cdadadff2662aaef6dba9de67dcf29f32bfcda6a96e2c0667bf96ab90a3e0dbcc80fe5f5cc94201dd5c29d1c78505ad598a9ae0e527ecefad39eceff8d82fcd8ffe2d62bc322bfd0f40daf5d91fbdf99f4d53f95bf9e3e4fbf98dcde2a2d6fdfa719ded127ccfdecf1bca31adda8ac1be559ca10abf1ebfa09f44f3915cbcd8e9e9a1d4dc7d3e5032eab1d94968d5e5ac449756762d5127dd1df006c4a8a366c1cdc45c08fc0986e889afa652a8bfed0bbabaa3a4ff5254e4d409a807be0e80ee0142f690f0cf33dcaaff0d4f078334da53cbccfbc18a8fb22e798154310956938411ef9c5aeefeb1d12dbb6dc0bc7ad1cd3f8dbf25ec10ae4aeaab15e1965b648ea7e8ad8ffc33662e0cddce7e685aa940fdabddd86b9afa39ccdfeb3f4adfdfa6d8218515fac9e405fcdd8c7cbea2f4ee5c6fffda3cfcb5decf0c09fd4cdbf87a9f72bf5baaa3ffb746505f38c9d6889aa1f1c7cb63f3f3f329953ffcaddd9f0ed7fe32fefa023088036d2c632e70bb5cdebd6499626aaa76b87ad81d944d4dce23ab682bc3c361f5ce186bb4dd3eff92dbee55b019c654ff325466c8cf3a9186483f6ddd6dfb5f4f6d2039feaebbd4beefd684abe4f461640d5c5f1a1bfba8a91c2a2dadbb1d8a7d932b6eefed8ae82bad52ddac6464f141bb2dca9bb9de1becbdda521efcd9dfb0deb40cb02fb8e611bf8bbfdd3af813dc1d8682ad494ebeaef4cdd69edc3e2fc1ad76cdc223630fdd6acf77a40c47a24aa8cec6e24183f8816d588efdda4eb4aab5cbb1d8b5ec8ca34c470e6b26f26ebf7adf065e7fdeb1c1ecce359cdd7bbda1eb2d52ddaebb00cae323ebbbc04fd4a2c13b3dc0644dfacdae7bb62e1f5a158dfdfef4c4dd83c8da8b0adc1fdbc0eb05cc903becece082e907eedee574b760da9c1bb32e6d8af7e7adc7d800fb245ebf5ab04acd7e6d142ee6b0ebe78dc5f0ffe3fa4c7940eea5b9e06a3f8dfacc036ea66ed1ba5605c4b1b4075a54c852ce9912f9aed88cfeca7bd90e80efd3ce98627a233ce44ee56ad62e9e25fa0e2b8d1ab3f8579dbc47763ae138db4f190df1ed4dde7beb0b6a0dc2b20cfb3f7c9bcefd4b3fc158dcb3adb033123ccbdfdd3bb82ce27acf453da9aa1bf47df278b2f0289dbb876ba70cdaaa5207cf4dd267cec783bcd8d7cbd8fc62b4a0c3b2cad94dad8c1efaaed13cad639ceeffff860626fe836be4adfc6f667ca5bda34fbe74e5c36acd5c0fe3f624ccd27a70bed404243bf41beaadb4eef7d5eaa0eeb24bccdbad2f2513c8d08dbbd9f0da52e7ff0f7aca7da106de3ee9c2314f8f9161ec0cd5e0edae4f9dd4efe1bbf8cae18cbd90f12d0d787f8b446abef1d7567cf6193eb47eeaebd51cab93eab1a1da8172ffe768bcc355d97184efb0dbad7c91deacefd3a04c7b29aacbfcf0f03fc22d0f10bdbcfebcdc0993e1eb3208ac201a72029baedfdf9f68cbdc6310d3dad0d0acc774cc77de627dd9cd7cbfae4f7af3dad08fa5d20a8b3b41f8ead7cf5f2bce4cdd6d1daafdf5e2efd317abc94e6bea6dd8fd8b829e6ce2f4eb698bc26730febcc08ba83e413e9dacefd2ca48ddf39c17b3a3a1f6dbb0de8e96c394a281eaef6abdc3e4d7c594afc6f649b25df03aee61d7c90aab9fcaf3c41bd5fb4b7115ea1545ebf3d4a78ce2cc7dcdc4d730ad9f9aa7bc8f11ca5fdfa0ded8fabfd1d3cf5ee7cab3e9c8d2f53b6acb5dbb5ed88a7da1b8421926e57cf9a5c68aea5c5ac7ea7d00afe2a4bb4f5ecee11cf2d3e7d4fb3243969da441b6ff5ef3ad8eedefccbaa91cea73a6b808879de7fe2edbfd5afeefc2e7f3e68c1de1aa8d6ad3e1d6be2e48067d1da9ba9dd4cfb4efdebfeb8d0e9129bcb4ecbd8eb3cbcdefbea299beff1dfe36a0da4bfd4fd6ddcdd2c1f77a167ab1c0d3f4e0121324aa4e3a8f42e38d8b3cb2dee1bfbfbde6ed9441f7c10aac9a80fe4daeadae49dda18caf2f3fbc482eeac8cfeab7b3e7a6bba8fcde74f7dafe5e27a90fbaafeefbccac0bdef65a02b4cdafa394cac3e0dde31aad4cc0ddcfe9a2362e9edd2c9ae2be91767d4defdefef4a38d6ee07bd3fe06834e5c804cc3bb2bce2a0aefca7ac49a41d65cadbab78a90225ae6edf63bd713ed93c0ab7d35d8d00623494ca08eccb9171229c1cd3d1806d25157de19a0d1c53b3dfb9aed2e3f8e5d0e78bd91dfbdbb57ece8fcb7c65e56b30fb0b75acc4dc3c0bba809b96bbbd808a7a1c0fd5b9afc172134eceba0eedfa4a70ccecc3fc531b7d9325e34adb93bd7da26ca11ad4abe2c66c42b0d3cbc8ef455aebccc30cbfd3dff0a5693d38bfa4f23ecebf5e42ba8cc86decbbdabc7e833bae03ea1d567f0fabf0a0c54994af7cc80dcf684722f1bfa7a77e2b16ae6baafef4fef92eae55ebbf36aa0f404a1fdfbd1cd7d2752b6f6eeac4cb354f92735b9ca5e8cc8bcb03ac894aaacf97ead12fbecc5c423d8a86b4f41928fd537a2ecbe57d691ede7d0b8a3db6f70abbcef7f6ebf1cdc3434210181dec41bf5be76cfc52464f6bebef6ad168ae204ec06ead1e6e5dc7cecf21656bbcce8a9c9f6d5be7a1cd656c21628b6ceb28d3d65b5d8afeb7ecf04fbeeadff1dd4ba1c922ebb829ebebf5da85c1bbeb5565125ed4a6c36fa491f1bd42aa1fed8d1882a5b01af1ffb28c87a3349a0df1bac1bab6aeefdefc9f34debb16acefc1bee058fcbaa0d5138cbc54e7dbe7d766dcda34d9a51eeec89aadaa6aa2f75a75abce7ad0bea22b7b14b9a8efae9aa0088dbce0f321c70ccb1c6afe86d58dffa3dfad1c1aa9be035aeaa0ffafc0b68ffb6e9a6944ca46debada27ebe4bceafac44afc5d31af04cdeaac9c2c918beefb3c1bcc8bd8ae2ab32cc99ff4b37ac7a6ecd67551aae5f02cd58ff5eb543a907224ea4e73af32e837cbbeaa6bbd06a2ec9bf7c59828fe21d4faf2aece37fa09d3bba8274bf7d2bfcb71feefdebaffcfe0cdb2d942e1dd9b3d11ed6ffd66c87288f68ab651de675e28ccbea33b10de6ac405305772d616fca9e4e16e7cc522e09f14831d26c4fdaeac1f9fbeef6fd4e7cf7eda2caecdf6351af7b37ce070d9b2660b861509ee63dea3c38e71ef9b10ae28a93afdf26cf7bde48abeaeb5674cce0c08102cdbd09ec14c691fdec8bcee16f1dd87f5b31bef3a10dd0faccefce3caafe205fcbb9bcef34acb422ba7d3d5530fef5d5c04570b90e2a95b51c3e3c53da1b5237bdfccafb5dae469bfaba3fcfdfd06a8f0a5e7b66e2caa6b8d188cff7b5ada73ee9b97b7fcbbc3b9bdaf86b2b55a5b00f9e4c1bc8f460ac3feb0e7a1ade2ff5dd582bffde5a1fcc06beac2fa28f571eeb1f4f5cde2d35bb8ee1ee284ab181c5f049a6ee6633b5e0acad7f0eed50e38cdd78593b32538c13d6acf7fb346fbdd874bd8b094a42923ee1df64cfb6dcd0d87e33ccfaade48e619db94387f90775edaec161fad5c0748c01ace105cfacd81b03d51d7a60ccbf43775db638fbbda0c3e7cda6feeadee238a5fccb65896efdd3febaff5a2d0c1ddf746f4fea7d7c5dbbe335bd8befcf69b8ffd9ef35e23fff5e20443bb7fc0adef49aa23ac343fbe8b75cea4cd96a1bfb42abebbb53a4538f7de3f8c630d353cbea2747bd36d7debfba2091cc925bea8fa7b108c0d62bd3e2e983be4d0dd50afaffb8a8aa48b5a87dce9f82fbdf9ee82ee0c81eaeeea69ebf5defad85f66ff0dfbda6cefcdfb1ae8089e97d4d230ef17376a74b2dacefe5ac2a78d75a3f64a2bd2ec4438ba6adff0df21fdaa4b85fc91cfd2955e84dac8efcfab3d7fa7cfffaa0a7385f0fd4fafbef40a0b939d8521ea6da2c9dad97bdfff8f56bf8d24b0f2d1f4bc8b2ae21b43f8cfccaf4bd216d545f1dadde450d8c5360d2dd88b30a5afe2fcb1e9176a2f34c6f2c3f94e3f2ae6bc4bedae525d52e2ba2c4f9a1edddb50f1ed0bbccae2797c2ecfedf8f652df9d8f0fb50ddbdf920f884a59c01e964f30b1fecdc2c477ae4b2808d3de6f211eba7a8f8fddd601a0464fd08fdca5115f2a19d5ba809c7200cb3cacbecab52b28477fd59b55aaf4fec40ce0d82cda4def5ec556cf938847cafaad903f4c4ca3f7dd74dcfbc7b2a3eb770a0a6eb9c6bf9ebde5a38dedf4eae05f29ee121ecdee9690b1adaa6cbbbecaac402bcdfd4298be2bd5aa28ec78d0a42e4cbca0ec33e911ac5ff02aabb5fb6e48bfb879ca7cdb8e34e072bde6fad7ad02e0a5eb68b0fcafdbb2daedb36d1fb4f2ffdb1cfcb7ada54c0d9e276a428c5f1ac0b861629b4df756a6bb0fd68ad5cbbbce6feee8bb7ef8c540e88f7dee705aa7caf2bbe60afe1616bb4cadf4bcf5e4dd9d1ccc3ce4cdf5b3fc0a5ffb1f2945dc61f4f33342dcd386bcefccfc1b4c7bac78cce75a1efb243b5cce6df1c186a35c0d5c0bdb520ef8eeddfa57aebda316fece80e66ebdedcbd9ddff6efd32aa30aa0dfab5cd4febf3ecdafd2d0ade7d3aa20841ea9cc2dd5fc4fca914f36aa75bffc51df44ba396eb13909ff2b2d3b0c9bebe9bfdd4b6dc6e67a97ebecc47140fffeeecc0d31aebcefe465bf6fd138ffd993676a4b4fc5fbedb1fcfc8a48ab33878bf5db81e7aeffbcef5d11f51a3aadcc3bbe4bd42c87dde44a1a2e4fe2dcd8ebbbbe36ce1f68db0ccfd3adf8a9fb9fc4e3898c65b87a4ed3b5a3dea1bd06c879bbefce51ecf2f656d96cacf80cf3cb8cfc8a38ef6fc26faf26a2dadcbf6ce883cfcabdfbfc922d26dc61ce7ad2a8e2b091ef4f9685ea6de102441e194b53ec7ac8d4bc0df791b2e62bd9deeefc9dc6dca5a9fc23e70e3026fb3b1afafb375cc2b0269991cbe57b9c6bdc43d24d8ecf6bf9fff1eca07eb69feecae1c101ff50ff731cbe88e1b099a830ac51e231a1d3afb0caea381e697affd8255d83bde297ed8d6da4a7b1e8a40be96c69b28b19fd5df04babbc4c838ab0d39a4c2c2a2eceb9dabfbb9320516ecfe6bd24b970c9e5c7eeea59b8cfadf1a089da141fca3dab481aecaf3c32a1a1eae0b4db7c52c9ce2ddfb9b8cffffc51afc3ef3bd2cbe35f6e5a455da1d2fdbfa86f9fdef24baaee8b8790df17fa5e2825dd86ffeb796c3d8dcfeaeeab73e7bedbcad2e1cbed3d125eedbb34fcb4bf88dbcb07c4c4a2f7eaf9edc06527a22f34f7e0b62dc53c9393444d4aeef0a7c5f74ac38adea23b65a0d1da60138eedd6e5b7c78d3fee1da3d7d24e3e1ab1ee96131b5ba1c5ff719d3dc56f3bcebb0fda6562fccdda88cb2b985cc1b824c3c8873adcc1602f832b5dbcbba5d72e868c8dbd8d7ecaed1d7188a7a94ecca0dd3afa6ac8a8e1d8492b86b6140c91fe787a8e0f3cbfec5b0dadbed60ba62acefba9f11b41d5e39aefacba3a9647019e50909843af8ace879e27a62ff56c23525bfbe8884afdb570358fa5d47fdc4ff3c60da1714d0af0df0dcdca835d732aef6d7e62c36ee024dcee4ebef002a24cdcbaa9b10e62f3ff8acb0ecb2df501662daba3e1a3ae5d3d16157bf9186ee4a4ecc1ab990db14ad2bd903dca1c02dcee9a5a8c3eae6befe19ce4ecff5b9aa1e2e074aaedea695b9fddd1ad8b1fcb7d4b3bfbe4a6bdebdb1cbca8ada1c6cdeb9cfc083aebc34b6cc14daf6692cd7c5ac978c0f9bef08678ba99e4cdefe2561e9abfd3fc6c7cc216cb4f518a0fb69d1bfd300aec106af30dbcc6c7edca5fffd48dfd3b671f07bbd4ee1e6e1a6b5ee7ffeb9875aef52e4757bb0bd30d8cdc277b75bcf2df6307de6dfa69bbfc9a9c848c2f3ac0670de7b8abfd30e2bcabeef39aef1c7238679adabf1dfe9beec2d40abce00bcd0223ea079fdfe451d1c5aff985e83fcf492b3e92dd205faa3bfaa0efdcbe4efe8235ceafb674ee573b4a179ed021f8fbd2b91dfca6a81bd3df26e60ade0e0286eebb6dfec2e9abb47bfb9fafce1c38cfde2c595fc2d86d5f20c12c665cf5e4ef63d6eb3e8c77a4fd3f31da041abbbdcfd2b629cba2a4abe262daadbff62ecddcf0ce7ebaa9c071acdd1ebfab5da3abd2e7e84b75a7d9d7f13eedff7f5402ec048bb83a4e849dfdd6cc9bdab867d4aca9eaecedbdcf0ad5e0c56cb8ab2ac6b234bc9837e1d6438dcd9cbfade477bbe4f356f84af2052eac1f8af94afede79cc3ae2fdec11beb720f243efa2ef5763fe4fdebe55b162f765119baa2ed5f8d4eab8aed83fd3cbe9dc39454e7b631eefb0bcf60ca91e634ec5b9725f7deabad2ceebaab0eefbd8c22d02eafc2b6b2b3dee6836ad213cd7b79ce8fa25cfd1ebbfdee3cda770c7e604fe2f6ead2d4bc06cadeca1fea47e38af6a8cdef7d084470f1dba2f24df01649cefb74ba0de0c7b8d419e5f3ebbbb71acea1da2fc3d05bb64aaf7d0eea75b0efbef78dafcc943c35b2bd5fdcbccfbfe5c5cea08f4e55e74dafef2bbbaef20cafbbad7a205ca9be2eefec83b9e96a4fb8bb4eff86fdee05ce23bbed4d78e69f44a12e398929eabed23e0dbcca9ee57a566f1f01b7af6ed9d2a9a07bfa2bca7fda2ed19f0b37aa980fcecec78fabe1e3fa0ff61e5c3dbd4bcfb5e87857c3fda2db83e8a8dedcd1b6ddd0cbd9a13a12bede8969eddaae4dc228db628bddcd2eb3a0f9ffaaff8f4eada3cff7310cbe5a09c7c8595e6d9dffddbeea8e7cc6e4bc15fd7f8433cae29a5803979dbbe4cb6d0a0d36163b6904ee795216d4b82ef9bdb350fcbce8a33c1cbef932228dbc4ab447bb207b7cad2464df4ebaedefbade52dba7577e0ce5abe72e3fd851eed3f38de84f0115c1f5b8aec019e11fc486dfa00757eac2df2be90eea19cfbd9ed9ef5b8daeb2c6e53d9fded1780f603dffc3bfeadf036aac30138004e4f1f2ed6ab07eee54f57bacaadec4415ddcfbe080dcfdcdacab162ab97cec062bdcaaefebfac771e2e7cffeee45b95def2dcbbe8ac7c09615cb5022ef1daaa17fdbc4ccea8b99cfc9dcf9c7fbd8e7ea89daffcac39392d04521113140e7eefe23eac46cccffa0fa4828cc3d66f90af116fed91b0fcfd0c7e1d2bcf3b929fe5ecb24480af95abf30d3dbceae7dae8bc2e82ac6dbfebd6e0992ee2fe75b9326ac3e5ba39b35fd7eedc1cf6e3f09ab23cadddeeeff983702a3a9cef381a1182af2bdc3e29f5a96e58af1e11df3c504cf115c3dcdd44a4ff3fce7ccbbbb83b3f2d1fa4caefcc83eaf6ea161c74d58d1447579ebf27ecbdaa74c31fbd571d16a07ceccd4ecabf7e06b1a6d311d9e1abe13ec404fc64908aa64f10e8acd63bae4cad87be343aea7ce190cbef46db83210afdceb8eb11c7b8df2446ebc0869b0cfcfedb613bbabe6ac91fa2e159a8bfd5dfd12e5ffefc1ee54a6caedfdeda05e60b6a3f3fd9377eba68ddaff9b455b02be492bda4f0fbaffd346c04f766d2a4fb45ef4ca085d95ce6a71c8efbe2fbbb2ca7fe80a92da3e66dbebeedb0cd446cbc4be96db641abe9bdecf43a7ddcbbd15bdfebdd581d7fb34e7718a1ee56e5f7ad1d029735ade8ef01a8bad6fce919be607ec7bbade65e3ef38a78d9ea8fb3a9e80bdb4ec56ef3db8ff833ac84233302e2076ef9ccecdf46a50f4e462a306c972f3abffcec398cf59f836db1b9d0fc379487f12b87e04d57f72bea09ea8721a6ce3afd76e42d3fccf7a553c80f7e0ef5c6d2d35db98c0b6baa5fe781b55bc69a5a00ffb19f3bddd0b3fd9f9948bbfaeea9c3f7cbeae0b2feed116bdaaaeabfae7dced8a5dafd6fea20459e2fca01b6d6a7adc6dcddd09d8cf97dbeafcdf11aa4ec0481741ef0c110abdaabffb24ddb91138bf9c3b8b505df7fa6a4e88370ea7eaf518f6761b308d7e2aaf07bf65efb93e3f5f9ab087fa3fc690e5f25eeebfdfac625bf98b62bb7b0ce41bfbf2cf7582985dd8fbadddfd7e7cab2af95acf7b14040a072b14f80eef55757ebadba7bc2394fbc9d56b7fdab023c53fed92bbb6ad6a3e3a6439f2c226d8db7bdc77ad25cbae5b5a5848ea94c6eefdf8fc754afe94d6aa4a4db8bc4f0f5f4b607ac13bdd3b6ab4ccc2e8aafda4dcf08a4eadf3ddeebf3dcfa730c1bc5e7a574dc5bcef11cea71d4b3bd13e6b1dc3e3a436dd92ab4d96c2d5ceb4e7e2d26ecbe6ccce10d9ed64e0eff4c6fb8a58164c1f3790cbfcfe6efd891fc4dcf99a4bf4d0c3b5ff2b75a5750a976cecedb5c53dec9d1195abec8af2fcee5dfc7deaa4c9eeb428744a0ff0dcee574bed94f54c17cd70debc25cf7cfe489fa82b4bc3eab2eedbab58e6b9aeb8dfa4c3ae5bce37a1bbccf3acfbc5b7a76f73d49867b3fd0f8be83afdefcafde18c4aacb82e31ccbcb484e48ea27b5e0fe2acf8ee717cfba05152ae6c1ab7cfb959cc41dc218ad930ac89d44a1fa15daa4ceacac4aaa556c9038ff8ddd8c56984bf4a42c45495fdfd0b8c3fe4f9d7c44235721adcecb611e8a7ffb2f1b3cebd4dea8275b12a58fd849a5b7dbd0affef79cfd2ce10e697a66bd5a788b16173a49fe88eddeefbf6825bcd0aa74fd2e968bfdbb2f7bd7e1bc5dff9d0f27debb66bdd4d446c1a29ba6fee8ed53ff37d7d6ee170b6fedd5c40d60ddb208b6ac7da7e2ba129b7fef0e72addd1722b8026126b20c47f27fdb0fa2e9a309a093f9dec1f97c9a642be7cbdfe0f4f7ca4b855b35915248f39abfc7d381fcfd7fbc816bdccafceb7faf06c1ef9bc8b39dffe9a72ffca79e48a8cdd4463ca5d8aaaf238c60bb46c18bcd01ea3fcd9f0dbc9f39011b6cce7cc9eccb735b5ea9eecfc95e51aaab675cfdbbdb0bfc4a9cb742a3311acbedfc3d7ba307ef5faeafdcfccc533ab638272fc8c7bd8d477697e38ebce0e3c2cb924effdd4f55deaab6efecb12f70af41f2cb9fb2ab4bbe0e6aaceed5bd9ade8bbdf2c155eb49a7dfa366c9bb6ef0eb1980b8bbe8d1afa4451aa176749fb94ddd1bfb9e27c9bdd35ce5abfd8bd7edbbf70c29d6abcbc4a1b37a964acbb6ed31f9ec5ba9a06dc2c3235ab04bbaa0aeeef9dfbecbef3ac69a4697c1d7c8cf6dd20a7fe8efeed6d2cdb0506c53f41a2f1ad0e20a92df8bcaddec3b0a2a8d0bbf5bdcf2d1daf6f35cdb072285ecbcdb9539fc2cac4cbf1dc8fd22d0fbf8e4d99cb04aa2496b8fb51bcda9db114bbd63842c08dfa8b83a8d01f73f7f1509ee38ce75b7a5c0a5cad8b70e45ac6ef03c916cbd183f6caf8a3802cdc54fefed71a6df146429f4dd6d1aa4fe0fea27bf222d583ca40ae329b8e45c64fd6fac3f385265af1c023320df581da243b72c1dd5e17392dcd6c84ddefcddcd3cc0db3d3cca19ab0cac330d7bbabacf4d4f1216aac30ed09e8d1eefd1bac23535c4b5a7abd56baf0edb1f6cbf6d4ffc9cbf24a6adcbfb3ad48ee3299a6fc74fbbeefc1832ed673dac4e73db3ed7bd83072f38fd432a037d506bdd9590e780b6aedf1e88f04bd9ee0446ace6fbbfcd4d01db2406ae8ee8adcb67ff6a7f4e405bbcba08b68caadc37ff2da23d4bc8fbfb7aefa1ffe1a95fdb5a8c1d6bdbeae116f15dcfb5a80cbf5b9be1a7304f85a3dd71bc55fcbad6e58a2a9dda599dee2ed2bbfaf6b20dddbaf3dd663b17cbd65decea492adb265bf860aef9a3f8e5ffb61e40ee56dfbb145fafb08bb7abdbe17ccde650cac6c2dcdd26a2b85bb4eef0ef0d9cc067e8e286beca4cdbf445636aa7d3aecd5afbb009d9aa3fd7e20aee9dad7dadbbb40ab74f83e09fb1df77efff8b93556dffedefa7a5ab281b8f1920532aaab25852ef6acdfae5e4fdb0e5ecb7bd7ccffbeecedd7fb5791c06da5aee3af2ec7b224e526ad1fa953d3929aa6e72d85ad0858eb69cbee3662e861c2efd6ef141adb3bf5b001bceb8ef3afb3c7eb31c3ea3fd9ba1d1fbbbedb8199e0ccae23aafec73afffe1f0532a6fc32bda497382d11dbaf5ce1b97b0c2ebecc8d5e0b80cdb7eed98003f09b4730fe6acda7ec3f9728b68f54e3045abed53dddf699d3df85ef526df5cfa392d6febd864e0a1fb4fec047be6e06127ade6e1dc6dba31099964e76b024dbf4ce6e1ab46c5582a82aca4fac4edc1beafefd8cde38cbfcf5f18045db436ad2710ddc0dd3d0da7f43d28cb69a00fb3fc7847d50db20ccb7d2cbdc2e55c1f46c95f7d31cfa7ac86bef61d3ec04edbeef23d0ed9fd497cd3aae3ea9b91923a5fafe1accf3c3c90839cecc4a9cceeecfd3dfcfd799e2e6cb3a085aa6ebe97fb99caa1aafea41dfcf0afe2faad927ac3adc1dce3d4fe05474ccbe9b6d6e7d29f682ecd15f4ac6960dabeed1f6fb372cdcfe022e87d9a30fb10d317ea0df9d3dfabcfb8ad2cf96c59735add2e6dba6fd30ce8ed692021d0eadddee5aa6c3a4ea9e3be0aa2cfabaa5917b41b60b77f53fd10739636baeddd00c4ca0087d7ab931abcfec432947e165991efff3fd672d8ed4cda9f39bf7cb64da775acfdc41f7b407fe3bfed48a06ff2cb53d0ddadbccae57cbd58fbf9e39bdc464fa710fd3befb9c5b4f5bacc6ac8f62acfe0c2c44180efdbdd171318fd719f21720b07d1aa3839cfcc8ae708a3f6cbfa409faf5d69eea9f4cc58586d88ae81b1edbff470a1bcb9b1aadcb1e04ef0bbf99fad2a5edcb3f96bf0bf6ddaf7ccba9c325d3fdfcb1e8ffae6be22fbbb76b3cdf60cdaec82663a6b4cb6aede7c44cb9cde77a80b5c3c7a78beb2b082e4c8f6c79a5a53f01c18a421aceddcade937a7ea2c74c9fd22ae04933fcec9bb1a0c69dac5df52deca86fca964ecf4db7da793c5f034c3ceff121101fc6ab146bfbb15ac7bd7d2cb188488d5dae7a0dabba1ef9d1181158dcccbbaa75d75f2d8dbd76c162da74a71b1decd9f4332ad9cdde5cfe56cb66d166a7fbfae91f3ccd1c5e067bee59217cc2f2784cb6fcd081abf95ea6ca95edffbebede6b3eef0cfdf64ef1fce60c1cf33c9c3526adc0a9c9e9d33b8bd8e7eaf4f757deeda0b8a21b6cfd14a2cba8ae6816afcc59da26de4eb45faaa642597fac3b2b4cc0bfcb1152fa8d2a5acb962f8d8e9f80eece4c5b68cd11bd9f88a11c8af6c05be48df0953feced98421c93eefc1ad6c4f6eff0da930ee099c1bc28349f7a4a7c4d2ae919e3434ba1dc5f23cdda4c6b2bffe7d4d35df91eb7bb198d4deae7a8efe2aa9c5af2afeba4eb2cfedee37bfcdfea4c3d29afc9091fa2b2357cedf4c22e2af3358aa595f19e3bbf6d797fa5a39db99dcbfedd549b3dd8f7f6dff7c000d231a33a4e0dd7d749c9581c5feceb0acbfaafe63ee15a90da4d7a5baca25007ad9eba0efa5f7ba77a72b488a8e88a9a2cb1c2fb62afa633f0d1ec9e2de7b0087422b7bbd0a8e15bd03f5f191afd7ef3de5568f7ae0cfec9e737cd4dde6bdbf02da5bf8bebb98327c6117275e0fa57dce2eb9afeed3cbf1388cefdbda4ee05ddadfbbbeda55f5ac70b0bcacebba030a21d08fc044c9a37f2ef1949a8fef8c3bf1bfd91d43db1c45bee6717d016dd0f6f6ebfeef1c9cacfbb7c7e1fac24df4eea0bbd5de66bb27cfd678b2b14578944a72fa2214fe7c2da24a21b8fc0d5ccfc76f0d5cadabaaacfc1e63ebeb1a2ea4edc7c3efbcafafd74deacfe75cdecc63f0d91b95aa3dabdde54436c511c2fdc1e78dcba0eee9f0d2bba9df37eeb2aa2eceefccf2caa00f429cdab4ba9089db62f2e8ab19abc56a0a2a9e8c1afad27b58681f2c9d35fe08d3b7f05e0252abc0fc695fba2985fe011e4caf8bcfdb4e2517cac3e3e2ef1bdc5bab24fbccb94dbcaed99e64b8bdbdfc1e8efd319b7a2deee7d45fa7a05ce692699ecacbb72df0ef812bbdb614a63fcff7e3bfdec221245b6dbfd26573e61a12d5e3470dadb7df53fabddfdeae1a0e99f568ecaaa9f3e4ff8b1ef7546c1cacc6a6baadcc6f6e8ea8acbaaebb0cbb1eaccf269b1adad1eedfe64ecfd82b86004da812ba9a2c0af99cbf1c30a82d4167782b1325ec1ebb30409ffbf0bdff4fa8edc18982d0d1d03116b4e18ec9da1da8aa6a6fcb8d2eb5ddbbc3a5bb7fcb87bedfa4c98dcfa0bba8adcc5cfbfcb1dba6bd48b0f99fbe8a2ca48f1c2a6cf182ab5c0efbf509e33f5062df2dcc7959ca7d0fd1eba6ce72f9dcdab97e69944a7c5b283ec94d4aa01fcbdfb25abd50bae75a7fbba7c52d2cadbce4ffb2db1cc33fa6dfb3e173abc9467f0c4ff35dd0dcb1e550410013e0bead1ffb4ddcac617f14cdbb1515e77dbf19df0bb2efaedce3f2b0f992ba2c4d1a3cd1fa15c0b6bcba3fd2afdcded76290dcd3ce86bbdf125d93b08dfe8caca45efaa3d28a20b8ac1bcee1caf0dabb1ceb3a4d62691b2bec138d7a64fbcf7dcf2c066b742ee95e726299d9ed8f0aeaaeded85bfebe36f984ac3fc32ce05505dfb062beaf7229fed6eb5ea927c53edf2f49be35f4dccb2d4d9cac3d190137ecfd4ef5d55cc7bf79f867c8ae0c4b42fbed52c7a7b2cede341c68cd4cbb6756b594cd9dc3981dfcef559ef0fcb6bbec2c7fadc7dd8a9a49cec17ccb8b0e3cc5f5873d483fc1478b22dff3f6b4c2ceed48da03f7729435af2fd11738a40adafebb7d9ef2e010ccf601a51c7edbbbcb6d50de2ad04ee5e7f6c2aa89bcde90a931c1acaf14df3e3a9aef551bb14b93c047200bd9be9bfaf53daffbba4faabe9bb2caae83a0c1b5bff7ff0ea6aaddfc9f6eefa0bff67d4d82958aead9f3a9decd71cd93ff7eb4f41cbd005d0b9b1423fe6dcbdba599ae42faeefdcdcdda60249f77f7ae92294dbbe7b15b9dbc0d7ffb0a588cc45a1f40f7b354c659aa0bd5a4de8bacdffca47f3bdc22e2d38211e3cfbbdc1b6abb466b7e4eb9ab6e6e6e842ebd07fdcec520d2a3912c27f855d2dd0edf6f0c68ad0f4f9baef2debff579d7bf3b6d1f2bed9674dc7e7bbbbd84cddefdac5f48d3dccbad1b1cb6b8b8bf0daf3b871d40e6ae98cadbff525fbb9ff8ee47dcfc5f3af8e1aaeb286e1b0080ab5e8bac2fd3b1cba15f8a1b0a5d5e2f5ccae5f11d5b1be17adec6f1a819792de1ef47bef7a63a3836580e7d74a3a0fd792f6c311bb9e51dd83e994e1e4b0c1b32d73b797e4be806fd20c5df71c42b9771fcdbc05d44c73fca04e41ebdef620e3b8fac67c87feecc61fcfbc4f3a83f4b2a0f313c2848c0ecc4b1875aa09cc2ceefbc7fff64025aa21e6b384fdeaf6beb2c1ca5c3bb6dd0dadaa96bd26fa559a4204ff1bb1e5ebbcb2db60bb8fbe28da5f44562533aab2efbeca3aef2dab6bd22c6fecb41dbb3ddc5894ffec65f55df08d06ffb9904de867b954ebbe9b9c6b26c690fd509a4a6acfffd0ecac9ff601f1d1ccbd1f517ff98e823bdded4df4a039ab6ea4cb6bc442bda4efcb94bd3d850c046ee69e9e3bff4fe5fb2bed62bbfb7e0fed8876fecfcdd1de165ef282bbfa83e7bd8dfb5abb65fea4ba19a2dafa035f16fdfdb203b9fb8cf5ff7f04a2dcdcb1b2200e7d9604d5cb3ff8af9244a4847fe7dceed89feb03bec9f0faf0fd2daf013235ff9cbffc2cfb3abb0bfcd97fbc9739b2ef10ce673cf03f1c17d986a8f20bfcffd95fcd5dde4f4bae1eb94cabeff0b11ec15a63d9e8b38e1235b9a5c86eba5c64fe86de7475eb8c1ae8ab2c90b86ef37e3fab1d8caf57da857cea9abd9fdaf2bf5ada00b46a6fabf8a15ab20facacd67ac6326c0d159015c1bf5cc2dbe84e7f6cade4fdfcba094c1ec4245b31f5dc1facde44fc76665dfb10b4b6af7ff77a1db3c06eeebdb2732a4266287c6bafd73e596aec9edecd65ebc3bfbade740fa44f095acb128faa8fffc1d9fbaacf5bafa8758f05edf065c1ca37fbe2e1cc9c5d35a2a5e2e5b76dc5ac9929d25463079fab27a7af26ec41a1abf3c4f387e4e8cbffaccd5bc70a8d3cd4acaac5d456cfce69b8af9ba3cd0e03105b0ee68eedeed2fbb5ea8f0e140a561da71914c11703fcd8e8c6cd2d0eec0eeacd6f8bbf7420e6cf3dbb6575ef3eda77e7f0cb1df8a1a74cb4cdbbecb7dc0bddcaf49b94f2f6bdc6cd32ba36db8f24cedca9becce7f22620ad38cabcf39a2454fd2eb60ed4fbaa849a7d958b4ec9bed3ba901181fd2ffe551258ed30ba785d6b31910b76a97f8a3afd894e1d2ed01c72a0155a18d497bb91ad75c0ca52ae2be4caec92bbe0c77d5179d34e2571c74a9ede5cb2d31ab472bf33617bcb8338fa701dbd03e6a416b61cab1a28de778fcab8988cae3ffdbb56f1a0d857aecbb4330d3cda8a73dae8dd0d7caffbe1d50ee271a20223ec154dccc10a59bdbbfcc3ddbb0d73d6079d8ad5ebafdbfef8fccaefdfcd500b0cd458c647a714df0cde0c5cab4f0e5c15ef54af3fe5c5ad4a9fc5a6515db262dcfbf5f2987ab18caecb4f68cfab6dbcfb5e434cadb77eebe4b1dce4d5bfd580114c43177e8a6a1a0c39dcf480abe5f7d9bf20aaa1a92207cbf050eddefa61aa2dfbdf7ca8d5fdec5aece5cde3db8fc4549e77579cdb88d259f4813c16be92a67adb4837ea6e0d60d68f3c6f05eefcf8b1b271b1b26c74e63d8153c8b00799cbfc1cace5adeb5b5de3cf5b204efbb185ad09f267041bdb31c6a0ac09efaeef3b05fe630debcd69feff7e5459cfcf13f9e3c5db11e68936acfafdbdd276d9dd4f8cfa14253e84226871cae3cb5c9e5bac39ffe886df7ad06e57f408e39ce75f138ca4ad4d1f6aeee4bbb142eadb9c3dff123bd2f6c5009c6d417fbf0dccead0bbd3fede2ddcc0fcdac25e15e6c7ad34f20e3ceda39c89ed21f54f2e2a8c85c34f0c1d39ef6535bff2c6dc7ab6eead9ef0fe8ad1decb108975b4bde045c2ed0927e15bae71e4468ea3b875fb5e79caebd063d851048eedfaa4aaa5ad9f7b8b1f80ab2dceca58d380b1c977ac7d6996abb97b70ae558fd9dfd1b70aeac5c0936ddca99b2a5aaaace65f31bdffeb2def275a1ef4ffedb0feb110de61b72b14de6d02cadfccdc8cdccfa89f1c3bfecc39b184217dcf1b653b6ada63f60bb1c022e57ce8ba8a3bfe364eee1ad8907648dbbc5ac26c33e97e8ffdc2cead9356f7aea1bfa3bca1bfd06ee656c0ca9fbd7bbac1f85f4e5e1d4b5ac2d22afb9cdc208a56c8cbc5a7acc07fc68ac9dc9c8202bfdf5abebbed6cdedb4b4a5c52c503ccbc0abe0a5d665bdaeef7c126e62daf5eebed8af7c674f4daf6d8ff0b2be9344df201cc1b3efd5a62c7c278c69a4b03a1be04abfecfb5decafe938ad5950644a302dc86aa10ffaa21befeb9ef929a9df103bab7c7deb0ddf1e4f9e0b0c5cdaacfdaf1f1caf32dad438cecb8bd6e29e7a18bd5ffffb6630ba98d5a5ee6eced51130c6cbebf3e91a9da4ccdb5eed871d0bddcab06fd5bdd4f53c8ea3f17cbe5d0dca4dfebd383084be4b2992eefbff25654fe98687da5faeda9decba9eeaebfaafd1d9a21fbf7d6aa4b1665ca494f8efea8f3a5d0fbf1d9511cef7e5d79e2a29042eaa196bd48705d341dfcb7aeeee864efa0f764d37d2af07034a1c686abc9ff0dc6f6486d63afe82ebeee1d994cdd13ea7629b7be4ecd31d59bdda7520e6a28fdf7a38038dd758aa6a2a67af09e93fcf6dceecfa4dd945cfd19c5ae46bca7d0fd11f19e853df40f42bda163b532b76eacc1585cf7bbe9f1fbd610e5b6fc8cd8a3e6aac62b23790ba6bc6cedecd16fbfabb8bda806fea0ee4aabfda16abe4eae1bc5eadeb4dbfdb4f12439acc5b39ffbc37efda9d4df6a937384d2ef10b0c5ba5cdb8f5ecb3ac054d7656fe30caf90bd4436726f3abee83008ff53c03b9bdfee6cd7ceeea0c0a5800dc251692e2e3a4173dacaaaabfdf04c9924c14f5ab3955faffaff4f2c6bffbbca7806ee3f85d3dc920f0e3bad0ca43f958909dfa9ffc6e9fded0bacfce384ccaa7ffc5c6bc2cf13bedff3cad1cbdfbffbbedbb8fcf7ee5ce488cd9970648cfe4eeeccf302507afd9ececd361bffb5ec8f5a8bc5bae78b0cb8d744a861aea23f48436efe799c02fe6ef668f9709def8ea3217cefdec61bf15709c4dca269a8dbaee4afd7b955db7b59bb4ca2daac85dbe3ce4d5fcf12aa610f8b80f3ccf1cca87cf55eebfc4f31cc4da6bc6859b06fdeea7a3a019c04f44d8d84ef32b48db55a501be4369fea6e8f67aba5dd1b12c211a3b2ec2cf33cecadc5ac6b98f7ab08d1db75e49926c48c36cea4aa838ff0bb4a08adad3bbe4faa5f87bc6bc57ce04130cabcbefb7797c15c7616c2e1ce0de802d23b09f2e5fd2ec83c4dd1bbac9144adde8cba7a1257270f1fe4795392bddaa5daa981f817dddf770faac61b5da06b4d9c4f158fd11abce0cfebc950d5bccfacb26c2cf3e14caeb4edfa9aa7f9d4fabecedc204d85bce23c7e08dd0d9c7aad935a8482b0d311b4dd71d7ebe4b4db3bd6cbae7d7baa43d0a6ecc0e489da3d92dfdffa45899b48db10cabfecafe0b6df8e00f2d06538da5b18e2ee511d1f229bbf7cea949ecce68094d8c1ebeee31af3c3b01bc3a96aeb53ffc690a46b1c851af09c8d4aac1ae59ad4907412bfe1f9f7aebf605f24f77d2a3e2ac71257bbbac61a5dda8e934e0b4cfdcb56532e39fed67ba3b3ebaef7db7566b5d60cc16f470ff8e50a3713e15abc1cef7ac80556e4fffa4c4bb6288b4f0d6ea1a5e9bfda44fe619a8908d6be97da8bad6beaaaceeb2a2c4dedbecf0fec48f06bb0ef36cbfcb42fea0cde92aabbcf41d27824eaf6a3ec5ded2efcb454be14d193fb70bdc98db7c1261b1aeaf97db2e124ebda15b3e4ecd7e650bf45e31264a41dc62bf4f2bdfefcbd9fbe7eb5c3b565feba8d916c13191deb4637597eba1b2e9f807d06dbb6af8ea17dbbfe4bc4b2ddfc90ca83a60d46e644ff536a38fde4d917cea2cf722febdbe35ef455f77ccd4e78ff7fec38bf1aef5f73ebaf8fd7aed6dce05a4d0dd3ff0a9dcdd98c99dbc3edc30b176b0aaaab65daa5e22cafdc5d31b6e856c7d1ff1ab0dd8cf29cffaae5b6e235ed4e1ce0989fa74bdabc5d040cbe6ce9a7b4bcf82a1fe3ef5aede6ae348a63055b60449a864755d8f37c69ddffecb32a4db6c2a0677450682e3bc8504b7fc71bca9dcc22d84ed9e9128d08803b926d90b55cec4ff94d1bbbca4edefd969cc3619abafad06ce5bdeefc1d11caa03bdae66a41b2fe1dbbaebae038d91f6e0d6972ccd6c463bfadc7ddd526bc3c88e5a9aacbca8bbdaa2ceab0ea9483b613d6e03167ff39cdcebdd9c77bdf7aa8e4709fdebfebb15c6cae72cbcd104651f06f3cdb7c9e8762a691d7ef1ea11d67e693dce3b7abb2af7d850ffaf38a28ff7a75b225cfd0d8572b08048fae17fe58e9cd4471f168356aa859cdeead3bd56c8d289b17143aeafae523fb4e5f3b2a9d88fa8ecc455b62f29f0dcaa4cab54d0a768b12e1e3d3af6dbae4c9aac61ad2673f7bae0f9ac4389e7f84b35d5bdec8acaeebb1ab9af1a87d62457d5ad298ebe77bdda8ecd19fe1db1eb05af438b0457bcf3a78a0ddc029782133a0ee812af251e7a2ea1f707bf262b9bacc66d48a50c4ffbf8abd54ec1ed9abce0b004bf22fb3eedc4ccadbac16caff8d767f4a9db163aa45122b200bad8d8205aff7d5f8928bda82eecfc2b85a52f28ece6ff5acaf6907a1eb7a1bbdcff3e78faaeced98a7dfff46a7f9e41ad39aecaad4d9aacbbcdc3bd8b42b83bd8ad466dace828b3caf0972ebdbf3ca7ba2dc3a4fddb08c6bf451c317b9db99cd4c4dcbaeaa95c6f23a62bbd16123aa5eaf9f6ce4c5b3df68f964df0dd71edcac30ac7fb66e4f3aa98bfc7cd27a1d012ecbfaeb29ece06f2f8d5bc462da5d28b9f8a3e6cdcfa7c278dba56d189c6ffde85166e2caef5595c7b6293bfae7d3ab4d94bf3acb792307b4ae3860f1a75cfcebdeaeef8bcdee27c2abe5ab15c227c6ada15eda16b70ddec6433de467fd4beccb198b9cdcb04fa058720c402fafabfcac0cdf48cf4e5af064d1ab1c64c8c03a7bf78540cdfa82bdce948ff8cbac79e6edde3dafdaffdddf57de6fd01efffc7fb5c5ac066bd0e94d4dadffcbb2e8bcc7c1bc69de4d1d2766bdde4433ed7021385eab7ccb8656ce3a90f77de98d2d8db5cbc6a4650e3ba905a756be53a5e7abfa7fcf5987a976d5ebfdec3ffb42c031e346affcb7cd6ddd3eee9009d397002f4aadc4eb4167cf4ed4f7f25cfcd22c28bf0a32ccef39e71d09ec029419c4fd2b7e51e35cfcdabb9b5fda7fb344c288c27e377a8d9afb3d6e154bf9b2b2028ae2163edecba26d05b06a9c90c4b51f3ba5d9688c8194de2b70edfcbf0f7e53ca4b7bfb9d2d0e629f06a2fc71f9edcee5f7bbd8d0b415b4a32ae4f272cabaec470c8ac2a1afaf825338ac1cbe67ae2354dbdaecd4cb0d6e7d296aafc8ec7e09f27dcea01f4ffe1ead77ffcb4d630a11c10fe8b91e9f027daadc19bb2b4b860ff28c0cebded0ce86f1d60a513b58efbcb9e5ad7fee49bba98ed19cd960477fb3930e6dde8ecc04c68dbefe4ef8ead95f4ffd1acfefd1df174bd7518876e1a0a57e7eded9a4b3abbfafc9db5b695afda73b228bc21047a70e4a63b9bfb8f6bfc1a6ed9da25d94d0d5ff5d3f8765bc89cdec7e16a34e34ce1eb10a6ff429296bddf68adbd4bc52aaa61cdbcbdf1c44c9cd33a03caabcdb13568733e023fad3038c8b0b77f70abc7ebb80fdcec9dc8acac22b166c5011e987a80feae3a690b6dcb3402a56c06d0bb5a6abbbaba6df7beb579cde1e30aeeda5f04ada97f365f48cc249bdfdab05bebdbadb44ee09ccdedacab45b345b8fb89cacfdbdc92bfe3381edeeef8e9f7d7cc6125690acbcedb7dbedc414acada12dc646fa78fa77bbd6fbedf08a0e2bddcba9f5fae93eab1ec69c8e5f0ddbfedde5bf4392aa6e6f58a724caa6add8fce3f94483b0ebccce1b3e268b50b3e6da3ed12cf75eabe7af1cbbe5571daa5ffbc99b8f5aadbc7ddcca11bf5c5a4f0aa36c0a4085458a36c392edecde61477afcef98fbabdb0bf6050dac2fcfc3d414bc198bb8bf24bff7bbb7abc3f2fcdffc03da0f8356eca2f8178862f0ca4de83d9a350fca648894e2c7ccc352bd73b39eb9abe655ca7ffbf2defacdf008af328f9b75bb784ac8670af559ea2afb23dbfc462ec40f4f3469970bf1aa393cdad6348afc97ac92ca5d5dbfd1978cbb775977d2bacc48b1d0a834cfe35dadd4eac11c4490bbca9e4cf6e1eafcfcaf3cbad8a20eca3b0796bf3a9b2bbc47abcb2a404842be4aa76cc4abfec8a47a0aefffc44e9cacb8974469ddafee0d1b9b1b6bbedf587bf1e26da1d2c684c4bfff584e4282ae4424ddc141dd43dddb299a6a0ed8ef2f78fa7ab68af3e5ce99bb4aa9bfe18a901dadbdc6def93e51afa6f953f94ff121beddca6826fe8f20cc66147acec01dc75fcea0fd3efcc7eab03339cae22e1674ad6277acdf5b7a30e3fc5ca1a30c6ee5caaecea6c6ffce4cf2a92dd3f68dc51f6bb42c43b2f6ada70e27220eb4a6ebaea4ee9cd71bdb0be0bc9cefbe20bedc9b0f184b9eac8b56b0503bc22122a1c8f0d3af0b37cce0d24afce3ebcf3b983a56bfb12b1fbda5dae62188ff2cb7cd73d60a8e2bb1cbfbdbaaf8acb32a8ae23bddf5b062aa3fe79e13ebdbc1aebffcf3b1dad4a92304fd1c2dab614fd82b1febeeedebc202068b0fa1df850e5e5f9ac6bff24ed22daa90b6c44f2a3ad94e07ff35bfd9be25142ab6ad96b1b5e5efaaff58ffc1d34debef8cafcde6fdf9ee8cd2f4cec3af1d767d18eadecffd71f2ccbf169c49c1edfca8fe3faad1a67f0242ed5da471b97aee81ec5f5d6ef23ccd2ab3d5b85df0acfcc9edd9808bc5f8ac5c1ee4af6ebbc40f1ecad24d8c86aa54a14a54df7ee1aff2e66be66658aab9fcf2f1cc2b2c6c826df4ba6996ebddef910da513acbb46af6cb7aaebea6fa968cbfaf682c5204f80bce1f4cfea8d1edc24ebd1e1c1588a5e95e7fededdecbd3bad96ceb8b04ace74465d16b6ca0fcfed5e34d0ac70a394d1b379df40d787cc9dc439cac3ffab3f15c2f0bc1ba76b5d8a1fbedb07e5bf5accea409687abd7da060cd8bdbc3fffcdf027c9e544d16bfaaa9b72cc540c7dd3f5e06fc7dcacecebf79fed4f98d84af5c5fe22af4904f89cb01ad0bcafe4ac5a4bdb0843712ddeedda17bcace4407adfb4c5d1a26e65aa6a52c99f22c129c29669d25bff30c89edc1c9fe5bfe9ef8d7b75bb832bebd21344f25d8d3d28489b6fbe673eecf4e5fdcbd928dae29aead1c61ff642ab3c77737fdf4eee520b5ca0c99abebe1fd6068aa31667db3dca3e1da1cd63be50c6c6de5fdd9cd8f02ce58b48535d685b79f7fbf1e056cebd5a9ff8c7d39f2eda6fe7bbad5da21feff4dffd91ac573bead5d0ccb4dc8dab9ad37ecfa7cabcae6e9cd3bf8db65aabfa69358dde5a546bae25bb8ae80acace29f3bd209e60bb2bab407da849a14d6d7ed605f7c5a9f4dbcfd6edff1dcf8d5faafed0c5b6a3ade0bdb6d8dceab1bfdc3225ce045190eda0f01dcbf3c8eb4b33e42f01ee5cbca74fa07dc502c8fc23bcd25f35f4f0fb829907b3e90aaddfdeda3cfbb78cde2dc5a679edd60f0f4ed699ccacee226aab7aba8aabd94d65ea204c4a02d27cfce50ac9d4b054ef848b566a7a112b8ebdc947afba97f8962e6bab20ef02e7adcafdaaedab8ccbb2cb04de0acf888d1f0d9b7c51e03df0138d48d3eb53fb0816fa2dd75babc15202a30c6abab8bd212faafcac0e57d0c3ec8e7f6f97ec9e5f0bdf5c80b68aca327a1eb8f863965e2ddfe4f08a0f3be9fd58c72afcb6dd0b0c2e88b6a3d4353bed988783c9ad1f7dfa5cef1ecfeab87bb3b54c6385c2afacba7deed6ee11aa8df03f1bba0e5b46e9bfbbeabdac10233cc0a6acae9be1fd1ea6c19dde32e9f4b546aaec4763e7c3a5bf0689f09c5d8cf8c5375afdbd8f5e8eb90aaec1af812f1a13e4a9af0c6decfe7869465ceeebbb852c0ddace73d5fc00be92f01019f2cede12faeca1c9d8c6b310afad5e26ccb00a903f4f0573e8f0f43aacbfa793e01ce2fe1ddba7bbdc922431efcfdfddcca0ff9bff035c61ac8d8ef1914e9c15b2b1b1aebb3edbe6f5cb44349d65d65c03f0ab8abac6bff8c76f5a2fd9df3fbccd9ad31af2dcadd3ccc0a5d9e0efcebcaaf4bce0e9bd882826aa84088d3cebaef4dee0b0e6bcec60cb8cc8447d1fe7de81cc48c9d7a0d451ffd0cf2e0ac1a1f4ea631231fa4f6ed4baf37ac3848beaaf8ab53b45ddcc95b45c5ffdc3223cd8d9c7583fec8ebdd3586606a744bdbe25a537d1edd1faa58af91d39da9fefcced7c9bb8aa09cc1aad9e991fcd3fee8752e96d1ee5ba79c6c8458fa2d4faafbe7058dafe8fa3c4dbade4fecb6b1e03d76ef2abaca5da906f305ddce740ac152eeed95fb974c9cf57c2e489c9ac0ccc2e1d4f91da1bbc2e756f6f24eddcad7de2c998bcc4bfa0d5e02d0dbba33c152e2cbbf1cfd8aebfdbaa9eba29ea6776debecedce7b72bebfbaf2b8ddd64f07f7c28f79a6bb1fc6b8fdf44d5c4b51689dcb80f209741adeadb7e8c1626c3ef3d2d6ff0e1cb5ab80bb49947ce3abdabbb12cdd9eac9c0baea2bc281827ff9f6c8698cf47c61e1c07c373c3e1a766c679fccfe149b1b8e92befecd5ccf7f027ee9f25ac8b78bbb58a7c9545aabb68415a97a7154e9b4e1cdeebf1a30eaca39c703c913ba0e1dbdfef1646b3ec33baa40c9d0ddb0816b2c9c5dd9fb6f7a5d59eca7bddcc81283765bce6bc2a4f30a5abfdaeda0cd48f1736be5fb27e230bca7b9e92d00dc9ee2a7059b4eefcbfef29b4eacd03e976fce5e9fadb9d051cebbf7f941d8b640424a25afe369dc00f94bed4fa452feb1e5cea39cc3a57fac6badd8fa6c38feeb3fdbea187bcaaf0b5a1fb4b8e457fd6332802aa6dcc5dacfdefe47ec8b6e07a62dedcdf11db4eecaffc074eddcb56ef83eddd96217f6bebb8fef18bbef1ef7558e8bc3d215d9f22d854e5fe7f155f73db54a05f3e520efdaef5bed0aecb62aeca77bad1da97daecc852a049e2e9fe36fed729db7bfbffad5b91991aff1ed0c38c254ae1dfcae8fd58d3dab7eb50aee77539a231a7da89ddc2ec5ac18b2fd30db19fac28e1ebacba08ed6604b8caa47f71a9aefcdd9b4e107085ed76e0eb6c1c811dc203419b95d958be0f3be01cfa28aae4f5b1fbee7226b3502f3aeb6f575ab28a23bfdd53aba4dde47daafce1bcd5fc64fc71fe454779f809574bddd0cf20ea41af4ddf16b26cbf069465f7adf554d54c0489cf039b620953d78064cbaec8a41b7eadb1cbbd8fdff3e7da4c0a00ec5a470adec8b08793e9cfcb5f7eacb3e0a7ae8f7ec87adca242ff001fad0ffde9a9ece202eed62695d8a53af6ffa06e26b5b261658c49f3f9a1293eef40e10b7fffa68e4c6cc9b1cbd8e0fce8c2dae166d1bb12bcea9cc63f72e0bed0764efacaaafe4e1fc8feafc6e9d2faafe1f2f07dfeb8ab6fbe941e9f6acc1bde4cf11b5ca7fbbccb9ddff1dd92c347dcb914796b3ecaa24be9fa5bed7ee69516b8f9baea9f8e4573dbbf8e591ddb5bb18d63bd2f1ebefbda5dd778cb305ffb72e6b2a9ee7ebc0dc37f9d1caf6ec70d8d0bf05e82f82cb81a0ec0fab0fa92605373aac837cbb29f8f24bc3d94901ab7ded8bddb64f3ac7cedca7615dddcadcba645acfec371daef69201fbbebacbd30f3f298fc853edfcb24c86bc90425a36fdce4b5cab6ca4819daf0ef9decb0e18f0e4cbc52e9ef452583be8af61a09b3dfcd3a5f7d8cdadb2839de93f8f0c47feecad7da385fdab1f8f1f9c1cebe2f857ebaab354960bad4ffbda8dd24c5be72c5f8ba4dcc4b7a46d11ea3214f3b1a7ae66fcdfd2a21edeba9d66c4bbf76e2eadb8ee86deabdd4bc7eaddefea2862cfbe1bcda48058aeea6b10bdfbb5fa4aaeb5fafe935fc7dfa5676ae3e67bacb6a9b0d617686e98c2aff3cbc1963b316be68cbfd7afa6b2cac3488ad4e882bca6f67ca6e899cf324fbba45a78753bc58cd37efeeefe85db2ffc512ec8b1adba67c6b1f6dcac40a8fa1bc166a2ca2045e81e507da9f7be29ddad96d2f9f2dfc08e5f5ba4e06f7f579b7adc86f7750b20bf3c85fc4f2ab8721ef2521e0aa6cdbc7f504cdada5ca9bca03cb8d12acae474ae4c8c9cbea8eeee65ced81ff6a8de7ef8968dbacc108d9ef4d00bc174e1cfeb49edc8dff022bebace3dd70f1b92bfd6dbf5b3c3e759f289911090deb1cb51ccbc991ae42b0dfe528edfd5b12aaeaff4237d9cec8f15137a3f85dee0200a68c052dff96ddbaa4b662cf194c16fb35debdaaa115cb7ddd6b37cf33ef7ee8b93369ae183455daad9aa1d90d5dcf111cd175086d0bc9aef2a7feecdeb6607ac985cb2ae2dfeca9bbf85b35b044eb1ffbeec3f1ce193ed1fdc4d4ad6f0da1f9ae33c4ecedeabeb9c4f9f3e810c6bafa513c654ffacc4bad10bab9acf79d5ef43efba99ce5cfae68dddf0695c4acaad76d7be51bbb1dbb71fca50ecb049febef848efee4d04ea99c3bfebe91a5162ec3c6abbfc05d91b844b8d68ca527a0f11eb53ab3aea4b1affffafebfa23ffbd8ee04a5fea3cb0ab5bd39b45b0f9f0d1ccaddeca0ffb1618aea12485520fdbf01a6dcefaf1deddbfd31b3fd03a0d9bc02abbdbffcb1eddcd64fe8d5ad05d5a4effc9213b754afc7a5bca7382a53c5425eaeb5eec581c2e9ec92afea02105fac2404eb233de142bbb1d0aaaef6ad5c6893ee3acb7c33d2ebb1fffd504aee020f876f8822aaeffa2b6f6dd95babdbd2f5de1acf9b5e9efa1ceb782206e0bd24dd2ddc4d6637cf4129da46efe25f3e33277aab1bfc1eca13accee4abb478d8aa3cdd337e78cccd7fedcaa9dfab9ea35f2ab29a8122b7e9b9afcf7faeddeaec79dc860606fdc64c82709c35fb15cac88ad4bbefd971b6ffbd9ebfcd1cc7a4193ea6e68fe88f34601839b8abd08a64aeedeba32be321ac72c1ebccec8d8ccdfe46bacf6bb7ba05ea5d7d3b857efaa17ecf075f2721629d42e56d9d7e7a3cd2bea68f4ad022eebdc57e2cdd797e476d35546eed6ab2ffecaf80c65dbfadacb250caac5bb3b5dc5794c08fe7b65f5a6e822b1a8f7cb1214bbf900de29e25fceadbdbadc1aabd198da0d2dd4a94bdca4ecfa4875cebac62d9ebd3cf84da4dc3436dbd8426903cda63cffca5f5d9ca99fa9938db7a156c2ffbe82a7c918eb65dfc0241e7328cdc75f12fd5a6d10fa3ec77a83ccebaaff755b7cc8b03bb1dd7634d6e6c037c46a696a3bfcfc356e69ad5e5fed71fd02ce310fa9ed5a67e51df9f96cce4b8a3fbcdf2fbe9d4537633b43cedb58cdeacb3d45ac9a78f6cb90a9ec34cfc96b22ccca56a98a9d1aa1ace29c54fdf3eb05d4cdb90d5cffcaeb4d8b0ed0fe09f6786cf5f2d44dcca10febfcdb8c9f2fb03c058f4dd6f9a9ced931b98aaabd1a7abd889ac0adbcf08f0f310d57c3a4a18caaba6bb27f120ce2f01e57aaab3a7b7fdefeea4345af5c6cacebf07112a3557004dbccbe4bef9fbfdfad69fa993bfdbbbd8e4eee35baac56dbbb1ad04326cfedbcfed3badeabf8ccab2883f2a9cde0ebed7befc737bf48b8bcd84bed1b7fd0cdca8bd55fc2ec3a4cabcedd8a25cd5dd5ccdfab3bd664caa3e1ea6eebad9e3c8bca33293eabc78dbe109c99e29e6cbaf5d08e8e4a6108dca58fdf42da6e25bcdf0bafd9b3a76baf8be35dadf5ee3fee040cfdf2bc6ebf0ebd92d075ff9fddf3a8fca9b4b9eaa3baed2d3f93581fc5ecdff6ddbcdfd8ba27bb0d3cdfe263c3cabbcdec08e57cc6bca02a9c400bd0de7bf66d13dbee829aed0f5abe2cb60f459cb44b786fef739d074ec7f37bbf4ecf710388ea669eeee64fa8bcf1dcfbedac4baf6c2dc378f6e78f2eb82ec5abc1b87069666abc3d7b87f4bde2bdd1edfe7eabaae27cd34ed1aa77bb44b17053eac0617adbea9ecb2f252eb6ce83ba4cddfcaf5fefc9bdacf2d43b7dbd28b8c737ddb09f6bb99a3a0f1fe6b1baae1547c108040bdfaece48891c6ace9ecc60bfdeffea2dfbef4ef093dd9fe18f31cb6dbac3ffeebfb8bafa243ad2aa391cc3ea88cf11fca6e1cde97acb9dadfefbce53af0f91cfe5ba48ebdcdbb5a11a0fded6409f546afdfb638e3f5ffce7cdc3cecd9dcf505d5a3bafacb9fdcaab58eb6e577b48a1a3f75bddeb1abfebd5bd1ab7cdae8ac18eab824f9ffae9abe8cbfacdb6deac1c02e93defd5a625bdbfcede7efce4a8cf13bcdaeecafae7c74db0e2ac5d85d3b28fbb5bfd5bcdf6ad2dd1deaa429beccf5ff6ab5dce89a92dbbc5221aaa193b5dbcd4adaa1db1fffaef747ffcdf9cbccff7a7e20b3f3ceec08d2ae004f7402b6dcc5bf10d1dec0685de84cfb9ffbedbfdd2ed437092e460ade9bfbadbfdaa9d6413ada2d8cfbaac5d8496e9f3f00a0deac9448dfdcefb29e9e5c28a69d334ea0e8cc57ddea7cbc7c45497d59ebaae627e451d9faaf35251ca5e86afc61274c9d6bf4ebe3bfdcfecbec780c3f20a29b1bcebde5b35cbfeafb0ebcabf6865bb1fbd99cfd6683addcb4e885a3a7e08d9ecdb696ef0b90785e519ffb652fa75bfb8dbe5bbc4eca010cf2cfc98330cef9dcd56deaec3afe1bb8ace3018eb10b8fcc8ea7b2eca096183acff41dccbf1cdac4d64fae3ed0edfc20277ea97ff144a3f809ecec2e699f7ffbe5da54aac0ea39d3ea7102dbf226ac806d07a7cffc602dd5dca7a88e8eec18dcdacae10c3b3ef5c325be136923dd7fc62ccfdee0ef380a9be4d89dcdbdcdcec560febac1501f377abf5f3ddc57aaca2faaffa37c490bbd5339a9fb3a1d5a145bf40fc97ed8cae35da31bb121b8dfbcf4bde06c817c8df949af1e35ceed4c1b7248d4d25dfb75b4bcccfda6aa9ffe57cd985ea02fb0338de9a43daee2d028bc1b7f4b2cfc32266f1bef19b0c03f53fc62e2c58db9998ee7be0bde4ad5f8bac0eaa7a3bfc2edb79cfde1bcfc85aaea9bbc3ec0dda6398eefe5b6e1a440c94e3b8ae4ea3f4a16f29cdefdecf49ab9ac58f87d811b3dd6dbeff7d328bcded2a1cabcedfc3ae7d073501f6c877e2b6822efe46b1ea3b69fcfa29971ad938cfc34bd4dfdb3be3a7a7f7d54314dd2d13c87c4dcffc3be79ddedeae27544cdda357ab8cbdfec318abcdb84e3c82f6972f3f2e07df51ed8e969ed9dafa3230c8caef0f4438e19c3eb2d83bea9988dab37d19adad78cb31de21eb4a2a3fe7fef1d72409f4d2b0dbb2603b0279aabd7bff22206ea8b3178f4ffd25f2c2e1d11df9edeaec10bd4b8d178b0bcbc8cadb75f75e86bb3fe4dacbba0f40db5031750e5f6e2be91ee32dfbeaa11be7ca775d521ea1d7a2fc76f44ad0a038fd8db01463ee3aa6dab3456a1edbdc3bc241b1fa0ba537aa3ebfaea319ab97f269ddafff120dde3d91343ddefdc9dd1b5ff324cf9218d3627e741d165678afed7fd24cf1966b119b91c75adea6db2a3a106425ef7d6ed715964fa909dc2a4348b31e1db6f39d83c5f2db6eecc8ee4f1be24a8e7edafef6ee05a45d4a2a8f72f3858d5aeed865ccc2d82e4bff9deb9fd94ca212a3cd8e0afa7e2affa9806e325c24fe8fa2d80ba4e2cfb5f1b032fddcee7f3e14fcf2ddd6d666abeaaac488faab5d75e09dcfee436eecce2dc29fe1ed2577a5cdb3ab7c2bf34cca3b6bab8e6436f55ecd0c91d9958cc5d7aa06fdea3faee78af3edfed3acf1edf2f4edfbdb65bba4eae8c26fbbbb273f1cd2681b5d84eadf683c9e0bae26bd7ef3be3c1909bb49afeaff1265d5d1674f8fdb0d2d04ccf4657bbed3770fefc302ddaa46ec7e52ccef7ad9a8eb2e6fbf0b1d7f1ccdf3a7bfdfafdee8b8a67625bbee09aedb7719427af364502b7df114759b1d4c838f5f72fc76ec7bbabd06d49eecbf22f79732eeebb1b607068baa40fcf6bfb8e2225c9da6bb62dfd2a7f1f2bbbe48dbc357e6b2aedac8ae499bdee2eb4fdba528d59beff79ffbf67dafdb86ccc161c3fb0fddd9455da73e8b5aadfe0c9a3e2c29fcba27ddb1fa7a50ca84573b38e78daac2c42fbbfd2f1cfa98e9e130cfda262e0ab55703dbceaadcfc62ad29d95accecc0ad50dfee8ec449cbd8ebfbe0777977cfb35d3f3d38dffd53ff6d483f951bc5fb98bd46f57079f32bf8a1fff124f335a79d6d31feff9ce9fceecddf0ab1a8ba9339a5b5eee8c8eba416d3ceba25a2cbf577cdfbd8122a976cbdb4467f575d6dfcdabf50598db028909fcac21d7ccfcbf7fd4cb3e304beb2260ebcbb2fccaeab65b9d592cf4d1786a84db39887cbda0b5f14e17576124a696b9cc32f3786cbd90cf4ab4ec3ea5cfa78b5bbde7c53feeb8efcbc09bd5a4fe8bb8b4b4f6a77dd0ecde2354d9cee7bdfca0bcee282dbc25f5931cf5effcafb38862f8ded3ddedac0a71fdea23e50ff1f72ef273d80dff32afcfffa6f773dfade7ab1ccc828d6edfeccda0cda2af2ecd7f9b0d8fb5c81bfdf55aeae615bf6fe131f289d03a8fbcc891e348c3001dd69038804403ead326b3c335b7d3bfe6cf63efefd760c37caac5b2f1821cbfecdc97aa0e44b93ca9eff9ff38ab6fcf6f4fd1caf5188ad1ac2ae26d3b0cffa2cba0e6edccfef02eeedeea6e8ceaf2d8c1eebdaecfbec854fa42aead150fdd39d5de2c8b57d3ef51dfa5e1fecc5eaf2ccaf2effb32a17fad3c6b42d58c6cc6b33ddbcbdeda18bec057de5f9c88bd111de9ca2e78a5faddcc3a00dd4aa8d8bda6ffd72fa687edff606fe6d037fdbf6aeb355af2cfbdd0bedeac196f8bcc40b1ed3fd3c87f6a209b70bfbbbc3b5a7c13fcb502ada4b02cddb7dc9eebae2aa0ff94f8d7a7866bb43c4bcc7ddcbfffc4640654326fab4cd0ba0457cd3ecb74c07bc3ffd0dee632c3daeeafcac93c0d5edbe9c0a56fa68a677e5aaedc3ba5e2bbfdd06f7e03498c1fd3461cea9c9df0bc300ec6cd8ae1ff6c2cbfe0f8290e1739b8babbb91032fe7aab20c9ca431124592f357efc7a892605caf7af9f5ea39939fdb83f8cd42a8debbffb0fc3c5dbd72e9cf40720ba175db1eb68da563cb0aebedefecda1be6b0eb0affafd26b6fdd87aaf5a1e0ea4dcba2319cabab596ff9dde5da1a9e8dd04fbaeaddacbbfb62fffc991abee21a3c1facbe9f561f22aa1ffedb8a1eb672eccde22244eafef6ff1d8efcb50ec1c28635cbefaded98cf2c260817b6bcd2bdccf783a5d694a83303fda05fbced36033418c06ab9d9e20f179cd1d2b0fe4cc6cfaf04ced9e712c28d7ce6fd19f2b4a05bd3c216bfe6feda5fadfdddb5afac7de84dde9ccb474f18a1dd1f9a34bcab4ae1b9f6d3967d4fabc2f5a7adfceea5692bc2c8eaa6beaf6f127da5aa0ace539a5ff591cd7fdf543fb32fd976789ff7b9dcadccf4df77d9a5dcbd56bd7663e77afa8b4fd5eb9054f3f1dd710914a6a6de0d499cca39e4df1b157caa79b1f7b13d07618cde9adfd089fb4b1b304139b7c89d2f5674f0eb5ae9c6ecf32740af602f5c5ddca550baf7eb1f86a2b5bdde47cb9ca2a12e809f7034e3ad6c7fcc9742efc1eba7b9ba69d93f3f0d98b7fbfed64fbb0f3c7cc94348b090bacd7fe75c7b4f9d6a83bc40cc5e83e12fc2c33bf7dcce1731933d25bedcdd6f311c7f99dafa5ebf250cf24528b3e5b26ea07f7dd7fe5f9ee2efbd3abf55b9826179588feee6efdf6bacb9d69f8c39eda97f0d9ee28ad1ef1fe89cdeffecad2cea5c2604ac936f0ba04d1df0ffeb8fbc9b42627ec459cc1ea35eba8bdb299ae1aa29aec23f3fbdbe86affabc3de7cfaefff0bedff5a0e9ec4f08f288bf9d575bae1d2fef7332bbd5aaabc7af61b81b6a70a87fea1a430825feddb5f75d23ead515b53020dd2d3ffea9c12ad1a8667ebb8e1caa6fda8f6da2cc0af3261f86bd8defecd0f9dbf5e0cb3dab91d4d59fede9f612cfbdfe396e033ffa6dafb9ecda8de3de319ea0edb60dcb14fcded6eefbe2e0dbe41ad7ecedfc5cdc6afc7b7b0f1de3cd680bbec3c9f400db186ae5239ea2c5488eadf78b3a99ada5b857fc01946afab4ccae0e7db65a58183df5becd98a9b70ecbb709d4d2f4ac2e9899a8b71bbd34379abd126faee09fa428ab2bebebbbd4a3aafbcfd6b1bb0b05ec1a43cbddfb1d3b992369aa555a89a47e072a274ab53f02cf94a3da83daa81fc9e3bbf8fd9c0ab5bfa39a1ee72f87bd4396b6b12475a0ef8a68f5bea4b31efaac9c8fe3b1b49d78cfa39ced7dceecddbf8eea51ef8b2602aedeb02ad5597108b712c638d5e2d1ccbe3a6410b4983e52fb940abe4d3f3dfaa0adcfcdce252e3165bdadc071efea5b22ff5f1e51b0f8cb58065ef4ba7a1cdc6c2f033bd3538cab0e750fefa2b5a7127cbff6d58fd4839c43af579b5c82c114acaa5fad9dcf46ee3dbbfdb85410f1eee187652638ef733fbc5873751fcdad20240f23cc6a0bf5130f0cff5cbfd0c80fa2a5fc306fd0eeeb7afec8c8c6aedf806b01fe0a65a49960e5d5eb13fca1eebddddf3756e0d684fcde612c233aecca278b53f76a8b8e747a9cdd31f0adbf1d5fbe2a938e7aaff6cabacdd5aaa7f1ffaa6cbcbed4cdb37fbfa2d5bb9d6c150181e22ed40efe1c53c02b1aa9cfe3b68f4b353dc5caa5cfb9d5ebeff1e62b3ca8ba3b43bf0baa81fcda8cb06cf3be04cab9e2fccbefe5fa4f09be1bbcdf0dabe4af455c9bc9ded5370fc8a44fde8ec96ccf5ac3e0c20d2b9d69ed12b87e7eccd9e08f25f304cee5bbcd41b9beacc3ffbe3ec989d9faaa0a11ddfab47edd8e85e91b52bad037969ce1ae6bb4f28c4bf511751af591dbb317112ce691fdc2be1fceaa8481f6adc4fb43e68bebb0d4a93b77ef6a07d3edee5b20e56aa4abcfdcfdff31ef23f2a7160e00ffa3d8f8fdb7acd6dae3ddbaedf76c2d808eeee467e26e3f04b2a553deffcaf8a7fbd746925be42fe146a56063bf1feb33cdc28bbb0ddae9e8a2bead0f27b83efe8dc1aaa5f6aaafb6e6cf57dcb0c3f2ee49d4ccfc66b90b702ffccefa509bb62faca7bda316fc7aef9c9d86befadab0571bd6ccce31d0f93f7deab8bcc716b6c6bcb1b4dec6e92ed49cd9caa259ad62aaac6cbdaaedbba55b42ac90ad3c213fe0c59ff3d16ffb0fedea3f910a45f69a1c3dfa5ef63e8c3af12dfe5a9e211fa92d9ad9cd1fb580ab50d1afea6c2c3d3cff5ecccbce63d3bad3ac18ae50b0f166230bfc5a582aaf34adbfd05a9bc63aad7dec2e2dbe3337c96ca3d207de0aceaddcf304fffce4c7beda69d9ca7a19ceaffaccf3525aaab7f3a1bb3e6e62777e9cc67ffa4da4e1e52d5e89e4564fe4fc37dde6cbf1ca98cfbad509ef1df062f9ecec0ba27bbeedc6c947fe844049a3e8e97bb2166adab6118be875b3bbbe75cdd4a7f57828c6e0b35270f257e3fea36d65e51a45431c8995e15b78b35f7b1bb6faffdf6bebfbfecd3db007ede82d83fe6b81e73de58d93b6ac4a4a7bbb9d240fb80ffdbc9ec061eaabccf361fc5d3f322c8a5ccb6acc2c0c8bec5a2c5c341fca94bc0c5eecdc0b08707766bda0d0ce2fa10b0b31a9aecfbeb1be9c5192fdd5ecf683b1f69cdfb5fdf6c2725135deda035c9a8bec755af712c5dcbfc40deeb24f8324c06b2e7fdfc74127c3a4ade9666bbb115a05fad0516deb93bb9dfbe8828703cfe3f5b40fefe9d5514b06529ee306edd67edb32d0bcef9b027aac9dfdca24f1ffa62beb1d6ea3f77d264dfbdebfd82fcd92a9389d7dac3dbacfe3becdfd2a784f4390c4a65c8a6138485bff692c001dfcd1c6f87309fd9fa4bcae9eecab2692731df4e86a46263295ff174385ba9c1d6711bfcee99fcebb9c1cf5bcab1ee5f2345e6cbcefde444c8e0066e6fdd4e2e26aa5bb0dcec4ecbdacf4ee920ed19dee6ec62cfafd88ce278d12f9dc4fe42cca5dde597eea4cadeea986efecb2fd0fbb438e9f6c1aff99f41aa46937bada8a42da9ac31abb5edbdfabc3514defebf88dac9e22a2a5bd031fb3014b8c07be21b0bee5cfefdaf6acdf4df0c8d42fc0a3a0c9fdf67cda93cd5a6f181d724da2ef31726abbd7eb2de463905f3eab2ba995a1b55fd09da580f09cfd9a4bfbb45d742dd1da36c2dbef00af73c5beccfc6cdcf1d0afef03cfe3ee3daf0e7433b5ee5abbfab3570fce94c7921cc75dbab70d3a213f8bfa10c7af3bce8ef5aefb3adeddec4bde5abd41baacc1db6c6d24ae13b8245a1dc57eda5cde15daac8675bf3c2587adb1eac70772adb42a09061e3fcbbd6ed5e8c0d424fb2ac589ba7e4059835a95950bb25af3cee7edc15fcda8c31365bddcc22ac1bfe1cdd5cb22d5b27f1d0ba9eeabf84db0cf0e8cacaad7cd5eee4d59dddbb1f3f02ad6ddcccbce4c00e8ac7d559cfd72eeaa9b67c89dfdfdadcadff7ef23c0a75eab56f5f5890e80b37d943a87cd4d6f2ab383947c3db180bc9a0b10fea8ffff94a8398af31a2f3a9a058fb22dfbb3ec00b5bdfba5fee78b0d6f1ccca41c0e11d72de9ddf1ff6ae29b47503dee1d73b3badee1b3cac974a636e5a9ea8582fb25a2ac7444bf5b615821fb7ac7fcafc950ccf6a0b5a3543735b80ae527ded5e8996c3c9b8404a59f5a4decdf41aa076ee8a8b6fd26ea2cf01ae1edba3f46d32b3d8e7c2bc1c5b6a8fc1b5c6ba284c867dadecb19ac211fb25abcfdaddb2f9a481f42bcbbdd45f20feadbcfff8dd4c129221c8b9dd2daafce6ab72fbd15c9dc31ba63baddbfc17c94b003de1cb0faf9df5dac707e6f2efa5efda0ecebeea14a9cee696e9a5ecbd4298a24149ccc7aaafd7aedf62f613ea5c6c668eb505cd35d3d54bd1fcdd5a1c75bbecfecc6dbca88d8c844fdc842a12f9a6d29cebad1adb6a5acfdb0edc88deac1e02bf1a623df7aefd1d5b71ae42f72154906bb03b05c2bfd267bebe04c9aba47f58be8df8becdeab65c700ea96abef64ae7bbb1d364fdc0da6ea97db855efecba2cef2c388b4ef217753bec2ec0d88dc7a456fb9cee6beed1dcf7e6bfea51fade18a8af87bfe0b137ebc0e6c69a8b0b5b637d391cd839eccd889ec32ab0ec1e12dd8a8ecd85ded77adaaba9cec994bb6bb8ecf777b29dcaecb7dcbc2bd03b44cefd41c0fdfee32d0ec9d7ea39ee72fce9ff47c2e008eb51e5e134b7bf48a09be9a0bbe94dc5ca0debe599e9e5b3f79b3a10bcf6f0d95bebac6b30ab028e9b849854a79bfacba9a2911cfae2449d8ae015a720bcdb33fcde0aea4b87cc0c5abd62c51eb8e89454049d83efed6cec2f7fee544dacecebefc0acf6c6ed5dba9f4aa1320ade5eef6cc8aaec9a8db90765abe2cbdee02a4c9818fa52b1d23db8ac0d1e6c7de7b6247f6e7adcd12fc6b1df6d63d5dedae8710e42ea8176ffb2d41065e9baf54cb6ec499dbf4a2c76697ac9b0ff65e02f9f34cf4aa806a065e4f7e70a41668be5ebeb2bdf98dca4fbdb66855d5b1d8f6822f794efbdcc9e56fd2eeeaa3e1e9f07b22cf5a4ee1eafa2a7aeccd5b506dfca5eb0d4dff46ecf99db060aa0afcf8fc4d9e00ffb5ec2eff8e06681cfdae57ecd7b1f4be36b23ea5bea3b4d7aedb42c7c483c23d03e835dcfbc16ed9eba9fe7ba88ffacfcaf4d051a7c21b03621e7adad811afc34c7be8cb4beb96ad5a262bcb2c3d7883fc0f0afbfddaefa51edeb0fcc03e04b35d3e2c0df3c57d5d51fbe48e2aafbe9363ecf61ded37835b1e133bd4c6196827ceec7cfadf365b5adec722d4b45df8883abddcd3bbba9b3246d1cd0b5baa8d0f33afd0eab91c8fb9705d67b3081597f8ccbfdcdfe94a10ee9eafee2fbc9dbea077a10bcc6b7bb5a9cc6eee7abda39d7e00bfadf783772c98ef13f0cd2dca2a3ad332cdb4634e988b21aadb52d4b5c7ade2ee0c4d248855a7ab174bbefd396547d4eae4be0406a31fafcd2df2bab2c996ca7c1d0c01d15b6b15e3afe553dc1cd675e21ce8effbeaa8b0aa38461e6bdfe42f47caf4dad6033e0e6eb09d18b32fba1d5a5fdd39fd6ff612950c1a7f178f1119adda695bae8d86bdb0c0ea853e1add3e044bbc8cc5fc1df87f0bdd5a9fd07b34daac5aab1dbcc51e9bbc1ed5fb9e2a542eea0fbd2450ac5bd9d0b904172fb3dfb58cd77ccccdfdba6d2c9e38cf0a2fee5ff53c3ab50b78bafc475e00ce7e5186fddcef4cd6a9b5c2decfcdc3cac26d6c6cc0a5b19560ab4c4baaebeee34eaa3e8e5b8811decf8347abcd025ba81063370598a7589b445ab79f41b20bcacaae5bf6cbffa7d72ffccb2cbbb0c56e4860aefbf19d3e6a2bd567abf399d0df95aacf8e7ffb3ba3d3bdbb2fe2d4bb7dc604d4fddc81ae01d9e4bfcf0dd45ee7008d71b719fff55b379a8df907c53bb43c561bbdbd1e452afa7ba3c1a4d911ac2ff9b259eb243f72b816af0079e88ad20fb2eeabc14bf9ff8e6b1bb25ac9b2dd1ea958cd50aeaf59161caaff06cbdf9a4ccba4e18ee8a9ab7caff67b4e3b7855e9b5a558fd06167c962c58868a919a070ba4fac9cbdbd4af24cccd58208921bacb8743f17ba776c1bdd0bbbcafcf7d0cdbcbd7b009ad7d1ae88fff006fa365c5b1dbeba9fa9a0e9dacee3b164cac609ff0e0aef68e8fc3f16cdf6fcdafdbfaabd8abba1fe75fc7bf34eeadf8c64cd02d1ded5724da2154e9cd542a1ea907c673ad7ae7e37a9b4fb92aa976b84a39d09feec11a266bd5eeb9bb5d9ad07ee309dddabdd4dde0eb8cf12bccbdddc285cd23c22626976cc5967ea301adebb6e6eec3598dc863faeedb1df05be55c69c20bc7dda588fe8ff2bffde6e6c080acb9f83cbeada2cec1052aeb53ed35459c2063c98aef9c8feb04ff6ffcab9fc0d8cbdc2dac67c6f7d66db74abedfa2a61cf9a9fb11c3d228f8c1ed6823e3ffaeabc540f9006a0df8d1fba73397ec5f7c681ad8f16abfa4249da7df2dd0c67ff7bfa389c1eaad6c322be154e40faf13aaee6ed9d2b9804a82af2ee6eb17eccbf7a54b4e53ccdc4e0f7fd28c048ddb74ea91d9cbacbcada3beb82deb95efc095e0e9fcb2f4218f4f106be47bcb5d3ceec38edcb17a3e5fade27ebfc3b54d23a0ccef2aaaab9438f8efce0bbef1dbad649987e4906fddcbd9231af63bddcbffe0160edd8b4a3fa56f6df5b0b1e8eef9164cd5cdd71fa3fcbd5769ecd911aafb782c4b75e0dfc3caa36ce14ad7c3d6cefe2a25a6a8ac6ce7b7eb44fedaeecede51dbf7368baba94aabfbfeadc2775710bb57aab6d35c2d5c4634d04bfbcdf47ca161b2eb922c2deccecca67cbcf55ed6ec8ffee94c6c2a127b46274ed32e6dcb83ec81b9cc184aee1fa6c367f34ad35dc4dbb26f7a597b8bf6b0f18a9d72bf5d1bb8deeacfa88c30dee92ab68a0dcacddf3fbabaec3142b6501d4b6bf2503b79df6e4f8b311e42db5c8dd6bc1dbf7db6ee56c2ababadd2d28de719f1dcb93c4ebc71fca1be4c572cca51c72bcaf1b0d7c05177ec7af67894eed2eb04fdedf0d217e9ebc7ef47ded9cf27dd6a4b67328e82aeea20fc7fddfdb9b56faea9abe10fcea6a8c339030d2b518968fa2878dd4e1b133e9ba8e090760bd72ae17ff0dd0325ad3deecf81fa7f1e952696ba7ecc9e5edab3b971940d80ab5114bf6098b4ee90c04bbfedd2aaaab2dc7beeb3ebd802fdf1caee1a0a0cedf2a5dfa0ff3c2c67c83ffe1867a311dbd62ecb3795dcf5baa1ee2a4e63f9724e72deb9ff1ea472fa1fbbbacbef85afe9bae7e85b5acbcaafdbacee0aa8790d6f390fc0e1567aa16c56dbbf1fad6fcbc90aeb74eb61d7c09ee57a54c209bfd217eced632464b46e4c52b27dcd9aaacf0abaf69185f9bda253cf6d28c20f46cefa3bbc45ed79adbc9effd460fad4304a561ef0ad14fcf0bbd930c3deb1bf9cab7c1d5b9da8077bfbfc11e3ffdee5a88fc7c7dce5cdf1ab5ea22fae25476db59f88971b7a6dd8f14e7cf13aed9aaefb73e2ebba2cfae7bbd4a0d7cb2c1622c159b8dd43a75ed85140bda0afbd79dbc0c37e49243f0f63fec9aa1b1ed0e293b8abace3c4edc67bd9dcc5d2fffe4fcccbbd97d093c44e14dd428e9eea563134d6aed0b698bbcfa01feca297abefa8da4eccd8a6a5ad8ae99ceecdde3054a56caf77cece6d62ffabecaedbfeb0340036b4df96df166d4cbce4672bdafaadfe126cf9bf0aca7c7f1df89bdf1a194decb17e898a44efaec234ec72799850280ffc93aabf0bdbcfa3b0def135ebce2e62d6cd52dff7c23cb35996a8a4ba85bb6811377e7bd3c15162eddcac337f99b4e1c535e1565f92905767da2cbfab5af020443beed376571ad736beeccf3afce3ef5950b1f9a0b8792b948c2498d0e427e62a1c2c8781e93aa29ad13ea4ba24cf0220a5165b597e1edcb9c2ddb3a54471dfbcbde5d5dec198cfbb94f9dde8f5c9be9dddd5ff4bede64360f28558bbe6dcc8ecdfdba0b551b04d3fdd11629dc36cabe39dd8d8ddef0e71b4df2fa2aef383f0a334153411bfa8b7e34b24686faa04a4f5dc8cbeb0fd646ef4bb2f67baca4f150e2a16befddf3ba1fb9ababc022e0baf6353c30c8fe5050b21cc19bf4bac5e03cb3daa2e4f28f3acf932beff34e1adc86dd2f1580120dbeafbec08b1b0ee8b3a60f2cf2ecddea8dcbb5efc8bde1e481ae5885abab2b89c52918fa67c53a0a731cc787c04c1db2aa9dbd25e09ddc38cbd9eff7bef31a4a5c50adf9c8fbeeaef17d6dcd58a6a4eb4daef9ece1264adeba5b81ac0fcfb66ee6eafe5b0e0d23cb8e4bdf2cda2a8ab213effa000dac44e130bea89fe82ffd63dfff95ceafa2c2ece8cf3adcff3eb0b76c93121794a94dbfcbdfae0a7fed33fd1bdddbfdf5a9befa0d611a3db0dcccafb75bdef8234ffb88fda822ac495b4d3cdd2ea3b2ddd0ceda5a9cdf64ebd8e50fb66706dff86eaab0b492f6720d61feaccfbd95c6ac8f9744e1a18c7ddcaa6ea32d0eacdbeb5be490e509de9b29be0ebb6d5e8af0b9be99cbbec91f7494a425f5a44d0a9c660d1d5770ae6b1c1ced9112db0e0d04af2cf47aa49c1dba65de9f3c6428da3ae6fed68dd8e986dc4c1f950e4aa2cac88bdbc9b63dacf9de13dc73a9c006f4d79eecdacc196b74cd8cd05d5c282c90dabb3c1df19efed0c535dc96d0b8cd2dede98718a439efa6a3da062a2b75e49cec2bbc4cbe9d2bcac4237acb619f46b5423cefbcdfd7970b3b04fda46f31ecb4e8fb6dcccaf8fdd7896a1b55abedad7f1a72c3a3d6dc38b8dd95d69fae1a03ecd5e94dda05b1cbe869d777ee1eb9cfe64f5a07deea07f8f7ecd8da18c7bddb57b9f6ac998c8e1cc02c2ec6f6ba7c0a89abb0be3662612b4ac91a363f03795ca2defea0cae4d3436dad0af1bb9edddd422fdf4a8cfe9d57eced5ed7ebdf6b6b500baf93d848fd35ee3d66aaa383aae47d44f5cc5c97cbd0cc9cade59fdcfeba5ed5b6abf0d2aa2bdaeee9ba8bddecba3ac025c25c9e1dd5e60de5ea0bf4ee47edb43291e40d04660e8d66ea3d38bbffc724f1fff1dbc8fd9f476cdb1a4cedeac2c697c35cd8bbcefda60ded2ec9dcaada46f2eb903aad72914c750707bfbfb2bfb7808b6c2afdbd7bcb8ecddcfb376f898a89dd9f85a4e051ecac4acb859a9deb60afeadfbb61d7b0ae11eae23a981109221435cab68edaabd3ea4d83604664ad883bcbe25dfd1956b1e1153cf12deb53de212f69f2b55dad976a696badf9cc4a4a2d76e8daa63eae6e6810bcee294fc2bd4a81cf99cee83eeafed6e87bad0683e17fa8f20d12dc8baafbaf14ad8c1a1393a2bcceff332ccdf0cddecdd01a5c90e5cabbfee3ab50a92bafcebadbf3f012daf0dd3c8b5b9e0ee4d6471a1ea07fd3ddd3a87d7bef38a629f334cda74cb9f2195a5d4fea09e5054bfa9afda2ed2feee014aa47effc3bb68c24ef2af3e4afe57b51e3bdbda709df7dc5a39ccfb74fff40eecd96bd09ee10270bed9e08606cc304ddbfce8f7b16f180614e4f6fde58ffc5d5efdcc283e1fe3dc28b4ca5ccd4c234bddc3f5a5eb6ebb01c7bb8fe03c99717b00f93cee37c9d5c69e31e2bda86f48380f2ec3b9cf095feda3c158e4bc2b3dbba37ded177e016cd05b7d185e0c912bcd7bbcda5160efdb3e3f9ca176bfd7df91dc5a066afedc4d5cb9d3fac0d9b9d30158c239ebec81dbad34ea33bdca3eb1104f9912ff7d8f7a5ff2eaf3f0be4ccad26dbf3ccad9e0cef9cad4db9abb2afa4606eea3e6bca41ca5a0da6b4f9e52ba78d6f558caada5f3fe84bed8a2ef8668c65dde3229a2afbdaec71fd00ccb5a9bf6f7f7cd2e228ded13ac98713c0c0fb75fcdb3eebfbe5039bf8a844cdfab3b223afdbef96045593abaccffbeaffbe4e7a324f8bdaf6b4f1ed443b77246bfdef5fa7ce3e79ea6af844cf7232fd01f0bbbfc2583400c0e0bdab18fa0f10ef2bdb0d67a426387cd8afdfccbb83dbe40466098959aa334cb12be8baa2e9bedd48552aa8fbc9aaaf5ee106adf54f82a18aaaced0a88daeabfe4e9b3c76a39ab570ce77cebcf3dbf4d55065ebfeeaf7635c04bb1b1b1fbdf00a042835db1703ebbf4a984dcf3accaee812ac18b94ae2d05dd4df219cca71fd2bcd2eb470812d613fd4245bf4a28a4d6d1a6bc2a74d9bc8b88de49b90fbe8dc9d1ace77b1dc6aac69e595dacd83d3fc66df7db8926baad08b0490dfd897f3f0f0fd04a615e32dbfbc2fb2bcb2bd388c989bafb3cbaadd6bbdeca1d17ebe6b38dccdaca9b4a4bb8aa79efae78554b2597acaaeccefdccafbeda87fea159b25bb8fc2b2efdf395923df142ca1d3b29fab4d9d28bc692bb1f8d2f9be133cafb5f3dfc36da8accfcfd443d5b2fed6e0e16fcbdbd3a221000e10ce2286eafa9cedea9dffa625cfdb21bf6eaee51d9bb4ee3c4f56ef1ecac7aaada45eb27ac6fbdbd4cb1806f1067eaa4cbaa0fdcac7fffcc19ba1d9d8186ae7e2c3efee24fd2f6d57cf1e491add5f47cbe4bff68113d672bb4a7f355d2de0e6ce7c0fc97e4bd13eacefd5ca7d8cfeef5eef3c43dafcc3eb37dde9cbae1323de4ee1be6dbdab7cddd6c1e2e5eb8ecc8eacced9d7bed9c6ebb4cbe9cd112f4cc61cace8e3859afefe6e140bd5e5f8ecaeddd6f53ac4b0acdacc5bfbbb251bac28ceefd9322e3cea0ec2a1f9dbbbaed7dafb70c61ed7da69dd0437ebf0e40de5855e80cce32f4d718f67fc7353b62a550fa7af48b8db65460d18ed01a7e3f5acbada8db9e6f9e5eaaaec88c555efbbba0ffaed0ebdcdde7df87efecc9d61e3c225c14afcde95c6f1ea374f83e2aa9beb89aa3c980c8052bb3e81d0d3ad5f2cc8af8f1eba69ac62f83ae088b3bebb19945dfefbb5e52a4260ca8d4f2ded26bf78fd5f0ad8a369affe6499c6510ac9f3bc8bfb1192a8fc7cb3eebefd87a468b47fd8d5acebd6f0febfbdeea40dc1ff3dfa9faded33f8da6ffdcd9d395c9178edfe126cd329ccb6aa956cfebc877ae5733ead0d1eafb612da3dd4869da5fa8b23eba063fdde0bdd764ed0cd4d69e3beb24c7fdfe26e0e2ebfb54706abeced452f95875bbaf814e661b588e7188dfafba3eac4d50e68fcf41fdbd5468f9802f46cedcd9d3ded3ebe072ed2ff9bfad51cb04dacf06ce7ffa2d43b4182a6b0afebac91cc65fbd4a35c4ab2dc38e5bf0ab5b3b4de54aa3eb08a5fd2f64d78b57665b0fa2ace7cce7ee7da4bbdf329eeb7d8e4b0c9583adaf340fa1ecebbf8c6045ee6b9de3b26e85a1c8583c13cf9dde06eefd067350eec8e86b91bb4aa1f3a75ca9c8faca5cb0cf85b9a2cb6aa66e22d0386a3fdeffdfa6a5aedea8d5d1fad1b6fdbdeeceadbdef781d2ded915acf1a5a35baee0feb9dce54b4f6a492639654fbb6f2eadc45d42bb2dccdc83bf8584647da5f4daeff54a95bcfbd6e1324af6cd0df1cebcdb7f0caea8813cb164a2ce3ddcff8ee6cfc6acbb5c669bdbbd0fe08c959f9ecf5f89dfefcafdadfdd0addaecb9c63dfa37dcb28840299caed58fdcbbcb2d77df23f598aeb1d7512bfbdbe5941fc1ebd6bccf459be236129ab7db60e5adf04bdaaadbbd0cc8fe43ed6fb5e895ca8aebd8afdf3bc5aaef4dedc71c5264a7dc9c7b8fe206d0de68fdfeb5c48cdec1bade8abca552eece752a0ae6fb0a9d7ad152cccfdbcc3868f4181e9c4ecbbad5cb48f728d3cd5e4ee2bba75f7f8e111279a41acc5bdc7ea9e376518ddfaef5102920628ae2ea66f5e4da6f7850d241e95da3bf3fd5bb3bbe905b3bb8fcf2bdbd508ba6e3a3d28369dd4ec26d947be15b0f6a6a82e9d3b6cd35e6ea9bdeb2160d23d9f0e5ca91def929ecfc6c3c18829bfc2d539ddde8dc36effed5cad110467bef2e6c063bc30c3ff5e560ae084fc1dcd2d2b6cf5c420b83d5e8510afdbfb5b2c3e6cd13bd8a690fe5bcea2250409c4da99ef3ee7bb48c9fdf029dabae97a13d2073ae9bab7ecd6b24644cd5f07c6af5de57ec2336d7dcfdb0dedf90393cd307a8596edb6b3dce434e5e7cea5f32df923c39aaaf7a1f0aad2fe8a5e69be02d0a2384ccc9bf6b44e10765cfd11d2cb07c40f0d4d4efe439c3b02e55af2ceaecf71cef2674e2bfb2badd5ddc9ecaf8c2dde042ab7d624ba9d3a56b3b0ef916d3f0b6d2afd83c6b9c7a5295bb3e8989ac1aaf7a279aa7f78ce9f07b5f6dc6fd4731af4d45fac39efd2e2cfcffdc4d7b7affafbf6dfd9cd2baf8e7e6efbf5bc137f5fcc2540e789e4f77a6eaec93cac28830d9b4a7266eafbfaf95ad4eb2e8ad6f918225dccc0dbfaee801c2ced9daf9dc715868ecb80a1843fbe5880e16a6e6f9b555630a1add7f1231fcde3d3ef10cdeebeb39dcdce70ddfecc908aee6ab47c0c401e85e05dde4e38b39f3b26cf48cfbeeaeeefe313e0ef0bb64b0d4adcf7bbbf1a00bcd8ac47ff10b0decfdd14d4c6dedfd0cbd9d1131deafc68e3fb1749c74c8a68bad34538c2fd6a13d75dabc89f060c85bbcc60364cf8dfcba9bcb55bcd062f34e3d851198e760ca0ea2880a3b8004f77e8dcfade8d8e7a868d74dfb97fbafde5cae0b7baebda98f003c9dbf0da5bd5709b5a5edacbf0d1f2ac71a6dd5ce0e20de1fd53aaa84c2ec2f8ae08927f958edfc77cab8ae47a210c3fb1bd4cb33aed6b6cacf2b4f5cd0f24750ddcbd2771b0c199bb0fee9abb13cdf1a4f97352b355205f1a77ab06533af5cbd508dff5eea094bbafff7dc9bcb29fcb9aced92c0eb9f88d66ff1520cedeb98edc1cc0eeea7a9fbe1dbed7bcd861fcbc9fa5b1f39fa211c8d3ba54ee7dfa0aac9ea2e46b23aacbaf8339af4c2e7c06ae7facab3e79a7df5ea1b752ce1db74fed02b8fd06ccc1ad05ef1aad26b6aa1352eeb767d43d263d82e0e4ed2c4a9d2baa6288b91dd024fa39b8cc912ab07b61961b5d702fec16cbea0058d68fde1b0e6d3ae6a3898ff1eb705cfa1b1dc4bdd31b1c1cddbac2eff8def7faff7fa18cb8b5cab2ddc6eaa89fc118efdc5b4b2ce2eccdf9f5a626c5bef9fbca8d8507d836b86b58f22cf1bd70cfaefb3fec6cb7f63afb29bf541c1d3830beb300127cfc76bc4af4fa8fca2cb72da1db0f0750afd4def0fd716c6753439ea4d1d0cb48a9fc025c2b48dab7e3e6fcfc49aae8a7fc3d3e913cffa598a803bca6bcea25635b5cb79e107b543c55dcc78cfef2ad6926e1caabacca849ef052eaaa31aa3bb9e5babfdf9b50b44cddfea0de7d2e68bb8d5ba76bd7699be75d44bfbbbcfd39fa3a2cb8f15aae24bcf5b0a58fb06a5a2fe28fb8f5eaadc8eedddf9eeabd8d04db9febeb8cff9a34c1f8aa3b53d37d27ddac025f4302fc34e468997d6f0de7b74312153f0c20c3fc31d09b744e7fe4ac79dd5293b24480ef1f5a11ee1bcedf3ca6b7bea4ee69a17a2a2a984e5ee67235e2b681d68bc1429e8bc88d02e329ebaae6ffc049e29ded65e4c09b42a15407aded8386a8d9d3b06c5b7ffe07750b13b1eb8b5a2022afa255e79fe328d8bb1dd861dbdd776bfa53f782cedbf6db93d06d056ced3cbb6e8feadaabd7d3bb4fc3acb0a0b9abdce1975b40414e37a052cadeebfb9af7c3ba4b1c4e04b09b112dedb13e2cf5c64f65bd4dfedd0e9ced63c1aeb3712af38579b627c31b69a7ed44e84bface3c5bccea84f8c6e99d375ce82deebca014369e29c9ef0a1ff9ecdea351c1dcd51ca31651fe61ede6c0e9a4ac3b805ded4cecd59d72afd9d9817f9b6c9fcfecb53b66daf398f2fc2c4add912634d9df2bbdaa555d92bc81cc2fa1a9a3bfeebddac1a94fb7bde5ad36f7822d5fdfe5a13572b0f545dc67b925b5ecd4f54b45fad26beed5dce3ac0d352a3a3bcefaaf018c8abcfadcff4f9db496daaf98f5b3e0a106b5efbf7cc98babaf09ceaf8e8fca57acdf81fa5f6aba2b8b6c0f0058c9db32baa6ebef84ed7efbe988ec930bc0dc73d63f9ba9efcb737ffb14fcfb91f11a1ec8bf5adc7daba9fe223a7ad2fbfbca60e4ed962a4c2feffcae98445c56afec573bf1fdfc4c7bd24ddea5abb26de74e22b251a1591dded73deeaabc6bc6c5aaec28eeb13f444acb0e66fb7a0b1bff77a1d0dddcc6a409ebeb36d85eae6fd6af1b6272fc97bfffe50eef60e1f3b7f7c8bf67a09b25def45f631ce8c256bce7bf6ac00fd94bee85aac5aecc9471f3ed11e307fddcc7490f28e68546ae6cde624aa35af0c5a6f5620efaddce62bf6d9ddc1bedbd5dec9d0debe0f2acef6c33dda26f8fe97aa6269e20cc346ce870eb11dbd0dce2da0ed7bb72af865e5faf1a2cad5dab88bcadd813d02e0ed3fc042b8c69fdceb29bfe5de3e3f91eb7f0ead270e952bcc29afdadbc5c3fcdea06ceeaeba8c0abcf1ea10bbc7b4c9fa7e722b6cbc4bd9be1366f63c249ccade33dca1be5ff5cb64b2feadcad030a3cfcf2ff60c6df106a029de8e3a1def7fcecfd65ba3a81cda70780561a08c98d1fa6aafd7babfbbad6f87ca82beea7dc96bf240c77bbc7dfdeaa6728986b40bf78118ee4b9d0a32d3296daff380a9d6f9ef1c2c939e515b8cf0fef7c3faf690ca8e955c2f4407971afefd9bdbd740fdceadfa0dfab8afddcafc21deabe1ca7f1acfc6f9aafebe4e7dbca427fdcc2ac5ddf23f0c9b4c53f31edfcbd0e39f284202b4cbc46744157ab85b9d1f954baacd5e3fddc69363a6ea6ca7fe9cafdcfcdbe9f7adbec288cc9fabfd7b4d4dcac8838eecb9820ee40e6c8c3a84d795661ab1d0bbba256fa984c058e0025eaf5db92c2cbcddda9f4c2f8a71c51336b1c8e6b0a50eabdad1bce8082bfadeed1e60a6f673a1d1de1badebdb9732efbc3cbd6fbf7cc2f1d7ec44e64fedb8cecee1c5ec88e1b6fdc28216d400ccc2cda15f920aaebafd1941bd8832b91104e962e1a477fc4be0b0cf0a2c5ab2ab7013c2bfe96ca8c6f75dce0b9efaca88efac9a5e3933ff25bae70bc7b8bbc7d17da2b81275cd20df80bb79abfbf466ff87a3ba6b7ef4e5efb7c66c56e2c5b7802fd8eecbd9b2d2cce751a3e1d5ad5bb9e10a646d203a5e94cd86ae7e2d60b58bcc3e0d9e9dc5d4c89eb6aed965eee8893f3c6d9fe844ebfbafc4bff2c1aacb18b254f8490f50de5acd841c5d4dcb9cb73f2faa227a9efd67dbd15a92e21fd0ab3214e62a2e2c9d87da19cbea4bbaef5d0cecfa7844ef657db8b6fa2fcaddfedfbc52e89626a707fe78d4aec6c0fcd1f36b5e875ba10da1545d9c7d55d7e8cf95fdcf0507d30bd5d2af16663866e4ddff2e5a8efeb8a300a8c7acdebacf988bc214bd42a0d3aa86f70900a0ebec328c223eb7ff2d5c22db9daa1e7fa9dd71d875b52f94fb6afafeeeea2dc9cfe671c80de3d9dcfba1a31e4de1fdf208fad81634c112080f7ed1b1dae2d8e1edfdb77f64ccec545ed8bcd59fd6dbc5cea3f582262a4480dd08509e533c1aec85cd549ccf0e52f645cde8ecdf90dc1ce2b3aafb3dcdd94abeceedba043d215fb7c934dddf4f5fdedf26fabed1cfb9dd04a7c79cab23c7383d8bb4bede1c932e7fccbbaceac7c96d3153bdfc09b1beb9c3ffeedd168f8c152aee98bd3a6289fea78c1c4efe8efeb448aba125ddf8ad8fdbbdaa69cccf198ab02beb950cdda58cfe66a77294badc9c9c8bbb32993ddeec24840a66efcffc47e396b51b1e7edaafbf77101ddeb4b53c7fbd4f4ef3648f37beb5d1ec29ec6a83d477fbdfcb401cf91eabebbdf9c0c71e8ebecbdab240910fabe437bd781d9f5ed4d9e96d989418bbc1ecc9db2be8b3e46afff9c9f7e9ae10a43bdb8eb0ccc8d66fff1bf514597ffacf30fef13e5f9cc84dcedd99cd55e8d4db7e2c7ad0c78bd786314fa3785af8157e1aafe2210cc3d151a1efafeaea5bd5ca6aceeba7a1dba1e8b89b17ecee208cd90be9da9cf8daf5a76a236facb8f53d2472c24785789ab04eaea6f5fc4873ec02f8aa985c52df4f2ededdf09a4f76c290f0c1fefb20e11681b05aa3850e725bcadd51def2b8e71ddb81e88f6f38ece8d5cd7fc6d3f3738f349db92f15e312f9acd248a768fb4096ccffa8bbeb15ad5954bd9d6db6dbff2d86ccaf3cfe437f98815e76544a55e49e6ac539153beefc8ead4dd1a46d1cd4acf9ec75c68d831aad9e2f0a0bee0dfca631efabced47459fd0bbadefe1ff1c8ba1b0cc0bcdbfe219aee9fb2ff19a53a8dbbd79ffe181c7ab3d50d7beea81bd95b9188df5ecab141d56da594b66cff6818a4d0c58ae0ec69ba7cb35a7698fdef6fbc1cbc61a5ce7ef27bdfed901b3861a63dc26e8a6e9d9bfb95554ba3be4f46dc5efcc979b8ab332dbc29b78f50abf07ecfcb95120357d096922772dde74a6942c3ae80ec8451fc90d5cf6be27c53df9ac0bafa2f0aaec1dfe7aa3b21d5ff34f8509496a2a5c2fd39754dcef8afbbff5ce2bcdca7ef1c1c7bcab9ce0dbecbfccf1e7baedaac24eacc9100e7361c8c035fdf2aebc039ab4a5df5d93dc6ba83ed9d8703b6f79c34f66acae23bb2d6fd80a0dad3f4155716a5cc04af2a34fdcee92d2a70cb468b72d8b4a0fceaa8bb17a9bcafacc04c647a1877bb46113646e500cdfb6ea7e1d0b2cf89bacca0927ac7dedcd2d71fad80cb6b42fdb0b3a7e8dc68d9edebfc6adc13b4a4dfd7b4bfa3c751d003151b27ed63a09680e5adf762dffba1d1eed7ce8b50de884e4b2fab7afceba190fe020ac8dc7fccac5c96fbb79fb4ae30bb9f5d0f9dc1a7a65d82052f039fd38bd2fea7d4477478e9fa015f41c25e0f3696a1e3de69dac2b3ddc6645c1ecb8ecbe5ece0c5aada72fdc5be1ebecef38bfaba6a1710a8e776bbe3d3b2adb3dc9e4d6db5c95e5fb12fd3562c2980b44bfaa0de47cc2bcb45fdccb7b9be58aa530dc0ecfb08fdcf16201bea15fd56d8027a4cbcbeeefeb2f4f2ce32c976f9891d6d0cb00ffd65acdd6c494554db4dface8cf5d001bdd7308a67dd34e38b6298cec14b1841da47bdaeab6cbae042fcbaeb769843fab9d1848b331f47e1afd5cf07c5bb93f36be72fab893f5dda18dbfaaca9affc63e5cbbf4a92ce352f3b3ab0a4ce6d90d1c59aeffdc606f49a32f76caeb4f5e923cebbc2f444ae27d5ce318c7026cc2631f33fa581ffc0ba2a2eac90abcc9bbc7f0e4ad05a9bec86c8b1bbbac335afb8cc0c38ddb327dcdb2af778b6c29bb8fa5224dab2f5f298da139a1ac3d1177852fb58313cbcc9edcbdedfeda2b3efbc3a0a49fa67dbadb25cc2b997873b3bed40749a0c7ef9c7b64f41abf6c1dc8483ba4baf6ab80cddbeb1baeab526050dfef8afb7cac7ad017a4cbe3e50b9b03b6e4e6bb4ebb3a1ad256951a86d7fc5bafd8d4f8d4fbc389de4b47bbfde33a2fa5d1e6bd6d3a85b5c423b3005ff7eef3fc1eecdca50f703b8a4ebaa3621eda6fbaca7c8d7cb0e4c3fc70c4d0cc963189cbaffac7438a1dde650e7baafad87be1d1f1f514d1bf72ba16ade89de134aa7fde6bd774daaf65bfb90bf0529e3af0a9bda6eddfe6cceae18e775ba11eceaeeeb9cbb23aff4bcea71f79f2d63efb707fbcd9f6ad38baaaf9ada2b0ccb8d5139d44a465a2c408b43346beff70eab6df006b2efcc3cde4748d26ed4aabfbf022377fababcfd2eb17a7181acbfca0dfe2ed1df080e2beb30d981f7a8914d9804a6e3cfbcb2ee8caaf2ffe9dd795fb253a6bcb5a0d6bc257e4bc8c5e0fbf12ad0e1bcbba4742b2fd6db46bbcfda3ef173a70ae02beb621eb2efe473c79a7af8d8fcc61b8fdfdd4cc88c7b35716edfcabeea6cad93651c66a0abc5d25aa0e1f1feee678845bfa2acdc5dc0eedbfeed07be2ef4b1af4fbdc9ed98c00cceeed8b951a9ddfded61ec3d75a5dc05bd6c4c0cb2e3c0618ddaba7ff185f8ac270ab59be19ab02a84286664094ceff6810e1e505a0aa5cc273ea2cd8ebcffb6bcee63e0b4b8fe9d440c2ff98b7bca7cdd17946a8fb6d4ee9f5f9ee8fca65188cfe2afb0cfdcfd4ee552f2fabd4d1cba7097adaaab0a63d8cf4cd21db6206d55fabddcefc0fd454dd0feaf6889854eec2c0bdd03aa8bf8ba3cd6da4ab59dc1bdf1bec9576ce9e4509cf04ceb2bcc9a70e2aacbbe1eb6aaa384d63b04afac6b55a7df12ff17d7e0ec46e41fcc93d5fb970d031a0fce7ffef1af6f32db4af15e0ddbf3e4ee27b71edffc924ad99d5d35f60abe7b697f46ebedfc38d06f418871cefba3cb477bf2e9abbd4d35a887ea7dc9d22ba42cae1a96f5e0e3da20deeefbd4fde40c657e89fc0a1391a3c59e356bcceba90d1f0afab1af5af91f0cc24fe6dfeece2d1dd7eff25b51681dc2cbe49cc04d39cf1f0d3620a59a2621a80986ba4f76dfcfa1205a3f09045c0c450afd1cbcd2cc13afda5b05df30f43afad6cfe9c9986be1b91c6ee9ad79e13b7471fb0ad03333a8c36a60d296b1be5653ba6e6aea8d27fabccb3c1d5dc0bf6a05f4657a070a23f0f28aababc74ec5e509cd0c4df19e1be302ef3e9ee26429bb7a5f625469f1f109bafa8b3cbaef33f2d992ffbd15c4abe7b92943ad187c40ceebdbcd9a6cacaa7af752a4aaf108cc7cdc214694d2fc87f6fd70b9ced3d31f0810bc2a0cafdaa6e0e1b2c0ec667e6bc026ffad0d5efece3dab4636bfd4fdac60c6fea8d96fb4be1ef8fe3f72f4a57e8cf985ee7eed2f5c4cdff3a47ff6dbbff014a4a9aa9c7ff7dca5b59f1ffd6bf58eca77c2bb478857e8eab9267dfdef63aa5bfcf84ea74fbefa421eef8af7a8c0c2ded21461a7ec441ef6bbf4d8dd64901d0f12f1c85e857149079b83fca8d11302ac6f712eead7f6c71b13358af1df2d271e688f2aaf3c8fba5b4b87b01cb49e6dcfc7cfceb9fddd6298afdd4afccc0fccdabbcbef20027269d6cd7448dd5bfedd743c021fce76b50826ff21469b24bdea3bd8d4692decc4f82ecbd5cef45e1eadca6bd9df88ebdd1fef2c82ee3ee1e23a1c49b6a26b898de0b81ec109d6a26edb24e3e5a5d20a79cd32cc9badd8bcfb83cba0ba29f6b31cc3ee423d541eaeb4e4f3caefeacf949ee018294e0bcbdf16eee6ebaf554db9c47b2edbdb8adea3eaca247a340c6a0cf7f31ae4323ccc1daf1a91c9cf1481e6fa12affcaca80555717e1b1f1a8c32aae8cdec7fbeb2d5fdaf7eead5ad92a7567f32e13c85edbee3b5b1acf75bbb8fb30ccfbac028bb9d2ca9aa6d6b6c346b4bd1cc8b56bbc234916ef453fb099aa9fd2e5adaeedef8f2201a86de1ef26e56aa2d48c91d4ee5deb10671f00f8be8a4d1bbd71ad8df2f0b675fac6ae4fc0ecea8fa7b823d3bb6e04e8fffa8dedce13befd7192ee7a948e271db52fb71c4aab81e96a72b04ca4cdb805a119cc76f1fdc5ae72b41456ba9f10adac7dbf78e76ee33556b7cc2d32303f265d33da51c2f4caccdea414fabecee3f41fab490e2968f44e7efeacb42bbebaf053a94819fe6bbca190d8b4fc3d1eabfc62a2aac14feedfafc1cbdaade76355b529412fcc2e4c98fb687aab44ce00ceeffc312fac0df06c0af9c8febfcb5fec6aa1767f1ed5f000f6a6fb2deb377e2fbb0e33fbbe7c68ab92a79ed0fda2ccfdfce2ebfd644cfec44db1641083b3e5eae961a049dd2ab4bf0f33c6c26268b5632a3eadd70c3bc6018e68ac9b1bcbab8572ffeb78a1185de5f0cbaf3bb1dadd217c0cfb0693ca3bcd4eedfa7ed87feef1e4e3f62a5ae0f9c3d5fb6e55c1a18ddef5b6a0f2ddfafcb1b8961871d0bc9617ba2eb7d07d8efedc10e947fbbc44ab7dcbcd9f0a8db39ece959bdfda505bbeb3ceba788d04964e4746f16aad227ff6b0d1ea99cda3fcf3bfbf666832f8a49518d4e60ebd8dbafc1eedd6e09d7e1cc4f7c9ea1e7bddcbabba3a96eb348f3addeb31e5df2f4bc52ab9fd7eaebeedfd1f33d990967cf01841eff1d6cdccaee4852f428c2adf5a172dfc2ce4f3ff23edeadcd501093c8b33fcf07cbcbeb1ffcacf3a380f5ff66559b6be8adddacefa6651dfc8e6fcc3f273c6a8b6dfa5ef8efab66cbe67efe0441753f0d713b82eefd182b0cd144169c342bccb0c3bb122b73bff89bfeff27fef797ea14ffef5815a6eed6b9b605da3ee74c39fea7edff0cb78bc7da225e8af73bddcf7f6cc7aa6b91c2cb117755fee024fed9b2abab96e1aabdca772fd5fa56dc5be0dd26fb5f5d305c63ab1bc1c9239fbded94cae0a7777b0aaeea5034bc405c01b69e3b597ef7ad1bca7facbc1e3b590ab8dc6bfb5c205ff72ba10edadc17d8cb2a55fad702bad30fbdddbdc5cee42be8af9cf6df43abd08ba89758da5b0157ceeca08ee2ac885f9fb09c77df14cbd8e5f10a2058bc5bc211a421f64754a8fcbf0ff68d372644e2b841aa4af6d79c4fd0bdc47c0d42f21b2b81fee93a22714fecdddb38d4aac9cad621ca9ea6fcaa67eed2dfec95d38d229ad7c37960f0d8dab16f768d03ee604f8dfb31d4ca42ae05acbfdb3efe3caafc3df74a18afb5f03c4ecc2fc34aaadbbc8d187eb0e4eeb2c744affb2f75f03c8da6525c9fbc4f0b477e295990d8570dbee425acdb4a6dba73aaf59be82bccb3d5ff2eab0ca5e9a810dc8f6bb58a8d3f25a27af1bce95a4eea2fde0430a88d55328bbc70c9a8cfce7dadb0e7c0e9e5561d1059cabbdb1aae5c2d7f2ede3e1cba0dfcbb6818dcaffbd36f7dce0386e0e6b0dfc8fb5b59f7e06e39eca3ee953dfa4a0c506ee6bc2faad1a9e1f1b320cc0201104a6f39cf3a27c6e455de4df1d2f3f3c3191ab7ccc1eacbad070b2d9da4d0d81f3ce5dbb0f94fc9cec0cd0d0b3f2c828e6342c7e715dfac0fb890c17a3bf31b5adaf5cc6e3fe45fa1015a39f53dfd9dfadb8af6500e95a1eeb9e5d23dccfc3026da71ae588b3cbd472d1b122e6ea05ad5e730cb482fdc37a368a2ef74baa8faafebfc7acabd0cd70ba1c7aecc2ffcf0690bbdf5ddf533d7da0a3601fbd39aab1aa86ad2bd70eb46ea43486fd7abf196131c7f813f718a3b0b9eac9eb84ecd5cdb7f4ec337849b04abb9cc08464bf7ba8dd3bb01d7eede5b6764b1cf5b93cb83ef6f6040695c27f3ecbcfd6fddc72c4c8c0f9388172db3d40abb8df374dc3d5cae8562a06abafcfe0dec03b72f60fffc6acbd1e787fc71aa6deadea8b2bfff6a5f06b44b001a911eccd56cb8e95a1aeef4cebc6c42a9ef442c1bde98e75ae031e5963bbbcf6996b45721acf7d36c4d8b73ab5e6b3805325d13aa83daf12dc2d1d6cbdfc9f4c91bc8bfa5b0aae69effc41d3aacfabb25b772c40a9af058bfbfbbd5f9b19ee5f79a4db9f2bebfc6099e4aaa08bd82dfcc2de36cf0ded3cca8cafceefcebfa893adeaab8c5d6760cafaa9b7f4f7ae8960d2a62de48ed8aacaca00eee9b0e9daf01e83943f8c3bc755f18a875cbab6d481877a05da33ac7d9bad8daffc7551ad09a0c5ccbffe8bc506c1b3c1715a04758be51fd4fb4b9cf9a61cb246ca6affab96ced5f57c97aeacc4d2bf4ab9d1dde4146dfc2cf4c4259b4e74d1dfee1cd1d2bc2b70e4fda2b7e14b1ad000fabc93b6ad73b63de85fce8fb5b0e1bdb161ba91defebe2dbfc7bb56192b7bfa29e1efe85a84b87a1c1f7fd1e7a094488fc344e959ecdb2e98f510e958c1d39faafe348a5fdce0a81cc481f02e33de030efd37c53c6c27c6edd8e022169e556f8e8dbb61a15e05eafa06d7be683af4f8cf9cb4bb6f2c52eda28f9cf8ce55f92996eae1013326ddc1ddf7d47f20efb7a98f2d008c8c882dd5a69b46e8db4a9e3a8f233babfabaab9591f6b38f5b320a6f97a4ed3dcb3fea4e46c2facc8f4c8f23ef93c40b0b97a0bc4f305bc71e8faad8affb8d8f491dfefbcb42b37b1dcfcf4a51cfde72e7ad4d3b0a42df75d2f9bd85dd7e332c0e0e59cf29cd8df570eba6ad054dfaec3869ef63eaa4ab2f779cb5c2cf9fab789f9f5e6927c571acbc2bbd4ef8ac48ef2c45f0ddc6a3f8dc3bf64de5dce3dad35ffc3bff77dd76ff80aacc921bbed21aecb6b20fdfeba37cf2edc8b249bf0e38c05eef58e6075c77a7ccd4efa4cbdf5cbc7fbdc7eb705cc75fdb1ff0b304fa3da997b4f696a43f6b7f58ee0dadc7e6deeee8da075249ac4b4cb86f4eaea67d6b7be50be1e2bcdad74efbfb6dcfaefe6aa0b40b27ca6a99cec98e34439a5309bebfceedad616f2f6ceaf28bcb6bdcc48e996b5f5448dcca5ca9ee8c21afcfa390f9bf2253fce5835f595ba0bf1f5fe2e7b41252e6fb9d210f48ffb46e5680a7afb55afed9c11bfdad1d2e6eca509efbf9aec18fdea7ecccbfb9daad9e77fe3fdfb4b0e3a69a234d0aefcbaaf3fcbb45a37845661aa3a17e2e1f5d7f4715fda7b56d14cfce6ac33f7e3f4f6ba7deaadbaffdce9c1a10eefcc7fed0a50df109b4a1fe6e4d297f65c74cc4a32323cbecf86416435caa6e8ba7efdae91ccbc579a53ba8d4dcc5e95df1a463ae4af9ceb428c80f0d753caa39a02fc6c07baed19c47af079ad8b6f4abb3dcdd07fd5de291a17d032eb09dabea6ae97babf7680dc22aeb6ffabc7ea744d6cbe65e0cb14edae1dbbb628cf6e4ff5b43302edb273c8df730f4091c343f7f4df98fb4f6d5afed6ca4f025709e6cb875d4685c7ce7ffcc3b9fb44d4f25ff6bbd3ed4b0b5fa6ad6b98d4ec1eb063c8becbd1b7f4a8afdfcf4caec88b0c8306fbfeadd0e62dd625eed22d85ff5cb1660ddb77d12bf4db53abdb7dfd6b4fb6abe66f0497d019dffb64f7df13cd277a2f5fbe88c5e65d57a1c5f8ecdf271aeedf1d48b657dbce412ea7f0be7b4c87b296ac66b084a47ea2d3d23cdb410cd94ecaa3af15cfd868d3f64eaceb04c72150741688bba935616a88efe625801df06f2f9c0c582feebc49f94d27eb6ce8121ebd9f52865f2fc21ef6e0a25b01d0d1efdcd306ecef2edced4cb3cdacc044bcfdee81cd7d7d617c99e6bc77b7d50b1da1f42dace1df516eefa77dbac8ba5c6d28fc537e37cfe1d20a9ac8dba11e60a5ffb4dabfda3ae6a36b5aaa15ac8f2fc02bf9b534b7caace0e938fef1dbd75dffbffc143b1abce29fe0dfa9fdea7eed22ef6fec7e09ab2c59d7cf2d911363a9a3bde9bd174dcb9f69a1b1ef19ef0aea516f8acfc5ac1083f048fe9761331cfc6eebbadab3a359c05bddc85e03a777cda2e5a5473c61a91241b1dbd8dc0bcd4c24a6a430db2bfb33c3a1b4e3cce8eeb76ead99d733caf6a55ebf42ab89698fc51a5e46aa4f24c3ccfcf78d4c58d9adbf9a81ffd8ffeec3f6a5ce1eb2118fcfae9f8f2adadf38a77a1bdd0bd34c97ffcc4ca81a17ae51d45bfe15f0facdeb0f95b8841fb90adafe1eef1fbcdada91aed2d98dea825df783172acdbf8cd3cd6cf924c933a4c95c028cf31be9fd6d23cfcd352e1c699ef1cc574cd9f419441f2c07652da974abbe9f638ad2c0bb8042a49f4ba66add2cbfbccbe2f79577cacdf49baedb3b7feac0ddcf4aeb33a1e98a0f09491fa6bcff5ddd5da99ddf10c485b513aad48a66a072b7ddee7c58cf973fada8a4a66eff816b0b6ee06b9c46bb04bea9b2ccafeaf01edeacdddd81fedb104a65bca7bbbf1eadda6b9da84fceac5ab0de34ac28aaefdeea7da626b3bc2a58ad8f2edfc20a1f0deea31bbae13ea2f79593d8eceb8c1af0f122274fcb6d56beff9f68b07fdd15cfa81208ddad89bcb033af8eba826f66d51b1fef2fcb0abcabe4c717abee6fe71e9bab0a80fc4dd337dc8eddb7ee3d05aac0e3e8fb0cdf3a6d951a8dbc5b4f9ba4f712af0d35ae25866caab76ddde931c0aa037dfcfa202defdbbcdd94af3bfdff6eac1c37e7cdeeaddadbd18b59ed8de85e2ee8bf2fdc63bef0cab71a66f5cd26b81dcd6cdb001ebb4fa204da0ddaeccc5aeb0cc7b18c9322a6ff3a400b1bb0efd1a07e782a7d7dbf747d1fb40a792b56f63cc78728e08baf5d24ca06ddcefeea2c88d11eb26c8e7dca5d5b7cdfb30dbeb50d6d7b8c75cd94dbeee8a588c4465b6cf62d2fc7fee82f896566afd04edf21d2b8bcdf40eedfba2e3b0b15bbc980b4d4bc16b0ecc5cac5cf8eedeb3c34ffdceef064ff534da6ff1aac7b6fd8992ab2fa1d9bc5cfb71da6cee3a2c49adefdd7f67ede1cbbeea7fb3aba19cbbf6e8eda74c115d7b09bb5d5cde2fe8a6d537adedfebadc7bef3cf6f16f76bf6faf00f3217a47669eb2949ff107ccd2f16bcf9c963090d711bf1bdffc55f0b9250c0a7f121cde228dca1a0c0ace0bfee7ace128b0aaf096e25fc6bb4b1a01abef9bdedd47d02245f6af722c3ab8c97e47dbeba79a9e3abd448f8e5f12a220c134ebcabeace61dcfebeaea4ed4a2f95ead3aaacc74f56fbd9557bf23a31b0c9d0adcfac82e78f402e115d6cd2b9a6e79d4463eb2c8ca04be44c1006eb57e4ad7f0c1dc79e6aae16464c1ed776204176d8efcbc0be1b3c4741cceebdf60e5411e42a3025543ee7784ceeba9b79bb709c5cf00fafc9e4fdeb5c6ab8c1a81fb5d734bc1e0b2a0936dc8c7fc03bd11df6feb92fb0b488394e84988d05df90cdb31c3d39ee7bc5f0a4ccaa82012f1a8fbf2a5cd1baabadc9c6fd9d779a4b285ccf889aa1ef9f1f4d6b1c69717e77df50e4dcaadcdccea2afa82dadf705e26e7d4e20a8b16ac68c51752f2c4c5f8baafacfce0ce8bc6fb9eba1bae433dc8bf27bdae2c9b69c2b61e514abc2961c02c38e8c35754faeac49135a8bdc6591cd2ed7fe640fa342b2aac12fc3b1fd32593ebd8be22fe1addbca8dfe0b3aac1ac943ef98f5ac86ef2fb9ec60ba4fd16cbf3aee8d8479a3ffe9fad9b60a5be6d8fd58c4c7edaebdefeec9b67f96caa34dbc3534bda2dba6daf2a49c3b13de67bd8707ae48ca1cbbeb60a60d34b3fbad943eea03c7cb60672a1d84034054f856dbc6ad506dacf1b61acd9cc632f33bc1b9f4066efdc6b2897973cc1ac7cce0d4e360466dafbca24abc58e737313b6c8aab7a3dbee50bdf4c774fcaacafcfb8a63b47de2e6e4a9adf093ddca35fe8baebba4c4a3e0c66834308b6b2ab8bc7792226987a9db6b1cd915aa91c1ab3ad1dad37cbeaf157b8deaec0d7e5ed4befaed02787cfcafc5eed9c61cccaad6ae650ecdfd74e91ba89bddfdfa7c0f28e4ad4e00a7ca31ab4bec1f9c5add8afefd4a64f8b57e1ffc70c2c8ed699be8c7668bb61f4cd481ea6d35f74da4cdf4d1af51bd15efc50def32fa27811ef83e8979f9934be286f0b0fbe118fa3c5e71ecbbbc22d1ea101afacb01f247a0c7dd3bb684a4a3b69b0f0c7eb5b5c6c648da0c9271775f86aee3e3b93ceb8921ab96cca16c2caff5150ab47a4ce52020be07ba95e425bc4d8d6fd3a8d8513c6ba0b06cd5d979ce53aa15d518d937cd0ddb2e1bd5faa84e6ecccaae78114071d7ddf4733187c4774efbb06beecc4ba788bdd694baac5cad6fb68a1b9ddc8e2aa198ce2ffdf9ab2080fdafea22209e0a71aec928951a81a4b3ad02bfcbfa2c0db01d7dc00abcc5c8daacafca661a56dc8178f1b9f2aacbbc5de4bffcbdcb1b03b22fabdb8fcd3a12af7dff9b50f1dd02d966a2bd9dedc5a99dbe441bb9615f801b822cd527b3aafebf331542ced74a7ccff4d4e06cee120ca1a8d57eaa7fde42affbfa86e089eff12b1ace39b32379103ff62ae6cd605c43cf6abda17bc0eeefbb5c5eefbb28f42d254ad70efe2b92ab1d4a5ae38d68ce85dfdd64ab0f1cc9ca024c33e363b0fae78c5abf6fdd1addccabc0310dfdaafdce06d689f4dcd47c4cadaffad9f3e5fb852c0cdfef8adf7a4ba59266c43fae9129439f8907a1963a603aaefaa8af99cfdf2712e4fbccef23fe9e8eca8ad02d281ab85bbbff66e54f2d47bf9cf51beacac9564c51622fd8be7a88b4fd472bf7c8f8e3c0663fe4f8f8983da1cb05e1df4f2ccdeaaa2fa2ef0e701bf4cb40940dd15195434dea41aea9199bd1c502ad0ce00aef63fa1f0a6b4adb145dd3cac5d1fa0d3bed20bfc4d6d7736aac0dfdccbea4336d5ac0beaeb0f9d2eef08161ee743fce9effad23eeafe7575ecdbb40ebbdbfbe86cf1e1f6afb2acb8edd237a615fee06ca1c532bceed6f1e3a7da2a2c90d24129cc0bcbaa86fad8c9b6f3c5d78c5d5cf04f6b70ec4e2bfb6eca58952aba0cfe558afed4fa6ffffc26922afd6e0ba2e5ea2ece8cb3faf3fbf4cc2ccb885d885c0c3bc786fbdec5dac7bc3aed0ddee33cdeed9acbb92ebdeca23b511d7040bcfdc7682cbce176dadbd87b0808def6ca1aefab93fd7bcd3fc5d88bdbcbe0bb763bba817ce6c2b5a0067be7f9eea2bccdaff1dabd16de5a6c7075b4ba1f0aa702be412ee78a9d95ccbce5b899efe7cb5ff31a0c57eab3aef23adc3dccba0ca24e7bc5b9757cacbda8b01aff12a3bb9a06e1d0fee0290fab8a3dd9acf29cff3cc337fd10ff054c9f5c861e1c4007ba2a06aeff882440c27ba69dcabc24c3572f622f6cf22a2fd65e8dafa12b6dabf638eeb2c4f9d34ad44a90ddd3b92fee60b48ec865a3fe2d63495eac94d5830eaa294cb34dfacc5fdece0b5e7cfb4dafdc3b8edebf68ffae260adf5e5d7430da7bdaa49959ee90d49fee2fc34f707accb8ef4dc0dec897234f4ceeeab5eac034332b760f9adef0cfdbf2ff82ff6ac3dd8f0e6b0eb9dcf6c757aff7c7e8dafd50f41d32cd37f3e970c7dea84fdc72fbb132cbb91c7ebe85039d89c5d49ee7fccafa91f6ece4ef31ccab37ba7b08652b8a577bfdccee631d8da190ce5bf9ad81a6eb4abaca34ce82d480d5a0c2e711215d9b9bea90f4c13470b1f983aca0fd2f7d6fce71eab7d03e0aeeeef8d42413de67be5a752e3cf08ebca9a0196f54abab5d2ee50eaffd2daee4f9696fb8a8ba5efb98386f651dc5efaed6c606b2f6fc5496e876d3d6f6bae61b23fc1d4fcab0bca53c65a343eabbb0a3cac08bc9eceef30bac4aef2ad38cbbef9ffb75ae6dcaa764aeee35e144bfbccacec8f0be9a233366f8bf3b968fcca0275d0e37fd2adbbd568d08108eebfdc51ef57fea3ce9fcde6e4cdc5188b3eccfc5e9a30c4aebbd2c5e06f5a34ce1820ea2b594573d61c9e7a369c8ddf1fc4edd56ebc13972b39d7f80dcad3a29e93ef4c93ac4441ff4aaf72d155d486df610e7baee5df0bde22d6dae1bad86e2c9e361fbfe38eee10a019e1a923b9eef2eeecb05e826b4c9bdf3f7bf67f1dfb24fb73fffd76ef6c0a7e2f36caddb5d130c74eeccc8af2edcd0fd3dd3beeb9808d84d3a8cf1b92f4e8a54ea63edbd5aa615e58ce3b9fba60dceecef1591bfeed7f4d63baefda1de2cb02bd508ab7f0768e253b91ccfb2a172bd6bd5be2c60841aaa079ad4ae9427ecfcbb9d30a8ebf4ae4ba3ee69c2fc008f7f2f9e3235dfff1720e675fedab8c727defadeb2afd923ddb12e8777fbabcbb026f771dc086ddcb56ed567eb2dd7c8851c71895a06d1f32ebcd0d8eafcab3d0c5aea0bdbb60ce1c1bffaadbbfa6bf65306fc396e587c333ad799a05d74e81c885c707d16def101bcfee1ab6ab5394f1d82ba9ed08aeab3a671dc4f3309e5daf554eb5455a7cecba68a3dfeeacde124ce1e7e0fbbb74cd59e907ed68feae6c0ea1decec8db3eeed273aedad0c2caffae1a0cd8fe0fe0baad9caf3aeeb12f20fd64fa1baf23e5ed3a35f49c7decadeab9f69598dfc6e7f7bd56ecf07ad3985c0faef18f5cbab2dfb067ad674339a7b03244edf6abadf2a42bfa8b80edc4edceaec2be6cfcc8ad455f0dfb901ce0a3c03bfeadfc4884fe70e385cfacde31ad28acfcd9dfa1fe4a2b9becedd6f777d3cbdb93daeb57bccefe3fecabe06fac40ff0acdda2ec0dbd4f1fcb3def5d7df7f7d30f3e1a0ecdbf75d7251fabf513edf1cfa2a423b217d325dcf9beeb5aee4bf647eb18f347fd7fb97e4cc5cda21e0b7b349ddacbbe7b8081dc7d26e6fb88b3e45fe93ced2a8dc009fec5df3ac23dcf3e5c910bb5f9cb3b57ef541ceb6fe3e7e00c425ff4caeaba96495cd9ca062b76aea40ec33cddbeacf2ff6fbefabe9cbde8ab8cfd9ef5cad692e114ca5dcb01ab3fdb68f33f8d337e2fb12a5b7ed4adbed12af4ccffbc8fa0bae4e8eee7a9a16bbd5d2ef5551dad1821db3c9c903dbfd2b2ef2c2b37eeddfef9d7a64a51b7c3c0d2cbaa6f2d8aec40a779e7fa66654d1dae1c858165f8d38fcf3fe6ed409166f6acc958d2edcb0cc56c5afecf2239662e648f2286a8f2f7eed95aa4dd3fbb3b8f5e5ec0bcdd9fd2db8d7822c11c27d0e74f5446ac64f84bdecdde71e9f92dbac88df844e74aac57f5de6324d412f7bad2cae2ac2b80b9dab56435d874bdd5e6aafe5a25af4d499c0afabc22c4cdae95caaade2a226b9ae028f1beabb6ac0b7756d8963e2a52fc7fd1f39eccaacc90947a0c7e5634d4b43bd0dc472aba281aa4cb935eb2fe5a9b5b6efe8aa7d1e0ae3be19c9cbed82b238dc0ffdab50990a74a960da8dab45cd168c85494faaeea079eedec2bf8e6f69942f86cf596caed8d6eaa8d7274c86b6ceff2acc0258b6ad8fcd6fb5ac854d7d88f3a9698d6641ea37baf3295be1cac4a4e5f48a7ec02dc2f47d3fcf92eecc2fcfc1fae1dbd6095db51ee1d2d4d984e270bfdfc574d3b2ee58a86e05f11df6ecdde958def8a2afcd3d6c354f7be2cf38fae5a79e4f5ca72d1ad1ad1aa6ab7a777df9a5e943c434ca8b56044cd4f5eff66b45fdeefe045903fe10cfaf9be4dee56a9ad4c9a4e7511af82de48e7f0ebea718df3ac44ab6c4b297b18899ea0b16cf62f764c0a5e9c9f44bb6acb9ac89c8d2b954a5b52ccdaaeeeb4c5032fb38aae1c5c6caef0ecfa7a5ccefba75c01727aea21bedfa1a63f4e64db4fd7ad1dc22cc174fada1472ab1ad54d56abb3cb8f3acb321cec46d72f8f6df65aaef2d078ce7ee51ef2f5f86c08dc39c93a20adfbde28c20fbdb3532ee114eae7c6f9c4557cc32ff10dbed3ccdb02d30caf4c5d2bfba699cd8beb58e0bfcec2139c97efde025abd03cadcb7a64c98ccf3b7ddde44bdee12bba0948ff014ac5e0ef5fbc99d61aba2f619cdca73fd51f0a98ab102a0f235ec4e2fbf552092dbe67d2bfc6cf6ed754acd38ebe426f763324c3d7dde410bbb8d6beabb376f2a5a5498fbdb4fdd7af47b2ee6ad2dec91091f119bda2cd5d2bf9848dfee78addedec8ba91900bacda4f1e2ef8b20a9a96683d4ef55c7bafdec1dca6c6faf65eeb8bce7de6bd0fe90e68ccae7bacfa4ecef9ab3c406fe0cf513e89399cb2a0c2357aecfe0ca3f1cc5aaff3d0ad9952b04ba1ec10846dd6c3eeaae3fedf87c731af12c25cb44d4ad13cbdd0c8fc10e4a43dbcbd82f462ba6fc5da36f346d17f37d7e165a73df3dba87b6d6e0ba57faed68a041bafa9936c4dbcf4582dfb2acabeaeacefa9c9d0a5b2fdfffa2081f9cceea236d4bd1c90ce7ddeedfd8dc85d4c5c07afabe80c0698ca3d6fac77d5eebc29a1ff9c59ff8dea8fb6a73d3636942f2fb1f563b53ed671664f181de6a226c6ebb28ab819ca4b6c6f55b7211f7dde5f466e6ebdcd3e5cd225cccebab2ec9c2cfcc0deae3939efbe46d7b35c8e76d4cfe0a6edd7dcfa2bbcdceb42e7c4ee0c4a9ef92c3ed321d456ae1ade9cbefabaec2a27b4ec9ababa1d9719e78bdf94bdbdcd44a9a5e1eaddbcecff26fcb6e2f5ad27ef05ef89c406eeead13e05e9efddd5b878a77cfe20adec5bdf0a73fff2ba44fd7cdb46b5cde5f44bddeabcc67f18d8cefead27bfa6ccd6079eaafce606e2dfbbe843f6fbffb3d17f1f96b4fdae3d4daa99471bf671fccd705adda3107fd8f3cfb658aacfb5eca6f8423eabfa1fdbed6acf34bc8c533cc2ecee43abe76438caf17fbade2ecd3fa0aac9a48cf5e38b6ef10d029c32fc2bcb7bbff932c924e9cd6dfa049fbb8eb0dbcf2cb8c3cdf63aa5cb0ccaadcc09accf5e5b6b965dbad6640e647cc6ebea50e28c1a1beadd4bad401b1b500e5a4cfef0e48b3bc4da3a0b24cb6d56acee0cbd2497aecd35cc3bca02bbdafcd91ef8777b5db1d99e810f0d86123af73427adfda303fffff42cead85ce1cd05eeecce67bf1f6314deb0ed53ee94f2dba9ba7eae9dfa24efadce3c1cc02dd21a3f3c4a4b9dbb2eaab942643dcfea091a10189ab760b3af8a81c748afa9c2aff55c84cfd3b5767dcea8e2da678e86dba19dc59603646a7d359052a4faddde4be3bab7715dfba0acf5bb3d017b9ce5f965df6b1dd4a2cf0bfebaa1a12611822a69a3fe0bc2db5183cb4cb1ef5ef3d8dae9fbbcfd7b43adade85d2df0f5fd0a6cefe4beca56c24e3a0ab89ce615aca99d7d71f46fc2cd9378eec70cfe6b3c8dedbb989dac7ef08c8fd8eecd11b42cdd9f9d14eaef31bbb08bb29b47badb0b3ecb4edc86ebebf3b9dbdde145dad1667c5af4de0f25ddd58f63efadfc7aa61ccbf874afa2a5aabe4faaccd4e9bb91eecde6017fdacf6caa22ec9a45070fa354e9107cdc478a76c3ccc0c8427f00a3cef30bf46cb272cb9bccef7ad4cd89dfaf12a428f37d0c1eaf7afacb75f00ae276df7a4aae9f34aceab3ae4a68c1348e2d4cbde0efd0d5abf8ae7dd3bc903875db7aabd3deecbfeee0228c06231ffdb6612c255dc4c3f4511da28b50fde56bac35f94eabf1aef9cdb9d7cc016bcbcaf2bd8eda8baf4afafc852878156c214dfb4e67457d7cbded0baeedd047b26cde5ac736c010d4fb82ed6ebebea5ffc3ebcda8e79364e93aaba15ce57c5f32fb37736b8abd8f273cf6bcd16181bd8c6f8fda5f18f32e0baad1c37f9cdbe4b99349bbadb5bd8afb9e8aee071fbae73ba3dfddf130ee0b971857d3fe2ff85f6de9f5d7bcb24faf9b12d87d7fbe92d0fa2a45bc64c2ed3ac188a11adfbf154fccb9f22c6fc881201bd0a5eefecaa07ed1bfa77dc8cb2e275a6b75cace71540d9443f2baffdbd9884c09c31feccf4abbdaaaa8bac2dc2fd14ac0ca392b8bb5ce858bb2e464abf42cabbaed8cdab30a838ec7c21157c3bfad2a05f733e07bbc8ff3cb6be9eea5fcc9e77c86cdafdbcadc4ae2cf1f452e2819f66cc0aa9efededf23ab87dc75ecfc0c3ddce3f674dada6b3e37e62a9b30966fdaa0967398fd20f43f7991bd7becacdf272feba25c878fa636a57a1ce0aee70d2ba934578b86f83ff7ae85b2f94abe3ecf17b8504cb0cd69dabe7b9bc5fb2f3edd8a1f200e2bb1fa5dffe29dffda2874fecd8efeaca4bc146bfe900ad7bbee435b116d25dcc801db28bfb5f7dac6cb882dafddb4acc24b6fee943527dac3375b9fee8a740709f87dfcbbebbd13cfb4fd243ddeaa4b440eb00498ca38c2ec7c1f86f28cb81b978acd242a50abdd0c3e39c736bf6e943078f38fc9bbaac113d8b5a43c1bf9d8ebd49d0ff2c7e186e05e0eea9108bf0a88c4dabb18dc053b283bcaa4b58c09f2fc0b1cb3bef677c2b128fc1fd93cfef88b7cf4ed0f18ac4ffed5f51502e89cf23ef421caafe26ee075ec1caecb18ecefceaa08fae15825c3d45e7bbcefbe7e5c35ff7ba94cce0bff3a5ca4f0bb597cd4ccb8de3baf9b44bd450b1a9e4f7dd874bce3985cc96ecde6fcb2e061efefac5a25bb38efa5699aa80d6affede86c1ed7794644cd30a7bad204303b87ba6f4d5ca9fc311fd77f9fbd0c5208affcd8089f30ecff3fe0a0cda6ec24ab444bcde7c7afe2badeaea39d6bcebd4d4efd8f54bb8ddc956208f1de9bd7d6921d3aadce53bc76eec9b74461afeecf7c09e3f3abd3bfcc9453eb17afa5d067f7728fbd7ca50f43fc11871b7f3d9c2e4642cdea1a0b8bdc00228ee2db71cef84d9194c0f9b1ebf54d02044ba9b9e8cd789c57ace8270bb61ddda87dcf222ec2ada3b7ac4b2a596daa1067b3448fac30f9db7a6bf9ba5cc7fdb2b491d331fdccfafb53df5dcf805dff6f2ac3178845ab2f9ca4b8ebbc3acdccb9da668deee5aa06216ebd342b7815ff8d6cef7fe34ddad84480c6696a1b4a31cfe7bfde03c0fc1c39fa3e37aa12fca9dc705579b898e7ad30a2ac7cef9bc2dadd432ff74b49dbfa42e22cdc21d0fb587f6ae7af9edb418aeeeb8c4a5d27f7549c81e6aa5495fe1acf1ab1adadadcbd186eba0a944edcceeeb4abd7bdba0eea3cb5ecd6e97bb43a9e52af99ece9eed20be67c9b8e376de2aa50941b57be0d8ffe9e4df8126b1bc67b79aec42aeb5cdbdbe006b7e3e9a79facff2bd07643c23b0ce4dcff1046ab88cbdd859179a5c565e4b3d1eb0bb3d3c854fdbe56a2d7af8ed1ee324c9f1fa66fee7ff1b1a90eb028cbd4fe9fd5adbb1e7251f0bd22e7e0a9cdb73b1ab01b847bbe4097eabea04ebdcb2cbadaceefbcfb1da5fdff6cae580a1714e95c1e3c103ccbfc2efec917d9bc3e3c26f399bedc5ca0fbce7c8e6fbeedcecd54ddbf9db8feb6d2bccc3018850cfbd7d2ab1dcae13aa2c6bd79cc74e7fac36d2d3839a01cece2d3bd53b9ec5f56e4e6eb8fca39d688b6b58feec3823c0788ddbdebff5afbfcee08dbcde9bd9ec2e0c371822ca6dbc5ec51324f486fa7b11fdfb1c99ffdcb77caafce1875cbdfcabf5fba7263a8c76ff0992cc83fd5cad43fefccf10b39e5a7cedec434547eeb3e48a07ca02f5cd57be8efdefda83acdbbafbdbd13aafced4aea4feba4df3a882dbf41de4a5f4bbbe6474ce691e3ee0e0e05ac2958dbdfd7cf7e16eb7e037edf47dacb2b3b06bb35feefa4ee3c73eb833de77fcff321fb41bcedada3f1aab6cd85da62823faac1bc73bd3b8721f2eabc8bcadc0d5bc2de2e05ec3904a875e2a2a35805ff70a8eb4ff13eb04e49b0783d62beebb3241b1d1dad63ebc56d9079c56cd3ab2aeafa7c4ee0cf5ff3ff86c3e4e6df11e0acecaf3beb04bcc3d7053227698aa3ddaea1de08ad8776cdab372cc7bda6cbce3f65c97d013acad0eaa7981aebb5b5c36dcaf5f7cdc384f0aa302b35920a9dc075c3c2b3dff2ab004d1efe5a6b4def6eec08dfe7fc0fe0d3c9a9be84d98dc4ee6d2cbb6bc1b3c4c5646e372a06ba2ada9e3dec09cb007aab1da0e0d0f0787bbbfaadf104c1bf5c0ef9298e14fadeafdc856edc1be403edfda4c4aaa5f4eee2f5b177ba1dafa14faaddbeab7dc8f528baa4add34ebfdad9fe887edfbb9ced900afeecc9ceebac50ad774dfff47f6fa45449c05da2e85188b641ff9dc1ea3fb71fa4bbc568e5e63fec961f2a68afcd121fdbbda3fea7fec4d04cce24c62e62ccae67e620ca1ab88c460e60e10159540e145ead922ffd9a8a76ac02bdac4f98bf4a7fe54b755b52e4add8ac79fd6cfe0dab24efadff0aa8b7f92bcccd9e1ceeaae7bed7ec2e0d71cdc66cf08526240cffb806d43c7df4a29c56b2f2c3d2affe0bdfbe2bf9b6efe05785ffaabc1f5ebc5abad9ce69a003fd0f3a7094f9af3efb8ad21e02ed38d04d4d50ce54a3e3100cbb66deaff5d448f8f284a69f84b08eb23ea795d4ceefcab22faafa4876e87c57dbc5eae173c1d3b1ce85ccfd373b3af89aaf1907ece4abe154c7dd530edfb3caaefe3e77d63e833499a3decbe0ecd9e7e837a7d37dfccefbf4a45bde3cf130bfbee741b3cb0f7c820cecbfdedbb97c6b628d6fb32eeea2ee6adab6b15025fcd2a3bb464ea8abaadcfbfddffeca93ba6ec2facfdd7a39cfc3c01ae4eb194eebc02a5efcdf16926e2b7fceead06bf912aab96ff45ca0208aef52d5cde4948a22b9dace24c53b2300b24f94d98ac3648e4c1abab319a9704ae038e5d5c29c0f4763026da2320aca7aa7cc932b3bbadbad3dacd6703a77cdc1cdaa8f410e98adda8bcff366ce2bd5a3f48cbef7cfa3ec7b4ae8fd3d8b846977bc9e2e6abd9a4b177ed10ce7da4accce3ebfecfbf4e5ba6ff3ec66538e1d23f2ef671bc02f66ae05fb42a2fe2b71a015e3e2054efb6bc083d68e7afda378a8de0a67baf2a8594b8150dead75beaddbcef7eed251a582df825af31adfe580d0bce73b3ee81cb42f1d4acced00c7beba6a5e4b2bdeeccf6fcb84a1dccddc736b45d3e85bbe7b71fcadda47e4fdcba2352aa21845b51db45baac3f7f4cfaf1eacbd8fc0f5b9878f09f1454d0bfb76abdd2efb73d7bbdb5f72eef42fc84bcddabbbe33a7c4b4ac179a3d0aba775dadcdc2aaecfce54501581c01cc7180f3f0b9aff2ca6e9ad3fad5c867c4ce298ff31a9cdc5fa6cf8c1bb98dbd742c7a97fac9fa8ff3bad5da4eca0b9d1e6edbef15c07bb5ce6a7bbbd0d7c4558744703055b9db759f6fdf26996d07aaecfe997dd1efed6b4692fbfccf0fc1ecc01da64303b2bdccee8812ac556798cf9e6077fd591f1353ca1b894b6d12fb86ddefefd03fefc04aebf2124aeabdc16afecabe4d0ff3fdcb3deb66ecbff31acdacd9b46a2fcaf1d3bcc8f80b8c5a6b91bfce8d5649dadd90eadc00f30a755f8bebb2f79799f9effda4f680d21ae8dc0d725a17dae3ef29a15ee0ce865edaae4130ce438e36b0912d7d13edcbd9c0b2fbbff66947f84b8c7985f45c7c363adb467deec13ed8ee3c0cee67222b074cec9bed0593ca35215bd1bcdcb30ffe509df0d2a0b98ce9f67d5fade6a6417dee7eb53efc4db8dafa8dde7257ded0cafadb5abdc6c1aedf85b1de4b9ba0b414e3f75aaf2a061cfa1e0b473feafaec6c0aad06f1de57af1b24a452cee64bd20f65cd9c20d800d987c45281b72fbbfffa552fb7ec60fdbee0b5af07ddcd4f11bdca2ae651ea7e8b335816ccc05ec2ab334fe4dafccb8a26bef4cbeec91bbaaccd0aed2cc7cf57984fb1fe713cc9783defd94fb62088fabc6a78bf2d922a139c9faddef06e3f9332d0a33696e3cefcfce8e871f1be8a0c710084a74cc7fd51eed4ff7bc0ab02a6b2267fe5ac8afdde8d8ec695dac3d40eaa2247db93d87fad8c14a7c4fedaebeb7db1c1938e56436dfbc3ddae38e7df2fb0cc9f9581bc7adfbebd20eab369865e12e4f9aa71a0baf95dcbc46c6cfee2edc9eb220a8e4bbe28faab6e78aacb719fbb0332cdb36fa11a85abbceb45b8faa70f5d1dc66e8abba541e6bc2ffe823fb4ccfd967eedba10cbc740c6ac98aef2e2d346dfd27eed90bdfcaee33af6ed582a3f1df8d10e9cefe391dc3990cb4bf8d6a7ad3cdfd2faf01af4bb27a5ec3dedc325b8cdbeacfefe9c3bfefb9e3db4ae1a48de084e28dedbbfe8e4cf17ea8eb8a1e1d42dae8f934588beb1db67eea39b1bd42efca62957f23efedc41fe4c1c6bc85c06f587f7fcdfd7c0ab26ce90c03faffe6ea9dd603dbcf295b2a1ec4e27ad68975a5af3fdcb90b4bac46de6d90f6a6f6abc83b0cf75956d78fd1360d66bdb5fbc436f79c3c6605b952e6684f659bb1f4ddb5eeb5dfe51bf84b1b9fdd430700ec1b99bfab5e8124574ec46ee6c10eb7583ccd5c6dddf72455fd12facabacbca6d180cd7fecf723abae81bcbab6f9eb76475fad45c2056cebdfd176a5a5eac5c7c6eeec41edae47c6b1102f86c3cecbba6d6b2cedcecfb9cd200fee97fdfefef3ba9abef31f4c0fc6fa8e24eecf75ffde2d582beca15fd1ca913928ab83fa4b4e6e28cb62aa6bf80adbfb65b0a704c3fdbb1f0a8ac8bb1b6b6dffa6df2bd6d3efa39ec0952f5c3fecf437cc55711cbcc6ede7c7898b6ed447c08c8ede0ecde7fad90f678aed85cb0346cb1088c25c4b7eeae0d1e438f9bc5cb45425c8fddf8ba56ead6af77dc6bcd3e0daf5b948e59fbdc36b73177f04a4afeb4e6bdad1cdaafb40df2e6f1deece30c6117c508fef3534c1fb1f3aaceb39cbb74979384ed055b72a85dbaa3189ef6eeab5ffefe996de18ebd40b6a21de4fde8cf2f5e75898adf318fd96b3e01e3d8d6c5aad06cd0afa0ba82fe0f8ce6bf71ff9d17fcc59c64c15d2a0eb8dcee16e5972e8c40f1bbfdca8bc8dac94c8b428e5be1c7e7fde50d106bc7e7cd09dfcfdbdad09ecb5d0bb79ecc6b785e27a4ddfafa9ceedbcdd38ec603ba1a1bccceca68a097ee218be5a6f63a41dc8fa3ccf3f2d6b1b79f4b7a638a7f5aa0bbbac0b0200aa96ae47ccf6c7c10b78ebbaaa822a0a6323ec72943c3294bec0cf08ff6c6d4bed4adaaeac5be0a6df35870fcabd1d393ae8c5bd7c3f3f7f3d6519333daca54bbcaef804cf1fbbf1d7a3e556cdce4b57a5c91fcd0a95ddaae543fa5493cefafdcafb63f9a7850bd4cce63dea2e63febaee42dd3bddd6eedceab304bbcb3cb5e3a58fa3aa704ba23afb1cd7ed8ff9909b70a1613c1fffdaaa130e89cb12b597befa680c6ccbbdf1d2b9abf9eaf2ba697fc9e1a6340bb33fd6be11c08c5eacafe991bffe926f4d6e4de7ba94fdff5b8bb3cee0aeb6187c68d8cabc8bed77ff54a8ed3ba87ed96dd1098ed8481bfad3219dd096e1140b3eefb6c07bccb6f5d2a9f4ffcbf57cb1831ddf0db3b346f0dc4232a9a0fdc4ea3bfbbbe94cb49b4ab6a01c116e9f1c3322d3121fe69cca90c0fee37dce6d4fec6e9c2d6d25ccd466bd909e9d97e5ddde0b96d8adbfd6f332ad3c293af5dd9dad3e8ef688c63eb28d3a6f83afbf4babbcd716405f6e7edc143d0bfa0effb0d6ab915c859de5d81f3e4cbd9adfdcb4dcb890f37bc1c1b7ae9d1f2cdd432e2d72264d9ff07f67ceabdeceab22c50748e622ecae1d09cd1abcfd5fafd6ac363deaaa4bbfaabd961abbd9d0c4ee96dcfc2d822e51c9a825b57421afbbd628320a5ca8f0cbbeccebc625faef878fa7eef12f6fff1abe57fae1683675a9efceaead868ea073111a64cd5eeadc22bc6fd3fcfca1fa3bf96e3ee5c1895ada074d137da81aacabe458e20f50bcad7802eaacfcb88fb45438bdbfb486dc65f030fd276e2707befcbb52e73731eac048a15ec4f80f7a27ecedb56ece7ffb32cec16d2a1e3f063fd75ae27abb39cd3d22989acaa95e71838374ca6d53a3ab7deab3d9aea4b9ef9e8ca74fffea033baa4b6fc0dd4489ca20661f2c0f28deefbfb2ec5fce3f4beaeb43f3aa4bd1b9faac40ddb40ebcead9605ffefb11b2c4da67742fa6579e98fbbc23a22096ccc51927c94d0a755f305cddc442c1ce45dca3d9c611950dc4fb546daafa8c0bfacfcc552cc3bac230b3ab026caae8605b7cff6f3d0ad8edc443ef9c6c4a875dc1a686ebcdecfcafe8fca0af3d2b479a5ad3c02eca591b82c216cfa77ec77a5c12e2f6d9af38cfc9e0dc7d6cb32e1d9fcc0ada8f87ed40a0d4b2aba8c4b0aede373f6ee4cd971ed58eabbe4fc8df5443c0ee6ca316ba7dcdb74bfd2d68800faf06fe0dff116435acbd7ca6f6443dd29daad8ecad53f9dbe739a6c1b22f68764aab7d95cbf29d4fdcec6f9ba68e90edd2fdc909a81dd70c6efdfe17d40f64a91d1b6ce5f7c3cacba0eb4f3b76041e0d1c83e4c7040e74dea76b47fff1ba937eaeabd23db6aeacff59b27b3bf866b5fbceb13f746b04ecb558d8fce4aa5ceae865027f0ee5e0a58b81ac800f3103cabd47dd9ece5066bb9bc7a35ba29bb5ae533ac8bfc4d55b2fe3ba625e18ffb4c9ba17becd16bad2fc3fe49fa3cf1dc1a5cafdff89edfada53a7a42da1677e1c7caafdfad6eadfcf82bf3babaeeb5fba82cef5302cbdc733afae5ab95ef2cf806c1e623f5f9a027ded2dea55bddbef07ea8c339af3ad555a9c2de41b100fdd51fa3b1ab619a6c1db0a948a81927caefd167de40dacfe10eb00e41bdd70810e46c187d42360edeae4acbdccd31b5cf193662a7d96d149ae32bdeb42ebbabd4401b3fc5eb8e8f0371b1baf04b0edc8eaebfb3ca9acbabdf9bcb49bcc19bdfb4cdce9d3ef6ffdc8e5e2a99b4e7fbabfaaea8edd15df5aa1baa64bfef64120bdb6ea46f20f420e80951cfe7eaa8474be0abcdf7f6d5cdfe38ffc15fcff33cbea93a9c2befe4ead1a50c9e985feffc9ebabdc4dda9629c8ef77b6d9eb31a5b4b0784df9f579e9ac7dfdf7a71ff180b2dff4bbccfc6fc5e8b0c1e628d9dd20fed1206c1caf21efacbb290bfbe63b4ba3ce6abfb6a78fd2f6ccda6245d6743b8eb479eba54aefe5feededd05d0deb37a1c01e49a683efb59ed8c614dca9ddededcee87bb44de12aa95a4d15e4b3f7beb5ab1993f4ffaf4d0af5bed4e48b0faa5ebadffa17b6805f922b321bdd90fdfbdfa252f0a38a33f7ffab488dcb77beaec6da837c5dced7dad0bafe5ff2a8adcca702dbb9a161da47a75b2dd28cafd552801ddd17dd3e81eb9eea248dd5ffd24bdf11e31f077b4a14f509f3506abfb1a0d0ba73c43019a5c9ec3c14d9c225db893dcbe90eec0da2a943618fc0f8c8bd4fab3c8e8f78db7cf0577a2cd277feab5e3615eacb1fdb19b6dc87dcd416eaee3ded0b1b1eae6c7ec6ceb5af78aa450c6ac5bc1968c8ac7ef2e3d8bebad8b9b3b7917a8ba21adf791a6b64fa6fd7ccb4dbfc1879ebbbef81f3ecc2a572eecab07aa69e3c149f214226acefb2a2ecc9e1edef14f3b8b16ea25ec3dedb444e3c4ffd6f400baaa359cb1dbc5a6a53fc6f0ada76b82ec5e548f4a931dccc6222afb4e80f136f94a3c060add59acacfdc4681669ad630a1e2dc6ad80aa39f66bbf792b815ab81b1dcc3dab56cd9e63adfb6ddd657463b646febdbe6a2dfc0eef6a48b15facaa916a67276bd80acba49a94cc3f0dddde8bd4c145c0aabdf6dfeacfea4c28d48dbaecc5cc57cbeee9dbeef3fea8c690cd3a1ab186cd408fdad3933cb0a09e538e9bdbe74ddde4ee2f9092c48f02e1696f63996d5026fa0c7779e5fbdef855ccfdead6adfd1a607a4e1a57c6f224c37f2fccb6f7bfec4683d4437b9b2cc79f36c9f46f2f5fcff4fcc4c1838bd239a841c8d55a0621e3deb40cebee39c0dbcf449e700be94dbaf9f4f05df2b03fe4dd1b685e66db7f3caf1cedecdd59ecfa4d962322cb22b7d8c03dfbd6f6cb81ab59bf6b244cf44ae62f6d5acc1b63edd0fabf3009fb1ef628b3d93b8ccb21abefc56c80ea4fd11baf9312f89ebed4fbde84adfaddbca67d7aaedef4ecd4aa183dfcb9bdecae95bdf53f8fc2249f0a46ebacc4aa97b38deba4babfcbc46aec62cbbbfd00c8b495ae08f35ebd7b9c15ea1eb891d86eddf6a5d5ed35cdf9ff927dace9ded8552afbbc2ed0dfa529e2eac4035cd1baaf30da5ccd2bac641c3e3b1949e7f43ee0b87dae4041bec27ccdc9de3ef0a6d1ffd3d0fb90a7d928f34f8ad4ba9bcaf06a235cbf2daee3ebb51bffda3f9fb3dddc5ebacba70f6fcab975caa3aa4734e2903d1e5e4366eedea4f7ffeac7bebfe4149cf40ff2cdc891effe0a3e04df0ae8c8fa3eec8a454eedcad054ce9d9b7a53aa7a6e7abe1aabbe0e5a9cebdfe84ce2aadb032a6cbeaf1eba9cfdc3edbfefd9e7e1ce03b5df6b6a2c51ffcb418e55a6ef20ef90633a6d28feddbcea97cd7dfdc1e6e93ef4ce31f6aee4c5cd6bb32b182ecdaba0d4e45cebb891b577ddfcd2ba0fbdbfd299a7bbc6d59e9c9c097aa1101de62b5ba3b89bf377ab6f70e6ab7cef299e8dafb3e330d6eeaca2b46db67dad437c243afd8afeb1a0ead24537e4a9e9d2dbeda9c908ac67426a0d4acd17b7bc11c6080d552dc16cbb67f0db4ccd68553ae912ac939e9deba4c69ca738dcb12a8bcdbfe95ffec9f5f4dabffda121f99dfcacecfcc17d2abea440ec17b6793cc081d3aabc89fb661a0e57ec58dfd5bd5d0fbf66acfbbf26beaf3daaf0baab9cd7df7f5e7afefcb4704d7fb60467dc061fc214fed4b1c08f6d21aa802c0bf3cfe457d6fc2edc0ed0aedb3760afa8beb805f2c51ffea55bacdb4e86a909afdfe4db9b20cafddaa65c3f13da4ed20c45f7e7d39ecf5eab2b760def3bf6aac965e7c72ffd5e4aa0fbfbd869b36febfd82bc97a7e9dfffcd7450aed29d87b4bed8cae3f1147ad2bbe705bc97dcbd8ac712e165bc13f3cdc8ffd693f335b3dc332adc9ef0c0a05c2d271da6da5cceb2f4af6978f21bf5dafbd8f2bcae8d302ac5bddab528aaf1f3eac5ad45bafcfa36d0d0f2adebbccf13c09a4bbf1edbf` diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations.go index b3d22b2c7158..fd8a5eab147f 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations.go @@ -7,11 +7,13 @@ import ( "strings" "github.com/prysmaticlabs/prysm/v5/api/pagination" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filters" "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen" "github.com/prysmaticlabs/prysm/v5/cmd" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" @@ -303,9 +305,16 @@ func (bs *Server) ListIndexedAttestationsElectra( // that it was included in a block. The attestation may have expired. // Refer to the ethereum consensus specification for more details on how // attestations are processed and when they are no longer valid. -// https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#attestations +// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#attestations func (bs *Server) AttestationPool(_ context.Context, req *ethpb.AttestationPoolRequest) (*ethpb.AttestationPoolResponse, error) { - atts, err := attestationsFromPool[*ethpb.Attestation](req.PageSize, bs.AttestationsPool) + var atts []*ethpb.Attestation + var err error + + if features.Get().EnableExperimentalAttestationPool { + atts, err = attestationsFromCache[*ethpb.Attestation](req.PageSize, bs.AttestationCache) + } else { + atts, err = attestationsFromPool[*ethpb.Attestation](req.PageSize, bs.AttestationsPool) + } if err != nil { return nil, err } @@ -332,10 +341,18 @@ func (bs *Server) AttestationPool(_ context.Context, req *ethpb.AttestationPoolR } func (bs *Server) AttestationPoolElectra(_ context.Context, req *ethpb.AttestationPoolRequest) (*ethpb.AttestationPoolElectraResponse, error) { - atts, err := attestationsFromPool[*ethpb.AttestationElectra](req.PageSize, bs.AttestationsPool) + var atts []*ethpb.AttestationElectra + var err error + + if features.Get().EnableExperimentalAttestationPool { + atts, err = attestationsFromCache[*ethpb.AttestationElectra](req.PageSize, bs.AttestationCache) + } else { + atts, err = attestationsFromPool[*ethpb.AttestationElectra](req.PageSize, bs.AttestationsPool) + } if err != nil { return nil, err } + // If there are no attestations, we simply return a response specifying this. // Otherwise, attempting to paginate 0 attestations below would result in an error. if len(atts) == 0 { @@ -465,3 +482,25 @@ func attestationsFromPool[T ethpb.Att](pageSize int32, pool attestations.Pool) ( } return atts, nil } + +func attestationsFromCache[T ethpb.Att](pageSize int32, c *cache.AttestationCache) ([]T, error) { + if int(pageSize) > cmd.Get().MaxRPCPageSize { + return nil, status.Errorf( + codes.InvalidArgument, + "Requested page size %d can not be greater than max size %d", + pageSize, + cmd.Get().MaxRPCPageSize, + ) + } + cacheAtts := c.GetAll() + atts := make([]T, 0, len(cacheAtts)) + for _, att := range cacheAtts { + a, ok := att.(T) + if !ok { + var expected T + return nil, status.Errorf(codes.Internal, "Attestation is of the wrong type (expected %T, got %T)", expected, att) + } + atts = append(atts, a) + } + return atts, nil +} diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations_test.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations_test.go index 8657ca5a3418..ad029c217be9 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/attestations_test.go @@ -765,6 +765,8 @@ func TestServer_ListIndexedAttestationsElectra(t *testing.T) { cb := primitives.NewAttestationCommitteeBits() cb.SetBitAt(0, true) blockExample := util.NewBeaconBlockElectra() + ab := bitfield.NewBitlist(128 / uint64(params.BeaconConfig().SlotsPerEpoch)) + ab.SetBitAt(0, true) blockExample.Block.Body.Attestations = []*ethpb.AttestationElectra{ { Signature: make([]byte, fieldparams.BLSSignatureLength), @@ -778,7 +780,7 @@ func TestServer_ListIndexedAttestationsElectra(t *testing.T) { }, Slot: i, }, - AggregationBits: bitfield.NewBitlist(128 / uint64(params.BeaconConfig().SlotsPerEpoch)), + AggregationBits: ab, CommitteeBits: cb, }, } diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/beacon_test.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/beacon_test.go index b3d984d13ff7..7cf8b99815c0 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/beacon_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/beacon_test.go @@ -1,6 +1,7 @@ package beacon import ( + "os" "testing" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" @@ -21,5 +22,5 @@ func TestMain(m *testing.M) { flags.Init(resetFlags) }() - m.Run() + os.Exit(m.Run()) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks.go index c3c7fc226bcd..f61c8db0a23c 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/blocks.go @@ -110,6 +110,14 @@ func convertToBlockContainer(blk interfaces.ReadOnlySignedBeaconBlock, root [32] ctr.Block = ðpb.BeaconBlockContainer_BlindedDenebBlock{BlindedDenebBlock: pbStruct} case *ethpb.SignedBeaconBlockDeneb: ctr.Block = ðpb.BeaconBlockContainer_DenebBlock{DenebBlock: pbStruct} + case *ethpb.SignedBlindedBeaconBlockElectra: + ctr.Block = ðpb.BeaconBlockContainer_BlindedElectraBlock{BlindedElectraBlock: pbStruct} + case *ethpb.SignedBeaconBlockElectra: + ctr.Block = ðpb.BeaconBlockContainer_ElectraBlock{ElectraBlock: pbStruct} + case *ethpb.SignedBlindedBeaconBlockFulu: + ctr.Block = ðpb.BeaconBlockContainer_BlindedFuluBlock{BlindedFuluBlock: pbStruct} + case *ethpb.SignedBeaconBlockFulu: + ctr.Block = ðpb.BeaconBlockContainer_FuluBlock{FuluBlock: pbStruct} default: return nil, errors.Errorf("block type is not recognized: %d", blk.Version()) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/beacon/server.go b/beacon-chain/rpc/prysm/v1alpha1/beacon/server.go index b1d3ef1ba3fa..a2b464105eca 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/beacon/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/beacon/server.go @@ -39,6 +39,7 @@ type Server struct { BlockNotifier blockfeed.Notifier AttestationNotifier operation.Notifier Broadcaster p2p.Broadcaster + AttestationCache *cache.AttestationCache AttestationsPool attestations.Pool SlashingsPool slashings.PoolManager ChainStartChan chan time.Time diff --git a/beacon-chain/rpc/prysm/v1alpha1/debug/server.go b/beacon-chain/rpc/prysm/v1alpha1/debug/server.go index d6bd27b41e47..e565a645651a 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/debug/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/debug/server.go @@ -56,9 +56,7 @@ func (_ *Server) SetLoggingLevel(_ context.Context, req *pbrpc.LoggingLevelReque // Libp2p specific logging. golog.SetAllLoggers(golog.LevelDebug) // Geth specific logging. - glogger := gethlog.NewGlogHandler(gethlog.StreamHandler(os.Stderr, gethlog.TerminalFormat(true))) - glogger.Verbosity(gethlog.LvlTrace) - gethlog.Root().SetHandler(glogger) + gethlog.SetDefault(gethlog.NewLogger(gethlog.NewTerminalHandlerWithLevel(os.Stderr, gethlog.LvlTrace, true))) } return &empty.Empty{}, nil } diff --git a/beacon-chain/rpc/prysm/v1alpha1/node/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/node/BUILD.bazel index 428753ab1481..7331e4ddab5d 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/node/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/node/BUILD.bazel @@ -12,13 +12,13 @@ go_library( "//beacon-chain/p2p:go_default_library", "//beacon-chain/sync:go_default_library", "//io/logs:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_golang_protobuf//ptypes/empty", "@com_github_golang_protobuf//ptypes/timestamp", "@com_github_libp2p_go_libp2p//core/network:go_default_library", "@com_github_libp2p_go_libp2p//core/peer:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//metadata:go_default_library", @@ -47,9 +47,7 @@ go_test( "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//crypto:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enode:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", "@org_golang_google_grpc//:go_default_library", - "@org_golang_google_grpc//metadata:go_default_library", "@org_golang_google_grpc//reflection:go_default_library", "@org_golang_google_protobuf//types/known/emptypb:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", diff --git a/beacon-chain/rpc/prysm/v1alpha1/node/server.go b/beacon-chain/rpc/prysm/v1alpha1/node/server.go index 67c3b863f8c1..135d08ee37e2 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/node/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/node/server.go @@ -21,9 +21,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync" "github.com/prysmaticlabs/prysm/v5/io/logs" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" diff --git a/beacon-chain/rpc/prysm/v1alpha1/node/server_test.go b/beacon-chain/rpc/prysm/v1alpha1/node/server_test.go index 1d99a2e7b3ab..cd5ed7813354 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/node/server_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/node/server_test.go @@ -3,14 +3,12 @@ package node import ( "context" "errors" - "fmt" "testing" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/p2p/enode" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" mock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" dbutil "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" @@ -24,7 +22,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" "google.golang.org/grpc" - "google.golang.org/grpc/metadata" "google.golang.org/grpc/reflection" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" @@ -92,8 +89,9 @@ func TestNodeServer_GetImplementedServices(t *testing.T) { res, err := ns.ListImplementedServices(context.Background(), &emptypb.Empty{}) require.NoError(t, err) - // We verify the services include the node service + the registered reflection service. - assert.Equal(t, 2, len(res.Services)) + // Expecting node service and Server reflect. As of grpc, v1.65.0, there are two version of server reflection + // Services: [ethereum.eth.v1alpha1.Node grpc.reflection.v1.ServerReflection grpc.reflection.v1alpha.ServerReflection] + assert.Equal(t, 3, len(res.Services)) } func TestNodeServer_GetHost(t *testing.T) { @@ -128,13 +126,12 @@ func TestNodeServer_GetPeer(t *testing.T) { } ethpb.RegisterNodeServer(server, ns) reflection.Register(server) - firstPeer := peersProvider.Peers().All()[0] - res, err := ns.GetPeer(context.Background(), ðpb.PeerRequest{PeerId: firstPeer.String()}) + res, err := ns.GetPeer(context.Background(), ðpb.PeerRequest{PeerId: mockP2p.MockRawPeerId0}) require.NoError(t, err) - assert.Equal(t, firstPeer.String(), res.PeerId, "Unexpected peer ID") + assert.Equal(t, "16Uiu2HAkyWZ4Ni1TpvDS8dPxsozmHY85KaiFjodQuV6Tz5tkHVeR" /* first peer's raw id */, res.PeerId, "Unexpected peer ID") assert.Equal(t, int(ethpb.PeerDirection_INBOUND), int(res.Direction), "Expected 1st peer to be an inbound connection") - assert.Equal(t, ethpb.ConnectionState_CONNECTED, res.ConnectionState, "Expected peer to be connected") + assert.Equal(t, int(ethpb.ConnectionState_CONNECTED), int(res.ConnectionState), "Expected peer to be connected") } func TestNodeServer_ListPeers(t *testing.T) { @@ -149,8 +146,25 @@ func TestNodeServer_ListPeers(t *testing.T) { res, err := ns.ListPeers(context.Background(), &emptypb.Empty{}) require.NoError(t, err) assert.Equal(t, 2, len(res.Peers)) - assert.Equal(t, int(ethpb.PeerDirection_INBOUND), int(res.Peers[0].Direction)) - assert.Equal(t, ethpb.PeerDirection_OUTBOUND, res.Peers[1].Direction) + + var ( + firstPeer *ethpb.Peer + secondPeer *ethpb.Peer + ) + + for _, p := range res.Peers { + if p.PeerId == mockP2p.MockRawPeerId0 { + firstPeer = p + } + if p.PeerId == mockP2p.MockRawPeerId1 { + secondPeer = p + } + } + + assert.NotNil(t, firstPeer) + assert.NotNil(t, secondPeer) + assert.Equal(t, int(ethpb.PeerDirection_INBOUND), int(firstPeer.Direction)) + assert.Equal(t, int(ethpb.PeerDirection_OUTBOUND), int(secondPeer.Direction)) } func TestNodeServer_GetETH1ConnectionStatus(t *testing.T) { @@ -190,11 +204,6 @@ func TestNodeServer_GetHealth(t *testing.T) { input: &mockSync.Sync{IsSyncing: false}, wantedErr: "service unavailable", }, - { - name: "custom sync status", - input: &mockSync.Sync{IsSyncing: true}, - customStatus: 206, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -204,21 +213,11 @@ func TestNodeServer_GetHealth(t *testing.T) { } ethpb.RegisterNodeServer(server, ns) reflection.Register(server) - ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) - _, err := ns.GetHealth(ctx, ðpb.HealthRequest{SyncingStatus: tt.customStatus}) + _, err := ns.GetHealth(context.Background(), ðpb.HealthRequest{SyncingStatus: tt.customStatus}) if tt.wantedErr == "" { require.NoError(t, err) return } - if tt.customStatus != 0 { - // Assuming the call was successful, now extract the headers - headers, _ := metadata.FromIncomingContext(ctx) - // Check for the specific header - values, ok := headers["x-http-code"] - require.Equal(t, true, ok && len(values) > 0) - require.Equal(t, fmt.Sprintf("%d", tt.customStatus), values[0]) - - } require.ErrorContains(t, tt.wantedErr, err) }) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel index 34ef244e1977..4eb081712a47 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/BUILD.bazel @@ -79,6 +79,7 @@ go_library( "//encoding/ssz:go_default_library", "//math:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/forks:go_default_library", "//proto/engine/v1:go_default_library", "//proto/eth/v1:go_default_library", @@ -211,7 +212,9 @@ go_test( embed = [":go_default_library"], eth_network = "minimal", tags = ["minimal"], - deps = common_deps, + deps = common_deps + [ + "//beacon-chain/operations/attestations/mock:go_default_library", + ], ) go_test( diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator.go b/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator.go index 4376d0cab058..77aa570af3de 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/aggregator.go @@ -3,14 +3,16 @@ package validator import ( "context" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -21,65 +23,25 @@ import ( func (vs *Server) SubmitAggregateSelectionProof(ctx context.Context, req *ethpb.AggregateSelectionRequest) (*ethpb.AggregateSelectionResponse, error) { ctx, span := trace.StartSpan(ctx, "AggregatorServer.SubmitAggregateSelectionProof") defer span.End() - span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot))) + span.SetAttributes(trace.Int64Attribute("slot", int64(req.Slot))) - if vs.SyncChecker.Syncing() { - return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond") - } - - // An optimistic validator MUST NOT participate in attestation - // (i.e., sign across the DOMAIN_BEACON_ATTESTER, DOMAIN_SELECTION_PROOF or DOMAIN_AGGREGATE_AND_PROOF domains). - if err := vs.optimisticStatus(ctx); err != nil { - return nil, err - } - - st, err := vs.HeadFetcher.HeadStateReadOnly(ctx) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not determine head state: %v", err) - } - - validatorIndex, exists := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(req.PublicKey)) - if !exists { - return nil, status.Error(codes.Internal, "Could not locate validator index in DB") - } - - epoch := slots.ToEpoch(req.Slot) - activeValidatorIndices, err := helpers.ActiveValidatorIndices(ctx, st, epoch) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not get validators: %v", err) - } - seed, err := helpers.Seed(st, epoch, params.BeaconConfig().DomainBeaconAttester) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not get seed: %v", err) - } - committee, err := helpers.BeaconCommittee(ctx, activeValidatorIndices, seed, req.Slot, req.CommitteeIndex) + indexInCommittee, validatorIndex, err := vs.processAggregateSelection(ctx, req) if err != nil { return nil, err } - // Check if the validator is an aggregator - isAggregator, err := helpers.IsAggregator(uint64(len(committee)), req.SlotSignature) - if err != nil { - return nil, status.Errorf(codes.Internal, "Could not get aggregator status: %v", err) - } - if !isAggregator { - return nil, status.Errorf(codes.InvalidArgument, "Validator is not an aggregator") - } + var atts []*ethpb.Attestation - atts := vs.AttPool.AggregatedAttestationsBySlotIndex(ctx, req.Slot, req.CommitteeIndex) - // Filter out the best aggregated attestation (ie. the one with the most aggregated bits). - if len(atts) == 0 { - atts = vs.AttPool.UnaggregatedAttestationsBySlotIndex(ctx, req.Slot, req.CommitteeIndex) + if features.Get().EnableExperimentalAttestationPool { + atts = cache.GetBySlotAndCommitteeIndex[*ethpb.Attestation](vs.AttestationCache, req.Slot, req.CommitteeIndex) + } else { + atts = vs.AttPool.AggregatedAttestationsBySlotIndex(ctx, req.Slot, req.CommitteeIndex) if len(atts) == 0 { - return nil, status.Errorf(codes.NotFound, "Could not find attestation for slot and committee in pool") + atts = vs.AttPool.UnaggregatedAttestationsBySlotIndex(ctx, req.Slot, req.CommitteeIndex) } } - - var indexInCommittee uint64 - for i, idx := range committee { - if idx == validatorIndex { - indexInCommittee = uint64(i) - } + if len(atts) == 0 { + return nil, status.Errorf(codes.NotFound, "Could not find attestation for slot and committee in pool") } best := bestAggregate(atts, req.CommitteeIndex, indexInCommittee) @@ -100,57 +62,78 @@ func (vs *Server) SubmitAggregateSelectionProofElectra( ) (*ethpb.AggregateSelectionElectraResponse, error) { ctx, span := trace.StartSpan(ctx, "AggregatorServer.SubmitAggregateSelectionProofElectra") defer span.End() - span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot))) + span.SetAttributes(trace.Int64Attribute("slot", int64(req.Slot))) + + indexInCommittee, validatorIndex, err := vs.processAggregateSelection(ctx, req) + if err != nil { + return nil, err + } + + var atts []*ethpb.AttestationElectra + if features.Get().EnableExperimentalAttestationPool { + atts = cache.GetBySlotAndCommitteeIndex[*ethpb.AttestationElectra](vs.AttestationCache, req.Slot, req.CommitteeIndex) + } else { + atts = vs.AttPool.AggregatedAttestationsBySlotIndexElectra(ctx, req.Slot, req.CommitteeIndex) + if len(atts) == 0 { + atts = vs.AttPool.UnaggregatedAttestationsBySlotIndexElectra(ctx, req.Slot, req.CommitteeIndex) + } + } + if len(atts) == 0 { + return nil, status.Errorf(codes.NotFound, "Could not find attestation for slot and committee in pool") + } + + best := bestAggregate(atts, req.CommitteeIndex, indexInCommittee) + attAndProof := ðpb.AggregateAttestationAndProofElectra{ + Aggregate: best, + SelectionProof: req.SlotSignature, + AggregatorIndex: validatorIndex, + } + return ðpb.AggregateSelectionElectraResponse{AggregateAndProof: attAndProof}, nil +} + +func (vs *Server) processAggregateSelection(ctx context.Context, req *ethpb.AggregateSelectionRequest) (uint64, primitives.ValidatorIndex, error) { if vs.SyncChecker.Syncing() { - return nil, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond") + return 0, 0, status.Errorf(codes.Unavailable, "Syncing to latest head, not ready to respond") } // An optimistic validator MUST NOT participate in attestation // (i.e., sign across the DOMAIN_BEACON_ATTESTER, DOMAIN_SELECTION_PROOF or DOMAIN_AGGREGATE_AND_PROOF domains). if err := vs.optimisticStatus(ctx); err != nil { - return nil, err + return 0, 0, err } st, err := vs.HeadFetcher.HeadStateReadOnly(ctx) if err != nil { - return nil, status.Errorf(codes.Internal, "Could not determine head state: %v", err) + return 0, 0, status.Errorf(codes.Internal, "Could not determine head state: %v", err) } validatorIndex, exists := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(req.PublicKey)) if !exists { - return nil, status.Error(codes.Internal, "Could not locate validator index in DB") + return 0, 0, status.Error(codes.Internal, "Could not locate validator index in DB") } epoch := slots.ToEpoch(req.Slot) activeValidatorIndices, err := helpers.ActiveValidatorIndices(ctx, st, epoch) if err != nil { - return nil, status.Errorf(codes.Internal, "Could not get validators: %v", err) + return 0, 0, status.Errorf(codes.Internal, "Could not get validators: %v", err) } seed, err := helpers.Seed(st, epoch, params.BeaconConfig().DomainBeaconAttester) if err != nil { - return nil, status.Errorf(codes.Internal, "Could not get seed: %v", err) + return 0, 0, status.Errorf(codes.Internal, "Could not get seed: %v", err) } committee, err := helpers.BeaconCommittee(ctx, activeValidatorIndices, seed, req.Slot, req.CommitteeIndex) if err != nil { - return nil, err + return 0, 0, err } // Check if the validator is an aggregator isAggregator, err := helpers.IsAggregator(uint64(len(committee)), req.SlotSignature) if err != nil { - return nil, status.Errorf(codes.Internal, "Could not get aggregator status: %v", err) + return 0, 0, status.Errorf(codes.Internal, "Could not get aggregator status: %v", err) } if !isAggregator { - return nil, status.Errorf(codes.InvalidArgument, "Validator is not an aggregator") - } - - atts := vs.AttPool.AggregatedAttestationsBySlotIndexElectra(ctx, req.Slot, req.CommitteeIndex) - if len(atts) == 0 { - atts = vs.AttPool.UnaggregatedAttestationsBySlotIndexElectra(ctx, req.Slot, req.CommitteeIndex) - if len(atts) == 0 { - return nil, status.Errorf(codes.NotFound, "No attestations found in pool") - } + return 0, 0, status.Errorf(codes.InvalidArgument, "Validator is not an aggregator") } var indexInCommittee uint64 @@ -159,14 +142,7 @@ func (vs *Server) SubmitAggregateSelectionProofElectra( indexInCommittee = uint64(i) } } - - best := bestAggregate(atts, req.CommitteeIndex, indexInCommittee) - attAndProof := ðpb.AggregateAttestationAndProofElectra{ - Aggregate: best, - SelectionProof: req.SlotSignature, - AggregatorIndex: validatorIndex, - } - return ðpb.AggregateSelectionElectraResponse{AggregateAndProof: attAndProof}, nil + return indexInCommittee, validatorIndex, nil } // SubmitSignedAggregateSelectionProof is called by a validator to broadcast a signed diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go index 26ab6d7c7586..342bac44e16c 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester.go @@ -8,11 +8,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" @@ -23,7 +24,7 @@ import ( func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.AttestationDataRequest) (*ethpb.AttestationData, error) { ctx, span := trace.StartSpan(ctx, "AttesterServer.RequestAttestation") defer span.End() - span.AddAttributes( + span.SetAttributes( trace.Int64Attribute("slot", int64(req.Slot)), trace.Int64Attribute("committeeIndex", int64(req.CommitteeIndex)), ) @@ -49,47 +50,57 @@ func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation return nil, err } - go func() { - attCopy := att.Copy() - if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy); err != nil { - log.WithError(err).Error("Could not save unaggregated attestation") - return + if features.Get().EnableExperimentalAttestationPool { + if err = vs.AttestationCache.Add(att); err != nil { + log.WithError(err).Error("Could not save attestation") } - }() + } else { + go func() { + attCopy := att.Copy() + if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy); err != nil { + log.WithError(err).Error("Could not save unaggregated attestation") + return + } + }() + } return resp, nil } // ProposeAttestationElectra is a function called by an attester to vote // on a block via an attestation object as defined in the Ethereum specification. -func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) { +func (vs *Server) ProposeAttestationElectra(ctx context.Context, singleAtt *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestationElectra") defer span.End() - if att.GetData().CommitteeIndex != 0 { - return nil, status.Errorf(codes.InvalidArgument, "Committee index must be set to 0") - } - committeeIndices := helpers.CommitteeIndices(att.CommitteeBits) - if len(committeeIndices) == 0 { - return nil, status.Errorf(codes.InvalidArgument, "Committee bits has no bit set") - } - if len(committeeIndices) > 1 { - return nil, status.Errorf(codes.InvalidArgument, "Committee bits has more than one bit set") + resp, err := vs.proposeAtt(ctx, singleAtt, singleAtt.GetCommitteeIndex()) + if err != nil { + return nil, err } - resp, err := vs.proposeAtt(ctx, att, committeeIndices[0]) + targetState, err := vs.AttestationStateFetcher.AttestationTargetState(ctx, singleAtt.Data.Target) if err != nil { - return nil, err + return nil, status.Error(codes.Internal, "Could not get target state") + } + committee, err := helpers.BeaconCommitteeFromState(ctx, targetState, singleAtt.Data.Slot, singleAtt.GetCommitteeIndex()) + if err != nil { + return nil, status.Error(codes.Internal, "Could not get committee") } - go func() { - ctx = trace.NewContext(context.Background(), trace.FromContext(ctx)) - attCopy := att.Copy() - if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy); err != nil { - log.WithError(err).Error("Could not save unaggregated attestation") - return + singleAttCopy := singleAtt.Copy() + att := singleAttCopy.ToAttestationElectra(committee) + if features.Get().EnableExperimentalAttestationPool { + if err = vs.AttestationCache.Add(att); err != nil { + log.WithError(err).Error("Could not save attestation") } - }() + } else { + go func() { + if err := vs.AttPool.SaveUnaggregatedAttestation(att); err != nil { + log.WithError(err).Error("Could not save unaggregated attestation") + return + } + }() + } return resp, nil } @@ -142,24 +153,37 @@ func (vs *Server) SubscribeCommitteeSubnets(ctx context.Context, req *ethpb.Comm return &emptypb.Empty{}, nil } -func (vs *Server) proposeAtt(ctx context.Context, att ethpb.Att, committee primitives.CommitteeIndex) (*ethpb.AttestResponse, error) { +func (vs *Server) proposeAtt( + ctx context.Context, + att ethpb.Att, + committeeIndex primitives.CommitteeIndex, +) (*ethpb.AttestResponse, error) { if _, err := bls.SignatureFromBytes(att.GetSignature()); err != nil { return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature") } root, err := att.GetData().HashTreeRoot() if err != nil { - return nil, status.Errorf(codes.Internal, "Could not tree hash attestation: %v", err) + return nil, status.Errorf(codes.Internal, "Could not get attestation root: %v", err) } // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node // of a received unaggregated attestation. - vs.OperationNotifier.OperationFeed().Send(&feed.Event{ - Type: operation.UnaggregatedAttReceived, - Data: &operation.UnAggregatedAttReceivedData{ - Attestation: att, - }, - }) + if att.IsSingle() { + vs.OperationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.SingleAttReceived, + Data: &operation.SingleAttReceivedData{ + Attestation: att, + }, + }) + } else { + vs.OperationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.UnaggregatedAttReceived, + Data: &operation.UnAggregatedAttReceivedData{ + Attestation: att, + }, + }) + } // Determine subnet to broadcast attestation to wantedEpoch := slots.ToEpoch(att.GetData().Slot) @@ -167,7 +191,7 @@ func (vs *Server) proposeAtt(ctx context.Context, att ethpb.Att, committee primi if err != nil { return nil, err } - subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committee, att.GetData().Slot) + subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committeeIndex, att.GetData().Slot) // Broadcast the new attestation to the network. if err := vs.P2P.BroadcastAttestation(ctx, subnet, att); err != nil { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_mainnet_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_mainnet_test.go index 3d05ef48ca80..5a7356e6d8ce 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_mainnet_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_mainnet_test.go @@ -65,7 +65,7 @@ func TestAttestationDataAtSlot_HandlesFarAwayJustifiedEpoch(t *testing.T) { OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)}, CoreService: &core.Service{ - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), HeadFetcher: &mock.ChainService{TargetRoot: blockRoot, Root: blockRoot[:], State: beaconState}, GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)}, FinalizedFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: justifiedCheckpoint}, diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go index 6fe5e884d4f9..6a5bab8c9bb4 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/attester_test.go @@ -31,11 +31,13 @@ import ( ) func TestProposeAttestation(t *testing.T) { + chainService := &mock.ChainService{} attesterServer := &Server{ - HeadFetcher: &mock.ChainService{}, - P2P: &mockp2p.MockBroadcaster{}, - AttPool: attestations.NewPool(), - OperationNotifier: (&mock.ChainService{}).OperationNotifier(), + HeadFetcher: chainService, + P2P: &mockp2p.MockBroadcaster{}, + AttPool: attestations.NewPool(), + OperationNotifier: (&mock.ChainService{}).OperationNotifier(), + AttestationStateFetcher: chainService, } head := util.NewBeaconBlock() head.Block.Slot = 999 @@ -79,81 +81,19 @@ func TestProposeAttestation(t *testing.T) { require.NoError(t, err) require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) require.NoError(t, state.SetValidators(validators)) + chainService.State = state - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(0, true) - req := ðpb.AttestationElectra{ + req := ðpb.SingleAttestation{ Signature: sig.Marshal(), Data: ðpb.AttestationData{ BeaconBlockRoot: root[:], Source: ðpb.Checkpoint{Root: make([]byte, 32)}, Target: ðpb.Checkpoint{Root: make([]byte, 32)}, }, - CommitteeBits: cb, } _, err = attesterServer.ProposeAttestationElectra(context.Background(), req) assert.NoError(t, err) }) - t.Run("Electra - non-zero committee index", func(t *testing.T) { - state, err := util.NewBeaconStateElectra() - require.NoError(t, err) - require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) - require.NoError(t, state.SetValidators(validators)) - - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(0, true) - req := ðpb.AttestationElectra{ - Signature: sig.Marshal(), - Data: ðpb.AttestationData{ - BeaconBlockRoot: root[:], - Source: ðpb.Checkpoint{Root: make([]byte, 32)}, - Target: ðpb.Checkpoint{Root: make([]byte, 32)}, - CommitteeIndex: 1, - }, - CommitteeBits: cb, - } - _, err = attesterServer.ProposeAttestationElectra(context.Background(), req) - assert.ErrorContains(t, "Committee index must be set to 0", err) - }) - t.Run("Electra - no committee bit set", func(t *testing.T) { - state, err := util.NewBeaconStateElectra() - require.NoError(t, err) - require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) - require.NoError(t, state.SetValidators(validators)) - - req := ðpb.AttestationElectra{ - Signature: sig.Marshal(), - Data: ðpb.AttestationData{ - BeaconBlockRoot: root[:], - Source: ðpb.Checkpoint{Root: make([]byte, 32)}, - Target: ðpb.Checkpoint{Root: make([]byte, 32)}, - }, - CommitteeBits: primitives.NewAttestationCommitteeBits(), - } - _, err = attesterServer.ProposeAttestationElectra(context.Background(), req) - assert.ErrorContains(t, "Committee bits has no bit set", err) - }) - t.Run("Electra - multiple committee bits set", func(t *testing.T) { - state, err := util.NewBeaconStateElectra() - require.NoError(t, err) - require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) - require.NoError(t, state.SetValidators(validators)) - - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(0, true) - cb.SetBitAt(1, true) - req := ðpb.AttestationElectra{ - Signature: sig.Marshal(), - Data: ðpb.AttestationData{ - BeaconBlockRoot: root[:], - Source: ðpb.Checkpoint{Root: make([]byte, 32)}, - Target: ðpb.Checkpoint{Root: make([]byte, 32)}, - }, - CommitteeBits: cb, - } - _, err = attesterServer.ProposeAttestationElectra(context.Background(), req) - assert.ErrorContains(t, "Committee bits has more than one bit set", err) - }) } func TestProposeAttestation_IncorrectSignature(t *testing.T) { @@ -204,7 +144,7 @@ func TestGetAttestationData_OK(t *testing.T) { Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second), }, FinalizedFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: justifiedCheckpoint}, - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, }, } @@ -259,7 +199,7 @@ func BenchmarkGetAttestationDataConcurrent(b *testing.B) { OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, TimeFetcher: &mock.ChainService{Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second)}, CoreService: &core.Service{ - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), HeadFetcher: &mock.ChainService{TargetRoot: targetRoot, Root: blockRoot[:]}, GenesisTimeFetcher: &mock.ChainService{ Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second), @@ -313,7 +253,7 @@ func TestGetAttestationData_Optimistic(t *testing.T) { CoreService: &core.Service{ GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now()}, HeadFetcher: &mock.ChainService{}, - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), OptimisticModeFetcher: &mock.ChainService{Optimistic: true}, }, } @@ -330,7 +270,7 @@ func TestGetAttestationData_Optimistic(t *testing.T) { OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, TimeFetcher: &mock.ChainService{Genesis: time.Now()}, CoreService: &core.Service{ - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), GenesisTimeFetcher: &mock.ChainService{Genesis: time.Now()}, HeadFetcher: &mock.ChainService{Optimistic: false, State: beaconState}, FinalizedFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: ðpb.Checkpoint{}}, @@ -440,7 +380,7 @@ func TestGetAttestationData_SucceedsInFirstEpoch(t *testing.T) { OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, TimeFetcher: &mock.ChainService{Genesis: prysmTime.Now().Add(time.Duration(-1*offset) * time.Second)}, CoreService: &core.Service{ - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), HeadFetcher: &mock.ChainService{ TargetRoot: targetRoot, Root: blockRoot[:], State: beaconState, }, @@ -514,7 +454,7 @@ func TestGetAttestationData_CommitteeIndexIsZeroPostElectra(t *testing.T) { Genesis: time.Now().Add(time.Duration(-1*offset) * time.Second), }, FinalizedFetcher: &mock.ChainService{CurrentJustifiedCheckPoint: justifiedCheckpoint}, - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), OptimisticModeFetcher: &mock.ChainService{Optimistic: false}, }, } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/blocks.go b/beacon-chain/rpc/prysm/v1alpha1/validator/blocks.go index 49f13afcb8db..7ac22d33395f 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/blocks.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/blocks.go @@ -170,6 +170,17 @@ func sendVerifiedBlocks(stream ethpb.BeaconNodeValidator_StreamBlocksAltairServe return nil } b.Block = ðpb.StreamBlocksResponse_ElectraBlock{ElectraBlock: phBlk} + case version.Fulu: + pb, err := data.SignedBlock.Proto() + if err != nil { + return errors.Wrap(err, "could not get protobuf block") + } + phBlk, ok := pb.(*ethpb.SignedBeaconBlockFulu) + if !ok { + log.Warn("Mismatch between version and block type, was expecting SignedBeaconBlockFulu") + return nil + } + b.Block = ðpb.StreamBlocksResponse_FuluBlock{FuluBlock: phBlk} } if err := stream.Send(b); err != nil { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/construct_generic_block.go b/beacon-chain/rpc/prysm/v1alpha1/validator/construct_generic_block.go index a4510e69eead..e9745103daeb 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/construct_generic_block.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/construct_generic_block.go @@ -26,34 +26,46 @@ func (vs *Server) constructGenericBeaconBlock(sBlk interfaces.SignedBeaconBlock, bidStr := primitives.WeiToBigInt(winningBid).String() switch sBlk.Version() { - case version.Electra: - return vs.constructElectraBlock(blockProto, isBlinded, bidStr, blobsBundle), nil - case version.Deneb: - return vs.constructDenebBlock(blockProto, isBlinded, bidStr, blobsBundle), nil - case version.Capella: - return vs.constructCapellaBlock(blockProto, isBlinded, bidStr), nil - case version.Bellatrix: - return vs.constructBellatrixBlock(blockProto, isBlinded, bidStr), nil - case version.Altair: - return vs.constructAltairBlock(blockProto), nil case version.Phase0: return vs.constructPhase0Block(blockProto), nil + case version.Altair: + return vs.constructAltairBlock(blockProto), nil + case version.Bellatrix: + return vs.constructBellatrixBlock(blockProto, isBlinded, bidStr), nil + case version.Capella: + return vs.constructCapellaBlock(blockProto, isBlinded, bidStr), nil + case version.Deneb: + return vs.constructDenebBlock(blockProto, isBlinded, bidStr, blobsBundle), nil + case version.Electra: + return vs.constructElectraBlock(blockProto, isBlinded, bidStr, blobsBundle), nil + case version.Fulu: + return vs.constructFuluBlock(blockProto, isBlinded, bidStr, blobsBundle), nil default: return nil, fmt.Errorf("unknown block version: %d", sBlk.Version()) } } // Helper functions for constructing blocks for each version -func (vs *Server) constructElectraBlock(blockProto proto.Message, isBlinded bool, payloadValue string, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock { +func (vs *Server) constructPhase0Block(pb proto.Message) *ethpb.GenericBeaconBlock { + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: pb.(*ethpb.BeaconBlock)}} +} + +func (vs *Server) constructAltairBlock(pb proto.Message) *ethpb.GenericBeaconBlock { + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: pb.(*ethpb.BeaconBlockAltair)}} +} + +func (vs *Server) constructBellatrixBlock(pb proto.Message, isBlinded bool, payloadValue string) *ethpb.GenericBeaconBlock { if isBlinded { - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedElectra{BlindedElectra: blockProto.(*ethpb.BlindedBeaconBlockElectra)}, IsBlinded: true, PayloadValue: payloadValue} + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: pb.(*ethpb.BlindedBeaconBlockBellatrix)}, IsBlinded: true, PayloadValue: payloadValue} } - electraContents := ðpb.BeaconBlockContentsElectra{Block: blockProto.(*ethpb.BeaconBlockElectra)} - if bundle != nil { - electraContents.KzgProofs = bundle.Proofs - electraContents.Blobs = bundle.Blobs + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}, IsBlinded: false, PayloadValue: payloadValue} +} + +func (vs *Server) constructCapellaBlock(pb proto.Message, isBlinded bool, payloadValue string) *ethpb.GenericBeaconBlock { + if isBlinded { + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: pb.(*ethpb.BlindedBeaconBlockCapella)}, IsBlinded: true, PayloadValue: payloadValue} } - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Electra{Electra: electraContents}, IsBlinded: false, PayloadValue: payloadValue} + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}, IsBlinded: false, PayloadValue: payloadValue} } func (vs *Server) constructDenebBlock(blockProto proto.Message, isBlinded bool, payloadValue string, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock { @@ -68,24 +80,26 @@ func (vs *Server) constructDenebBlock(blockProto proto.Message, isBlinded bool, return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Deneb{Deneb: denebContents}, IsBlinded: false, PayloadValue: payloadValue} } -func (vs *Server) constructCapellaBlock(pb proto.Message, isBlinded bool, payloadValue string) *ethpb.GenericBeaconBlock { +func (vs *Server) constructElectraBlock(blockProto proto.Message, isBlinded bool, payloadValue string, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock { if isBlinded { - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: pb.(*ethpb.BlindedBeaconBlockCapella)}, IsBlinded: true, PayloadValue: payloadValue} + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedElectra{BlindedElectra: blockProto.(*ethpb.BlindedBeaconBlockElectra)}, IsBlinded: true, PayloadValue: payloadValue} } - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: pb.(*ethpb.BeaconBlockCapella)}, IsBlinded: false, PayloadValue: payloadValue} + electraContents := ðpb.BeaconBlockContentsElectra{Block: blockProto.(*ethpb.BeaconBlockElectra)} + if bundle != nil { + electraContents.KzgProofs = bundle.Proofs + electraContents.Blobs = bundle.Blobs + } + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Electra{Electra: electraContents}, IsBlinded: false, PayloadValue: payloadValue} } -func (vs *Server) constructBellatrixBlock(pb proto.Message, isBlinded bool, payloadValue string) *ethpb.GenericBeaconBlock { +func (vs *Server) constructFuluBlock(blockProto proto.Message, isBlinded bool, payloadValue string, bundle *enginev1.BlobsBundle) *ethpb.GenericBeaconBlock { if isBlinded { - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: pb.(*ethpb.BlindedBeaconBlockBellatrix)}, IsBlinded: true, PayloadValue: payloadValue} + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedFulu{BlindedFulu: blockProto.(*ethpb.BlindedBeaconBlockFulu)}, IsBlinded: true, PayloadValue: payloadValue} } - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: pb.(*ethpb.BeaconBlockBellatrix)}, IsBlinded: false, PayloadValue: payloadValue} -} - -func (vs *Server) constructAltairBlock(pb proto.Message) *ethpb.GenericBeaconBlock { - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: pb.(*ethpb.BeaconBlockAltair)}} -} - -func (vs *Server) constructPhase0Block(pb proto.Message) *ethpb.GenericBeaconBlock { - return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: pb.(*ethpb.BeaconBlock)}} + fuluContents := ðpb.BeaconBlockContentsFulu{Block: blockProto.(*ethpb.BeaconBlockElectra)} + if bundle != nil { + fuluContents.KzgProofs = bundle.Proofs + fuluContents.Blobs = bundle.Blobs + } + return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Fulu{Fulu: fuluContents}, IsBlinded: false, PayloadValue: payloadValue} } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/construct_generic_block_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/construct_generic_block_test.go index 9a8365d3c0fa..7a037da0c7f8 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/construct_generic_block_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/construct_generic_block_test.go @@ -22,6 +22,21 @@ func TestConstructGenericBeaconBlock(t *testing.T) { require.ErrorContains(t, "block cannot be nil", err) }) + // Test for Fulu version + t.Run("fulu block", func(t *testing.T) { + eb := util.NewBeaconBlockFulu() + b, err := blocks.NewSignedBeaconBlock(eb) + require.NoError(t, err) + r1, err := eb.Block.HashTreeRoot() + require.NoError(t, err) + result, err := vs.constructGenericBeaconBlock(b, nil, primitives.ZeroWei()) + require.NoError(t, err) + r2, err := result.GetFulu().Block.HashTreeRoot() + require.NoError(t, err) + require.Equal(t, r1, r2) + require.Equal(t, result.IsBlinded, false) + }) + // Test for Electra version t.Run("electra block", func(t *testing.T) { eb := util.NewBeaconBlockElectra() @@ -69,7 +84,6 @@ func TestConstructGenericBeaconBlock(t *testing.T) { require.Equal(t, result.IsBlinded, false) }) - // Test for blind Deneb version t.Run("blind deneb block", func(t *testing.T) { b, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockDeneb()) require.NoError(t, err) @@ -99,7 +113,6 @@ func TestConstructGenericBeaconBlock(t *testing.T) { require.Equal(t, result.IsBlinded, false) }) - // Test for blind Capella version t.Run("blind capella block", func(t *testing.T) { b, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella()) require.NoError(t, err) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go index 6faba0afd60e..3c60fb263261 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go @@ -26,12 +26,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "golang.org/x/sync/errgroup" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -50,7 +50,7 @@ const ( func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error) { ctx, span := trace.StartSpan(ctx, "ProposerServer.GetBeaconBlock") defer span.End() - span.AddAttributes(trace.Int64Attribute("slot", int64(req.Slot))) + span.SetAttributes(trace.Int64Attribute("slot", int64(req.Slot))) t, err := slots.ToTime(uint64(vs.TimeFetcher.GenesisTime().Unix()), req.Slot) if err != nil { @@ -99,14 +99,18 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) ( } resp, err := vs.BuildBlockParallel(ctx, sBlk, head, req.SkipMevBoost, builderBoostFactor) - log.WithFields(logrus.Fields{ + log := log.WithFields(logrus.Fields{ "slot": req.Slot, "sinceSlotStartTime": time.Since(t), "validator": sBlk.Block().ProposerIndex(), - }).Info("Finished building block") + }) + if err != nil { + log.WithError(err).Error("Finished building block") return nil, errors.Wrap(err, "could not build block in parallel") } + + log.Info("Finished building block") return resp, nil } @@ -236,7 +240,12 @@ func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.Signed // There's no reason to try to get a builder bid if local override is true. var builderBid builderapi.Bid if !(local.OverrideBuilder || skipMevBoost) { - builderBid, err = vs.getBuilderPayloadAndBlobs(ctx, sBlk.Block().Slot(), sBlk.Block().ProposerIndex()) + latestHeader, err := head.LatestExecutionPayloadHeader() + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not get latest execution payload header: %v", err) + } + parentGasLimit := latestHeader.GasLimit() + builderBid, err = vs.getBuilderPayloadAndBlobs(ctx, sBlk.Block().Slot(), sBlk.Block().ProposerIndex(), parentGasLimit) if err != nil { builderGetPayloadMissCount.Inc() log.WithError(err).Error("Could not get builder payload") @@ -277,8 +286,8 @@ func (vs *Server) ProposeBeaconBlock(ctx context.Context, req *ethpb.GenericSign var sidecars []*ethpb.BlobSidecar if block.IsBlinded() { block, sidecars, err = vs.handleBlindedBlock(ctx, block) - } else { - sidecars, err = vs.handleUnblindedBlock(block, req) + } else if block.Version() >= version.Deneb { + sidecars, err = vs.blobSidecarsFromUnblindedBlock(block, req) } if err != nil { return nil, status.Errorf(codes.Internal, "%s: %v", "handle block failed", err) @@ -339,19 +348,18 @@ func (vs *Server) handleBlindedBlock(ctx context.Context, block interfaces.Signe sidecars, err := unblindBlobsSidecars(copiedBlock, bundle) if err != nil { - return nil, nil, errors.Wrap(err, "unblind sidecars failed") + return nil, nil, errors.Wrap(err, "unblind blobs sidecars: commitment value doesn't match block") } return copiedBlock, sidecars, nil } -// handleUnblindedBlock processes unblinded beacon blocks. -func (vs *Server) handleUnblindedBlock(block interfaces.SignedBeaconBlock, req *ethpb.GenericSignedBeaconBlock) ([]*ethpb.BlobSidecar, error) { - dbBlockContents := req.GetDeneb() - if dbBlockContents == nil { - return nil, nil +func (vs *Server) blobSidecarsFromUnblindedBlock(block interfaces.SignedBeaconBlock, req *ethpb.GenericSignedBeaconBlock) ([]*ethpb.BlobSidecar, error) { + rawBlobs, proofs, err := blobsAndProofs(req) + if err != nil { + return nil, err } - return BuildBlobSidecars(block, dbBlockContents.Blobs, dbBlockContents.KzgProofs) + return BuildBlobSidecars(block, rawBlobs, proofs) } // broadcastReceiveBlock broadcasts a block and handles its reception. @@ -409,7 +417,7 @@ func (vs *Server) PrepareBeaconProposer( for _, r := range request.Recipients { recipient := hexutil.Encode(r.FeeRecipient) if !common.IsHexAddress(recipient) { - return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Invalid fee recipient address: %v", recipient)) + return nil, status.Errorf(codes.InvalidArgument, "Invalid fee recipient address: %v", recipient) } // Use default address if the burn address is return feeRecipient := primitives.ExecutionAddress(r.FeeRecipient) @@ -430,7 +438,7 @@ func (vs *Server) PrepareBeaconProposer( if len(validatorIndices) != 0 { log.WithFields(logrus.Fields{ "validatorCount": len(validatorIndices), - }).Info("Updated fee recipient addresses for validator indices") + }).Debug("Updated fee recipient addresses for validator indices") } return &emptypb.Empty{}, nil } @@ -462,7 +470,7 @@ func (vs *Server) GetFeeRecipientByPubKey(ctx context.Context, request *ethpb.Fe }, nil } else { log.WithError(err).Error("An error occurred while retrieving fee recipient from db") - return nil, status.Errorf(codes.Internal, err.Error()) + return nil, status.Errorf(codes.Internal, "error=%s", err) } } return ðpb.FeeRecipientByPubKeyResponse{ @@ -502,3 +510,19 @@ func (vs *Server) SubmitValidatorRegistrations(ctx context.Context, reg *ethpb.S return &emptypb.Empty{}, nil } + +func blobsAndProofs(req *ethpb.GenericSignedBeaconBlock) ([][]byte, [][]byte, error) { + switch { + case req.GetDeneb() != nil: + dbBlockContents := req.GetDeneb() + return dbBlockContents.Blobs, dbBlockContents.KzgProofs, nil + case req.GetElectra() != nil: + dbBlockContents := req.GetElectra() + return dbBlockContents.Blobs, dbBlockContents.KzgProofs, nil + case req.GetFulu() != nil: + dbBlockContents := req.GetFulu() + return dbBlockContents.Blobs, dbBlockContents.KzgProofs, nil + default: + return nil, nil, errors.Errorf("unknown request type provided: %T", req) + } +} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go index abb1564724ea..c99fdd51ca84 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_altair.go @@ -9,11 +9,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" synccontribution "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation/aggregation/sync_contribution" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) func (vs *Server) setSyncAggregate(ctx context.Context, blk interfaces.SignedBeaconBlock) { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations.go index f278b9316ab6..c1f16310a850 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations.go @@ -2,18 +2,20 @@ package validator import ( "bytes" + "cmp" "context" "fmt" + "slices" "sort" "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation/aggregation" @@ -21,7 +23,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) type proposerAtts []ethpb.Att @@ -30,21 +31,22 @@ func (vs *Server) packAttestations(ctx context.Context, latestState state.Beacon ctx, span := trace.StartSpan(ctx, "ProposerServer.packAttestations") defer span.End() - atts := vs.AttPool.AggregatedAttestations() - atts, err := vs.validateAndDeleteAttsInPool(ctx, latestState, atts) - if err != nil { - return nil, errors.Wrap(err, "could not filter attestations") - } + var atts []ethpb.Att - uAtts, err := vs.AttPool.UnaggregatedAttestations() - if err != nil { - return nil, errors.Wrap(err, "could not get unaggregated attestations") - } - uAtts, err = vs.validateAndDeleteAttsInPool(ctx, latestState, uAtts) - if err != nil { - return nil, errors.Wrap(err, "could not filter attestations") + if features.Get().EnableExperimentalAttestationPool { + atts = vs.AttestationCache.GetAll() + atts = vs.validateAndDeleteAttsInPool(ctx, latestState, atts) + } else { + atts = vs.AttPool.AggregatedAttestations() + atts = vs.validateAndDeleteAttsInPool(ctx, latestState, atts) + + uAtts, err := vs.AttPool.UnaggregatedAttestations() + if err != nil { + return nil, errors.Wrap(err, "could not get unaggregated attestations") + } + uAtts = vs.validateAndDeleteAttsInPool(ctx, latestState, uAtts) + atts = append(atts, uAtts...) } - atts = append(atts, uAtts...) // Checking the state's version here will give the wrong result if the last slot of Deneb is missed. // The head state will still be in Deneb while we are trying to build an Electra block. @@ -65,6 +67,8 @@ func (vs *Server) packAttestations(ctx context.Context, latestState state.Beacon } } + var err error + // Remove duplicates from both aggregated/unaggregated attestations. This // prevents inefficient aggregates being created. versionAtts, err = proposerAtts(versionAtts).dedup() @@ -91,14 +95,7 @@ func (vs *Server) packAttestations(ctx context.Context, latestState state.Beacon var attsForInclusion proposerAtts if postElectra { - // TODO: hack for Electra devnet-1, take only one aggregate per ID - // (which essentially means one aggregate for an attestation_data+committee combination - topAggregates := make([]ethpb.Att, 0) - for _, v := range attsById { - topAggregates = append(topAggregates, v[0]) - } - - attsForInclusion, err = computeOnChainAggregate(topAggregates) + attsForInclusion, err = onChainAggregates(attsById) if err != nil { return nil, err } @@ -113,14 +110,68 @@ func (vs *Server) packAttestations(ctx context.Context, latestState state.Beacon if err != nil { return nil, err } - sorted, err := deduped.sort() - if err != nil { - return nil, err + + var sorted proposerAtts + if postElectra { + sorted, err = deduped.sortOnChainAggregates() + if err != nil { + return nil, err + } + } else { + sorted, err = deduped.sort() + if err != nil { + return nil, err + } } + atts = sorted.limitToMaxAttestations() return vs.filterAttestationBySignature(ctx, atts, latestState) } +func onChainAggregates(attsById map[attestation.Id][]ethpb.Att) (proposerAtts, error) { + var result proposerAtts + var err error + + // When constructing on-chain aggregates, we want to combine the most profitable + // aggregate for each ID, then the second most profitable, and so on and so forth. + // Because of this we sort attestations at the beginning. + for id, as := range attsById { + attsById[id], err = proposerAtts(as).sort() + if err != nil { + return nil, err + } + } + + // We construct the first on-chain aggregate by taking the first aggregate for each ID. + // We construct the second on-chain aggregate by taking the second aggregate for each ID. + // We continue doing this until we run out of aggregates. + idx := 0 + for { + topAggregates := make([]ethpb.Att, 0, len(attsById)) + for _, as := range attsById { + // In case there are no more aggregates for an ID, we skip that ID. + if len(as) > idx { + topAggregates = append(topAggregates, as[idx]) + } + } + + // Once there are no more aggregates for any ID, we are done. + if len(topAggregates) == 0 { + break + } + + onChainAggs, err := computeOnChainAggregate(topAggregates) + if err != nil { + return nil, err + } + result = append(result, onChainAggs...) + + idx++ + } + + return result, nil +} + // filter separates attestation list into two groups: valid and invalid attestations. // The first group passes the all the required checks for attestation to be considered for proposing. // And attestations from the second group should be deleted. @@ -217,10 +268,25 @@ func (a proposerAtts) sort() (proposerAtts, error) { return a, nil } - if features.Get().EnableCommitteeAwarePacking { - return a.sortBySlotAndCommittee() + if features.Get().DisableCommitteeAwarePacking { + return a.sortByProfitabilityUsingMaxCover() } - return a.sortByProfitabilityUsingMaxCover() + return a.sortBySlotAndCommittee() +} + +func (a proposerAtts) sortOnChainAggregates() (proposerAtts, error) { + if len(a) < 2 { + return a, nil + } + + // Sort by slot first, then by bit count. + slices.SortFunc(a, func(a, b ethpb.Att) int { + return cmp.Or( + -cmp.Compare(a.GetData().Slot, b.GetData().Slot), + -cmp.Compare(a.GetAggregationBits().Count(), b.GetAggregationBits().Count())) + }) + + return a, nil } // Separate attestations by slot, as slot number takes higher precedence when sorting. @@ -231,7 +297,6 @@ func (a proposerAtts) sortBySlotAndCommittee() (proposerAtts, error) { type slotAtts struct { candidates map[primitives.CommitteeIndex]proposerAtts selected map[primitives.CommitteeIndex]proposerAtts - leftover map[primitives.CommitteeIndex]proposerAtts } var slots []primitives.Slot @@ -250,7 +315,6 @@ func (a proposerAtts) sortBySlotAndCommittee() (proposerAtts, error) { var err error for _, sa := range attsBySlot { sa.selected = make(map[primitives.CommitteeIndex]proposerAtts) - sa.leftover = make(map[primitives.CommitteeIndex]proposerAtts) for ci, committeeAtts := range sa.candidates { sa.selected[ci], err = committeeAtts.sortByProfitabilityUsingMaxCover_committeeAwarePacking() if err != nil { @@ -266,9 +330,6 @@ func (a proposerAtts) sortBySlotAndCommittee() (proposerAtts, error) { for _, slot := range slots { sortedAtts = append(sortedAtts, sortSlotAttestations(attsBySlot[slot].selected)...) } - for _, slot := range slots { - sortedAtts = append(sortedAtts, sortSlotAttestations(attsBySlot[slot].leftover)...) - } return sortedAtts, nil } @@ -287,15 +348,11 @@ func (a proposerAtts) sortByProfitabilityUsingMaxCover_committeeAwarePacking() ( return nil, err } } - // Add selected candidates on top, those that are not selected - append at bottom. selectedKeys, _, err := aggregation.MaxCover(candidates, len(candidates), true /* allowOverlaps */) if err != nil { log.WithError(err).Debug("MaxCover aggregation failed") return a, nil } - - // Pick selected attestations first, leftover attestations will be appended at the end. - // Both lists will be sorted by number of bits set. selected := make(proposerAtts, selectedKeys.Count()) for i, key := range selectedKeys.BitIndices() { selected[i] = a[key] @@ -409,15 +466,15 @@ func (a proposerAtts) dedup() (proposerAtts, error) { } // This filters the input attestations to return a list of valid attestations to be packaged inside a beacon block. -func (vs *Server) validateAndDeleteAttsInPool(ctx context.Context, st state.BeaconState, atts []ethpb.Att) ([]ethpb.Att, error) { +func (vs *Server) validateAndDeleteAttsInPool(ctx context.Context, st state.BeaconState, atts []ethpb.Att) []ethpb.Att { ctx, span := trace.StartSpan(ctx, "ProposerServer.validateAndDeleteAttsInPool") defer span.End() validAtts, invalidAtts := proposerAtts(atts).filter(ctx, st) if err := vs.deleteAttsInPool(ctx, invalidAtts); err != nil { - return nil, err + log.WithError(err).Error("Could not delete invalid attestations") } - return validAtts, nil + return validAtts } // The input attestations are processed and seen by the node, this deletes them from pool @@ -430,13 +487,19 @@ func (vs *Server) deleteAttsInPool(ctx context.Context, atts []ethpb.Att) error if ctx.Err() != nil { return ctx.Err() } - if helpers.IsAggregated(att) { - if err := vs.AttPool.DeleteAggregatedAttestation(att); err != nil { - return err + if features.Get().EnableExperimentalAttestationPool { + if err := vs.AttestationCache.DeleteCovered(att); err != nil { + return errors.Wrap(err, "could not delete attestation") } } else { - if err := vs.AttPool.DeleteUnaggregatedAttestation(att); err != nil { - return err + if att.IsAggregated() { + if err := vs.AttPool.DeleteAggregatedAttestation(att); err != nil { + return err + } + } else { + if err := vs.AttPool.DeleteUnaggregatedAttestation(att); err != nil { + return err + } } } } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go index e15df73bcaa4..4c3fb63f33e3 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go @@ -13,6 +13,9 @@ import ( // computeOnChainAggregate constructs a final aggregate form a list of network aggregates with equal attestation data. // It assumes that each network aggregate has exactly one committee bit set. // +// Our implementation allows to pass aggregates for different attestation data, in which case the function will return +// one final aggregate per attestation data. +// // Spec definition: // // def compute_on_chain_aggregate(network_aggregates: Sequence[Attestation]) -> Attestation: diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_test.go index d15cdfd7b1d9..5aeb930ca553 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_test.go @@ -3,16 +3,21 @@ package validator import ( "bytes" "context" + "math/rand" "sort" + "strconv" "testing" "github.com/prysmaticlabs/go-bitfield" chainMock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations/mock" "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls/blst" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -21,6 +26,11 @@ import ( ) func TestProposer_ProposerAtts_sort(t *testing.T) { + feat := features.Get() + feat.DisableCommitteeAwarePacking = true + reset := features.InitWithReset(feat) + defer reset() + type testData struct { slot primitives.Slot bits bitfield.Bitlist @@ -186,11 +196,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) { } t.Run("no atts", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - atts := getAtts([]testData{}) want := getAtts([]testData{}) atts, err := atts.sort() @@ -201,11 +206,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) { }) t.Run("single att", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - atts := getAtts([]testData{ {4, bitfield.Bitlist{0b11100000, 0b1}}, }) @@ -220,11 +220,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) { }) t.Run("single att per slot", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - atts := getAtts([]testData{ {1, bitfield.Bitlist{0b11000000, 0b1}}, {4, bitfield.Bitlist{0b11100000, 0b1}}, @@ -241,10 +236,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) { }) t.Run("two atts on one of the slots", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() atts := getAtts([]testData{ {1, bitfield.Bitlist{0b11000000, 0b1}}, @@ -263,11 +254,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) { }) t.Run("compare to native sort", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - // The max-cover based approach will select 0b00001100 instead, despite lower bit count // (since it has two new/unknown bits). t.Run("max-cover", func(t *testing.T) { @@ -289,11 +275,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) { }) t.Run("multiple slots", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - atts := getAtts([]testData{ {2, bitfield.Bitlist{0b11100000, 0b1}}, {4, bitfield.Bitlist{0b11100000, 0b1}}, @@ -316,11 +297,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) { }) t.Run("follows max-cover", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - // Items at slot 4 must be first split into two lists by max-cover, with // 0b10000011 being selected and 0b11100001 being leftover (despite naive bit count suggesting otherwise). atts := getAtts([]testData{ @@ -350,11 +326,6 @@ func TestProposer_ProposerAtts_committeeAwareSort(t *testing.T) { func TestProposer_sort_DifferentCommittees(t *testing.T) { t.Run("one att per committee", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - c1_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11111000, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 1}}) c2_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11100000, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 2}}) atts := proposerAtts{c1_a1, c2_a1} @@ -364,11 +335,6 @@ func TestProposer_sort_DifferentCommittees(t *testing.T) { assert.DeepEqual(t, want, atts) }) t.Run("multiple atts per committee", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - c1_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11111100, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 1}}) c1_a2 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b10000010, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 1}}) c2_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11110000, 0b1}, Data: ðpb.AttestationData{CommitteeIndex: 2}}) @@ -381,11 +347,6 @@ func TestProposer_sort_DifferentCommittees(t *testing.T) { assert.DeepEqual(t, want, atts) }) t.Run("multiple atts per committee, multiple slots", func(t *testing.T) { - feat := features.Get() - feat.EnableCommitteeAwarePacking = true - reset := features.InitWithReset(feat) - defer reset() - s2_c1_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11111100, 0b1}, Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 1}}) s2_c1_a2 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b10000010, 0b1}, Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 1}}) s2_c2_a1 := util.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b11110000, 0b1}, Data: ðpb.AttestationData{Slot: 2, CommitteeIndex: 2}}) @@ -724,6 +685,214 @@ func Test_packAttestations(t *testing.T) { }) } +func Test_packAttestations_ElectraOnChainAggregates(t *testing.T) { + ctx := context.Background() + + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.ElectraForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + + key, err := blst.RandKey() + require.NoError(t, err) + sig := key.Sign([]byte{'X'}) + + cb0 := primitives.NewAttestationCommitteeBits() + cb0.SetBitAt(0, true) + cb1 := primitives.NewAttestationCommitteeBits() + cb1.SetBitAt(1, true) + + data0 := util.HydrateAttestationData(ðpb.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte{'0'}, 32)}) + data1 := util.HydrateAttestationData(ðpb.AttestationData{BeaconBlockRoot: bytesutil.PadTo([]byte{'1'}, 32)}) + + // Glossary: + // - Single Aggregate: aggregate with exactly one committee bit set, from which an On-Chain Aggregate is constructed + // - On-Chain Aggregate: final aggregate packed into a block + // + // We construct the following number of single aggregates: + // - data_root_0 and committee_index_0: 3 single aggregates + // - data_root_0 and committee_index_1: 2 single aggregates + // - data_root_1 and committee_index_0: 1 single aggregate + // - data_root_1 and committee_index_1: 3 single aggregates + // + // Because the function tries to aggregate attestations, we have to create attestations which are not aggregatable + // and are not redundant when using MaxCover. + // The function should also sort attestation by ID before computing the On-Chain Aggregate, so we want unsorted aggregation bits + // to test the sorting part. + // + // The result should be the following six on-chain aggregates: + // - for data_root_0 combining the most profitable aggregate for each committee + // - for data_root_0 combining the second most profitable aggregate for each committee + // - for data_root_0 constructed from the single aggregate at index 2 for committee_index_0 + // - for data_root_1 combining the most profitable aggregate for each committee + // - for data_root_1 constructed from the single aggregate at index 1 for committee_index_1 + // - for data_root_1 constructed from the single aggregate at index 2 for committee_index_1 + + d0_c0_a1 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1000011}, + CommitteeBits: cb0, + Data: data0, + Signature: sig.Marshal(), + } + d0_c0_a2 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1100101}, + CommitteeBits: cb0, + Data: data0, + Signature: sig.Marshal(), + } + d0_c0_a3 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1111000}, + CommitteeBits: cb0, + Data: data0, + Signature: sig.Marshal(), + } + d0_c1_a1 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1111100}, + CommitteeBits: cb1, + Data: data0, + Signature: sig.Marshal(), + } + d0_c1_a2 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1001111}, + CommitteeBits: cb1, + Data: data0, + Signature: sig.Marshal(), + } + d1_c0_a1 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1111111}, + CommitteeBits: cb0, + Data: data1, + Signature: sig.Marshal(), + } + d1_c1_a1 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1000011}, + CommitteeBits: cb1, + Data: data1, + Signature: sig.Marshal(), + } + d1_c1_a2 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1100101}, + CommitteeBits: cb1, + Data: data1, + Signature: sig.Marshal(), + } + d1_c1_a3 := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1111000}, + CommitteeBits: cb1, + Data: data1, + Signature: sig.Marshal(), + } + + pool := &mock.PoolMock{} + require.NoError(t, pool.SaveAggregatedAttestations([]ethpb.Att{d0_c0_a1, d0_c0_a2, d0_c0_a3, d0_c1_a1, d0_c1_a2, d1_c0_a1, d1_c1_a1, d1_c1_a2, d1_c1_a3})) + slot := primitives.Slot(1) + s := &Server{AttPool: pool, HeadFetcher: &chainMock.ChainService{}, TimeFetcher: &chainMock.ChainService{Slot: &slot}} + + // We need the correct number of validators so that there are at least 2 committees per slot + // and each committee has exactly 6 validators (this is because we have 6 aggregation bits). + st, _ := util.DeterministicGenesisStateElectra(t, 192) + + require.NoError(t, st.SetSlot(params.BeaconConfig().SlotsPerEpoch+1)) + + t.Run("ok", func(t *testing.T) { + atts, err := s.packAttestations(ctx, st, params.BeaconConfig().SlotsPerEpoch) + require.NoError(t, err) + require.Equal(t, 6, len(atts)) + assert.Equal(t, true, + atts[0].GetAggregationBits().Count() >= atts[1].GetAggregationBits().Count() && + atts[1].GetAggregationBits().Count() >= atts[2].GetAggregationBits().Count() && + atts[2].GetAggregationBits().Count() >= atts[3].GetAggregationBits().Count() && + atts[3].GetAggregationBits().Count() >= atts[4].GetAggregationBits().Count() && + atts[4].GetAggregationBits().Count() >= atts[5].GetAggregationBits().Count(), + "on-chain aggregates are not sorted by aggregation bit count", + ) + }) + + t.Run("slot takes precedence", func(t *testing.T) { + moreRecentAtt := ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1100000}, // we set only one bit for committee_index_0 + CommitteeBits: cb1, + Data: util.HydrateAttestationData(ðpb.AttestationData{Slot: 1, BeaconBlockRoot: bytesutil.PadTo([]byte{'0'}, 32)}), + Signature: sig.Marshal(), + } + require.NoError(t, pool.SaveUnaggregatedAttestations([]ethpb.Att{moreRecentAtt})) + atts, err := s.packAttestations(ctx, st, params.BeaconConfig().SlotsPerEpoch) + require.NoError(t, err) + require.Equal(t, 7, len(atts)) + assert.Equal(t, true, atts[0].GetData().Slot == 1) + }) +} + +func Benchmark_packAttestations_Electra(b *testing.B) { + ctx := context.Background() + + params.SetupTestConfigCleanup(b) + cfg := params.MainnetConfig().Copy() + cfg.ElectraForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + + valCount := uint64(1048576) + committeeCount := helpers.SlotCommitteeCount(valCount) + valsPerCommittee := valCount / committeeCount / uint64(params.BeaconConfig().SlotsPerEpoch) + + st, _ := util.DeterministicGenesisStateElectra(b, valCount) + + key, err := blst.RandKey() + require.NoError(b, err) + sig := key.Sign([]byte{'X'}) + + r := rand.New(rand.NewSource(123)) + + var atts []ethpb.Att + for c := uint64(0); c < committeeCount; c++ { + for a := uint64(0); a < params.BeaconConfig().TargetAggregatorsPerCommittee; a++ { + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(c, true) + + var att *ethpb.AttestationElectra + // Last two aggregators send aggregates for some random block root with only a few bits set. + if a >= params.BeaconConfig().TargetAggregatorsPerCommittee-2 { + root := bytesutil.PadTo([]byte("root_"+strconv.Itoa(r.Intn(100))), 32) + att = ðpb.AttestationElectra{ + Data: util.HydrateAttestationData(ðpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch - 1, BeaconBlockRoot: root}), + AggregationBits: bitfield.NewBitlist(valsPerCommittee), + CommitteeBits: cb, + Signature: sig.Marshal(), + } + for bit := uint64(0); bit < valsPerCommittee; bit++ { + att.AggregationBits.SetBitAt(bit, r.Intn(100) < 2) // 2% that the bit is set + } + } else { + att = ðpb.AttestationElectra{ + Data: util.HydrateAttestationData(ðpb.AttestationData{Slot: params.BeaconConfig().SlotsPerEpoch - 1, BeaconBlockRoot: bytesutil.PadTo([]byte("root"), 32)}), + AggregationBits: bitfield.NewBitlist(valsPerCommittee), + CommitteeBits: cb, + Signature: sig.Marshal(), + } + for bit := uint64(0); bit < valsPerCommittee; bit++ { + att.AggregationBits.SetBitAt(bit, r.Intn(100) < 98) // 98% that the bit is set + } + } + + atts = append(atts, att) + } + } + + pool := &mock.PoolMock{} + require.NoError(b, pool.SaveAggregatedAttestations(atts)) + + slot := primitives.Slot(1) + s := &Server{AttPool: pool, HeadFetcher: &chainMock.ChainService{}, TimeFetcher: &chainMock.ChainService{Slot: &slot}} + + require.NoError(b, st.SetSlot(params.BeaconConfig().SlotsPerEpoch)) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err = s.packAttestations(ctx, st, params.BeaconConfig().SlotsPerEpoch+1) + require.NoError(b, err) + } +} + func Test_limitToMaxAttestations(t *testing.T) { t.Run("Phase 0", func(t *testing.T) { atts := make([]ethpb.Att, params.BeaconConfig().MaxAttestations+1) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go index 636858144ae6..ffb3777f48fd 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go @@ -21,12 +21,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/ssz" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/forks" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) var ( @@ -51,6 +51,7 @@ var emptyTransactionsRoot = [32]byte{127, 254, 36, 30, 166, 1, 135, 253, 176, 24 // blockBuilderTimeout is the maximum amount of time allowed for a block builder to respond to a // block request. This value is known as `BUILDER_PROPOSAL_DELAY_TOLERANCE` in builder spec. const blockBuilderTimeout = 1 * time.Second +const gasLimitAdjustmentFactor = 1024 // Sets the execution data for the block. Execution data can come from local EL client or remote builder depends on validator registration and circuit breaker conditions. func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, local *blocks.GetPayloadResponse, bid builder.Bid, builderBoostFactor primitives.Gwei) (primitives.Wei, *enginev1.BlobsBundle, error) { @@ -71,18 +72,11 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) } - var builderKzgCommitments [][]byte builderPayload, err := bid.Header() if err != nil { log.WithError(err).Warn("Proposer: failed to retrieve header from BuilderBid") return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) } - if bid.Version() >= version.Deneb { - builderKzgCommitments, err = bid.BlobKzgCommitments() - if err != nil { - log.WithError(err).Warn("Proposer: failed to retrieve kzg commitments from BuilderBid") - } - } switch { case blk.Version() >= version.Capella: @@ -134,7 +128,28 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc // If we can't get the builder value, just use local block. if higherValueBuilder && withdrawalsMatched { // Builder value is higher and withdrawals match. - if err := setBuilderExecution(blk, builderPayload, builderKzgCommitments); err != nil { + var builderKzgCommitments [][]byte + if bid.Version() >= version.Deneb { + bidDeneb, ok := bid.(builder.BidDeneb) + if !ok { + log.Warnf("bid type %T does not implement builder.BidDeneb", bid) + return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) + } else { + builderKzgCommitments = bidDeneb.BlobKzgCommitments() + } + } + + var executionRequests *enginev1.ExecutionRequests + if bid.Version() >= version.Electra { + bidElectra, ok := bid.(builder.BidElectra) + if !ok { + log.Warnf("bid type %T does not implement builder.BidElectra", bid) + return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) + } else { + executionRequests = bidElectra.ExecutionRequests() + } + } + if err := setBuilderExecution(blk, builderPayload, builderKzgCommitments, executionRequests); err != nil { log.WithError(err).Warn("Proposer: failed to set builder payload") return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) } else { @@ -149,7 +164,7 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc "builderBoostFactor": builderBoostFactor, }).Warn("Proposer: using local execution payload because higher value") } - span.AddAttributes( + span.SetAttributes( trace.BoolAttribute("higherValueBuilder", higherValueBuilder), trace.Int64Attribute("localGweiValue", int64(localValueGwei)), // lint:ignore uintcast -- This is OK for tracing. trace.Int64Attribute("localBoostPercentage", int64(boost)), // lint:ignore uintcast -- This is OK for tracing. @@ -158,7 +173,7 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc ) return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) default: // Bellatrix case. - if err := setBuilderExecution(blk, builderPayload, builderKzgCommitments); err != nil { + if err := setBuilderExecution(blk, builderPayload, nil, nil); err != nil { log.WithError(err).Warn("Proposer: failed to set builder payload") return local.Bid, local.BlobsBundle, setLocalExecution(blk, local) } else { @@ -169,7 +184,11 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc // This function retrieves the payload header and kzg commitments given the slot number and the validator index. // It's a no-op if the latest head block is not versioned bellatrix. -func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitives.Slot, idx primitives.ValidatorIndex) (builder.Bid, error) { +func (vs *Server) getPayloadHeaderFromBuilder( + ctx context.Context, + slot primitives.Slot, + idx primitives.ValidatorIndex, + parentGasLimit uint64) (builder.Bid, error) { ctx, span := trace.StartSpan(ctx, "ProposerServer.getPayloadHeaderFromBuilder") defer span.End() @@ -198,7 +217,7 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv if err != nil { return nil, err } - if signedBid.IsNil() { + if signedBid == nil || signedBid.IsNil() { return nil, errors.New("builder returned nil bid") } fork, err := forks.Fork(slots.ToEpoch(slot)) @@ -217,7 +236,7 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv if err != nil { return nil, errors.Wrap(err, "could not get bid") } - if bid.IsNil() { + if bid == nil || bid.IsNil() { return nil, errors.New("builder returned nil bid") } @@ -242,6 +261,16 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv return nil, fmt.Errorf("incorrect parent hash %#x != %#x", header.ParentHash(), h.BlockHash()) } + reg, err := vs.BlockBuilder.RegistrationByValidatorID(ctx, idx) + if err != nil { + log.WithError(err).Warn("Proposer: failed to get registration by validator ID, could not check gas limit") + } else { + gasLimit := expectedGasLimit(parentGasLimit, reg.GasLimit) + if gasLimit != header.GasLimit() { + return nil, fmt.Errorf("incorrect header gas limit %d != %d", gasLimit, header.GasLimit()) + } + } + t, err := slots.ToTime(uint64(vs.TimeFetcher.GenesisTime().Unix()), slot) if err != nil { return nil, err @@ -256,20 +285,20 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv var kzgCommitments [][]byte if bid.Version() >= version.Deneb { - kzgCommitments, err = bid.BlobKzgCommitments() - if err != nil { - return nil, errors.Wrap(err, "could not get blob kzg commitments") + dBid, ok := bid.(builder.BidDeneb) + if !ok { + return nil, fmt.Errorf("bid type %T does not implement builder.BidDeneb", dBid) } - if len(kzgCommitments) > fieldparams.MaxBlobsPerBlock { - return nil, fmt.Errorf("builder returned too many kzg commitments: %d", len(kzgCommitments)) - } - for _, c := range kzgCommitments { - if len(c) != fieldparams.BLSPubkeyLength { - return nil, fmt.Errorf("builder returned invalid kzg commitment length: %d", len(c)) - } + kzgCommitments = dBid.BlobKzgCommitments() + } + var executionRequests *enginev1.ExecutionRequests + if bid.Version() >= version.Electra { + eBid, ok := bid.(builder.BidElectra) + if !ok { + return nil, fmt.Errorf("bid type %T does not implement builder.BidElectra", eBid) } + executionRequests = eBid.ExecutionRequests() } - l := log.WithFields(logrus.Fields{ "gweiValue": primitives.WeiToGwei(v), "builderPubKey": fmt.Sprintf("%#x", bid.Pubkey()), @@ -281,9 +310,14 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv if len(kzgCommitments) > 0 { l = l.WithField("kzgCommitmentCount", len(kzgCommitments)) } + if executionRequests != nil { + l = l.WithField("depositRequestCount", len(executionRequests.Deposits)) + l = l.WithField("withdrawalRequestCount", len(executionRequests.Withdrawals)) + l = l.WithField("consolidationRequestCount", len(executionRequests.Consolidations)) + } l.Info("Received header with bid") - span.AddAttributes( + span.SetAttributes( trace.StringAttribute("value", primitives.WeiToBigInt(v).String()), trace.StringAttribute("builderPubKey", fmt.Sprintf("%#x", bid.Pubkey())), trace.StringAttribute("blockHash", fmt.Sprintf("%#x", header.BlockHash())), @@ -300,14 +334,14 @@ func validateBuilderSignature(signedBid builder.SignedBid) error { if err != nil { return err } - if signedBid.IsNil() { + if signedBid == nil || signedBid.IsNil() { return errors.New("nil builder bid") } bid, err := signedBid.Message() if err != nil { return errors.Wrap(err, "could not get bid") } - if bid.IsNil() { + if bid == nil || bid.IsNil() { return errors.New("builder returned nil bid") } return signing.VerifySigningRoot(bid, bid.Pubkey(), signedBid.Signature(), d) @@ -344,18 +378,23 @@ func setLocalExecution(blk interfaces.SignedBeaconBlock, local *blocks.GetPayloa if local.BlobsBundle != nil { kzgCommitments = local.BlobsBundle.KzgCommitments } - return setExecution(blk, local.ExecutionData, false, kzgCommitments) + if local.ExecutionRequests != nil { + if err := blk.SetExecutionRequests(local.ExecutionRequests); err != nil { + return errors.Wrap(err, "could not set execution requests") + } + } + return setExecution(blk, local.ExecutionData, false, kzgCommitments, local.ExecutionRequests) } // setBuilderExecution sets the execution context for a builder's beacon block. // It delegates to setExecution for the actual work. -func setBuilderExecution(blk interfaces.SignedBeaconBlock, execution interfaces.ExecutionData, builderKzgCommitments [][]byte) error { - return setExecution(blk, execution, true, builderKzgCommitments) +func setBuilderExecution(blk interfaces.SignedBeaconBlock, execution interfaces.ExecutionData, builderKzgCommitments [][]byte, requests *enginev1.ExecutionRequests) error { + return setExecution(blk, execution, true, builderKzgCommitments, requests) } // setExecution sets the execution context for a beacon block. It also sets KZG commitments based on the block version. // The function is designed to be flexible and handle both local and builder executions. -func setExecution(blk interfaces.SignedBeaconBlock, execution interfaces.ExecutionData, isBlinded bool, kzgCommitments [][]byte) error { +func setExecution(blk interfaces.SignedBeaconBlock, execution interfaces.ExecutionData, isBlinded bool, kzgCommitments [][]byte, requests *enginev1.ExecutionRequests) error { if execution == nil { return errors.New("execution is nil") } @@ -375,13 +414,55 @@ func setExecution(blk interfaces.SignedBeaconBlock, execution interfaces.Executi } // Set the KZG commitments for the block - errMessage = "failed to set local kzg commitments" + kzgErr := "failed to set local kzg commitments" if isBlinded { - errMessage = "failed to set builder kzg commitments" + kzgErr = "failed to set builder kzg commitments" } if err := blk.SetBlobKzgCommitments(kzgCommitments); err != nil { - return errors.Wrap(err, errMessage) + return errors.Wrap(err, kzgErr) } + // If the block version is below Electra, no further actions are needed + if blk.Version() < version.Electra { + return nil + } + + // Set the execution requests + requestsErr := "failed to set local execution requests" + if isBlinded { + requestsErr = "failed to set builder execution requests" + } + if err := blk.SetExecutionRequests(requests); err != nil { + return errors.Wrap(err, requestsErr) + } return nil } + +// Calculates expected gas limit based on parent gas limit and target gas limit. +// Spec code: +// +// def expected_gas_limit(parent_gas_limit, target_gas_limit, adjustment_factor): +// max_gas_limit_difference = (parent_gas_limit // adjustment_factor) - 1 +// if target_gas_limit > parent_gas_limit: +// gas_diff = target_gas_limit - parent_gas_limit +// return parent_gas_limit + min(gas_diff, max_gas_limit_difference) +// else: +// gas_diff = parent_gas_limit - target_gas_limit +// return parent_gas_limit - min(gas_diff, max_gas_limit_difference) +func expectedGasLimit(parentGasLimit, proposerGasLimit uint64) uint64 { + maxGasLimitDiff := uint64(0) + if parentGasLimit > gasLimitAdjustmentFactor { + maxGasLimitDiff = parentGasLimit/gasLimitAdjustmentFactor - 1 + } + if proposerGasLimit > parentGasLimit { + if proposerGasLimit-parentGasLimit > maxGasLimitDiff { + return parentGasLimit + maxGasLimitDiff + } + return proposerGasLimit + } + + if parentGasLimit-proposerGasLimit > maxGasLimitDiff { + return parentGasLimit - maxGasLimitDiff + } + return proposerGasLimit +} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go index 7d02c392539e..271575ce3884 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix_test.go @@ -28,7 +28,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/encoding/ssz" v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" "github.com/prysmaticlabs/prysm/v5/time/slots" @@ -94,14 +93,14 @@ func TestServer_setExecutionData(t *testing.T) { ForkchoiceFetcher: &blockchainTest.ChainService{}, TrackedValidatorsCache: cache.NewTrackedValidatorsCache(), } - + gasLimit := uint64(30000000) t.Run("No builder configured. Use local block", func(t *testing.T) { blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella()) require.NoError(t, err) b := blk.Block() res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.NoError(t, err) require.IsNil(t, builderBid) _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor) @@ -115,7 +114,11 @@ func TestServer_setExecutionData(t *testing.T) { blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella()) require.NoError(t, err) require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()}, - []*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) + []*ethpb.ValidatorRegistrationV1{{ + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + Timestamp: uint64(time.Now().Unix()), + GasLimit: gasLimit, + Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) ti, err := slots.ToTime(uint64(time.Now().Unix()), 0) require.NoError(t, err) sk, err := bls.RandKey() @@ -135,6 +138,7 @@ func TestServer_setExecutionData(t *testing.T) { BlockHash: make([]byte, fieldparams.RootLength), TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength), WithdrawalsRoot: make([]byte, fieldparams.RootLength), + GasLimit: gasLimit, }, Pubkey: sk.PublicKey().Marshal(), Value: bytesutil.PadTo([]byte{1}, 32), @@ -164,15 +168,10 @@ func TestServer_setExecutionData(t *testing.T) { res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.NoError(t, err) _, err = builderBid.Header() require.NoError(t, err) - builderKzgCommitments, err := builderBid.BlobKzgCommitments() - if builderBid.Version() >= version.Deneb { - require.NoError(t, err) - } - require.DeepEqual(t, [][]uint8{}, builderKzgCommitments) _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor) require.NoError(t, err) require.IsNil(t, bundle) @@ -184,7 +183,11 @@ func TestServer_setExecutionData(t *testing.T) { blk, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella()) require.NoError(t, err) require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()}, - []*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) + []*ethpb.ValidatorRegistrationV1{{ + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + Timestamp: uint64(time.Now().Unix()), + GasLimit: gasLimit, + Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) ti, err := slots.ToTime(uint64(time.Now().Unix()), 0) require.NoError(t, err) sk, err := bls.RandKey() @@ -207,6 +210,7 @@ func TestServer_setExecutionData(t *testing.T) { BlockHash: make([]byte, fieldparams.RootLength), TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength), WithdrawalsRoot: wr[:], + GasLimit: gasLimit, }, Pubkey: sk.PublicKey().Marshal(), Value: bytesutil.PadTo(builderValue, 32), @@ -236,15 +240,10 @@ func TestServer_setExecutionData(t *testing.T) { b := blk.Block() res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.NoError(t, err) _, err = builderBid.Header() require.NoError(t, err) - builderKzgCommitments, err := builderBid.BlobKzgCommitments() - if builderBid.Version() >= version.Deneb { - require.NoError(t, err) - } - require.DeepEqual(t, [][]uint8{}, builderKzgCommitments) _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor) require.NoError(t, err) require.IsNil(t, bundle) @@ -256,7 +255,11 @@ func TestServer_setExecutionData(t *testing.T) { blk, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella()) require.NoError(t, err) require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()}, - []*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) + []*ethpb.ValidatorRegistrationV1{{ + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + Timestamp: uint64(time.Now().Unix()), + GasLimit: gasLimit, + Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) ti, err := slots.ToTime(uint64(time.Now().Unix()), 0) require.NoError(t, err) sk, err := bls.RandKey() @@ -278,6 +281,7 @@ func TestServer_setExecutionData(t *testing.T) { Timestamp: uint64(ti.Unix()), BlockNumber: 2, WithdrawalsRoot: wr[:], + GasLimit: gasLimit, }, Pubkey: sk.PublicKey().Marshal(), Value: bytesutil.PadTo(builderValue, 32), @@ -307,15 +311,10 @@ func TestServer_setExecutionData(t *testing.T) { b := blk.Block() res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.NoError(t, err) _, err = builderBid.Header() require.NoError(t, err) - builderKzgCommitments, err := builderBid.BlobKzgCommitments() - if builderBid.Version() >= version.Deneb { - require.NoError(t, err) - } - require.DeepEqual(t, [][]uint8{}, builderKzgCommitments) _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, math.MaxUint64) require.NoError(t, err) require.IsNil(t, bundle) @@ -327,7 +326,11 @@ func TestServer_setExecutionData(t *testing.T) { blk, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella()) require.NoError(t, err) require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()}, - []*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) + []*ethpb.ValidatorRegistrationV1{{ + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + Timestamp: uint64(time.Now().Unix()), + GasLimit: gasLimit, + Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) ti, err := slots.ToTime(uint64(time.Now().Unix()), 0) require.NoError(t, err) sk, err := bls.RandKey() @@ -349,6 +352,7 @@ func TestServer_setExecutionData(t *testing.T) { Timestamp: uint64(ti.Unix()), BlockNumber: 2, WithdrawalsRoot: wr[:], + GasLimit: gasLimit, }, Pubkey: sk.PublicKey().Marshal(), Value: bytesutil.PadTo(builderValue, 32), @@ -378,15 +382,10 @@ func TestServer_setExecutionData(t *testing.T) { b := blk.Block() res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.NoError(t, err) _, err = builderBid.Header() require.NoError(t, err) - builderKzgCommitments, err := builderBid.BlobKzgCommitments() - if builderBid.Version() >= version.Deneb { - require.NoError(t, err) - } - require.DeepEqual(t, [][]uint8{}, builderKzgCommitments) _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, 0) require.NoError(t, err) require.IsNil(t, bundle) @@ -404,15 +403,10 @@ func TestServer_setExecutionData(t *testing.T) { b := blk.Block() res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.NoError(t, err) _, err = builderBid.Header() require.NoError(t, err) - builderKzgCommitments, err := builderBid.BlobKzgCommitments() - if builderBid.Version() >= version.Deneb { - require.NoError(t, err) - } - require.DeepEqual(t, [][]uint8{}, builderKzgCommitments) _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor) require.NoError(t, err) require.IsNil(t, bundle) @@ -436,15 +430,10 @@ func TestServer_setExecutionData(t *testing.T) { b := blk.Block() res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.NoError(t, err) _, err = builderBid.Header() require.NoError(t, err) - builderKzgCommitments, err := builderBid.BlobKzgCommitments() - if builderBid.Version() >= version.Deneb { - require.NoError(t, err) - } - require.DeepEqual(t, [][]uint8{}, builderKzgCommitments) _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor) require.NoError(t, err) require.IsNil(t, bundle) @@ -471,15 +460,10 @@ func TestServer_setExecutionData(t *testing.T) { b := blk.Block() res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.NoError(t, err) - builderKzgCommitments, err := builderBid.BlobKzgCommitments() - if builderBid.Version() >= version.Deneb { - require.NoError(t, err) - } _, err = builderBid.Header() require.NoError(t, err) - require.DeepEqual(t, [][]uint8{}, builderKzgCommitments) _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor) require.NoError(t, err) require.IsNil(t, bundle) @@ -503,7 +487,7 @@ func TestServer_setExecutionData(t *testing.T) { b := blk.Block() res, err := vs.getLocalPayload(ctx, b, capellaTransitionState) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit) require.ErrorIs(t, consensus_types.ErrNilObjectWrapped, err) // Builder returns fault. Use local block require.IsNil(t, builderBid) _, bundle, err := setExecutionData(context.Background(), blk, res, nil, defaultBuilderBoostFactor) @@ -578,6 +562,7 @@ func TestServer_setExecutionData(t *testing.T) { WithdrawalsRoot: wr[:], BlobGasUsed: 123, ExcessBlobGas: 456, + GasLimit: gasLimit, }, Pubkey: sk.PublicKey().Marshal(), Value: bytesutil.PadTo(builderValue, 32), @@ -599,7 +584,11 @@ func TestServer_setExecutionData(t *testing.T) { Cfg: &builderTest.Config{BeaconDB: beaconDB}, } require.NoError(t, beaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()}, - []*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) + []*ethpb.ValidatorRegistrationV1{{ + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + Timestamp: uint64(time.Now().Unix()), + GasLimit: gasLimit, + Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockDeneb()) require.NoError(t, err) @@ -619,12 +608,13 @@ func TestServer_setExecutionData(t *testing.T) { require.NoError(t, err) blk.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch) * params.BeaconConfig().SlotsPerEpoch) require.NoError(t, err) - builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, blk.Block().Slot(), blk.Block().ProposerIndex()) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, blk.Block().Slot(), blk.Block().ProposerIndex(), gasLimit) require.NoError(t, err) builderPayload, err := builderBid.Header() require.NoError(t, err) - builderKzgCommitments, err := builderBid.BlobKzgCommitments() - require.NoError(t, err) + dbid, ok := builderBid.(builder.BidDeneb) + require.Equal(t, true, ok) + builderKzgCommitments := dbid.BlobKzgCommitments() require.DeepEqual(t, bid.BlobKzgCommitments, builderKzgCommitments) require.Equal(t, bid.Header.BlockNumber, builderPayload.BlockNumber()) // header should be the same from block @@ -638,6 +628,134 @@ func TestServer_setExecutionData(t *testing.T) { require.NoError(t, err) require.DeepEqual(t, bid.BlobKzgCommitments, got) }) + t.Run("Can get builder payload, blobs, and execution requests Electra", func(t *testing.T) { + cfg := params.BeaconConfig().Copy() + cfg.ElectraForkEpoch = 0 + params.OverrideBeaconConfig(cfg) + params.SetupTestConfigCleanup(t) + + blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockElectra()) + require.NoError(t, err) + ti, err := slots.ToTime(uint64(time.Now().Unix()), 0) + require.NoError(t, err) + sk, err := bls.RandKey() + require.NoError(t, err) + wr, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(t, err) + builderValue := bytesutil.ReverseByteOrder(big.NewInt(1e9).Bytes()) + + requests := &v1.ExecutionRequests{ + Deposits: []*v1.DepositRequest{ + { + Pubkey: bytesutil.PadTo([]byte{byte('a')}, fieldparams.BLSPubkeyLength), + WithdrawalCredentials: bytesutil.PadTo([]byte{byte('b')}, fieldparams.RootLength), + Amount: params.BeaconConfig().MinActivationBalance, + Signature: bytesutil.PadTo([]byte{byte('c')}, fieldparams.BLSSignatureLength), + Index: 0, + }, + }, + Withdrawals: []*v1.WithdrawalRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('d')}, common.AddressLength), + ValidatorPubkey: bytesutil.PadTo([]byte{byte('e')}, fieldparams.BLSPubkeyLength), + Amount: params.BeaconConfig().MinActivationBalance, + }, + }, + Consolidations: []*v1.ConsolidationRequest{ + { + SourceAddress: bytesutil.PadTo([]byte{byte('f')}, common.AddressLength), + SourcePubkey: bytesutil.PadTo([]byte{byte('g')}, fieldparams.BLSPubkeyLength), + TargetPubkey: bytesutil.PadTo([]byte{byte('h')}, fieldparams.BLSPubkeyLength), + }, + }, + } + + bid := ðpb.BuilderBidElectra{ + Header: &v1.ExecutionPayloadHeaderDeneb{ + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength), + ParentHash: params.BeaconConfig().ZeroHash[:], + Timestamp: uint64(ti.Unix()), + BlockNumber: 2, + WithdrawalsRoot: wr[:], + BlobGasUsed: 123, + ExcessBlobGas: 456, + GasLimit: gasLimit, + }, + Pubkey: sk.PublicKey().Marshal(), + Value: bytesutil.PadTo(builderValue, 32), + BlobKzgCommitments: [][]byte{bytesutil.PadTo([]byte{2}, fieldparams.BLSPubkeyLength), bytesutil.PadTo([]byte{5}, fieldparams.BLSPubkeyLength)}, + ExecutionRequests: requests, + } + + d := params.BeaconConfig().DomainApplicationBuilder + domain, err := signing.ComputeDomain(d, nil, nil) + require.NoError(t, err) + sr, err := signing.ComputeSigningRoot(bid, domain) + require.NoError(t, err) + sBid := ðpb.SignedBuilderBidElectra{ + Message: bid, + Signature: sk.Sign(sr[:]).Marshal(), + } + vs.BlockBuilder = &builderTest.MockBuilderService{ + BidElectra: sBid, + HasConfigured: true, + Cfg: &builderTest.Config{BeaconDB: beaconDB}, + } + require.NoError(t, beaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()}, + []*ethpb.ValidatorRegistrationV1{{ + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + Timestamp: uint64(time.Now().Unix()), + GasLimit: gasLimit, + Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}})) + wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockElectra()) + require.NoError(t, err) + chain := &blockchainTest.ChainService{ForkChoiceStore: doublylinkedtree.New(), Genesis: time.Now(), Block: wb} + vs.ForkFetcher = chain + vs.ForkchoiceFetcher.SetForkChoiceGenesisTime(uint64(time.Now().Unix())) + vs.TimeFetcher = chain + vs.HeadFetcher = chain + + ed, err := blocks.NewWrappedExecutionData(&v1.ExecutionPayloadDeneb{BlockNumber: 4, Withdrawals: withdrawals}) + require.NoError(t, err) + vs.ExecutionEngineCaller = &powtesting.EngineClient{ + PayloadIDBytes: id, + GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed}, + } + + require.NoError(t, err) + blk.SetSlot(0) + require.NoError(t, err) + builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, blk.Block().Slot(), blk.Block().ProposerIndex(), gasLimit) + require.NoError(t, err) + builderPayload, err := builderBid.Header() + require.NoError(t, err) + eBid, ok := builderBid.(builder.BidElectra) + require.Equal(t, true, ok) + require.DeepEqual(t, bid.BlobKzgCommitments, eBid.BlobKzgCommitments()) + require.DeepEqual(t, bid.ExecutionRequests, eBid.ExecutionRequests()) + require.Equal(t, bid.Header.BlockNumber, builderPayload.BlockNumber()) // header should be the same from block + + res, err := vs.getLocalPayload(ctx, blk.Block(), denebTransitionState) + require.NoError(t, err) + _, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor) + require.NoError(t, err) + require.IsNil(t, bundle) + + got, err := blk.Block().Body().BlobKzgCommitments() + require.NoError(t, err) + require.DeepEqual(t, bid.BlobKzgCommitments, got) + + gRequests, err := blk.Block().Body().ExecutionRequests() + require.NoError(t, err) + require.DeepEqual(t, bid.ExecutionRequests, gRequests) + }) } func TestServer_getPayloadHeader(t *testing.T) { @@ -660,6 +778,8 @@ func TestServer_getPayloadHeader(t *testing.T) { sk, err := bls.RandKey() require.NoError(t, err) + + gasLimit := uint64(30000000) bid := ðpb.BuilderBid{ Header: &v1.ExecutionPayloadHeader{ FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), @@ -672,6 +792,7 @@ func TestServer_getPayloadHeader(t *testing.T) { TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength), ParentHash: params.BeaconConfig().ZeroHash[:], Timestamp: uint64(ti.Unix()), + GasLimit: gasLimit, }, Pubkey: sk.PublicKey().Marshal(), Value: bytesutil.PadTo([]byte{1, 2, 3}, 32), @@ -709,6 +830,7 @@ func TestServer_getPayloadHeader(t *testing.T) { ParentHash: params.BeaconConfig().ZeroHash[:], Timestamp: uint64(tiCapella.Unix()), WithdrawalsRoot: wr[:], + GasLimit: gasLimit, }, Pubkey: sk.PublicKey().Marshal(), Value: bytesutil.PadTo([]byte{1, 2, 3}, 32), @@ -720,7 +842,29 @@ func TestServer_getPayloadHeader(t *testing.T) { Signature: sk.Sign(srCapella[:]).Marshal(), } - require.NoError(t, err) + incorrectGasLimitBid := ðpb.BuilderBid{ + Header: &v1.ExecutionPayloadHeader{ + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength), + ParentHash: params.BeaconConfig().ZeroHash[:], + Timestamp: uint64(tiCapella.Unix()), + GasLimit: 31000000, + }, + Pubkey: sk.PublicKey().Marshal(), + Value: bytesutil.PadTo([]byte{1, 2, 3}, 32), + } + signedIncorrectGasLimitBid := + ðpb.SignedBuilderBid{ + Message: incorrectGasLimitBid, + Signature: sk.Sign(srCapella[:]).Marshal(), + } + tests := []struct { name string head interfaces.ReadOnlySignedBeaconBlock @@ -847,15 +991,39 @@ func TestServer_getPayloadHeader(t *testing.T) { }, returnedHeaderCapella: bidCapella.Header, }, + { + name: "incorrect gas limit", + mock: &builderTest.MockBuilderService{ + Bid: signedIncorrectGasLimitBid, + }, + fetcher: &blockchainTest.ChainService{ + Block: func() interfaces.ReadOnlySignedBeaconBlock { + wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockBellatrix()) + require.NoError(t, err) + wb.SetSlot(primitives.Slot(params.BeaconConfig().BellatrixForkEpoch) * params.BeaconConfig().SlotsPerEpoch) + return wb + }(), + }, + err: "incorrect header gas limit 30000000 != 31000000", + }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - vs := &Server{BlockBuilder: tc.mock, HeadFetcher: tc.fetcher, TimeFetcher: &blockchainTest.ChainService{ + vs := &Server{BeaconDB: dbTest.SetupDB(t), BlockBuilder: tc.mock, HeadFetcher: tc.fetcher, TimeFetcher: &blockchainTest.ChainService{ Genesis: genesis, }} + regCache := cache.NewRegistrationCache() + regCache.UpdateIndexToRegisteredMap(context.Background(), map[primitives.ValidatorIndex]*ethpb.ValidatorRegistrationV1{ + 0: { + GasLimit: gasLimit, + FeeRecipient: make([]byte, 20), + Pubkey: make([]byte, 48), + }, + }) + tc.mock.RegistrationCache = regCache hb, err := vs.HeadFetcher.HeadBlock(context.Background()) require.NoError(t, err) - bid, err := vs.getPayloadHeaderFromBuilder(context.Background(), hb.Block().Slot(), 0) + bid, err := vs.getPayloadHeaderFromBuilder(context.Background(), hb.Block().Slot(), 0, 30000000) if tc.err != "" { require.ErrorContains(t, tc.err, err) } else { @@ -971,3 +1139,87 @@ func TestEmptyTransactionsRoot(t *testing.T) { require.NoError(t, err) require.DeepEqual(t, r, emptyTransactionsRoot) } + +func Test_expectedGasLimit(t *testing.T) { + type args struct { + parentGasLimit uint64 + targetGasLimit uint64 + } + tests := []struct { + name string + args args + want uint64 + }{ + { + name: "Increase within limit", + args: args{ + parentGasLimit: 15000000, + targetGasLimit: 15000100, + }, + want: 15000100, + }, + { + name: "Increase exceeding limit", + args: args{ + parentGasLimit: 15000000, + targetGasLimit: 16000000, + }, + want: 15014647, // maxGasLimitDiff = (15000000 / 1024) - 1 = 1464 + }, + { + name: "Decrease within limit", + args: args{ + parentGasLimit: 15000000, + targetGasLimit: 14999990, + }, + want: 14999990, + }, + { + name: "Decrease exceeding limit", + args: args{ + parentGasLimit: 15000000, + targetGasLimit: 14000000, + }, + want: 14985353, // maxGasLimitDiff = (15000000 / 1024) - 1 = 1464 + }, + { + name: "Target equals parent", + args: args{ + parentGasLimit: 15000000, + targetGasLimit: 15000000, + }, + want: 15000000, // No change + }, + { + name: "Very small parent gas limit", + args: args{ + parentGasLimit: 1025, + targetGasLimit: 2000, + }, + want: 1025 + ((1025 / 1024) - 1), + }, + { + name: "Target far below parent but limited", + args: args{ + parentGasLimit: 20000000, + targetGasLimit: 10000000, + }, + want: 19980470, // maxGasLimitDiff = (20000000 / 1024) - 1 + }, + { + name: "Parent gas limit under flows", + args: args{ + parentGasLimit: 1023, + targetGasLimit: 30000000, + }, + want: 1023, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := expectedGasLimit(tt.args.parentGasLimit, tt.args.targetGasLimit); got != tt.want { + t.Errorf("expectedGasLimit() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go index b85244cadf13..660aea71425a 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder.go @@ -9,8 +9,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // Returns true if builder (ie outsourcing block construction) can be used. Both conditions have to meet: @@ -24,7 +24,7 @@ func (vs *Server) canUseBuilder(ctx context.Context, slot primitives.Slot, idx p return false, nil } activated, err := vs.circuitBreakBuilder(slot) - span.AddAttributes(trace.BoolAttribute("circuitBreakerActivated", activated)) + span.SetAttributes(trace.BoolAttribute("circuitBreakerActivated", activated)) if err != nil { tracing.AnnotateError(span, err) return false, err diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder_test.go index 70785d91c633..0a2c16ccaec1 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_builder_test.go @@ -14,9 +14,10 @@ import ( state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" - v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" logTest "github.com/sirupsen/logrus/hooks/test" @@ -149,7 +150,7 @@ func createState( payloadHash [32]byte, justified *ethpb.Checkpoint, finalized *ethpb.Checkpoint, -) (state.BeaconState, [32]byte, error) { +) (state.BeaconState, blocks.ROBlock, error) { base := ðpb.BeaconStateBellatrix{ Slot: slot, @@ -157,7 +158,7 @@ func createState( BlockRoots: make([][]byte, 1), CurrentJustifiedCheckpoint: justified, FinalizedCheckpoint: finalized, - LatestExecutionPayloadHeader: &v1.ExecutionPayloadHeader{ + LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeader{ BlockHash: payloadHash[:], }, LatestBlockHeader: ðpb.BeaconBlockHeader{ @@ -167,5 +168,24 @@ func createState( base.BlockRoots[0] = append(base.BlockRoots[0], blockRoot[:]...) st, err := state_native.InitializeFromProtoBellatrix(base) - return st, blockRoot, err + if err != nil { + return nil, blocks.ROBlock{}, err + } + blk := ðpb.SignedBeaconBlockBellatrix{ + Block: ðpb.BeaconBlockBellatrix{ + Slot: slot, + ParentRoot: parentRoot[:], + Body: ðpb.BeaconBlockBodyBellatrix{ + ExecutionPayload: &enginev1.ExecutionPayload{ + BlockHash: payloadHash[:], + }, + }, + }, + } + signed, err := blocks.NewSignedBeaconBlock(blk) + if err != nil { + return nil, blocks.ROBlock{}, err + } + roblock, err := blocks.NewROBlockWithRoot(signed, blockRoot) + return st, roblock, err } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb.go index 589f100fd692..2f57f409bd88 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb.go @@ -2,60 +2,13 @@ package validator import ( "errors" - "sync" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" ) -var bundleCache = &blobsBundleCache{} - -// BlobsBundleCache holds the KZG commitments and other relevant sidecar data for a local beacon block. -type blobsBundleCache struct { - sync.Mutex - slot primitives.Slot - bundle *enginev1.BlobsBundle -} - -// add adds a blobs bundle to the cache. -// same slot overwrites the previous bundle. -func (c *blobsBundleCache) add(slot primitives.Slot, bundle *enginev1.BlobsBundle) { - c.Lock() - defer c.Unlock() - - if slot >= c.slot { - c.bundle = bundle - c.slot = slot - } -} - -// get gets a blobs bundle from the cache. -func (c *blobsBundleCache) get(slot primitives.Slot) *enginev1.BlobsBundle { - c.Lock() - defer c.Unlock() - - if c.slot == slot { - return c.bundle - } - - return nil -} - -// prune acquires the lock before pruning. -func (c *blobsBundleCache) prune(minSlot primitives.Slot) { - c.Lock() - defer c.Unlock() - - if minSlot > c.slot { - c.slot = 0 - c.bundle = nil - } -} - // BuildBlobSidecars given a block, builds the blob sidecars for the block. func BuildBlobSidecars(blk interfaces.SignedBeaconBlock, blobs [][]byte, kzgProofs [][]byte) ([]*ethpb.BlobSidecar, error) { if blk.Version() < version.Deneb { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb_test.go index dd191d1d7dfc..a9f83e7ab386 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deneb_test.go @@ -6,44 +6,11 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" - enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func TestAdd(t *testing.T) { - slot := primitives.Slot(1) - bundle := &enginev1.BlobsBundle{KzgCommitments: [][]byte{{'a'}}} - bundleCache.add(slot, bundle) - require.Equal(t, bundleCache.bundle, bundle) - - slot = primitives.Slot(2) - bundle = &enginev1.BlobsBundle{KzgCommitments: [][]byte{{'b'}}} - bundleCache.add(slot, bundle) - require.Equal(t, bundleCache.bundle, bundle) -} - -func TestGet(t *testing.T) { - slot := primitives.Slot(3) - bundle := &enginev1.BlobsBundle{KzgCommitments: [][]byte{{'a'}}} - bundleCache.add(slot, bundle) - require.Equal(t, bundleCache.get(slot), bundle) -} - -func TestPrune(t *testing.T) { - slot1 := primitives.Slot(4) - bundle1 := &enginev1.BlobsBundle{KzgCommitments: [][]byte{{'a'}}} - - bundleCache.add(slot1, bundle1) - bundleCache.prune(slot1 + 1) - - if bundleCache.get(slot1) != nil { - t.Errorf("Prune did not remove the bundle at slot1") - } -} - func TestServer_buildBlobSidecars(t *testing.T) { kzgCommitments := [][]byte{bytesutil.PadTo([]byte{'a'}, 48), bytesutil.PadTo([]byte{'b'}, 48)} blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockDeneb()) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go index 3e322963c78d..5504c4a246bb 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_deposits.go @@ -7,15 +7,16 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/container/trie" "github.com/prysmaticlabs/prysm/v5/math" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "golang.org/x/sync/errgroup" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -71,6 +72,10 @@ func (vs *Server) packDepositsAndAttestations( // this eth1data has enough support to be considered for deposits inclusion. If current vote has // enough support, then use that vote for basis of determining deposits, otherwise use current state // eth1data. +// In the post-electra phase, this function will usually return an empty list, +// as the legacy deposit process is deprecated. (EIP-6110) +// NOTE: During the transition period, the legacy deposit process +// may still be active and managed. This function handles that scenario. func (vs *Server) deposits( ctx context.Context, beaconState state.BeaconState, @@ -87,6 +92,12 @@ func (vs *Server) deposits( log.Warn("not connected to eth1 node, skip pending deposit insertion") return []*ethpb.Deposit{}, nil } + + // skip legacy deposits if eth1 deposit index is already at the index of deposit requests start + if helpers.DepositRequestsStarted(beaconState) { + return []*ethpb.Deposit{}, nil + } + // Need to fetch if the deposits up to the state's latest eth1 data matches // the number of all deposits in this RPC call. If not, then we return nil. canonicalEth1Data, canonicalEth1DataHeight, err := vs.canonicalEth1Data(ctx, beaconState, currentVote) diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_empty_block.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_empty_block.go index 01ea1d46df18..90ac877e3f0b 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_empty_block.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_empty_block.go @@ -16,6 +16,11 @@ func getEmptyBlock(slot primitives.Slot) (interfaces.SignedBeaconBlock, error) { var err error epoch := slots.ToEpoch(slot) switch { + case epoch >= params.BeaconConfig().FuluForkEpoch: + sBlk, err = blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockFulu{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{}}}) + if err != nil { + return nil, status.Errorf(codes.Internal, "Could not initialize block for proposal: %v", err) + } case epoch >= params.BeaconConfig().ElectraForkEpoch: sBlk, err = blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockElectra{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{}}}) if err != nil { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_empty_block_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_empty_block_test.go index 122dc1fcccf2..6a1078e058bc 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_empty_block_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_empty_block_test.go @@ -19,6 +19,7 @@ func Test_getEmptyBlock(t *testing.T) { config.CapellaForkEpoch = 3 config.DenebForkEpoch = 4 config.ElectraForkEpoch = 5 + config.FuluForkEpoch = 6 params.OverrideBeaconConfig(config) tests := []struct { @@ -71,6 +72,15 @@ func Test_getEmptyBlock(t *testing.T) { return b }, }, + { + name: "fulu", + slot: primitives.Slot(params.BeaconConfig().FuluForkEpoch) * params.BeaconConfig().SlotsPerEpoch, + want: func() interfaces.ReadOnlySignedBeaconBlock { + b, err := blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockFulu{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{}}}) + require.NoError(t, err) + return b + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go index 92eb2960dae9..92f3750463d4 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" fastssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -30,10 +31,17 @@ import ( // - Otherwise: // - Determine the vote with the highest count. Prefer the vote with the highest eth1 block height in the event of a tie. // - This vote's block is the eth1 block to use for the block proposal. +// +// After Electra and eth1 deposit transition period voting will no longer be needed func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.BeaconState) (*ethpb.Eth1Data, error) { ctx, cancel := context.WithTimeout(ctx, eth1dataTimeout) defer cancel() + // post eth1 deposits, the Eth 1 data will then be frozen + if helpers.DepositRequestsStarted(beaconState) { + return beaconState.Eth1Data(), nil + } + slot := beaconState.Slot() votingPeriodStartTime := vs.slotStartTime(slot) @@ -54,7 +62,7 @@ func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.Be // by ETH1_FOLLOW_DISTANCE. The head state should maintain the same ETH1Data until this condition has passed, so // trust the existing head for the right eth1 vote until we can get a meaningful value from the deposit contract. if latestValidTime < genesisTime+followDistanceSeconds { - log.WithField("genesisTime", genesisTime).WithField("latestValidTime", latestValidTime).Warn("voting period before genesis + follow distance, using eth1data from head") + log.WithField("genesisTime", genesisTime).WithField("latestValidTime", latestValidTime).Warn("Voting period before genesis + follow distance, using eth1data from head") return vs.HeadFetcher.HeadETH1Data(), nil } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go index 78db18d85c14..e220ac58b611 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_execution_payload.go @@ -21,11 +21,11 @@ import ( payloadattribute "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) var ( @@ -59,20 +59,31 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe slot := blk.Slot() vIdx := blk.ProposerIndex() headRoot := blk.ParentRoot() + + return vs.getLocalPayloadFromEngine(ctx, st, headRoot, slot, vIdx) +} + +// This returns the local execution payload of a slot, proposer ID, and parent root assuming payload Is cached. +// If the payload ID is not cached, the function will prepare a new payload through local EL engine and return it by using the head state. +func (vs *Server) getLocalPayloadFromEngine( + ctx context.Context, + st state.BeaconState, + parentRoot [32]byte, + slot primitives.Slot, + proposerId primitives.ValidatorIndex) (*consensusblocks.GetPayloadResponse, error) { logFields := logrus.Fields{ - "validatorIndex": vIdx, + "validatorIndex": proposerId, "slot": slot, - "headRoot": fmt.Sprintf("%#x", headRoot), + "headRoot": fmt.Sprintf("%#x", parentRoot), } - payloadId, ok := vs.PayloadIDCache.PayloadID(slot, headRoot) + payloadId, ok := vs.PayloadIDCache.PayloadID(slot, parentRoot) - val, tracked := vs.TrackedValidatorsCache.Validator(vIdx) + val, tracked := vs.TrackedValidatorsCache.Validator(proposerId) if !tracked { logrus.WithFields(logFields).Warn("could not find tracked proposer index") } setFeeRecipientIfBurnAddress(&val) - var err error if ok && payloadId != [8]byte{} { // Payload ID is cache hit. Return the cached payload ID. var pid primitives.PayloadID @@ -90,7 +101,7 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe return nil, errors.Wrap(err, "could not get cached payload from execution client") } } - log.WithFields(logFields).Debug("payload ID cache miss") + log.WithFields(logFields).Debug("Payload ID cache miss") parentHash, err := vs.getParentBlockHash(ctx, st, slot) switch { case errors.Is(err, errActivationNotReached) || errors.Is(err, errNoTerminalBlockHash): @@ -125,7 +136,7 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe } var attr payloadattribute.Attributer switch st.Version() { - case version.Deneb, version.Electra: + case version.Deneb, version.Electra, version.Fulu: withdrawals, _, err := st.ExpectedWithdrawals() if err != nil { return nil, err @@ -135,7 +146,7 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe PrevRandao: random, SuggestedFeeRecipient: val.FeeRecipient[:], Withdrawals: withdrawals, - ParentBeaconBlockRoot: headRoot[:], + ParentBeaconBlockRoot: parentRoot[:], }) if err != nil { return nil, err @@ -179,7 +190,7 @@ func (vs *Server) getLocalPayload(ctx context.Context, blk interfaces.ReadOnlyBe } warnIfFeeRecipientDiffers(val.FeeRecipient[:], res.ExecutionData.FeeRecipient()) - log.WithField("value", res.Bid).Debug("received execution payload from local engine") + log.WithField("value", res.Bid).Debug("Received execution payload from local engine") return res, nil } @@ -228,7 +239,8 @@ func (vs *Server) getTerminalBlockHashIfExists(ctx context.Context, transitionTi func (vs *Server) getBuilderPayloadAndBlobs(ctx context.Context, slot primitives.Slot, - vIdx primitives.ValidatorIndex) (builder.Bid, error) { + vIdx primitives.ValidatorIndex, + parentGasLimit uint64) (builder.Bid, error) { ctx, span := trace.StartSpan(ctx, "ProposerServer.getBuilderPayloadAndBlobs") defer span.End() @@ -239,12 +251,12 @@ func (vs *Server) getBuilderPayloadAndBlobs(ctx context.Context, if err != nil { return nil, errors.Wrap(err, "failed to check if we can use the builder") } - span.AddAttributes(trace.BoolAttribute("canUseBuilder", canUseBuilder)) + span.SetAttributes(trace.BoolAttribute("canUseBuilder", canUseBuilder)) if !canUseBuilder { return nil, nil } - return vs.getPayloadHeaderFromBuilder(ctx, slot, vIdx) + return vs.getPayloadHeaderFromBuilder(ctx, slot, vIdx, parentGasLimit) } var errActivationNotReached = errors.New("activation epoch not reached") diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index 39bfb8b6d67c..5b439e0a2f0c 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -90,7 +90,7 @@ func TestServer_GetBeaconBlock_Phase0(t *testing.T) { require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") - proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + proposerServer := getProposerServer(ctx, db, beaconState, parentRoot[:]) randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) require.NoError(t, err) @@ -162,7 +162,7 @@ func TestServer_GetBeaconBlock_Altair(t *testing.T) { require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") - proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + proposerServer := getProposerServer(ctx, db, beaconState, parentRoot[:]) randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) require.NoError(t, err) @@ -275,7 +275,7 @@ func TestServer_GetBeaconBlock_Bellatrix(t *testing.T) { Timestamp: uint64(timeStamp.Unix()), } - proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + proposerServer := getProposerServer(ctx, db, beaconState, parentRoot[:]) proposerServer.Eth1BlockFetcher = c ed, err := blocks.NewWrappedExecutionData(payload) require.NoError(t, err) @@ -401,7 +401,7 @@ func TestServer_GetBeaconBlock_Capella(t *testing.T) { Withdrawals: make([]*enginev1.Withdrawal, 0), } - proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + proposerServer := getProposerServer(ctx, db, beaconState, parentRoot[:]) ed, err := blocks.NewWrappedExecutionData(payload) require.NoError(t, err) proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{ @@ -524,7 +524,7 @@ func TestServer_GetBeaconBlock_Deneb(t *testing.T) { proofs := [][]byte{[]byte("proof"), []byte("proof1"), []byte("proof2")} blobs := [][]byte{[]byte("blob"), []byte("blob1"), []byte("blob2")} bundle := &enginev1.BlobsBundle{KzgCommitments: kc, Proofs: proofs, Blobs: blobs} - proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + proposerServer := getProposerServer(ctx, db, beaconState, parentRoot[:]) proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{ PayloadIDBytes: &enginev1.PayloadIDBytes{1}, GetPayloadResponse: &blocks.GetPayloadResponse{ @@ -586,6 +586,27 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) { require.NoError(t, err) var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte + dr := []*enginev1.DepositRequest{{ + Pubkey: bytesutil.PadTo(privKeys[0].PublicKey().Marshal(), 48), + WithdrawalCredentials: bytesutil.PadTo([]byte("wc"), 32), + Amount: 123, + Signature: bytesutil.PadTo([]byte("sig"), 96), + Index: 456, + }} + wr := []*enginev1.WithdrawalRequest{ + { + SourceAddress: bytesutil.PadTo([]byte("sa"), 20), + ValidatorPubkey: bytesutil.PadTo(privKeys[1].PublicKey().Marshal(), 48), + Amount: 789, + }, + } + cr := []*enginev1.ConsolidationRequest{ + { + SourceAddress: bytesutil.PadTo([]byte("sa"), 20), + SourcePubkey: bytesutil.PadTo(privKeys[1].PublicKey().Marshal(), 48), + TargetPubkey: bytesutil.PadTo(privKeys[2].PublicKey().Marshal(), 48), + }, + } blk := ðpb.SignedBeaconBlockElectra{ Block: ðpb.BeaconBlockElectra{ Slot: electraSlot + 1, @@ -596,7 +617,7 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) { Graffiti: genesis.Block.Body.Graffiti, Eth1Data: genesis.Block.Body.Eth1Data, SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, - ExecutionPayload: &enginev1.ExecutionPayloadElectra{ + ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ ParentHash: make([]byte, fieldparams.RootLength), FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), StateRoot: make([]byte, fieldparams.RootLength), @@ -606,6 +627,11 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) { BaseFeePerGas: make([]byte, fieldparams.RootLength), BlockHash: make([]byte, fieldparams.RootLength), }, + ExecutionRequests: &enginev1.ExecutionRequests{ + Withdrawals: wr, + Deposits: dr, + Consolidations: cr, + }, }, }, } @@ -620,6 +646,75 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) { require.NoError(t, err) timeStamp, err := slots.ToTime(beaconState.GenesisTime(), electraSlot+1) require.NoError(t, err) + payload := &enginev1.ExecutionPayloadDeneb{ + Timestamp: uint64(timeStamp.Unix()), + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: random, + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + } + proposerServer := getProposerServer(ctx, db, beaconState, parentRoot[:]) + ed, err := blocks.NewWrappedExecutionData(payload) + require.NoError(t, err) + proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{ + PayloadIDBytes: &enginev1.PayloadIDBytes{1}, + GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed, ExecutionRequests: &enginev1.ExecutionRequests{ + Withdrawals: wr, + Deposits: dr, + Consolidations: cr, + }}, + } + + randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) + require.NoError(t, err) + + graffiti := bytesutil.ToBytes32([]byte("eth2")) + require.NoError(t, err) + req := ðpb.BlockRequest{ + Slot: electraSlot + 1, + RandaoReveal: randaoReveal, + Graffiti: graffiti[:], + } + + _, err = proposerServer.GetBeaconBlock(ctx, req) + require.NoError(t, err) +} + +func TestServer_GetBeaconBlock_Fulu(t *testing.T) { + db := dbutil.SetupDB(t) + ctx := context.Background() + transition.SkipSlotCache.Disable() + + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.FuluForkEpoch = 6 + cfg.ElectraForkEpoch = 5 + cfg.DenebForkEpoch = 4 + cfg.CapellaForkEpoch = 3 + cfg.BellatrixForkEpoch = 2 + cfg.AltairForkEpoch = 1 + params.OverrideBeaconConfig(cfg) + beaconState, privKeys := util.DeterministicGenesisState(t, 64) + + stateRoot, err := beaconState.HashTreeRoot(ctx) + require.NoError(t, err, "Could not hash genesis state") + + genesis := b.NewGenesisBlock(stateRoot[:]) + util.SaveBlock(t, ctx, db, genesis) + + parentRoot, err := genesis.Block.HashTreeRoot() + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, parentRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, parentRoot), "Could not save genesis state") + + fuluSlot, err := slots.EpochStart(params.BeaconConfig().FuluForkEpoch) + require.NoError(t, err) + + var scBits [fieldparams.SyncAggregateSyncCommitteeBytesLength]byte dr := []*enginev1.DepositRequest{{ Pubkey: bytesutil.PadTo(privKeys[0].PublicKey().Marshal(), 48), WithdrawalCredentials: bytesutil.PadTo([]byte("wc"), 32), @@ -641,27 +736,66 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) { TargetPubkey: bytesutil.PadTo(privKeys[2].PublicKey().Marshal(), 48), }, } - payload := &enginev1.ExecutionPayloadElectra{ - Timestamp: uint64(timeStamp.Unix()), - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, fieldparams.LogsBloomLength), - PrevRandao: random, - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - DepositRequests: dr, - WithdrawalRequests: wr, - ConsolidationRequests: cr, + blk := ðpb.SignedBeaconBlockFulu{ + Block: ðpb.BeaconBlockElectra{ + Slot: fuluSlot + 1, + ParentRoot: parentRoot[:], + StateRoot: genesis.Block.StateRoot, + Body: ðpb.BeaconBlockBodyElectra{ + RandaoReveal: genesis.Block.Body.RandaoReveal, + Graffiti: genesis.Block.Body.Graffiti, + Eth1Data: genesis.Block.Body.Eth1Data, + SyncAggregate: ðpb.SyncAggregate{SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96)}, + ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: make([]byte, fieldparams.RootLength), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, + ExecutionRequests: &enginev1.ExecutionRequests{ + Withdrawals: wr, + Deposits: dr, + Consolidations: cr, + }, + }, + }, } - proposerServer := getProposerServer(db, beaconState, parentRoot[:]) + blkRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + require.NoError(t, err, "Could not get signing root") + require.NoError(t, db.SaveState(ctx, beaconState, blkRoot), "Could not save genesis state") + require.NoError(t, db.SaveHeadBlockRoot(ctx, blkRoot), "Could not save genesis state") + + random, err := helpers.RandaoMix(beaconState, slots.ToEpoch(beaconState.Slot())) + require.NoError(t, err) + timeStamp, err := slots.ToTime(beaconState.GenesisTime(), fuluSlot+1) + require.NoError(t, err) + payload := &enginev1.ExecutionPayloadDeneb{ + Timestamp: uint64(timeStamp.Unix()), + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, fieldparams.LogsBloomLength), + PrevRandao: random, + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + } + proposerServer := getProposerServer(ctx, db, beaconState, parentRoot[:]) ed, err := blocks.NewWrappedExecutionData(payload) require.NoError(t, err) proposerServer.ExecutionEngineCaller = &mockExecution.EngineClient{ - PayloadIDBytes: &enginev1.PayloadIDBytes{1}, - GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed}, + PayloadIDBytes: &enginev1.PayloadIDBytes{1}, + GetPayloadResponse: &blocks.GetPayloadResponse{ExecutionData: ed, ExecutionRequests: &enginev1.ExecutionRequests{ + Withdrawals: wr, + Deposits: dr, + Consolidations: cr, + }}, } randaoReveal, err := util.RandaoReveal(beaconState, 0, privKeys) @@ -670,16 +804,13 @@ func TestServer_GetBeaconBlock_Electra(t *testing.T) { graffiti := bytesutil.ToBytes32([]byte("eth2")) require.NoError(t, err) req := ðpb.BlockRequest{ - Slot: electraSlot + 1, + Slot: fuluSlot + 1, RandaoReveal: randaoReveal, Graffiti: graffiti[:], } - got, err := proposerServer.GetBeaconBlock(ctx, req) + _, err = proposerServer.GetBeaconBlock(ctx, req) require.NoError(t, err) - p := got.GetElectra().Block.Body.ExecutionPayload - require.DeepEqual(t, dr, p.DepositRequests) - require.DeepEqual(t, wr, p.WithdrawalRequests) } func TestServer_GetBeaconBlock_Optimistic(t *testing.T) { @@ -709,7 +840,7 @@ func TestServer_GetBeaconBlock_Optimistic(t *testing.T) { require.ErrorContains(t, errOptimisticMode.Error(), err) } -func getProposerServer(db db.HeadAccessDatabase, headState state.BeaconState, headRoot []byte) *Server { +func getProposerServer(ctx context.Context, db db.HeadAccessDatabase, headState state.BeaconState, headRoot []byte) *Server { mockChainService := &mock.ChainService{State: headState, Root: headRoot, ForkChoiceStore: doublylinkedtree.New()} return &Server{ HeadFetcher: mockChainService, @@ -879,33 +1010,6 @@ func TestProposer_ProposeBlock_OK(t *testing.T) { }, err: "blob KZG commitments don't match number of blobs or KZG proofs", }, - { - name: "electra block no blob", - block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock { - sb := ðpb.SignedBeaconBlockContentsElectra{ - Block: ðpb.SignedBeaconBlockElectra{ - Block: ðpb.BeaconBlockElectra{Slot: 5, ParentRoot: parent[:], Body: util.HydrateBeaconBlockBodyElectra(ðpb.BeaconBlockBodyElectra{})}, - }, - } - blk := ðpb.GenericSignedBeaconBlock_Electra{Electra: sb} - return ðpb.GenericSignedBeaconBlock{Block: blk, IsBlinded: false} - }, - }, - { - name: "electra block some blob", - block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock { - - sb := ðpb.SignedBeaconBlockContentsElectra{ - Block: ðpb.SignedBeaconBlockElectra{ - Block: ðpb.BeaconBlockElectra{Slot: 5, ParentRoot: parent[:], Body: util.HydrateBeaconBlockBodyElectra(ðpb.BeaconBlockBodyElectra{})}, - }, - KzgProofs: [][]byte{{0x01}, {0x02}, {0x03}}, - Blobs: [][]byte{{0x01}, {0x02}, {0x03}}, - } - blk := ðpb.GenericSignedBeaconBlock_Electra{Electra: sb} - return ðpb.GenericSignedBeaconBlock{Block: blk, IsBlinded: false} - }, - }, { name: "blind deneb block some blobs", block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock { @@ -941,7 +1045,58 @@ func TestProposer_ProposeBlock_OK(t *testing.T) { return ðpb.GenericSignedBeaconBlock{Block: blk} }, useBuilder: true, - err: "unblind sidecars failed: commitment value doesn't match block", + err: "unblind blobs sidecars: commitment value doesn't match block", + }, + { + name: "electra block no blob", + block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock { + sb := ðpb.SignedBeaconBlockContentsElectra{ + Block: ðpb.SignedBeaconBlockElectra{ + Block: ðpb.BeaconBlockElectra{Slot: 5, ParentRoot: parent[:], Body: util.HydrateBeaconBlockBodyElectra(ðpb.BeaconBlockBodyElectra{})}, + }, + } + blk := ðpb.GenericSignedBeaconBlock_Electra{Electra: sb} + return ðpb.GenericSignedBeaconBlock{Block: blk, IsBlinded: false} + }, + }, + { + name: "electra block some blob", + block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock { + sb := ðpb.SignedBeaconBlockContentsElectra{ + Block: ðpb.SignedBeaconBlockElectra{ + Block: ðpb.BeaconBlockElectra{ + Slot: 5, ParentRoot: parent[:], + Body: util.HydrateBeaconBlockBodyElectra(ðpb.BeaconBlockBodyElectra{ + BlobKzgCommitments: [][]byte{bytesutil.PadTo([]byte("kc"), 48), bytesutil.PadTo([]byte("kc1"), 48), bytesutil.PadTo([]byte("kc2"), 48)}, + }), + }, + }, + KzgProofs: [][]byte{{0x01}, {0x02}, {0x03}}, + Blobs: [][]byte{{0x01}, {0x02}, {0x03}}, + } + blk := ðpb.GenericSignedBeaconBlock_Electra{Electra: sb} + return ðpb.GenericSignedBeaconBlock{Block: blk, IsBlinded: false} + }, + }, + { + name: "electra block some blob (kzg and blob count mismatch)", + block: func(parent [32]byte) *ethpb.GenericSignedBeaconBlock { + sb := ðpb.SignedBeaconBlockContentsElectra{ + Block: ðpb.SignedBeaconBlockElectra{ + Block: ðpb.BeaconBlockElectra{ + Slot: 5, ParentRoot: parent[:], + Body: util.HydrateBeaconBlockBodyElectra(ðpb.BeaconBlockBodyElectra{ + BlobKzgCommitments: [][]byte{bytesutil.PadTo([]byte("kc"), 48), bytesutil.PadTo([]byte("kc1"), 48)}, + }), + }, + }, + KzgProofs: [][]byte{{0x01}, {0x02}, {0x03}}, + Blobs: [][]byte{{0x01}, {0x02}, {0x03}}, + } + blk := ðpb.GenericSignedBeaconBlock_Electra{Electra: sb} + return ðpb.GenericSignedBeaconBlock{Block: blk, IsBlinded: false} + }, + err: "blob KZG commitments don't match number of blobs or KZG proofs", }, } @@ -2543,6 +2698,41 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) { expectedHash := []byte("eth1data") assert.DeepEqual(t, expectedHash, hash) }) + + t.Run("post electra the head eth1data should be returned", func(t *testing.T) { + p := mockExecution.New(). + InsertBlock(50, earliestValidTime, []byte("earliest")). + InsertBlock(100, latestValidTime, []byte("latest")) + p.Eth1Data = ðpb.Eth1Data{ + BlockHash: []byte("eth1data"), + } + + depositCache, err := depositsnapshot.New() + require.NoError(t, err) + + beaconState, err := state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{ + Slot: slot, + Eth1Data: ðpb.Eth1Data{BlockHash: []byte("legacy"), DepositCount: 1}, + }) + require.NoError(t, err) + + ps := &Server{ + ChainStartFetcher: p, + Eth1InfoFetcher: p, + Eth1BlockFetcher: p, + BlockFetcher: p, + DepositFetcher: depositCache, + } + + ctx := context.Background() + majorityVoteEth1Data, err := ps.eth1DataMajorityVote(ctx, beaconState) + require.NoError(t, err) + + hash := majorityVoteEth1Data.BlockHash + + expectedHash := []byte("legacy") + assert.DeepEqual(t, expectedHash, hash) + }) } func TestProposer_FilterAttestation(t *testing.T) { @@ -2558,7 +2748,6 @@ func TestProposer_FilterAttestation(t *testing.T) { tests := []struct { name string - wantedErr string inputAtts func() []ethpb.Att expectedAtts func(inputAtts []ethpb.Att) []ethpb.Att }{ @@ -2634,14 +2823,8 @@ func TestProposer_FilterAttestation(t *testing.T) { HeadFetcher: &mock.ChainService{State: st, Root: genesisRoot[:]}, } atts := tt.inputAtts() - received, err := proposerServer.validateAndDeleteAttsInPool(context.Background(), st, atts) - if tt.wantedErr != "" { - assert.ErrorContains(t, tt.wantedErr, err) - assert.Equal(t, nil, received) - } else { - assert.NoError(t, err) - assert.DeepEqual(t, tt.expectedAtts(atts), received) - } + received := proposerServer.validateAndDeleteAttsInPool(context.Background(), st, atts) + assert.DeepEqual(t, tt.expectedAtts(atts), received) }) } } @@ -3092,3 +3275,15 @@ func TestProposer_GetParentHeadState(t *testing.T) { require.LogsContain(t, hook, "late block attempted reorg failed") }) } + +func TestProposer_ElectraBlobsAndProofs(t *testing.T) { + electraContents := ðpb.SignedBeaconBlockContentsElectra{Block: ðpb.SignedBeaconBlockElectra{}} + electraContents.KzgProofs = make([][]byte, 10) + electraContents.Blobs = make([][]byte, 10) + + genBlock := ðpb.GenericSignedBeaconBlock{Block: ðpb.GenericSignedBeaconBlock_Electra{Electra: electraContents}} + blobs, proofs, err := blobsAndProofs(genBlock) + require.NoError(t, err) + require.Equal(t, 10, len(blobs)) + require.Equal(t, 10, len(proofs)) +} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go index 5dc6190151f6..d125abfbd694 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/server.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/server.go @@ -32,7 +32,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/network/forks" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "github.com/prysmaticlabs/prysm/v5/time/slots" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" @@ -43,47 +42,50 @@ import ( // and committees in which particular validators need to perform their responsibilities, // and more. type Server struct { - Ctx context.Context - PayloadIDCache *cache.PayloadIDCache - TrackedValidatorsCache *cache.TrackedValidatorsCache - HeadFetcher blockchain.HeadFetcher - ForkFetcher blockchain.ForkFetcher - ForkchoiceFetcher blockchain.ForkchoiceFetcher - GenesisFetcher blockchain.GenesisFetcher - FinalizationFetcher blockchain.FinalizationFetcher - TimeFetcher blockchain.TimeFetcher - BlockFetcher execution.POWBlockFetcher - DepositFetcher cache.DepositFetcher - ChainStartFetcher execution.ChainStartFetcher - Eth1InfoFetcher execution.ChainInfoFetcher - OptimisticModeFetcher blockchain.OptimisticModeFetcher - SyncChecker sync.Checker - StateNotifier statefeed.Notifier - BlockNotifier blockfeed.Notifier - P2P p2p.Broadcaster - AttPool attestations.Pool - SlashingsPool slashings.PoolManager - ExitPool voluntaryexits.PoolManager - SyncCommitteePool synccommittee.Pool - BlockReceiver blockchain.BlockReceiver - BlobReceiver blockchain.BlobReceiver - MockEth1Votes bool - Eth1BlockFetcher execution.POWBlockFetcher - PendingDepositsFetcher depositsnapshot.PendingDepositsFetcher - OperationNotifier opfeed.Notifier - StateGen stategen.StateManager - ReplayerBuilder stategen.ReplayerBuilder - BeaconDB db.HeadAccessDatabase - ExecutionEngineCaller execution.EngineCaller - BlockBuilder builder.BlockBuilder - BLSChangesPool blstoexec.PoolManager - ClockWaiter startup.ClockWaiter - CoreService *core.Service + Ctx context.Context + PayloadIDCache *cache.PayloadIDCache + TrackedValidatorsCache *cache.TrackedValidatorsCache + HeadFetcher blockchain.HeadFetcher + ForkFetcher blockchain.ForkFetcher + ForkchoiceFetcher blockchain.ForkchoiceFetcher + GenesisFetcher blockchain.GenesisFetcher + FinalizationFetcher blockchain.FinalizationFetcher + TimeFetcher blockchain.TimeFetcher + BlockFetcher execution.POWBlockFetcher + DepositFetcher cache.DepositFetcher + ChainStartFetcher execution.ChainStartFetcher + Eth1InfoFetcher execution.ChainInfoFetcher + OptimisticModeFetcher blockchain.OptimisticModeFetcher + SyncChecker sync.Checker + StateNotifier statefeed.Notifier + BlockNotifier blockfeed.Notifier + P2P p2p.Broadcaster + AttestationCache *cache.AttestationCache + AttPool attestations.Pool + SlashingsPool slashings.PoolManager + ExitPool voluntaryexits.PoolManager + SyncCommitteePool synccommittee.Pool + BlockReceiver blockchain.BlockReceiver + BlobReceiver blockchain.BlobReceiver + MockEth1Votes bool + Eth1BlockFetcher execution.POWBlockFetcher + PendingDepositsFetcher depositsnapshot.PendingDepositsFetcher + OperationNotifier opfeed.Notifier + StateGen stategen.StateManager + ReplayerBuilder stategen.ReplayerBuilder + BeaconDB db.HeadAccessDatabase + ExecutionEngineCaller execution.EngineCaller + BlockBuilder builder.BlockBuilder + BLSChangesPool blstoexec.PoolManager + ClockWaiter startup.ClockWaiter + CoreService *core.Service + AttestationStateFetcher blockchain.AttestationStateFetcher } // WaitForActivation checks if a validator public key exists in the active validator registry of the current // beacon state, if not, then it creates a stream which listens for canonical states which contain // the validator with the public key as an active validator record. +// Deprecated: do not use, just poll validator status every epoch. func (vs *Server) WaitForActivation(req *ethpb.ValidatorActivationRequest, stream ethpb.BeaconNodeValidator_WaitForActivationServer) error { activeValidatorExists, validatorStatuses, err := vs.activationStatus(stream.Context(), req.PublicKeys) if err != nil { @@ -207,25 +209,3 @@ func (vs *Server) WaitForChainStart(_ *emptypb.Empty, stream ethpb.BeaconNodeVal } return stream.Send(res) } - -// PruneBlobsBundleCacheRoutine prunes the blobs bundle cache at 6s mark of the slot. -func (vs *Server) PruneBlobsBundleCacheRoutine() { - go func() { - clock, err := vs.ClockWaiter.WaitForClock(vs.Ctx) - if err != nil { - log.WithError(err).Error("PruneBlobsBundleCacheRoutine failed to receive genesis data") - return - } - - pruneInterval := time.Second * time.Duration(params.BeaconConfig().SecondsPerSlot/2) - ticker := slots.NewSlotTickerWithIntervals(clock.GenesisTime(), []time.Duration{pruneInterval}) - for { - select { - case <-vs.Ctx.Done(): - return - case slotInterval := <-ticker.C(): - bundleCache.prune(slotInterval.Slot) - } - } - }() -} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/status.go b/beacon-chain/rpc/prysm/v1alpha1/validator/status.go index 67bf6da2a60d..1d8e22d6b98d 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/status.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/status.go @@ -14,10 +14,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/contracts/deposit" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -269,7 +269,7 @@ func (vs *Server) optimisticStatus(ctx context.Context) error { return nil } - return status.Errorf(codes.Unavailable, errOptimisticMode.Error()) + return status.Errorf(codes.Unavailable, "error=%v", errOptimisticMode) } // validatorStatus searches for the requested validator's state and deposit to retrieve its inclusion estimate. Also returns the validators index. @@ -287,6 +287,9 @@ func (vs *Server) validatorStatus( Status: ethpb.ValidatorStatus_UNKNOWN_STATUS, ActivationEpoch: params.BeaconConfig().FarFutureEpoch, } + if len(pubKey) == 0 { + return resp, nonExistentIndex + } vStatus, idx, err := statusForPubKey(headState, pubKey) if err != nil && !errors.Is(err, errPubkeyDoesNotExist) { tracing.AnnotateError(span, err) @@ -402,16 +405,13 @@ func statusForPubKey(headState state.ReadOnlyBeaconState, pubKey []byte) (ethpb. func assignmentStatus(beaconState state.ReadOnlyBeaconState, validatorIndex primitives.ValidatorIndex) ethpb.ValidatorStatus { validator, err := beaconState.ValidatorAtIndexReadOnly(validatorIndex) - if err != nil { + if err != nil || validator.IsNil() { return ethpb.ValidatorStatus_UNKNOWN_STATUS } + currentEpoch := time.CurrentEpoch(beaconState) farFutureEpoch := params.BeaconConfig().FarFutureEpoch validatorBalance := validator.EffectiveBalance() - - if validator.IsNil() { - return ethpb.ValidatorStatus_UNKNOWN_STATUS - } if currentEpoch < validator.ActivationEligibilityEpoch() { return depositStatus(validatorBalance) } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/sync_committee.go b/beacon-chain/rpc/prysm/v1alpha1/validator/sync_committee.go index aa90df196d44..291b8fdef34a 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/sync_committee.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/sync_committee.go @@ -36,7 +36,7 @@ func (vs *Server) GetSyncMessageBlockRoot( // It also saves the sync committee message into the pending pool for block inclusion. func (vs *Server) SubmitSyncMessage(ctx context.Context, msg *ethpb.SyncCommitteeMessage) (*emptypb.Empty, error) { if err := vs.CoreService.SubmitSyncMessage(ctx, msg); err != nil { - return &emptypb.Empty{}, status.Errorf(core.ErrorReasonToGRPC(err.Reason), err.Err.Error()) + return &emptypb.Empty{}, status.Errorf(core.ErrorReasonToGRPC(err.Reason), "error=%s", err.Err) } return &emptypb.Empty{}, nil } @@ -105,7 +105,7 @@ func (vs *Server) SubmitSignedContributionAndProof( ) (*emptypb.Empty, error) { err := vs.CoreService.SubmitSignedContributionAndProof(ctx, s) if err != nil { - return &emptypb.Empty{}, status.Errorf(core.ErrorReasonToGRPC(err.Reason), err.Err.Error()) + return &emptypb.Empty{}, status.Errorf(core.ErrorReasonToGRPC(err.Reason), "error=%s", err.Err) } return &emptypb.Empty{}, nil } diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/validator_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/validator_test.go index a31f948f785b..14a7240551ac 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/validator_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/validator_test.go @@ -2,6 +2,7 @@ package validator import ( "io" + "os" "testing" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -16,5 +17,5 @@ func TestMain(m *testing.M) { defer params.OverrideBeaconConfig(prevConfig) params.OverrideBeaconConfig(params.MinimalSpecConfig()) - m.Run() + os.Exit(m.Run()) } diff --git a/beacon-chain/rpc/prysm/validator/BUILD.bazel b/beacon-chain/rpc/prysm/validator/BUILD.bazel index 86cdf38192b0..22baf6da1d2c 100644 --- a/beacon-chain/rpc/prysm/validator/BUILD.bazel +++ b/beacon-chain/rpc/prysm/validator/BUILD.bazel @@ -17,13 +17,12 @@ go_library( "//beacon-chain/rpc/eth/shared:go_default_library", "//beacon-chain/rpc/lookup:go_default_library", "//consensus-types/primitives:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -64,7 +63,6 @@ go_test( "//time:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], ) diff --git a/beacon-chain/rpc/prysm/validator/handlers.go b/beacon-chain/rpc/prysm/validator/handlers.go index 4c48a8708876..f7082a6d66d3 100644 --- a/beacon-chain/rpc/prysm/validator/handlers.go +++ b/beacon-chain/rpc/prysm/validator/handlers.go @@ -5,14 +5,13 @@ import ( "net/http" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // GetParticipation retrieves the validator participation information for a given epoch, @@ -22,7 +21,7 @@ func (s *Server) GetParticipation(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "validator.GetParticipation") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return @@ -67,7 +66,7 @@ func (s *Server) GetActiveSetChanges(w http.ResponseWriter, r *http.Request) { ctx, span := trace.StartSpan(r.Context(), "validator.GetActiveSetChanges") defer span.End() - stateId := mux.Vars(r)["state_id"] + stateId := r.PathValue("state_id") if stateId == "" { httputil.HandleError(w, "state_id is required in URL params", http.StatusBadRequest) return diff --git a/beacon-chain/rpc/prysm/validator/handlers_test.go b/beacon-chain/rpc/prysm/validator/handlers_test.go index 9956926e54e9..0d84df4c1b9e 100644 --- a/beacon-chain/rpc/prysm/validator/handlers_test.go +++ b/beacon-chain/rpc/prysm/validator/handlers_test.go @@ -13,7 +13,6 @@ import ( "time" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/api/server/structs" mock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" @@ -150,7 +149,7 @@ func TestServer_GetValidatorParticipation_CurrentAndPrevEpoch(t *testing.T) { url := "http://example.com" request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -250,7 +249,7 @@ func TestServer_GetValidatorParticipation_OrphanedUntilGenesis(t *testing.T) { url := "http://example.com" request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -380,7 +379,7 @@ func runGetValidatorParticipationCurrentEpoch(t *testing.T, genState state.Beaco url := "http://example.com" request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "head"}) + request.SetPathValue("state_id", "head") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -430,7 +429,7 @@ func TestServer_GetValidatorActiveSetChanges_NoState(t *testing.T) { url := "http://example.com" + fmt.Sprintf("%d", slots.ToEpoch(s.CoreService.GenesisTimeFetcher.CurrentSlot())+1) request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": ""}) + request.SetPathValue("state_id", "") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} @@ -507,7 +506,7 @@ func TestServer_GetValidatorActiveSetChanges(t *testing.T) { url := "http://example.com" request := httptest.NewRequest(http.MethodGet, url, nil) - request = mux.SetURLVars(request, map[string]string{"state_id": "genesis"}) + request.SetPathValue("state_id", "genesis") writer := httptest.NewRecorder() writer.Body = &bytes.Buffer{} diff --git a/beacon-chain/rpc/prysm/validator/validator_performance.go b/beacon-chain/rpc/prysm/validator/validator_performance.go index faa8325a78b9..a924dc090607 100644 --- a/beacon-chain/rpc/prysm/validator/validator_performance.go +++ b/beacon-chain/rpc/prysm/validator/validator_performance.go @@ -8,9 +8,9 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/core" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // GetPerformance is an HTTP handler for GetPerformance. diff --git a/beacon-chain/rpc/service.go b/beacon-chain/rpc/service.go index 335b60e0ad38..08585a2201bb 100644 --- a/beacon-chain/rpc/service.go +++ b/beacon-chain/rpc/service.go @@ -4,17 +4,16 @@ package rpc import ( "context" + "fmt" "net" + "net/http" "sync" - "github.com/gorilla/mux" middleware "github.com/grpc-ecosystem/go-grpc-middleware" recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" grpcprometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/builder" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" @@ -56,24 +55,6 @@ import ( const attestationBufferSize = 100 -var ( - httpRequestLatency = promauto.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "http_request_latency_seconds", - Help: "Latency of HTTP requests in seconds", - Buckets: []float64{0.001, 0.01, 0.025, 0.1, 0.25, 1, 2.5, 10}, - }, - []string{"endpoint", "code", "method"}, - ) - httpRequestCount = promauto.NewCounterVec( - prometheus.CounterOpts{ - Name: "http_request_count", - Help: "Number of HTTP requests", - }, - []string{"endpoint", "code", "method"}, - ) -) - // Service defining an RPC server for a beacon node. type Service struct { cfg *Config @@ -90,55 +71,56 @@ type Service struct { // Config options for the beacon node RPC server. type Config struct { - ExecutionPayloadReconstructor execution.PayloadReconstructor - Host string - Port string - CertFlag string - KeyFlag string - BeaconMonitoringHost string - BeaconMonitoringPort int - BeaconDB db.HeadAccessDatabase - ChainInfoFetcher blockchain.ChainInfoFetcher - HeadFetcher blockchain.HeadFetcher - CanonicalFetcher blockchain.CanonicalFetcher - ForkFetcher blockchain.ForkFetcher - ForkchoiceFetcher blockchain.ForkchoiceFetcher - FinalizationFetcher blockchain.FinalizationFetcher - AttestationReceiver blockchain.AttestationReceiver - BlockReceiver blockchain.BlockReceiver - BlobReceiver blockchain.BlobReceiver - ExecutionChainService execution.Chain - ChainStartFetcher execution.ChainStartFetcher - ExecutionChainInfoFetcher execution.ChainInfoFetcher - GenesisTimeFetcher blockchain.TimeFetcher - GenesisFetcher blockchain.GenesisFetcher - MockEth1Votes bool - EnableDebugRPCEndpoints bool - AttestationsPool attestations.Pool - ExitPool voluntaryexits.PoolManager - SlashingsPool slashings.PoolManager - SyncCommitteeObjectPool synccommittee.Pool - BLSChangesPool blstoexec.PoolManager - SyncService chainSync.Checker - Broadcaster p2p.Broadcaster - PeersFetcher p2p.PeersProvider - PeerManager p2p.PeerManager - MetadataProvider p2p.MetadataProvider - DepositFetcher cache.DepositFetcher - PendingDepositFetcher depositsnapshot.PendingDepositsFetcher - StateNotifier statefeed.Notifier - BlockNotifier blockfeed.Notifier - OperationNotifier opfeed.Notifier - StateGen *stategen.State - MaxMsgSize int - ExecutionEngineCaller execution.EngineCaller - OptimisticModeFetcher blockchain.OptimisticModeFetcher - BlockBuilder builder.BlockBuilder - Router *mux.Router - ClockWaiter startup.ClockWaiter - BlobStorage *filesystem.BlobStorage - TrackedValidatorsCache *cache.TrackedValidatorsCache - PayloadIDCache *cache.PayloadIDCache + ExecutionReconstructor execution.Reconstructor + Host string + Port string + CertFlag string + KeyFlag string + BeaconMonitoringHost string + BeaconMonitoringPort int + BeaconDB db.HeadAccessDatabase + ChainInfoFetcher blockchain.ChainInfoFetcher + HeadFetcher blockchain.HeadFetcher + CanonicalFetcher blockchain.CanonicalFetcher + ForkFetcher blockchain.ForkFetcher + ForkchoiceFetcher blockchain.ForkchoiceFetcher + FinalizationFetcher blockchain.FinalizationFetcher + AttestationReceiver blockchain.AttestationReceiver + BlockReceiver blockchain.BlockReceiver + BlobReceiver blockchain.BlobReceiver + ExecutionChainService execution.Chain + ChainStartFetcher execution.ChainStartFetcher + ExecutionChainInfoFetcher execution.ChainInfoFetcher + GenesisTimeFetcher blockchain.TimeFetcher + GenesisFetcher blockchain.GenesisFetcher + MockEth1Votes bool + EnableDebugRPCEndpoints bool + AttestationCache *cache.AttestationCache + AttestationsPool attestations.Pool + ExitPool voluntaryexits.PoolManager + SlashingsPool slashings.PoolManager + SyncCommitteeObjectPool synccommittee.Pool + BLSChangesPool blstoexec.PoolManager + SyncService chainSync.Checker + Broadcaster p2p.Broadcaster + PeersFetcher p2p.PeersProvider + PeerManager p2p.PeerManager + MetadataProvider p2p.MetadataProvider + DepositFetcher cache.DepositFetcher + PendingDepositFetcher depositsnapshot.PendingDepositsFetcher + StateNotifier statefeed.Notifier + BlockNotifier blockfeed.Notifier + OperationNotifier opfeed.Notifier + StateGen *stategen.State + MaxMsgSize int + ExecutionEngineCaller execution.EngineCaller + OptimisticModeFetcher blockchain.OptimisticModeFetcher + BlockBuilder builder.BlockBuilder + Router *http.ServeMux + ClockWaiter startup.ClockWaiter + BlobStorage *filesystem.BlobStorage + TrackedValidatorsCache *cache.TrackedValidatorsCache + PayloadIDCache *cache.PayloadIDCache } // NewService instantiates a new RPC service instance that will @@ -222,7 +204,7 @@ func NewService(ctx context.Context, cfg *Config) *Service { Broadcaster: s.cfg.Broadcaster, SyncCommitteePool: s.cfg.SyncCommitteeObjectPool, OperationNotifier: s.cfg.OperationNotifier, - AttestationCache: cache.NewAttestationCache(), + AttestationCache: cache.NewAttestationDataCache(), StateGen: s.cfg.StateGen, P2P: s.cfg.Broadcaster, FinalizedFetcher: s.cfg.FinalizationFetcher, @@ -230,42 +212,44 @@ func NewService(ctx context.Context, cfg *Config) *Service { OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, } validatorServer := &validatorv1alpha1.Server{ - Ctx: s.ctx, - AttPool: s.cfg.AttestationsPool, - ExitPool: s.cfg.ExitPool, - HeadFetcher: s.cfg.HeadFetcher, - ForkFetcher: s.cfg.ForkFetcher, - ForkchoiceFetcher: s.cfg.ForkchoiceFetcher, - GenesisFetcher: s.cfg.GenesisFetcher, - FinalizationFetcher: s.cfg.FinalizationFetcher, - TimeFetcher: s.cfg.GenesisTimeFetcher, - BlockFetcher: s.cfg.ExecutionChainService, - DepositFetcher: s.cfg.DepositFetcher, - ChainStartFetcher: s.cfg.ChainStartFetcher, - Eth1InfoFetcher: s.cfg.ExecutionChainService, - OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, - SyncChecker: s.cfg.SyncService, - StateNotifier: s.cfg.StateNotifier, - BlockNotifier: s.cfg.BlockNotifier, - OperationNotifier: s.cfg.OperationNotifier, - P2P: s.cfg.Broadcaster, - BlockReceiver: s.cfg.BlockReceiver, - BlobReceiver: s.cfg.BlobReceiver, - MockEth1Votes: s.cfg.MockEth1Votes, - Eth1BlockFetcher: s.cfg.ExecutionChainService, - PendingDepositsFetcher: s.cfg.PendingDepositFetcher, - SlashingsPool: s.cfg.SlashingsPool, - StateGen: s.cfg.StateGen, - SyncCommitteePool: s.cfg.SyncCommitteeObjectPool, - ReplayerBuilder: ch, - ExecutionEngineCaller: s.cfg.ExecutionEngineCaller, - BeaconDB: s.cfg.BeaconDB, - BlockBuilder: s.cfg.BlockBuilder, - BLSChangesPool: s.cfg.BLSChangesPool, - ClockWaiter: s.cfg.ClockWaiter, - CoreService: coreService, - TrackedValidatorsCache: s.cfg.TrackedValidatorsCache, - PayloadIDCache: s.cfg.PayloadIDCache, + Ctx: s.ctx, + AttestationCache: s.cfg.AttestationCache, + AttPool: s.cfg.AttestationsPool, + ExitPool: s.cfg.ExitPool, + HeadFetcher: s.cfg.HeadFetcher, + ForkFetcher: s.cfg.ForkFetcher, + ForkchoiceFetcher: s.cfg.ForkchoiceFetcher, + GenesisFetcher: s.cfg.GenesisFetcher, + FinalizationFetcher: s.cfg.FinalizationFetcher, + TimeFetcher: s.cfg.GenesisTimeFetcher, + BlockFetcher: s.cfg.ExecutionChainService, + DepositFetcher: s.cfg.DepositFetcher, + ChainStartFetcher: s.cfg.ChainStartFetcher, + Eth1InfoFetcher: s.cfg.ExecutionChainService, + OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, + SyncChecker: s.cfg.SyncService, + StateNotifier: s.cfg.StateNotifier, + BlockNotifier: s.cfg.BlockNotifier, + OperationNotifier: s.cfg.OperationNotifier, + P2P: s.cfg.Broadcaster, + BlockReceiver: s.cfg.BlockReceiver, + BlobReceiver: s.cfg.BlobReceiver, + MockEth1Votes: s.cfg.MockEth1Votes, + Eth1BlockFetcher: s.cfg.ExecutionChainService, + PendingDepositsFetcher: s.cfg.PendingDepositFetcher, + SlashingsPool: s.cfg.SlashingsPool, + StateGen: s.cfg.StateGen, + SyncCommitteePool: s.cfg.SyncCommitteeObjectPool, + ReplayerBuilder: ch, + ExecutionEngineCaller: s.cfg.ExecutionEngineCaller, + BeaconDB: s.cfg.BeaconDB, + BlockBuilder: s.cfg.BlockBuilder, + BLSChangesPool: s.cfg.BLSChangesPool, + ClockWaiter: s.cfg.ClockWaiter, + CoreService: coreService, + TrackedValidatorsCache: s.cfg.TrackedValidatorsCache, + PayloadIDCache: s.cfg.PayloadIDCache, + AttestationStateFetcher: s.cfg.AttestationReceiver, } s.validatorServer = validatorServer nodeServer := &nodev1alpha1.Server{ @@ -285,6 +269,7 @@ func NewService(ctx context.Context, cfg *Config) *Service { beaconChainServer := &beaconv1alpha1.Server{ Ctx: s.ctx, BeaconDB: s.cfg.BeaconDB, + AttestationCache: s.cfg.AttestationCache, AttestationsPool: s.cfg.AttestationsPool, SlashingsPool: s.cfg.SlashingsPool, OptimisticModeFetcher: s.cfg.OptimisticModeFetcher, @@ -309,10 +294,12 @@ func NewService(ctx context.Context, cfg *Config) *Service { endpoints := s.endpoints(s.cfg.EnableDebugRPCEndpoints, blocker, stater, rewardFetcher, validatorServer, coreService, ch) for _, e := range endpoints { - s.cfg.Router.HandleFunc( - e.template, - e.handlerWithMiddleware(), - ).Methods(e.methods...) + for i := range e.methods { + s.cfg.Router.HandleFunc( + fmt.Sprintf("%s %s", e.methods[i], e.template), + e.handlerWithMiddleware(), + ) + } } ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer) @@ -344,7 +331,6 @@ var _ stategen.CurrentSlotter = blockchain.ChainInfoFetcher(nil) // Start the gRPC server. func (s *Service) Start() { grpcprometheus.EnableHandlingTimeHistogram() - s.validatorServer.PruneBlobsBundleCacheRoutine() go func() { if s.listener != nil { if err := s.grpcServer.Serve(s.listener); err != nil { diff --git a/beacon-chain/rpc/service_test.go b/beacon-chain/rpc/service_test.go index 13d8e2fde61f..4cd599c41913 100644 --- a/beacon-chain/rpc/service_test.go +++ b/beacon-chain/rpc/service_test.go @@ -4,10 +4,10 @@ import ( "context" "errors" "io" + "net/http" "testing" "time" - "github.com/gorilla/mux" mock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" mockExecution "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" @@ -49,7 +49,7 @@ func TestLifecycle_OK(t *testing.T) { GenesisTimeFetcher: chainService, ExecutionChainService: &mockExecution.Chain{}, StateNotifier: chainService.StateNotifier(), - Router: mux.NewRouter(), + Router: http.NewServeMux(), ClockWaiter: startup.NewClockSynchronizer(), }) @@ -91,7 +91,7 @@ func TestRPC_InsecureEndpoint(t *testing.T) { HeadFetcher: chainService, ExecutionChainService: &mockExecution.Chain{}, StateNotifier: chainService.StateNotifier(), - Router: mux.NewRouter(), + Router: http.NewServeMux(), ClockWaiter: startup.NewClockSynchronizer(), }) diff --git a/beacon-chain/slasher/BUILD.bazel b/beacon-chain/slasher/BUILD.bazel index 00bf4aaaeacc..f8665433b4d1 100644 --- a/beacon-chain/slasher/BUILD.bazel +++ b/beacon-chain/slasher/BUILD.bazel @@ -39,15 +39,15 @@ go_library( "//consensus-types/primitives:go_default_library", "//container/slice:go_default_library", "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", - "@org_golang_x_exp//maps:go_default_library", ], ) @@ -83,6 +83,7 @@ go_test( "//crypto/bls/common:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", diff --git a/beacon-chain/slasher/chunks.go b/beacon-chain/slasher/chunks.go index 01b5943c66b5..0c371c82cc9a 100644 --- a/beacon-chain/slasher/chunks.go +++ b/beacon-chain/slasher/chunks.go @@ -11,6 +11,7 @@ import ( slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/sirupsen/logrus" ) @@ -232,6 +233,43 @@ func (m *MinSpanChunksSlice) CheckSlashable( surroundingVotesTotal.Inc() + // Both attestations should have the same type. If not, we convert both to Electra attestations. + unifyAttWrapperVersion(existingAttWrapper, incomingAttWrapper) + + postElectra := existingAttWrapper.IndexedAttestation.Version() >= version.Electra + if postElectra { + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "existing attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + existingAttWrapper.IndexedAttestation, + ) + } + incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "incoming attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + incomingAttWrapper.IndexedAttestation, + ) + } + slashing := ðpb.AttesterSlashingElectra{ + Attestation_1: existing, + Attestation_2: incoming, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: incoming, + Attestation_2: existing, + } + } + + return slashing, nil + } + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) if !ok { return nil, fmt.Errorf( @@ -328,6 +366,43 @@ func (m *MaxSpanChunksSlice) CheckSlashable( surroundedVotesTotal.Inc() + // Both attestations should have the same type. If not, we convert the non-Electra attestation into an Electra attestation. + unifyAttWrapperVersion(existingAttWrapper, incomingAttWrapper) + + postElectra := existingAttWrapper.IndexedAttestation.Version() >= version.Electra + if postElectra { + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "existing attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + existingAttWrapper.IndexedAttestation, + ) + } + incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "incoming attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + incomingAttWrapper.IndexedAttestation, + ) + } + slashing := ðpb.AttesterSlashingElectra{ + Attestation_1: existing, + Attestation_2: incoming, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: incoming, + Attestation_2: existing, + } + } + + return slashing, nil + } + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) if !ok { return nil, fmt.Errorf( diff --git a/beacon-chain/slasher/chunks_test.go b/beacon-chain/slasher/chunks_test.go index 7fc1ab7a6501..0a66bcbf7c50 100644 --- a/beacon-chain/slasher/chunks_test.go +++ b/beacon-chain/slasher/chunks_test.go @@ -3,12 +3,14 @@ package slasher import ( "context" "math" + "reflect" "testing" dbtest "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -82,6 +84,99 @@ func TestMaxSpanChunksSlice_MaxChunkSpanFrom(t *testing.T) { func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) { ctx := context.Background() + + for _, v := range []int{version.Phase0, version.Electra} { + t.Run(version.String(v), func(t *testing.T) { + slasherDB := dbtest.SetupSlasherDB(t) + params := &Parameters{ + chunkSize: 3, + validatorChunkSize: 2, + historyLength: 3, + } + validatorIdx := primitives.ValidatorIndex(1) + source := primitives.Epoch(1) + target := primitives.Epoch(2) + att := createAttestationWrapperEmptySig(t, v, source, target, nil, nil) + + // A faulty chunk should lead to error. + chunk := &MinSpanChunksSlice{ + params: params, + data: []uint16{}, + } + _, err := chunk.CheckSlashable(ctx, nil, validatorIdx, att) + require.ErrorContains(t, "could not get min target for validator", err) + + // We initialize a proper slice with 2 chunks with chunk size 3, 2 validators, and + // a history length of 3 representing a perfect attesting history. + // + // val0 val1 + // { } { } + // [2, 2, 2, 2, 2, 2] + data := []uint16{2, 2, 2, 2, 2, 2} + chunk, err = MinChunkSpansSliceFrom(params, data) + require.NoError(t, err) + + // An attestation with source 1 and target 2 should not be slashable + // based on our min chunk for either validator. + slashing, err := chunk.CheckSlashable(ctx, slasherDB, validatorIdx, att) + require.NoError(t, err) + require.Equal(t, nil, slashing) + + slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx.Sub(1), att) + require.NoError(t, err) + require.Equal(t, nil, slashing) + + // Next up we initialize an empty chunks slice and mark an attestation + // with (source 1, target 2) as attested. + chunk = EmptyMinSpanChunksSlice(params) + source = primitives.Epoch(1) + target = primitives.Epoch(2) + att = createAttestationWrapperEmptySig(t, v, source, target, nil, nil) + chunkIndex := uint64(0) + startEpoch := target + currentEpoch := target + _, err = chunk.Update(chunkIndex, currentEpoch, validatorIdx, startEpoch, target) + require.NoError(t, err) + + // Next up, we create a surrounding vote, but it should NOT be slashable + // because we DO NOT have an existing attestation record in our database at the min target epoch. + source = primitives.Epoch(0) + target = primitives.Epoch(3) + surroundingVote := createAttestationWrapperEmptySig(t, v, source, target, nil, nil) + + slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote) + require.NoError(t, err) + require.Equal(t, nil, slashing) + + // Next up, we save the old attestation record, then check if the + // surrounding vote is indeed slashable. + attData := att.IndexedAttestation.GetData() + attRecord := createAttestationWrapperEmptySig(t, v, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1}) + err = slasherDB.SaveAttestationRecordsForValidators( + ctx, + []*slashertypes.IndexedAttestationWrapper{attRecord}, + ) + require.NoError(t, err) + + slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote) + require.NoError(t, err) + require.Equal(t, false, reflect.ValueOf(slashing).IsNil()) + + // We check the attestation with the lower data root is the first attestation. + // Firstly we require the setup to have the surrounding vote as the second attestation. + // Then we modify the root of the surrounding vote and expect the vote to be the first attestation. + require.DeepEqual(t, surroundingVote.IndexedAttestation, slashing.SecondAttestation()) + surroundingVote.DataRoot = [32]byte{} + slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote) + require.NoError(t, err) + require.Equal(t, false, reflect.ValueOf(slashing).IsNil()) + assert.DeepEqual(t, surroundingVote.IndexedAttestation, slashing.FirstAttestation()) + }) + } +} + +func TestMinSpanChunksSlice_CheckSlashable_DifferentVersions(t *testing.T) { + ctx := context.Background() slasherDB := dbtest.SetupSlasherDB(t) params := &Parameters{ chunkSize: 3, @@ -91,75 +186,138 @@ func TestMinSpanChunksSlice_CheckSlashable(t *testing.T) { validatorIdx := primitives.ValidatorIndex(1) source := primitives.Epoch(1) target := primitives.Epoch(2) - att := createAttestationWrapperEmptySig(t, source, target, nil, nil) - // A faulty chunk should lead to error. - chunk := &MinSpanChunksSlice{ - params: params, - data: []uint16{}, - } - _, err := chunk.CheckSlashable(ctx, nil, validatorIdx, att) - require.ErrorContains(t, "could not get min target for validator", err) + // We create a vote with Phase0 version. + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) - // We initialize a proper slice with 2 chunks with chunk size 3, 2 validators, and - // a history length of 3 representing a perfect attesting history. - // - // val0 val1 - // { } { } - // [2, 2, 2, 2, 2, 2] - data := []uint16{2, 2, 2, 2, 2, 2} - chunk, err = MinChunkSpansSliceFrom(params, data) - require.NoError(t, err) - - // An attestation with source 1 and target 2 should not be slashable - // based on our min chunk for either validator. - slashing, err := chunk.CheckSlashable(ctx, slasherDB, validatorIdx, att) - require.NoError(t, err) - require.Equal(t, nil, slashing) - - slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx.Sub(1), att) - require.NoError(t, err) - require.Equal(t, nil, slashing) - - // Next up we initialize an empty chunks slice and mark an attestation - // with (source 1, target 2) as attested. - chunk = EmptyMinSpanChunksSlice(params) - source = primitives.Epoch(1) - target = primitives.Epoch(2) - att = createAttestationWrapperEmptySig(t, source, target, nil, nil) + // We initialize an empty chunks slice and mark an attestation with (source 1, target 2) as attested. + chunk := EmptyMinSpanChunksSlice(params) chunkIndex := uint64(0) startEpoch := target currentEpoch := target - _, err = chunk.Update(chunkIndex, currentEpoch, validatorIdx, startEpoch, target) + _, err := chunk.Update(chunkIndex, currentEpoch, validatorIdx, startEpoch, target) require.NoError(t, err) - // Next up, we create a surrounding vote, but it should NOT be slashable - // because we DO NOT have an existing attestation record in our database at the min target epoch. + // We create a surrounding vote with Electra version. source = primitives.Epoch(0) target = primitives.Epoch(3) - surroundingVote := createAttestationWrapperEmptySig(t, source, target, nil, nil) + surroundingVote := createAttestationWrapperEmptySig(t, version.Electra, source, target, nil, nil) - slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote) - require.NoError(t, err) - require.Equal(t, nil, slashing) - - // Next up, we save the old attestation record, then check if the - // surrounding vote is indeed slashable. + // We save the old attestation record, then check if the surrounding vote is indeed slashable. attData := att.IndexedAttestation.GetData() - attRecord := createAttestationWrapperEmptySig(t, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1}) + attRecord := createAttestationWrapperEmptySig(t, version.Phase0, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1}) err = slasherDB.SaveAttestationRecordsForValidators( ctx, []*slashertypes.IndexedAttestationWrapper{attRecord}, ) require.NoError(t, err) - slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote) + slashing, err := chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundingVote) require.NoError(t, err) - require.NotEqual(t, (*ethpb.AttesterSlashing)(nil), slashing) + // The old record should be converted to Electra and the resulting slashing should be an Electra slashing. + electraSlashing, ok := slashing.(*ethpb.AttesterSlashingElectra) + require.Equal(t, true, ok, "slashing has the wrong type") + assert.NotNil(t, electraSlashing) } func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) { ctx := context.Background() + + for _, v := range []int{version.Phase0, version.Electra} { + t.Run(version.String(v), func(t *testing.T) { + slasherDB := dbtest.SetupSlasherDB(t) + params := &Parameters{ + chunkSize: 4, + validatorChunkSize: 2, + historyLength: 4, + } + validatorIdx := primitives.ValidatorIndex(1) + source := primitives.Epoch(1) + target := primitives.Epoch(2) + att := createAttestationWrapperEmptySig(t, v, source, target, nil, nil) + + // A faulty chunk should lead to error. + chunk := &MaxSpanChunksSlice{ + params: params, + data: []uint16{}, + } + _, err := chunk.CheckSlashable(ctx, nil, validatorIdx, att) + require.ErrorContains(t, "could not get max target for validator", err) + + // We initialize a proper slice with 2 chunks with chunk size 4, 2 validators, and + // a history length of 4 representing a perfect attesting history. + // + // val0 val1 + // { } { } + // [0, 0, 0, 0, 0, 0, 0, 0] + data := []uint16{0, 0, 0, 0, 0, 0, 0, 0} + chunk, err = MaxChunkSpansSliceFrom(params, data) + require.NoError(t, err) + + // An attestation with source 1 and target 2 should not be slashable + // based on our max chunk for either validator. + slashing, err := chunk.CheckSlashable(ctx, slasherDB, validatorIdx, att) + require.NoError(t, err) + require.Equal(t, nil, slashing) + + slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx.Sub(1), att) + require.NoError(t, err) + require.Equal(t, nil, slashing) + + // Next up we initialize an empty chunks slice and mark an attestation + // with (source 0, target 3) as attested. + chunk = EmptyMaxSpanChunksSlice(params) + source = primitives.Epoch(0) + target = primitives.Epoch(3) + att = createAttestationWrapperEmptySig(t, v, source, target, nil, nil) + chunkIndex := uint64(0) + startEpoch := source + currentEpoch := target + _, err = chunk.Update(chunkIndex, currentEpoch, validatorIdx, startEpoch, target) + require.NoError(t, err) + + // Next up, we create a surrounded vote, but it should NOT be slashable + // because we DO NOT have an existing attestation record in our database at the max target epoch. + source = primitives.Epoch(1) + target = primitives.Epoch(2) + surroundedVote := createAttestationWrapperEmptySig(t, v, source, target, nil, nil) + + slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote) + require.NoError(t, err) + require.Equal(t, nil, slashing) + + // Next up, we save the old attestation record, then check if the + // surroundedVote vote is indeed slashable. + attData := att.IndexedAttestation.GetData() + signingRoot := [32]byte{1} + attRecord := createAttestationWrapperEmptySig( + t, v, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, signingRoot[:], + ) + err = slasherDB.SaveAttestationRecordsForValidators( + ctx, + []*slashertypes.IndexedAttestationWrapper{attRecord}, + ) + require.NoError(t, err) + + slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote) + require.NoError(t, err) + require.Equal(t, false, reflect.ValueOf(slashing).IsNil()) + + // We check the attestation with the lower data root is the first attestation. + // Firstly we require the setup to have the surrounded vote as the second attestation. + // Then we modify the root of the surrounded vote and expect the vote to be the first attestation. + require.DeepEqual(t, surroundedVote.IndexedAttestation, slashing.SecondAttestation()) + surroundedVote.DataRoot = [32]byte{} + slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote) + require.NoError(t, err) + require.Equal(t, false, reflect.ValueOf(slashing).IsNil()) + assert.DeepEqual(t, surroundedVote.IndexedAttestation, slashing.FirstAttestation()) + }) + } +} + +func TestMaxSpanChunksSlice_CheckSlashable_DifferentVersions(t *testing.T) { + ctx := context.Background() slasherDB := dbtest.SetupSlasherDB(t) params := &Parameters{ chunkSize: 4, @@ -167,76 +325,38 @@ func TestMaxSpanChunksSlice_CheckSlashable(t *testing.T) { historyLength: 4, } validatorIdx := primitives.ValidatorIndex(1) - source := primitives.Epoch(1) - target := primitives.Epoch(2) - att := createAttestationWrapperEmptySig(t, source, target, nil, nil) - - // A faulty chunk should lead to error. - chunk := &MaxSpanChunksSlice{ - params: params, - data: []uint16{}, - } - _, err := chunk.CheckSlashable(ctx, nil, validatorIdx, att) - require.ErrorContains(t, "could not get max target for validator", err) - - // We initialize a proper slice with 2 chunks with chunk size 4, 2 validators, and - // a history length of 4 representing a perfect attesting history. - // - // val0 val1 - // { } { } - // [0, 0, 0, 0, 0, 0, 0, 0] - data := []uint16{0, 0, 0, 0, 0, 0, 0, 0} - chunk, err = MaxChunkSpansSliceFrom(params, data) - require.NoError(t, err) + source := primitives.Epoch(0) + target := primitives.Epoch(3) - // An attestation with source 1 and target 2 should not be slashable - // based on our max chunk for either validator. - slashing, err := chunk.CheckSlashable(ctx, slasherDB, validatorIdx, att) - require.NoError(t, err) - require.Equal(t, nil, slashing) + // We create a vote with Phase0 version. + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) - slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx.Sub(1), att) - require.NoError(t, err) - require.Equal(t, nil, slashing) - - // Next up we initialize an empty chunks slice and mark an attestation - // with (source 0, target 3) as attested. - chunk = EmptyMaxSpanChunksSlice(params) - source = primitives.Epoch(0) - target = primitives.Epoch(3) - att = createAttestationWrapperEmptySig(t, source, target, nil, nil) + // We initialize an empty chunks slice and mark an attestation with (source 0, target 3) as attested. + chunk := EmptyMaxSpanChunksSlice(params) chunkIndex := uint64(0) - startEpoch := source - currentEpoch := target - _, err = chunk.Update(chunkIndex, currentEpoch, validatorIdx, startEpoch, target) + _, err := chunk.Update(chunkIndex, target, validatorIdx, source, target) require.NoError(t, err) - // Next up, we create a surrounded vote, but it should NOT be slashable - // because we DO NOT have an existing attestation record in our database at the max target epoch. + // We create a surrounded vote with Electra version. source = primitives.Epoch(1) target = primitives.Epoch(2) - surroundedVote := createAttestationWrapperEmptySig(t, source, target, nil, nil) + surroundedVote := createAttestationWrapperEmptySig(t, version.Electra, source, target, nil, nil) - slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote) - require.NoError(t, err) - require.Equal(t, nil, slashing) - - // Next up, we save the old attestation record, then check if the - // surroundedVote vote is indeed slashable. + // We save the old attestation record, then check if the surrounded vote is indeed slashable. attData := att.IndexedAttestation.GetData() - signingRoot := [32]byte{1} - attRecord := createAttestationWrapperEmptySig( - t, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, signingRoot[:], - ) + attRecord := createAttestationWrapperEmptySig(t, version.Phase0, attData.Source.Epoch, attData.Target.Epoch, []uint64{uint64(validatorIdx)}, []byte{1}) err = slasherDB.SaveAttestationRecordsForValidators( ctx, []*slashertypes.IndexedAttestationWrapper{attRecord}, ) require.NoError(t, err) - slashing, err = chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote) + slashing, err := chunk.CheckSlashable(ctx, slasherDB, validatorIdx, surroundedVote) require.NoError(t, err) - require.NotEqual(t, (*ethpb.AttesterSlashing)(nil), slashing) + // The old record should be converted to Electra and the resulting slashing should be an Electra slashing. + electraSlashing, ok := slashing.(*ethpb.AttesterSlashingElectra) + require.Equal(t, true, ok, "slashing has wrong type") + assert.NotNil(t, electraSlashing) } func TestMinSpanChunksSlice_Update_MultipleChunks(t *testing.T) { diff --git a/beacon-chain/slasher/detect_attestations.go b/beacon-chain/slasher/detect_attestations.go index 0817e12ce6ae..99c1bf1d483c 100644 --- a/beacon-chain/slasher/detect_attestations.go +++ b/beacon-chain/slasher/detect_attestations.go @@ -4,14 +4,16 @@ import ( "bytes" "context" "fmt" + "maps" + "slices" "github.com/pkg/errors" slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" - "golang.org/x/exp/maps" + "github.com/prysmaticlabs/prysm/v5/runtime/version" ) // Takes in a list of indexed attestation wrappers and returns any @@ -193,33 +195,69 @@ func (s *Service) checkDoubleVotes( // This is a double vote. doubleVotesTotal.Inc() - existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) - if !ok { - return nil, fmt.Errorf( - "existing attestation has wrong type (expected %T, got %T)", - ðpb.IndexedAttestation{}, - existingAttWrapper.IndexedAttestation, - ) - } - incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) - if !ok { - return nil, fmt.Errorf( - "incoming attestation has wrong type (expected %T, got %T)", - ðpb.IndexedAttestation{}, - incomingAttWrapper.IndexedAttestation, - ) - } + var slashing ethpb.AttSlashing - slashing := ðpb.AttesterSlashing{ - Attestation_1: existing, - Attestation_2: incoming, - } + // Both attestations should have the same type. If not, we convert both to Electra attestations. + unifyAttWrapperVersion(existingAttWrapper, incomingAttWrapper) - // Ensure the attestation with the lower data root is the first attestation. - if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + postElectra := existingAttWrapper.IndexedAttestation.Version() >= version.Electra + if postElectra { + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "existing attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + existingAttWrapper.IndexedAttestation, + ) + } + incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "incoming attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + incomingAttWrapper.IndexedAttestation, + ) + } + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: existing, + Attestation_2: incoming, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: incoming, + Attestation_2: existing, + } + } + } else { + existing, ok := existingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) + if !ok { + return nil, fmt.Errorf( + "existing attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestation{}, + existingAttWrapper.IndexedAttestation, + ) + } + incoming, ok := incomingAttWrapper.IndexedAttestation.(*ethpb.IndexedAttestation) + if !ok { + return nil, fmt.Errorf( + "incoming attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestation{}, + incomingAttWrapper.IndexedAttestation, + ) + } slashing = ðpb.AttesterSlashing{ - Attestation_1: incoming, - Attestation_2: existing, + Attestation_1: existing, + Attestation_2: incoming, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(existingAttWrapper.DataRoot[:], incomingAttWrapper.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashing{ + Attestation_1: incoming, + Attestation_2: existing, + } } } @@ -245,33 +283,69 @@ func (s *Service) checkDoubleVotes( wrapper_1 := doubleVote.Wrapper_1 wrapper_2 := doubleVote.Wrapper_2 - att_1, ok := wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestation) - if !ok { - return nil, fmt.Errorf( - "first attestation has wrong type (expected %T, got %T)", - ðpb.IndexedAttestation{}, - wrapper_1.IndexedAttestation, - ) - } - att_2, ok := wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestation) - if !ok { - return nil, fmt.Errorf( - "second attestation has wrong type (expected %T, got %T)", - ðpb.IndexedAttestation{}, - wrapper_2.IndexedAttestation, - ) - } + var slashing ethpb.AttSlashing - slashing := ðpb.AttesterSlashing{ - Attestation_1: att_1, - Attestation_2: att_2, - } + // Both attestations should have the same type. If not, we convert both to Electra attestations. + unifyAttWrapperVersion(wrapper_1, wrapper_2) - // Ensure the attestation with the lower data root is the first attestation. - if bytes.Compare(wrapper_1.DataRoot[:], wrapper_2.DataRoot[:]) > 0 { + postElectra := wrapper_1.IndexedAttestation.Version() >= version.Electra + if postElectra { + att_1, ok := wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "first attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + wrapper_1.IndexedAttestation, + ) + } + att_2, ok := wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestationElectra) + if !ok { + return nil, fmt.Errorf( + "second attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestationElectra{}, + wrapper_2.IndexedAttestation, + ) + } + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: att_1, + Attestation_2: att_2, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(wrapper_1.DataRoot[:], wrapper_2.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: att_2, + Attestation_2: att_1, + } + } + } else { + att_1, ok := wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestation) + if !ok { + return nil, fmt.Errorf( + "first attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestation{}, + wrapper_1.IndexedAttestation, + ) + } + att_2, ok := wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestation) + if !ok { + return nil, fmt.Errorf( + "second attestation has wrong type (expected %T, got %T)", + ðpb.IndexedAttestation{}, + wrapper_2.IndexedAttestation, + ) + } slashing = ðpb.AttesterSlashing{ - Attestation_1: att_2, - Attestation_2: att_1, + Attestation_1: att_1, + Attestation_2: att_2, + } + + // Ensure the attestation with the lower data root is the first attestation. + if bytes.Compare(wrapper_1.DataRoot[:], wrapper_2.DataRoot[:]) > 0 { + slashing = ðpb.AttesterSlashing{ + Attestation_1: att_2, + Attestation_2: att_1, + } } } @@ -319,7 +393,7 @@ func (s *Service) updatedChunkByChunkIndex( } // Transform the map of needed chunk indexes to a slice. - neededChunkIndexes := maps.Keys(neededChunkIndexesMap) + neededChunkIndexes := slices.Collect(maps.Keys(neededChunkIndexesMap)) // Retrieve needed chunks from the database. chunkByChunkIndex, err := s.loadChunksFromDisk(ctx, validatorChunkIndex, chunkKind, neededChunkIndexes) diff --git a/beacon-chain/slasher/detect_attestations_test.go b/beacon-chain/slasher/detect_attestations_test.go index 0026f36877fc..4c0fd8401969 100644 --- a/beacon-chain/slasher/detect_attestations_test.go +++ b/beacon-chain/slasher/detect_attestations_test.go @@ -20,6 +20,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls/common" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -30,6 +31,7 @@ import ( func Test_processAttestations(t *testing.T) { type ( attestationInfo struct { + ver int source primitives.Epoch target primitives.Epoch indices []uint64 @@ -37,6 +39,7 @@ func Test_processAttestations(t *testing.T) { } slashingInfo struct { + ver int attestationInfo_1 *attestationInfo attestationInfo_2 *attestationInfo } @@ -46,661 +49,740 @@ func Test_processAttestations(t *testing.T) { attestationsInfo []*attestationInfo expectedSlashingsInfo []*slashingInfo } + + test struct { + ver int + name string + steps []*step + } ) - tests := []struct { - name string - steps []*step - }{ - { - name: "Same target with different signing roots - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, - }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - attestationInfo_2: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + var tests []test + + for _, v := range []int{version.Phase0, version.Electra} { + tests = append(tests, []test{ + { + ver: v, + name: "Same target with different signing roots - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + attestationInfo_2: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, }, }, }, }, - }, - { - name: "Same target with different signing roots - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + { + ver: v, + name: "Same target with different signing roots - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - attestationInfo_2: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + attestationInfo_2: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, }, }, }, }, - }, - { - name: "Same target with same signing roots - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + { + ver: v, + name: "Same target with same signing roots - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Same target with same signing roots - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + { + ver: v, + name: "Same target with same signing roots - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Detects surrounding vote (source 1, target 2), (source 0, target 3) - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Detects surrounding vote (source 1, target 2), (source 0, target 3) - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, }, }, }, }, - }, - { - name: "Detects surrounding vote (source 1, target 2), (source 0, target 3) - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Detects surrounding vote (source 1, target 2), (source 0, target 3) - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, }, }, }, }, - }, - { - name: "Detects surrounding vote (source 50, target 51), (source 0, target 1000) - single step", - steps: []*step{ - { - currentEpoch: 1000, - attestationsInfo: []*attestationInfo{ - {source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, - {source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, - }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + { + ver: v, + name: "Detects surrounding vote (source 50, target 51), (source 0, target 1000) - single step", + steps: []*step{ + { + currentEpoch: 1000, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: v, source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: v, source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + }, }, }, }, }, - }, - { - name: "Detects surrounding vote (source 50, target 51), (source 0, target 1000) - two steps", - steps: []*step{ - { - currentEpoch: 1000, - attestationsInfo: []*attestationInfo{ - {source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, - }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 1000, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + { + ver: v, + name: "Detects surrounding vote (source 50, target 51), (source 0, target 1000) - two steps", + steps: []*step{ + { + currentEpoch: 1000, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + { + currentEpoch: 1000, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 0, target: 1000, indices: []uint64{0}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: v, source: 50, target: 51, indices: []uint64{0}, beaconBlockRoot: nil}, + }, }, }, }, }, - }, - { - name: "Detects surrounded vote (source 0, target 3), (source 1, target 2) - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Detects surrounded vote (source 0, target 3), (source 1, target 2) - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, }, }, }, }, - }, - { - name: "Detects surrounded vote (source 0, target 3), (source 1, target 2) - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Detects surrounded vote (source 0, target 3), (source 1, target 2) - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, }, }, }, }, - }, - { - name: "Detects double vote, (source 1, target 2), (source 0, target 2) - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Detects double vote, (source 1, target 2), (source 0, target 2) - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: v, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: v, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, }, }, }, }, - }, - { - name: "Detects double vote, (source 1, target 2), (source 0, target 2) - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Detects double vote, (source 1, target 2), (source 0, target 2) - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: []*slashingInfo{ - { - attestationInfo_1: &attestationInfo{source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - attestationInfo_2: &attestationInfo{source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: v, + attestationInfo_1: &attestationInfo{ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + attestationInfo_2: &attestationInfo{ver: v, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, }, }, }, }, - }, - { - name: "Not slashable, surrounding but non-overlapping attesting indices within same validator chunk index - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0}, beaconBlockRoot: nil}, - {source: 0, target: 3, indices: []uint64{1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, surrounding but non-overlapping attesting indices within same validator chunk index - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: v, source: 0, target: 3, indices: []uint64{1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, surrounding but non-overlapping attesting indices within same validator chunk index - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, surrounding but non-overlapping attesting indices within same validator chunk index - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{1}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, surrounded but non-overlapping attesting indices within same validator chunk index - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 1, target: 2, indices: []uint64{2, 3}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, surrounded but non-overlapping attesting indices within same validator chunk index - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: v, source: 1, target: 2, indices: []uint64{2, 3}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, surrounded but non-overlapping attesting indices within same validator chunk index - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, surrounded but non-overlapping attesting indices within same validator chunk index - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{2, 3}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{2, 3}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, surrounding but non-overlapping attesting indices in different validator chunk index - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, - {source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, surrounding but non-overlapping attesting indices in different validator chunk index - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: v, source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, surrounding but non-overlapping attesting indices in different validator chunk index - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, surrounding but non-overlapping attesting indices in different validator chunk index - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, surrounded but non-overlapping attesting indices in different validator chunk index - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, - {source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, surrounded but non-overlapping attesting indices in different validator chunk index - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + {ver: v, source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, surrounded but non-overlapping attesting indices in different validator chunk index - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, surrounded but non-overlapping attesting indices in different validator chunk index - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{params.BeaconConfig().MinGenesisActiveValidatorCount - 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, (source 1, target 2), (source 2, target 3) - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 2, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, (source 1, target 2), (source 2, target 3) - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: v, source: 2, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, (source 1, target 2), (source 2, target 3) - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, (source 1, target 2), (source 2, target 3) - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 2, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 2, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, (source 0, target 3), (source 2, target 4) - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 2, target: 4, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, (source 0, target 3), (source 2, target 4) - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: v, source: 2, target: 4, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, (source 0, target 3), (source 2, target 4) - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, (source 0, target 3), (source 2, target 4) - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 2, target: 4, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 2, target: 4, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, (source 0, target 2), (source 0, target 3) - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, (source 0, target 2), (source 0, target 3) - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, (source 0, target 2), (source 0, target 3) - two steps", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, (source 0, target 2), (source 0, target 3) - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, + }, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + { + ver: v, + name: "Not slashable, (source 0, target 3), (source 0, target 2) - single step", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: v, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, (source 0, target 3), (source 0, target 2) - single step", - steps: []*step{ - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + { + ver: v, + name: "Not slashable, (source 0, target 3), (source 0, target 2) - two steps", + steps: []*step{ + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, + }, + { + currentEpoch: 4, + attestationsInfo: []*attestationInfo{ + {ver: v, source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + }, + expectedSlashingsInfo: nil, }, - expectedSlashingsInfo: nil, }, }, - }, - { - name: "Not slashable, (source 0, target 3), (source 0, target 2) - two steps", + }...) + + tests = append(tests, test{ + name: "Different versions, same target with different signing roots - single step", steps: []*step{ { currentEpoch: 4, attestationsInfo: []*attestationInfo{ - {source: 0, target: 3, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + {ver: version.Phase0, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + {ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, }, - expectedSlashingsInfo: nil, - }, - { - currentEpoch: 4, - attestationsInfo: []*attestationInfo{ - {source: 0, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: nil}, + expectedSlashingsInfo: []*slashingInfo{ + { + ver: version.Electra, + attestationInfo_1: &attestationInfo{ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{1}}, + attestationInfo_2: &attestationInfo{ver: version.Electra, source: 1, target: 2, indices: []uint64{0, 1}, beaconBlockRoot: []byte{2}}, + }, }, - expectedSlashingsInfo: nil, }, }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Create context. - ctx := context.Background() + }) - // Configure logging. - hook := logTest.NewGlobal() - defer hook.Reset() + for _, tt := range tests { + name := version.String(tt.ver) + ": " + tt.name + t.Run(name, func(t *testing.T) { + // Create context. + ctx := context.Background() - // Configure the slasher database. - slasherDB := dbtest.SetupSlasherDB(t) + // Configure logging. + hook := logTest.NewGlobal() + defer hook.Reset() - // Configure the beacon state. - beaconState, err := util.NewBeaconState() - require.NoError(t, err) + // Configure the slasher database. + slasherDB := dbtest.SetupSlasherDB(t) - // Create the mock chain service. - mockChain := &mock.ChainService{State: beaconState} + // Configure the beacon state. + beaconState, err := util.NewBeaconState() + require.NoError(t, err) - // Create the mock slashing pool inserter. - mockSlashingPoolInserter := &slashingsmock.PoolMock{} + // Create the mock chain service. + mockChain := &mock.ChainService{State: beaconState} - // Create the service configuration. - serviceConfig := &ServiceConfig{ - Database: slasherDB, - HeadStateFetcher: mockChain, - AttestationStateFetcher: mockChain, - SlashingPoolInserter: mockSlashingPoolInserter, - } + // Create the mock slashing pool inserter. + mockSlashingPoolInserter := &slashingsmock.PoolMock{} - // Create the slasher service. - slasherService, err := New(context.Background(), serviceConfig) - require.NoError(t, err) - - // Initialize validators in the state. - numVals := params.BeaconConfig().MinGenesisActiveValidatorCount - validators := make([]*ethpb.Validator, numVals) - privateKeys := make([]bls.SecretKey, numVals) + // Create the service configuration. + serviceConfig := &ServiceConfig{ + Database: slasherDB, + HeadStateFetcher: mockChain, + AttestationStateFetcher: mockChain, + SlashingPoolInserter: mockSlashingPoolInserter, + } - for i := uint64(0); i < numVals; i++ { - // Create a random private key. - privateKey, err := bls.RandKey() + // Create the slasher service. + slasherService, err := New(context.Background(), serviceConfig) require.NoError(t, err) - // Add the private key to the list. - privateKeys[i] = privateKey + // Initialize validators in the state. + numVals := params.BeaconConfig().MinGenesisActiveValidatorCount + validators := make([]*ethpb.Validator, numVals) + privateKeys := make([]bls.SecretKey, numVals) - // Derive the public key from the private key. - publicKey := privateKey.PublicKey().Marshal() + for i := uint64(0); i < numVals; i++ { + // Create a random private key. + privateKey, err := bls.RandKey() + require.NoError(t, err) - // Initialize the validator. - validator := ðpb.Validator{PublicKey: publicKey} + // Add the private key to the list. + privateKeys[i] = privateKey - // Add the validator to the list. - validators[i] = validator - } - - // Set the validators into the state. - err = beaconState.SetValidators(validators) - require.NoError(t, err) + // Derive the public key from the private key. + publicKey := privateKey.PublicKey().Marshal() - // Compute the signing domain. - domain, err := signing.Domain( - beaconState.Fork(), - 0, - params.BeaconConfig().DomainBeaconAttester, - beaconState.GenesisValidatorsRoot(), - ) - require.NoError(t, err) + // Initialize the validator. + validator := ðpb.Validator{PublicKey: publicKey} - for _, step := range tt.steps { - // Build attestation wrappers. - attestationsCount := len(step.attestationsInfo) - attestationWrappers := make([]*slashertypes.IndexedAttestationWrapper, 0, attestationsCount) - for _, attestationInfo := range step.attestationsInfo { - // Create a wrapped attestation. - attestationWrapper := createAttestationWrapper( - t, - domain, - privateKeys, - attestationInfo.source, - attestationInfo.target, - attestationInfo.indices, - attestationInfo.beaconBlockRoot, - ) - - // Add the wrapped attestation to the list. - attestationWrappers = append(attestationWrappers, attestationWrapper) + // Add the validator to the list. + validators[i] = validator } - // Build expected attester slashings. - expectedSlashings := make(map[[fieldparams.RootLength]byte]*ethpb.AttesterSlashing, len(step.expectedSlashingsInfo)) - - for _, slashingInfo := range step.expectedSlashingsInfo { - // Create attestations. - wrapper_1 := createAttestationWrapper( - t, - domain, - privateKeys, - slashingInfo.attestationInfo_1.source, - slashingInfo.attestationInfo_1.target, - slashingInfo.attestationInfo_1.indices, - slashingInfo.attestationInfo_1.beaconBlockRoot, - ) - - wrapper_2 := createAttestationWrapper( - t, - domain, - privateKeys, - slashingInfo.attestationInfo_2.source, - slashingInfo.attestationInfo_2.target, - slashingInfo.attestationInfo_2.indices, - slashingInfo.attestationInfo_2.beaconBlockRoot, - ) - - // Create the attester slashing. - expectedSlashing := ðpb.AttesterSlashing{ - Attestation_1: wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestation), - Attestation_2: wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestation), - } + // Set the validators into the state. + err = beaconState.SetValidators(validators) + require.NoError(t, err) - root, err := expectedSlashing.HashTreeRoot() - require.NoError(t, err, "failed to hash tree root") + // Compute the signing domain. + domain, err := signing.Domain( + beaconState.Fork(), + 0, + params.BeaconConfig().DomainBeaconAttester, + beaconState.GenesisValidatorsRoot(), + ) + require.NoError(t, err) - // Add the attester slashing to the map. - expectedSlashings[root] = expectedSlashing - } + for _, step := range tt.steps { + // Build attestation wrappers. + attestationsCount := len(step.attestationsInfo) + attestationWrappers := make([]*slashertypes.IndexedAttestationWrapper, 0, attestationsCount) + for _, attestationInfo := range step.attestationsInfo { + // Create a wrapped attestation. + attestationWrapper := createAttestationWrapper( + t, + attestationInfo.ver, + domain, + privateKeys, + attestationInfo.source, + attestationInfo.target, + attestationInfo.indices, + attestationInfo.beaconBlockRoot, + ) + + // Add the wrapped attestation to the list. + attestationWrappers = append(attestationWrappers, attestationWrapper) + } - // Get the currentSlot for the current epoch. - currentSlot, err := slots.EpochStart(step.currentEpoch) - require.NoError(t, err) + // Build expected attester slashings. + expectedSlashings := make(map[[fieldparams.RootLength]byte]ethpb.AttSlashing, len(step.expectedSlashingsInfo)) + + for _, slashingInfo := range step.expectedSlashingsInfo { + // Create attestations. + wrapper_1 := createAttestationWrapper( + t, + slashingInfo.attestationInfo_1.ver, + domain, + privateKeys, + slashingInfo.attestationInfo_1.source, + slashingInfo.attestationInfo_1.target, + slashingInfo.attestationInfo_1.indices, + slashingInfo.attestationInfo_1.beaconBlockRoot, + ) + + wrapper_2 := createAttestationWrapper( + t, + slashingInfo.attestationInfo_2.ver, + domain, + privateKeys, + slashingInfo.attestationInfo_2.source, + slashingInfo.attestationInfo_2.target, + slashingInfo.attestationInfo_2.indices, + slashingInfo.attestationInfo_2.beaconBlockRoot, + ) + + // Create the attester slashing. + var expectedSlashing ethpb.AttSlashing + + if slashingInfo.ver >= version.Electra { + expectedSlashing = ðpb.AttesterSlashingElectra{ + Attestation_1: wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestationElectra), + Attestation_2: wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestationElectra), + } + } else { + expectedSlashing = ðpb.AttesterSlashing{ + Attestation_1: wrapper_1.IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_2: wrapper_2.IndexedAttestation.(*ethpb.IndexedAttestation), + } + } + + root, err := expectedSlashing.HashTreeRoot() + require.NoError(t, err, "failed to hash tree root") + + // Add the attester slashing to the map. + expectedSlashings[root] = expectedSlashing + } + + // Get the currentSlot for the current epoch. + currentSlot, err := slots.EpochStart(step.currentEpoch) + require.NoError(t, err) - // Process the attestations. - processedSlashings := slasherService.processAttestations(ctx, attestationWrappers, currentSlot) + // Process the attestations. + processedSlashings := slasherService.processAttestations(ctx, attestationWrappers, currentSlot) - // Check the processed slashings correspond to the expected slashings. - require.Equal(t, len(expectedSlashings), len(processedSlashings), "processed slashings count not equal to expected") + // Check the processed slashings correspond to the expected slashings. + require.Equal(t, len(expectedSlashings), len(processedSlashings), "processed slashings count not equal to expected") - for root := range expectedSlashings { - // Check the expected slashing is in the processed slashings. - processedSlashing, ok := processedSlashings[root] - require.Equal(t, true, ok, "processed slashing not found") + for root := range expectedSlashings { + // Check the expected slashing is in the processed slashings. + processedSlashing, ok := processedSlashings[root] + require.Equal(t, true, ok, "processed slashing not found") - // Check the root matches - controlRoot, err := processedSlashing.HashTreeRoot() - require.NoError(t, err, "failed to hash tree root") - require.Equal(t, root, controlRoot, "root not equal") + // Check the root matches + controlRoot, err := processedSlashing.HashTreeRoot() + require.NoError(t, err, "failed to hash tree root") + require.Equal(t, root, controlRoot, "root not equal") + } } - } - }) + }) + } } } @@ -757,7 +839,7 @@ func Test_processQueuedAttestations_MultipleChunkIndices(t *testing.T) { } var sr [32]byte copy(sr[:], fmt.Sprintf("%d", i)) - att := createAttestationWrapperEmptySig(t, source, target, []uint64{0}, sr[:]) + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, []uint64{0}, sr[:]) s.attsQueue = newAttestationsQueue() s.attsQueue.push(att) slot, err := slots.EpochStart(i) @@ -814,8 +896,8 @@ func Test_processQueuedAttestations_OverlappingChunkIndices(t *testing.T) { }() // We create two attestations fully spanning chunk indices 0 and chunk 1 - att1 := createAttestationWrapperEmptySig(t, primitives.Epoch(slasherParams.chunkSize-2), primitives.Epoch(slasherParams.chunkSize), []uint64{0, 1}, nil) - att2 := createAttestationWrapperEmptySig(t, primitives.Epoch(slasherParams.chunkSize-1), primitives.Epoch(slasherParams.chunkSize+1), []uint64{0, 1}, nil) + att1 := createAttestationWrapperEmptySig(t, version.Phase0, primitives.Epoch(slasherParams.chunkSize-2), primitives.Epoch(slasherParams.chunkSize), []uint64{0, 1}, nil) + att2 := createAttestationWrapperEmptySig(t, version.Phase0, primitives.Epoch(slasherParams.chunkSize-1), primitives.Epoch(slasherParams.chunkSize+1), []uint64{0, 1}, nil) // We attempt to process the batch. s.attsQueue = newAttestationsQueue() @@ -1152,7 +1234,7 @@ func Test_applyAttestationForValidator_MinSpanChunk(t *testing.T) { // We apply attestation with (source 1, target 2) for our validator. source := primitives.Epoch(1) target := primitives.Epoch(2) - att := createAttestationWrapperEmptySig(t, source, target, nil, nil) + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err := srv.applyAttestationForValidator( ctx, chunksByChunkIdx, @@ -1175,7 +1257,7 @@ func Test_applyAttestationForValidator_MinSpanChunk(t *testing.T) { // expect a slashable offense to be returned. source = primitives.Epoch(0) target = primitives.Epoch(3) - slashableAtt := createAttestationWrapperEmptySig(t, source, target, nil, nil) + slashableAtt := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err = srv.applyAttestationForValidator( ctx, chunksByChunkIdx, @@ -1209,7 +1291,7 @@ func Test_applyAttestationForValidator_MaxSpanChunk(t *testing.T) { // We apply attestation with (source 0, target 3) for our validator. source := primitives.Epoch(0) target := primitives.Epoch(3) - att := createAttestationWrapperEmptySig(t, source, target, nil, nil) + att := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err := srv.applyAttestationForValidator( ctx, chunksByChunkIdx, @@ -1232,7 +1314,7 @@ func Test_applyAttestationForValidator_MaxSpanChunk(t *testing.T) { // expect a slashable offense to be returned. source = primitives.Epoch(1) target = primitives.Epoch(2) - slashableAtt := createAttestationWrapperEmptySig(t, source, target, nil, nil) + slashableAtt := createAttestationWrapperEmptySig(t, version.Phase0, source, target, nil, nil) slashing, err = srv.applyAttestationForValidator( ctx, chunksByChunkIdx, @@ -1347,7 +1429,7 @@ func TestService_processQueuedAttestations(t *testing.T) { require.NoError(t, err) s.attsQueue.extend([]*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{0, 1} /* indices */, nil /* signingRoot */), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{0, 1} /* indices */, nil /* signingRoot */), }) ctx, cancel := context.WithCancel(context.Background()) tickerChan := make(chan primitives.Slot) @@ -1482,6 +1564,7 @@ func runAttestationsBenchmark(b *testing.B, s *Service, numAtts, numValidators u copy(signingRoot[:], fmt.Sprintf("%d", i)) atts[i] = createAttestationWrapperEmptySig( b, + version.Phase0, source, target, /* target */ indices, /* indices */ @@ -1546,7 +1629,7 @@ func Benchmark_checkSurroundVotes(b *testing.B) { // Create the attestation wrapper. // This benchmark assume that all validators produced the exact same head, source and target votes. - attWrapper := createAttestationWrapperEmptySig(b, sourceEpoch, targetEpoch, validatorIndexes, nil) + attWrapper := createAttestationWrapperEmptySig(b, version.Phase0, sourceEpoch, targetEpoch, validatorIndexes, nil) attWrappers := []*slashertypes.IndexedAttestationWrapper{attWrapper} // Run the benchmark. @@ -1566,6 +1649,7 @@ func Benchmark_checkSurroundVotes(b *testing.B) { // The signature of the returned wrapped attestation is empty. func createAttestationWrapperEmptySig( t testing.TB, + ver int, source, target primitives.Epoch, indices []uint64, beaconBlockRoot []byte, @@ -1585,6 +1669,17 @@ func createAttestationWrapperEmptySig( dataRoot, err := data.HashTreeRoot() require.NoError(t, err) + if ver >= version.Electra { + return &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: data, + Signature: params.BeaconConfig().EmptySignature[:], + }, + DataRoot: dataRoot, + } + } + return &slashertypes.IndexedAttestationWrapper{ IndexedAttestation: ðpb.IndexedAttestation{ AttestingIndices: indices, @@ -1601,6 +1696,7 @@ func createAttestationWrapperEmptySig( // if validatorIndice = indices[i], then the corresponding private key is privateKeys[validatorIndice]. func createAttestationWrapper( t testing.TB, + ver int, domain []byte, privateKeys []common.SecretKey, source, target primitives.Epoch, @@ -1648,6 +1744,17 @@ func createAttestationWrapper( signature := bls.AggregateSignatures(signatures).Marshal() // Create the attestation wrapper. + if ver >= version.Electra { + return &slashertypes.IndexedAttestationWrapper{ + IndexedAttestation: ðpb.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: attestationData, + Signature: signature, + }, + DataRoot: attestationDataRoot, + } + } + return &slashertypes.IndexedAttestationWrapper{ IndexedAttestation: ðpb.IndexedAttestation{ AttestingIndices: indices, diff --git a/beacon-chain/slasher/detect_blocks.go b/beacon-chain/slasher/detect_blocks.go index 17d354d41962..144e0cdd1c0a 100644 --- a/beacon-chain/slasher/detect_blocks.go +++ b/beacon-chain/slasher/detect_blocks.go @@ -5,8 +5,8 @@ import ( "github.com/pkg/errors" slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // detectProposerSlashings takes in signed block header wrappers and returns a list of proposer slashings detected. diff --git a/beacon-chain/slasher/doc.go b/beacon-chain/slasher/doc.go index 46efb460b2af..44c09e2a0b55 100644 --- a/beacon-chain/slasher/doc.go +++ b/beacon-chain/slasher/doc.go @@ -129,7 +129,7 @@ A chunk value is stored on 2 bytes (uint16). ==> A chunk takes 8192 bytes = 8KB There is 4096 epochs / 16 epochs per chunk = 256 chunks per batch of 256 validators. -Storing all values fo a batch of 256 validators takes 256 * 8KB = 2MB +Storing all values of a batch of 256 validators takes 256 * 8KB = 2MB With 1_048_576 validators, we need 4096 * 2MB = 8GB Storing both MIN and MAX spans for 1_048_576 validators takes 16GB. diff --git a/beacon-chain/slasher/helpers.go b/beacon-chain/slasher/helpers.go index 6c6be1990c09..e13ea04135a1 100644 --- a/beacon-chain/slasher/helpers.go +++ b/beacon-chain/slasher/helpers.go @@ -13,6 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/container/slice" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/sirupsen/logrus" ) @@ -97,10 +98,7 @@ func (s *Service) filterAttestations( // detection (except for the genesis epoch). func validateAttestationIntegrity(att ethpb.IndexedAtt) bool { // If an attestation is malformed, we drop it. - if att == nil || - att.GetData() == nil || - att.GetData().Source == nil || - att.GetData().Target == nil { + if att == nil || att.IsNil() || att.GetData().Source == nil || att.GetData().Target == nil { return false } @@ -252,3 +250,24 @@ func closeDB(d *slasherkv.Store) { log.WithError(err).Error("could not close database") } } + +// unifyAttWrapperVersion ensures that the two wrappers wrap indexed attestations of the same version. +// If versions differ, the wrapped attestation with the lower version will be converted to the higher version. +func unifyAttWrapperVersion(w1 *slashertypes.IndexedAttestationWrapper, w2 *slashertypes.IndexedAttestationWrapper) { + if w1.IndexedAttestation.Version() == w2.IndexedAttestation.Version() { + return + } + if w1.IndexedAttestation.Version() != version.Electra { + w1.IndexedAttestation = ðpb.IndexedAttestationElectra{ + AttestingIndices: w1.IndexedAttestation.GetAttestingIndices(), + Data: w1.IndexedAttestation.GetData(), + Signature: w1.IndexedAttestation.GetSignature(), + } + return + } + w2.IndexedAttestation = ðpb.IndexedAttestationElectra{ + AttestingIndices: w2.IndexedAttestation.GetAttestingIndices(), + Data: w2.IndexedAttestation.GetData(), + Signature: w2.IndexedAttestation.GetSignature(), + } +} diff --git a/beacon-chain/slasher/helpers_test.go b/beacon-chain/slasher/helpers_test.go index 0b6284195300..3fff33f92477 100644 --- a/beacon-chain/slasher/helpers_test.go +++ b/beacon-chain/slasher/helpers_test.go @@ -9,6 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" logTest "github.com/sirupsen/logrus/hooks/test" ) @@ -32,13 +33,13 @@ func TestService_groupByValidatorChunkIndex(t *testing.T) { validatorChunkSize: 2, }, atts: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil), - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 1}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 1}, nil), }, want: map[uint64][]*slashertypes.IndexedAttestationWrapper{ 0: { - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil), - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 1}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 1}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 1}, nil), }, }, }, @@ -48,17 +49,17 @@ func TestService_groupByValidatorChunkIndex(t *testing.T) { validatorChunkSize: 2, }, atts: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 2, 4}, nil), }, want: map[uint64][]*slashertypes.IndexedAttestationWrapper{ 0: { - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 2, 4}, nil), }, 1: { - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 2, 4}, nil), }, 2: { - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0, 2, 4}, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0, 2, 4}, nil), }, }, }, @@ -95,13 +96,13 @@ func TestService_groupByChunkIndex(t *testing.T) { historyLength: 3, }, atts: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, nil, nil), - createAttestationWrapperEmptySig(t, 1, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, nil, nil), }, want: map[uint64][]*slashertypes.IndexedAttestationWrapper{ 0: { - createAttestationWrapperEmptySig(t, 0, 0, nil, nil), - createAttestationWrapperEmptySig(t, 1, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, nil, nil), }, }, }, @@ -112,17 +113,17 @@ func TestService_groupByChunkIndex(t *testing.T) { historyLength: 3, }, atts: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, nil, nil), - createAttestationWrapperEmptySig(t, 1, 0, nil, nil), - createAttestationWrapperEmptySig(t, 2, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 2, 0, nil, nil), }, want: map[uint64][]*slashertypes.IndexedAttestationWrapper{ 0: { - createAttestationWrapperEmptySig(t, 0, 0, nil, nil), - createAttestationWrapperEmptySig(t, 1, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, nil, nil), }, 1: { - createAttestationWrapperEmptySig(t, 2, 0, nil, nil), + createAttestationWrapperEmptySig(t, version.Phase0, 2, 0, nil, nil), }, }, }, @@ -207,7 +208,7 @@ func TestService_filterAttestations(t *testing.T) { { name: "Source > target gets dropped", input: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 1, 0, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 0, []uint64{1}, make([]byte, 32)), }, inputEpoch: 0, wantedDropped: 1, @@ -215,33 +216,33 @@ func TestService_filterAttestations(t *testing.T) { { name: "Source < target is valid", input: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, make([]byte, 32)), }, inputEpoch: 1, wantedValid: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, make([]byte, 32)), }, wantedDropped: 0, }, { name: "Source == target is valid", input: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{1}, make([]byte, 32)), }, inputEpoch: 1, wantedValid: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{1}, make([]byte, 32)), }, wantedDropped: 0, }, { name: "Attestation from the future is deferred", input: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 2, []uint64{1}, make([]byte, 32)), }, inputEpoch: 1, wantedDeferred: []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 2, []uint64{1}, make([]byte, 32)), }, wantedDropped: 0, }, @@ -271,22 +272,22 @@ func Test_logSlashingEvent(t *testing.T) { { name: "Surrounding vote", slashing: ðpb.AttesterSlashing{ - Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), - Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_1: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_2: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), }, }, { name: "Surrounded vote", slashing: ðpb.AttesterSlashing{ - Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), - Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_1: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_2: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), }, }, { name: "Double vote", slashing: ðpb.AttesterSlashing{ - Attestation_1: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), - Attestation_2: createAttestationWrapperEmptySig(t, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_1: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), + Attestation_2: createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, nil, nil).IndexedAttestation.(*ethpb.IndexedAttestation), }, }, } diff --git a/beacon-chain/slasher/queue_test.go b/beacon-chain/slasher/queue_test.go index 04350ae36b5a..03295cc2ea8b 100644 --- a/beacon-chain/slasher/queue_test.go +++ b/beacon-chain/slasher/queue_test.go @@ -5,6 +5,7 @@ import ( slashertypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -12,8 +13,8 @@ func Test_attestationsQueue(t *testing.T) { t.Run("push_and_dequeue", func(tt *testing.T) { attQueue := newAttestationsQueue() wantedAtts := []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)), - createAttestationWrapperEmptySig(t, 1, 2, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, []uint64{1}, make([]byte, 32)), } attQueue.push(wantedAtts[0]) attQueue.push(wantedAtts[1]) @@ -27,8 +28,8 @@ func Test_attestationsQueue(t *testing.T) { t.Run("extend_and_dequeue", func(tt *testing.T) { attQueue := newAttestationsQueue() wantedAtts := []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, make([]byte, 32)), - createAttestationWrapperEmptySig(t, 1, 2, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, make([]byte, 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, []uint64{1}, make([]byte, 32)), } attQueue.extend(wantedAtts) require.DeepEqual(t, 2, attQueue.size()) diff --git a/beacon-chain/slasher/receive_test.go b/beacon-chain/slasher/receive_test.go index 3bb389be3b78..4b66ac2fe2d4 100644 --- a/beacon-chain/slasher/receive_test.go +++ b/beacon-chain/slasher/receive_test.go @@ -13,6 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" @@ -38,8 +39,8 @@ func TestSlasher_receiveAttestations_OK(t *testing.T) { }() firstIndices := []uint64{1, 2, 3} secondIndices := []uint64{4, 5, 6} - att1 := createAttestationWrapperEmptySig(t, 1, 2, firstIndices, nil) - att2 := createAttestationWrapperEmptySig(t, 1, 2, secondIndices, nil) + att1 := createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, firstIndices, nil) + att2 := createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, secondIndices, nil) wrappedAtt1 := &slashertypes.WrappedIndexedAtt{IndexedAtt: att1.IndexedAttestation} wrappedAtt2 := &slashertypes.WrappedIndexedAtt{IndexedAtt: att2.IndexedAttestation} indexedAttsChan <- wrappedAtt1 @@ -67,14 +68,14 @@ func TestService_pruneSlasherDataWithinSlidingWindow_AttestationsPruned(t *testi // Setup attestations for 2 validators at each epoch for epochs 0, 1, 2, 3. err := slasherDB.SaveAttestationRecordsForValidators(ctx, []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 0, []uint64{0}, bytesutil.PadTo([]byte("0a"), 32)), - createAttestationWrapperEmptySig(t, 0, 0, []uint64{1}, bytesutil.PadTo([]byte("0b"), 32)), - createAttestationWrapperEmptySig(t, 0, 1, []uint64{0}, bytesutil.PadTo([]byte("1a"), 32)), - createAttestationWrapperEmptySig(t, 0, 1, []uint64{1}, bytesutil.PadTo([]byte("1b"), 32)), - createAttestationWrapperEmptySig(t, 0, 2, []uint64{0}, bytesutil.PadTo([]byte("2a"), 32)), - createAttestationWrapperEmptySig(t, 0, 2, []uint64{1}, bytesutil.PadTo([]byte("2b"), 32)), - createAttestationWrapperEmptySig(t, 0, 3, []uint64{0}, bytesutil.PadTo([]byte("3a"), 32)), - createAttestationWrapperEmptySig(t, 0, 3, []uint64{1}, bytesutil.PadTo([]byte("3b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{0}, bytesutil.PadTo([]byte("0a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 0, []uint64{1}, bytesutil.PadTo([]byte("0b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{0}, bytesutil.PadTo([]byte("1a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 1, []uint64{1}, bytesutil.PadTo([]byte("1b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 2, []uint64{0}, bytesutil.PadTo([]byte("2a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 2, []uint64{1}, bytesutil.PadTo([]byte("2b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 3, []uint64{0}, bytesutil.PadTo([]byte("3a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 3, []uint64{1}, bytesutil.PadTo([]byte("3b"), 32)), }) require.NoError(t, err) @@ -95,8 +96,8 @@ func TestService_pruneSlasherDataWithinSlidingWindow_AttestationsPruned(t *testi // Setup attestations for 2 validators at epoch 4. err = slasherDB.SaveAttestationRecordsForValidators(ctx, []*slashertypes.IndexedAttestationWrapper{ - createAttestationWrapperEmptySig(t, 0, 4, []uint64{0}, bytesutil.PadTo([]byte("4a"), 32)), - createAttestationWrapperEmptySig(t, 0, 4, []uint64{1}, bytesutil.PadTo([]byte("4b"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 4, []uint64{0}, bytesutil.PadTo([]byte("4a"), 32)), + createAttestationWrapperEmptySig(t, version.Phase0, 0, 4, []uint64{1}, bytesutil.PadTo([]byte("4b"), 32)), }) require.NoError(t, err) @@ -224,7 +225,7 @@ func TestSlasher_receiveAttestations_OnlyValidAttestations(t *testing.T) { firstIndices := []uint64{1, 2, 3} secondIndices := []uint64{4, 5, 6} // Add a valid attestation. - validAtt := createAttestationWrapperEmptySig(t, 1, 2, firstIndices, nil) + validAtt := createAttestationWrapperEmptySig(t, version.Phase0, 1, 2, firstIndices, nil) wrappedValidAtt := &slashertypes.WrappedIndexedAtt{IndexedAtt: validAtt.IndexedAttestation} indexedAttsChan <- wrappedValidAtt // Send an invalid, bad attestation which will not diff --git a/beacon-chain/slasher/service_test.go b/beacon-chain/slasher/service_test.go index 2cd4c94c857a..1b4b5f97844c 100644 --- a/beacon-chain/slasher/service_test.go +++ b/beacon-chain/slasher/service_test.go @@ -3,6 +3,7 @@ package slasher import ( "context" "io" + "os" "testing" "time" @@ -23,7 +24,7 @@ func TestMain(m *testing.M) { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(io.Discard) - m.Run() + os.Exit(m.Run()) } func TestService_StartStop_ChainInitialized(t *testing.T) { diff --git a/beacon-chain/state/fieldtrie/field_trie_helpers.go b/beacon-chain/state/fieldtrie/field_trie_helpers.go index bef64470976b..9d6585005d00 100644 --- a/beacon-chain/state/fieldtrie/field_trie_helpers.go +++ b/beacon-chain/state/fieldtrie/field_trie_helpers.go @@ -14,21 +14,6 @@ import ( ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) -// ProofFromMerkleLayers creates a proof starting at the leaf index of the state Merkle layers. -func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex int) [][]byte { - // The merkle tree structure looks as follows: - // [[r1, r2, r3, r4], [parent1, parent2], [root]] - proof := make([][]byte, 0) - currentIndex := startingLeafIndex - for i := 0; i < len(layers)-1; i++ { - neighborIdx := currentIndex ^ 1 - neighbor := layers[i][neighborIdx] - proof = append(proof, neighbor) - currentIndex = currentIndex / 2 - } - return proof -} - func (f *FieldTrie) validateIndices(idxs []uint64) error { length := f.length if f.dataType == types.CompressedArray { diff --git a/beacon-chain/state/genesis/BUILD.bazel b/beacon-chain/state/genesis/BUILD.bazel index 41948e5b6482..2c5a225e98a8 100644 --- a/beacon-chain/state/genesis/BUILD.bazel +++ b/beacon-chain/state/genesis/BUILD.bazel @@ -8,7 +8,10 @@ go_library( ], embedsrcs = ["mainnet.ssz.snappy"], importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/genesis", - visibility = ["//beacon-chain/db:__subpackages__"], + visibility = [ + "//beacon-chain/db:__subpackages__", + "//config/params:__pkg__", + ], deps = [ "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", diff --git a/beacon-chain/state/interfaces.go b/beacon-chain/state/interfaces.go index 39f2a476d24b..3161f2c6c720 100644 --- a/beacon-chain/state/interfaces.go +++ b/beacon-chain/state/interfaces.go @@ -105,7 +105,6 @@ type WriteOnlyBeaconState interface { AppendHistoricalRoots(root [32]byte) error AppendHistoricalSummaries(*ethpb.HistoricalSummary) error SetLatestExecutionPayloadHeader(payload interfaces.ExecutionData) error - SaveValidatorIndices() } // ReadOnlyValidator defines a struct which only has read access to validator methods. @@ -117,8 +116,12 @@ type ReadOnlyValidator interface { ExitEpoch() primitives.Epoch PublicKey() [fieldparams.BLSPubkeyLength]byte GetWithdrawalCredentials() []byte + Copy() *ethpb.Validator Slashed() bool IsNil() bool + HasETH1WithdrawalCredentials() bool + HasCompoundingWithdrawalCredentials() bool + HasExecutionWithdrawalCredentials() bool } // ReadOnlyValidators defines a struct which only has read access to validators methods. @@ -140,7 +143,6 @@ type ReadOnlyBalances interface { Balances() []uint64 BalanceAtIndex(idx primitives.ValidatorIndex) (uint64, error) BalancesLength() int - ActiveBalanceAtIndex(idx primitives.ValidatorIndex) (uint64, error) } // ReadOnlyCheckpoint defines a struct which only has read access to checkpoint methods. @@ -199,6 +201,7 @@ type ReadOnlyWithdrawals interface { NextWithdrawalValidatorIndex() (primitives.ValidatorIndex, error) NextWithdrawalIndex() (uint64, error) PendingBalanceToWithdraw(idx primitives.ValidatorIndex) (uint64, error) + PendingPartialWithdrawals() ([]*ethpb.PendingPartialWithdrawal, error) NumPendingPartialWithdrawals() (uint64, error) HasPendingBalanceToWithdraw(idx primitives.ValidatorIndex) (bool, error) } @@ -223,7 +226,7 @@ type ReadOnlySyncCommittee interface { type ReadOnlyDeposits interface { DepositBalanceToConsume() (primitives.Gwei, error) DepositRequestsStartIndex() (uint64, error) - PendingBalanceDeposits() ([]*ethpb.PendingBalanceDeposit, error) + PendingDeposits() ([]*ethpb.PendingDeposit, error) } type ReadOnlyConsolidations interface { @@ -257,7 +260,7 @@ type WriteOnlyEth1Data interface { // WriteOnlyValidators defines a struct which only has write access to validators methods. type WriteOnlyValidators interface { SetValidators(val []*ethpb.Validator) error - ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error + ApplyToEveryValidator(f func(idx int, val ReadOnlyValidator) (*ethpb.Validator, error)) error UpdateValidatorAtIndex(idx primitives.ValidatorIndex, val *ethpb.Validator) error AppendValidator(val *ethpb.Validator) error } @@ -316,7 +319,7 @@ type WriteOnlySyncCommittee interface { type WriteOnlyWithdrawals interface { AppendPendingPartialWithdrawal(ppw *ethpb.PendingPartialWithdrawal) error - DequeuePartialWithdrawals(num uint64) error + DequeuePendingPartialWithdrawals(num uint64) error SetNextWithdrawalIndex(i uint64) error SetNextWithdrawalValidatorIndex(i primitives.ValidatorIndex) error } @@ -329,8 +332,8 @@ type WriteOnlyConsolidations interface { } type WriteOnlyDeposits interface { - AppendPendingBalanceDeposit(index primitives.ValidatorIndex, amount uint64) error + AppendPendingDeposit(pd *ethpb.PendingDeposit) error SetDepositRequestsStartIndex(index uint64) error - SetPendingBalanceDeposits(val []*ethpb.PendingBalanceDeposit) error + SetPendingDeposits(val []*ethpb.PendingDeposit) error SetDepositBalanceToConsume(primitives.Gwei) error } diff --git a/beacon-chain/state/state-native/BUILD.bazel b/beacon-chain/state/state-native/BUILD.bazel index da2f397025f1..6d14d26723d6 100644 --- a/beacon-chain/state/state-native/BUILD.bazel +++ b/beacon-chain/state/state-native/BUILD.bazel @@ -3,16 +3,15 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "beacon_state_mainnet.go", - "beacon_state_minimal.go", # keep + "beacon_state.go", "doc.go", "error.go", "getters_attestation.go", - "getters_balance_deposits.go", "getters_block.go", "getters_checkpoint.go", "getters_consolidation.go", "getters_deposit_requests.go", + "getters_deposits.go", "getters_eth1.go", "getters_exit.go", "getters_misc.go", @@ -28,12 +27,12 @@ go_library( "proofs.go", "readonly_validator.go", "setters_attestation.go", - "setters_balance_deposits.go", "setters_block.go", "setters_checkpoint.go", "setters_churn.go", "setters_consolidation.go", "setters_deposit_requests.go", + "setters_deposits.go", "setters_eth1.go", "setters_misc.go", "setters_participation.go", @@ -47,7 +46,6 @@ go_library( "ssz.go", "state_trie.go", "types.go", - "validator_index_cache.go", ], importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native", visibility = ["//visibility:public"], @@ -68,11 +66,13 @@ go_library( "//consensus-types/primitives:go_default_library", "//container/multi-value-slice:go_default_library", "//container/slice:go_default_library", + "//container/trie:go_default_library", "//crypto/bls:go_default_library", "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", "//math:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", @@ -82,7 +82,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) @@ -91,11 +90,11 @@ go_test( name = "go_default_test", srcs = [ "getters_attestation_test.go", - "getters_balance_deposits_test.go", "getters_block_test.go", "getters_checkpoint_test.go", "getters_consolidation_test.go", "getters_deposit_requests_test.go", + "getters_deposits_test.go", "getters_exit_test.go", "getters_participation_test.go", "getters_test.go", @@ -107,10 +106,10 @@ go_test( "readonly_validator_test.go", "references_test.go", "setters_attestation_test.go", - "setters_balance_deposits_test.go", "setters_churn_test.go", "setters_consolidation_test.go", "setters_deposit_requests_test.go", + "setters_deposits_test.go", "setters_eth1_test.go", "setters_misc_test.go", "setters_participation_test.go", @@ -121,7 +120,6 @@ go_test( "state_test.go", "state_trie_test.go", "types_test.go", - "validator_index_cache_test.go", ], data = glob(["testdata/**"]) + [ "@consensus_spec_tests_mainnet//:test_data", @@ -137,7 +135,6 @@ go_test( "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", - "//consensus-types:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", diff --git a/beacon-chain/state/state-native/beacon_state_minimal.go b/beacon-chain/state/state-native/beacon_state.go similarity index 93% rename from beacon-chain/state/state-native/beacon_state_minimal.go rename to beacon-chain/state/state-native/beacon_state.go index ad5a51d9349f..83ed2ff84b5a 100644 --- a/beacon-chain/state/state-native/beacon_state_minimal.go +++ b/beacon-chain/state/state-native/beacon_state.go @@ -1,5 +1,3 @@ -//go:build minimal - package state_native import ( @@ -31,7 +29,6 @@ type BeaconState struct { stateRoots customtypes.StateRoots stateRootsMultiValue *MultiValueStateRoots historicalRoots customtypes.HistoricalRoots - historicalSummaries []*ethpb.HistoricalSummary eth1Data *ethpb.Eth1Data eth1DataVotes []*ethpb.Eth1Data eth1DepositIndex uint64 @@ -57,9 +54,11 @@ type BeaconState struct { latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader latestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella latestExecutionPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb - latestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra - nextWithdrawalIndex uint64 - nextWithdrawalValidatorIndex primitives.ValidatorIndex + + // Capella fields + nextWithdrawalIndex uint64 + nextWithdrawalValidatorIndex primitives.ValidatorIndex + historicalSummaries []*ethpb.HistoricalSummary // Electra fields depositRequestsStartIndex uint64 @@ -68,7 +67,7 @@ type BeaconState struct { earliestExitEpoch primitives.Epoch consolidationBalanceToConsume primitives.Gwei earliestConsolidationEpoch primitives.Epoch - pendingBalanceDeposits []*ethpb.PendingBalanceDeposit // pending_balance_deposits: List[PendingBalanceDeposit, PENDING_BALANCE_DEPOSITS_LIMIT] + pendingDeposits []*ethpb.PendingDeposit // pending_deposits: List[PendingDeposit, PENDING_DEPOSITS_LIMIT] pendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal // pending_partial_withdrawals: List[PartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT] pendingConsolidations []*ethpb.PendingConsolidation // pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT] @@ -79,7 +78,6 @@ type BeaconState struct { stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie rebuildTrie map[types.FieldIndex]bool valMapHandler *stateutil.ValidatorMapHandler - validatorIndexCache *finalizedValidatorIndexCache merkleLayers [][][]byte sharedFieldReferences map[types.FieldIndex]*stateutil.Reference } @@ -94,7 +92,6 @@ type beaconStateMarshalable struct { BlockRoots customtypes.BlockRoots `json:"block_roots" yaml:"block_roots"` StateRoots customtypes.StateRoots `json:"state_roots" yaml:"state_roots"` HistoricalRoots customtypes.HistoricalRoots `json:"historical_roots" yaml:"historical_roots"` - HistoricalSummaries []*ethpb.HistoricalSummary `json:"historical_summaries" yaml:"historical_summaries"` Eth1Data *ethpb.Eth1Data `json:"eth_1_data" yaml:"eth_1_data"` Eth1DataVotes []*ethpb.Eth1Data `json:"eth_1_data_votes" yaml:"eth_1_data_votes"` Eth1DepositIndex uint64 `json:"eth_1_deposit_index" yaml:"eth_1_deposit_index"` @@ -116,16 +113,16 @@ type beaconStateMarshalable struct { LatestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader `json:"latest_execution_payload_header" yaml:"latest_execution_payload_header"` LatestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella `json:"latest_execution_payload_header_capella" yaml:"latest_execution_payload_header_capella"` LatestExecutionPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb `json:"latest_execution_payload_header_deneb" yaml:"latest_execution_payload_header_deneb"` - LatestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra `json:"latest_execution_payload_header_electra" yaml:"latest_execution_payload_header_electra"` NextWithdrawalIndex uint64 `json:"next_withdrawal_index" yaml:"next_withdrawal_index"` NextWithdrawalValidatorIndex primitives.ValidatorIndex `json:"next_withdrawal_validator_index" yaml:"next_withdrawal_validator_index"` + HistoricalSummaries []*ethpb.HistoricalSummary `json:"historical_summaries" yaml:"historical_summaries"` DepositRequestsStartIndex uint64 `json:"deposit_requests_start_index" yaml:"deposit_requests_start_index"` DepositBalanceToConsume primitives.Gwei `json:"deposit_balance_to_consume" yaml:"deposit_balance_to_consume"` ExitBalanceToConsume primitives.Gwei `json:"exit_balance_to_consume" yaml:"exit_balance_to_consume"` EarliestExitEpoch primitives.Epoch `json:"earliest_exit_epoch" yaml:"earliest_exit_epoch"` ConsolidationBalanceToConsume primitives.Gwei `json:"consolidation_balance_to_consume" yaml:"consolidation_balance_to_consume"` EarliestConsolidationEpoch primitives.Epoch `json:"earliest_consolidation_epoch" yaml:"earliest_consolidation_epoch"` - PendingBalanceDeposits []*ethpb.PendingBalanceDeposit `json:"pending_balance_deposits" yaml:"pending_balance_deposits"` + PendingDeposits []*ethpb.PendingDeposit `json:"pending_deposits" yaml:"pending_deposits"` PendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal `json:"pending_partial_withdrawals" yaml:"pending_partial_withdrawals"` PendingConsolidations []*ethpb.PendingConsolidation `json:"pending_consolidations" yaml:"pending_consolidations"` } @@ -164,7 +161,6 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) { BlockRoots: bRoots, StateRoots: sRoots, HistoricalRoots: b.historicalRoots, - HistoricalSummaries: b.historicalSummaries, Eth1Data: b.eth1Data, Eth1DataVotes: b.eth1DataVotes, Eth1DepositIndex: b.eth1DepositIndex, @@ -186,16 +182,16 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) { LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader, LatestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapella, LatestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDeneb, - LatestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectra, NextWithdrawalIndex: b.nextWithdrawalIndex, NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex, + HistoricalSummaries: b.historicalSummaries, DepositRequestsStartIndex: b.depositRequestsStartIndex, DepositBalanceToConsume: b.depositBalanceToConsume, ExitBalanceToConsume: b.exitBalanceToConsume, EarliestExitEpoch: b.earliestExitEpoch, ConsolidationBalanceToConsume: b.consolidationBalanceToConsume, EarliestConsolidationEpoch: b.earliestConsolidationEpoch, - PendingBalanceDeposits: b.pendingBalanceDeposits, + PendingDeposits: b.pendingDeposits, PendingPartialWithdrawals: b.pendingPartialWithdrawals, PendingConsolidations: b.pendingConsolidations, } diff --git a/beacon-chain/state/state-native/beacon_state_mainnet.go b/beacon-chain/state/state-native/beacon_state_mainnet.go deleted file mode 100644 index 922f870989d0..000000000000 --- a/beacon-chain/state/state-native/beacon_state_mainnet.go +++ /dev/null @@ -1,203 +0,0 @@ -//go:build !minimal - -package state_native - -import ( - "encoding/json" - "sync" - - "github.com/prysmaticlabs/go-bitfield" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/fieldtrie" - customtypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/custom-types" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil" - "github.com/prysmaticlabs/prysm/v5/config/features" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" -) - -// BeaconState defines a struct containing utilities for the Ethereum Beacon Chain state, defining -// getters and setters for its respective values and helpful functions such as HashTreeRoot(). -type BeaconState struct { - version int - genesisTime uint64 - genesisValidatorsRoot [32]byte - slot primitives.Slot - fork *ethpb.Fork - latestBlockHeader *ethpb.BeaconBlockHeader - blockRoots customtypes.BlockRoots - blockRootsMultiValue *MultiValueBlockRoots - stateRoots customtypes.StateRoots - stateRootsMultiValue *MultiValueStateRoots - historicalRoots customtypes.HistoricalRoots - historicalSummaries []*ethpb.HistoricalSummary - eth1Data *ethpb.Eth1Data - eth1DataVotes []*ethpb.Eth1Data - eth1DepositIndex uint64 - validators []*ethpb.Validator - validatorsMultiValue *MultiValueValidators - balances []uint64 - balancesMultiValue *MultiValueBalances - randaoMixes customtypes.RandaoMixes - randaoMixesMultiValue *MultiValueRandaoMixes - slashings []uint64 - previousEpochAttestations []*ethpb.PendingAttestation - currentEpochAttestations []*ethpb.PendingAttestation - previousEpochParticipation []byte - currentEpochParticipation []byte - justificationBits bitfield.Bitvector4 - previousJustifiedCheckpoint *ethpb.Checkpoint - currentJustifiedCheckpoint *ethpb.Checkpoint - finalizedCheckpoint *ethpb.Checkpoint - inactivityScores []uint64 - inactivityScoresMultiValue *MultiValueInactivityScores - currentSyncCommittee *ethpb.SyncCommittee - nextSyncCommittee *ethpb.SyncCommittee - latestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader - latestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella - latestExecutionPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb - latestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra - nextWithdrawalIndex uint64 - nextWithdrawalValidatorIndex primitives.ValidatorIndex - - // Electra fields - depositRequestsStartIndex uint64 - depositBalanceToConsume primitives.Gwei - exitBalanceToConsume primitives.Gwei - earliestExitEpoch primitives.Epoch - consolidationBalanceToConsume primitives.Gwei - earliestConsolidationEpoch primitives.Epoch - pendingBalanceDeposits []*ethpb.PendingBalanceDeposit // pending_balance_deposits: List[PendingBalanceDeposit, PENDING_BALANCE_DEPOSITS_LIMIT] - pendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal // pending_partial_withdrawals: List[PartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT] - pendingConsolidations []*ethpb.PendingConsolidation // pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT] - - id uint64 - lock sync.RWMutex - dirtyFields map[types.FieldIndex]bool - dirtyIndices map[types.FieldIndex][]uint64 - stateFieldLeaves map[types.FieldIndex]*fieldtrie.FieldTrie - rebuildTrie map[types.FieldIndex]bool - valMapHandler *stateutil.ValidatorMapHandler - validatorIndexCache *finalizedValidatorIndexCache - merkleLayers [][][]byte - sharedFieldReferences map[types.FieldIndex]*stateutil.Reference -} - -type beaconStateMarshalable struct { - Version int `json:"version" yaml:"version"` - GenesisTime uint64 `json:"genesis_time" yaml:"genesis_time"` - GenesisValidatorsRoot [32]byte `json:"genesis_validators_root" yaml:"genesis_validators_root"` - Slot primitives.Slot `json:"slot" yaml:"slot"` - Fork *ethpb.Fork `json:"fork" yaml:"fork"` - LatestBlockHeader *ethpb.BeaconBlockHeader `json:"latest_block_header" yaml:"latest_block_header"` - BlockRoots customtypes.BlockRoots `json:"block_roots" yaml:"block_roots"` - StateRoots customtypes.StateRoots `json:"state_roots" yaml:"state_roots"` - HistoricalRoots customtypes.HistoricalRoots `json:"historical_roots" yaml:"historical_roots"` - HistoricalSummaries []*ethpb.HistoricalSummary `json:"historical_summaries" yaml:"historical_summaries"` - Eth1Data *ethpb.Eth1Data `json:"eth_1_data" yaml:"eth_1_data"` - Eth1DataVotes []*ethpb.Eth1Data `json:"eth_1_data_votes" yaml:"eth_1_data_votes"` - Eth1DepositIndex uint64 `json:"eth_1_deposit_index" yaml:"eth_1_deposit_index"` - Validators []*ethpb.Validator `json:"validators" yaml:"validators"` - Balances []uint64 `json:"balances" yaml:"balances"` - RandaoMixes customtypes.RandaoMixes `json:"randao_mixes" yaml:"randao_mixes"` - Slashings []uint64 `json:"slashings" yaml:"slashings"` - PreviousEpochAttestations []*ethpb.PendingAttestation `json:"previous_epoch_attestations" yaml:"previous_epoch_attestations"` - CurrentEpochAttestations []*ethpb.PendingAttestation `json:"current_epoch_attestations" yaml:"current_epoch_attestations"` - PreviousEpochParticipation []byte `json:"previous_epoch_participation" yaml:"previous_epoch_participation"` - CurrentEpochParticipation []byte `json:"current_epoch_participation" yaml:"current_epoch_participation"` - JustificationBits bitfield.Bitvector4 `json:"justification_bits" yaml:"justification_bits"` - PreviousJustifiedCheckpoint *ethpb.Checkpoint `json:"previous_justified_checkpoint" yaml:"previous_justified_checkpoint"` - CurrentJustifiedCheckpoint *ethpb.Checkpoint `json:"current_justified_checkpoint" yaml:"current_justified_checkpoint"` - FinalizedCheckpoint *ethpb.Checkpoint `json:"finalized_checkpoint" yaml:"finalized_checkpoint"` - InactivityScores []uint64 `json:"inactivity_scores" yaml:"inactivity_scores"` - CurrentSyncCommittee *ethpb.SyncCommittee `json:"current_sync_committee" yaml:"current_sync_committee"` - NextSyncCommittee *ethpb.SyncCommittee `json:"next_sync_committee" yaml:"next_sync_committee"` - LatestExecutionPayloadHeader *enginev1.ExecutionPayloadHeader `json:"latest_execution_payload_header" yaml:"latest_execution_payload_header"` - LatestExecutionPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella `json:"latest_execution_payload_header_capella" yaml:"latest_execution_payload_header_capella"` - LatestExecutionPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb `json:"latest_execution_payload_header_deneb" yaml:"latest_execution_payload_header_deneb"` - LatestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra `json:"latest_execution_payload_header_electra" yaml:"latest_execution_payload_header_electra"` - NextWithdrawalIndex uint64 `json:"next_withdrawal_index" yaml:"next_withdrawal_index"` - NextWithdrawalValidatorIndex primitives.ValidatorIndex `json:"next_withdrawal_validator_index" yaml:"next_withdrawal_validator_index"` - DepositRequestsStartIndex uint64 `json:"deposit_requests_start_index" yaml:"deposit_requests_start_index"` - DepositBalanceToConsume primitives.Gwei `json:"deposit_balance_to_consume" yaml:"deposit_balance_to_consume"` - ExitBalanceToConsume primitives.Gwei `json:"exit_balance_to_consume" yaml:"exit_balance_to_consume"` - EarliestExitEpoch primitives.Epoch `json:"earliest_exit_epoch" yaml:"earliest_exit_epoch"` - ConsolidationBalanceToConsume primitives.Gwei `json:"consolidation_balance_to_consume" yaml:"consolidation_balance_to_consume"` - EarliestConsolidationEpoch primitives.Epoch `json:"earliest_consolidation_epoch" yaml:"earliest_consolidation_epoch"` - PendingBalanceDeposits []*ethpb.PendingBalanceDeposit `json:"pending_balance_deposits" yaml:"pending_balance_deposits"` - PendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal `json:"pending_partial_withdrawals" yaml:"pending_partial_withdrawals"` - PendingConsolidations []*ethpb.PendingConsolidation `json:"pending_consolidations" yaml:"pending_consolidations"` -} - -func (b *BeaconState) MarshalJSON() ([]byte, error) { - var bRoots customtypes.BlockRoots - var sRoots customtypes.StateRoots - var mixes customtypes.RandaoMixes - var balances []uint64 - var inactivityScores []uint64 - var vals []*ethpb.Validator - - if features.Get().EnableExperimentalState { - bRoots = b.blockRootsMultiValue.Value(b) - sRoots = b.stateRootsMultiValue.Value(b) - mixes = b.randaoMixesMultiValue.Value(b) - balances = b.balancesMultiValue.Value(b) - inactivityScores = b.inactivityScoresMultiValue.Value(b) - vals = b.validatorsMultiValue.Value(b) - } else { - bRoots = b.blockRoots - sRoots = b.stateRoots - mixes = b.randaoMixes - balances = b.balances - inactivityScores = b.inactivityScores - vals = b.validators - } - - marshalable := &beaconStateMarshalable{ - Version: b.version, - GenesisTime: b.genesisTime, - GenesisValidatorsRoot: b.genesisValidatorsRoot, - Slot: b.slot, - Fork: b.fork, - LatestBlockHeader: b.latestBlockHeader, - BlockRoots: bRoots, - StateRoots: sRoots, - HistoricalRoots: b.historicalRoots, - HistoricalSummaries: b.historicalSummaries, - Eth1Data: b.eth1Data, - Eth1DataVotes: b.eth1DataVotes, - Eth1DepositIndex: b.eth1DepositIndex, - Validators: vals, - Balances: balances, - RandaoMixes: mixes, - Slashings: b.slashings, - PreviousEpochAttestations: b.previousEpochAttestations, - CurrentEpochAttestations: b.currentEpochAttestations, - PreviousEpochParticipation: b.previousEpochParticipation, - CurrentEpochParticipation: b.currentEpochParticipation, - JustificationBits: b.justificationBits, - PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, - CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, - FinalizedCheckpoint: b.finalizedCheckpoint, - InactivityScores: inactivityScores, - CurrentSyncCommittee: b.currentSyncCommittee, - NextSyncCommittee: b.nextSyncCommittee, - LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader, - LatestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapella, - LatestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDeneb, - LatestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectra, - NextWithdrawalIndex: b.nextWithdrawalIndex, - NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex, - DepositRequestsStartIndex: b.depositRequestsStartIndex, - DepositBalanceToConsume: b.depositBalanceToConsume, - ExitBalanceToConsume: b.exitBalanceToConsume, - EarliestExitEpoch: b.earliestExitEpoch, - ConsolidationBalanceToConsume: b.consolidationBalanceToConsume, - EarliestConsolidationEpoch: b.earliestConsolidationEpoch, - PendingBalanceDeposits: b.pendingBalanceDeposits, - PendingPartialWithdrawals: b.pendingPartialWithdrawals, - PendingConsolidations: b.pendingConsolidations, - } - return json.Marshal(marshalable) -} diff --git a/beacon-chain/state/state-native/getters_deposit_requests.go b/beacon-chain/state/state-native/getters_deposit_requests.go index 2e91709d8ef8..7b1567721c5c 100644 --- a/beacon-chain/state/state-native/getters_deposit_requests.go +++ b/beacon-chain/state/state-native/getters_deposit_requests.go @@ -4,7 +4,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/runtime/version" ) -// DepositRequestsStartIndex is used for returning the deposit receipts start index which is used for eip6110 +// DepositRequestsStartIndex is used for returning the deposit requests start index which is used for eip6110 func (b *BeaconState) DepositRequestsStartIndex() (uint64, error) { if b.version < version.Electra { return 0, errNotSupported("DepositRequestsStartIndex", b.version) diff --git a/beacon-chain/state/state-native/getters_balance_deposits.go b/beacon-chain/state/state-native/getters_deposits.go similarity index 66% rename from beacon-chain/state/state-native/getters_balance_deposits.go rename to beacon-chain/state/state-native/getters_deposits.go index b31b872f082e..99e8ee6eb5cb 100644 --- a/beacon-chain/state/state-native/getters_balance_deposits.go +++ b/beacon-chain/state/state-native/getters_deposits.go @@ -18,22 +18,22 @@ func (b *BeaconState) DepositBalanceToConsume() (primitives.Gwei, error) { return b.depositBalanceToConsume, nil } -// PendingBalanceDeposits is a non-mutating call to the beacon state which returns a deep copy of +// PendingDeposits is a non-mutating call to the beacon state which returns a deep copy of // the pending balance deposit slice. This method requires access to the RLock on the state and // only applies in electra or later. -func (b *BeaconState) PendingBalanceDeposits() ([]*ethpb.PendingBalanceDeposit, error) { +func (b *BeaconState) PendingDeposits() ([]*ethpb.PendingDeposit, error) { if b.version < version.Electra { - return nil, errNotSupported("PendingBalanceDeposits", b.version) + return nil, errNotSupported("PendingDeposits", b.version) } b.lock.RLock() defer b.lock.RUnlock() - return b.pendingBalanceDepositsVal(), nil + return b.pendingDepositsVal(), nil } -func (b *BeaconState) pendingBalanceDepositsVal() []*ethpb.PendingBalanceDeposit { - if b.pendingBalanceDeposits == nil { +func (b *BeaconState) pendingDepositsVal() []*ethpb.PendingDeposit { + if b.pendingDeposits == nil { return nil } - return ethpb.CopySlice(b.pendingBalanceDeposits) + return ethpb.CopySlice(b.pendingDeposits) } diff --git a/beacon-chain/state/state-native/getters_balance_deposits_test.go b/beacon-chain/state/state-native/getters_deposits_test.go similarity index 56% rename from beacon-chain/state/state-native/getters_balance_deposits_test.go rename to beacon-chain/state/state-native/getters_deposits_test.go index ab1738e0b754..4deaf1a53f6d 100644 --- a/beacon-chain/state/state-native/getters_balance_deposits_test.go +++ b/beacon-chain/state/state-native/getters_deposits_test.go @@ -25,21 +25,40 @@ func TestDepositBalanceToConsume(t *testing.T) { require.ErrorContains(t, "not supported", err) } -func TestPendingBalanceDeposits(t *testing.T) { +func TestPendingDeposits(t *testing.T) { s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{ - PendingBalanceDeposits: []*eth.PendingBalanceDeposit{ - {Index: 1, Amount: 2}, - {Index: 3, Amount: 4}, + PendingDeposits: []*eth.PendingDeposit{ + { + PublicKey: []byte{1, 2, 3}, + WithdrawalCredentials: []byte{4, 5, 6}, + Amount: 2, + Signature: []byte{7, 8, 9}, + Slot: 1, + }, + { + PublicKey: []byte{11, 22, 33}, + WithdrawalCredentials: []byte{44, 55, 66}, + Amount: 4, + Signature: []byte{77, 88, 99}, + Slot: 2, + }, }, }) require.NoError(t, err) - pbd, err := s.PendingBalanceDeposits() + pbd, err := s.PendingDeposits() require.NoError(t, err) require.Equal(t, 2, len(pbd)) - require.Equal(t, primitives.ValidatorIndex(1), pbd[0].Index) + require.DeepEqual(t, []byte{1, 2, 3}, pbd[0].PublicKey) + require.DeepEqual(t, []byte{4, 5, 6}, pbd[0].WithdrawalCredentials) require.Equal(t, uint64(2), pbd[0].Amount) - require.Equal(t, primitives.ValidatorIndex(3), pbd[1].Index) + require.DeepEqual(t, []byte{7, 8, 9}, pbd[0].Signature) + require.Equal(t, primitives.Slot(1), pbd[0].Slot) + + require.DeepEqual(t, []byte{11, 22, 33}, pbd[1].PublicKey) + require.DeepEqual(t, []byte{44, 55, 66}, pbd[1].WithdrawalCredentials) require.Equal(t, uint64(4), pbd[1].Amount) + require.DeepEqual(t, []byte{77, 88, 99}, pbd[1].Signature) + require.Equal(t, primitives.Slot(2), pbd[1].Slot) // Fails for older than electra state s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{}) diff --git a/beacon-chain/state/state-native/getters_payload_header.go b/beacon-chain/state/state-native/getters_payload_header.go index 577105346c5a..d269058ade8a 100644 --- a/beacon-chain/state/state-native/getters_payload_header.go +++ b/beacon-chain/state/state-native/getters_payload_header.go @@ -17,16 +17,17 @@ func (b *BeaconState) LatestExecutionPayloadHeader() (interfaces.ExecutionData, b.lock.RLock() defer b.lock.RUnlock() - switch b.version { - case version.Bellatrix: - return blocks.WrappedExecutionPayloadHeader(b.latestExecutionPayloadHeader.Copy()) - case version.Capella: - return blocks.WrappedExecutionPayloadHeaderCapella(b.latestExecutionPayloadHeaderCapella.Copy()) - case version.Deneb: + if b.version >= version.Deneb { return blocks.WrappedExecutionPayloadHeaderDeneb(b.latestExecutionPayloadHeaderDeneb.Copy()) - case version.Electra: - return blocks.WrappedExecutionPayloadHeaderElectra(b.latestExecutionPayloadHeaderElectra.Copy()) - default: - return nil, fmt.Errorf("unsupported version (%s) for latest execution payload header", version.String(b.version)) } + + if b.version >= version.Capella { + return blocks.WrappedExecutionPayloadHeaderCapella(b.latestExecutionPayloadHeaderCapella.Copy()) + } + + if b.version >= version.Bellatrix { + return blocks.WrappedExecutionPayloadHeader(b.latestExecutionPayloadHeader.Copy()) + } + + return nil, fmt.Errorf("unsupported version (%s) for latest execution payload header", version.String(b.version)) } diff --git a/beacon-chain/state/state-native/getters_state.go b/beacon-chain/state/state-native/getters_state.go index 66f512369f9b..e7d0e3701747 100644 --- a/beacon-chain/state/state-native/getters_state.go +++ b/beacon-chain/state/state-native/getters_state.go @@ -22,12 +22,22 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { rm := b.randaoMixesVal().Slice() var vals []*ethpb.Validator var bals []uint64 + var inactivityScores []uint64 + if features.Get().EnableExperimentalState { - vals = b.validatorsVal() - bals = b.balancesVal() + if b.balancesMultiValue != nil { + bals = b.balancesMultiValue.Value(b) + } + if b.inactivityScoresMultiValue != nil { + inactivityScores = b.inactivityScoresMultiValue.Value(b) + } + if b.validatorsMultiValue != nil { + vals = b.validatorsMultiValue.Value(b) + } } else { - vals = b.validators bals = b.balances + inactivityScores = b.inactivityScores + vals = b.validators } switch b.version { @@ -78,7 +88,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, FinalizedCheckpoint: b.finalizedCheckpoint, - InactivityScores: b.inactivityScoresVal(), + InactivityScores: inactivityScores, CurrentSyncCommittee: b.currentSyncCommittee, NextSyncCommittee: b.nextSyncCommittee, } @@ -105,7 +115,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, FinalizedCheckpoint: b.finalizedCheckpoint, - InactivityScores: b.inactivityScoresVal(), + InactivityScores: inactivityScores, CurrentSyncCommittee: b.currentSyncCommittee, NextSyncCommittee: b.nextSyncCommittee, LatestExecutionPayloadHeader: b.latestExecutionPayloadHeader, @@ -133,7 +143,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, FinalizedCheckpoint: b.finalizedCheckpoint, - InactivityScores: b.inactivityScoresVal(), + InactivityScores: inactivityScores, CurrentSyncCommittee: b.currentSyncCommittee, NextSyncCommittee: b.nextSyncCommittee, LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderCapella, @@ -164,7 +174,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, FinalizedCheckpoint: b.finalizedCheckpoint, - InactivityScores: b.inactivityScoresVal(), + InactivityScores: inactivityScores, CurrentSyncCommittee: b.currentSyncCommittee, NextSyncCommittee: b.nextSyncCommittee, LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderDeneb, @@ -172,7 +182,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex, HistoricalSummaries: b.historicalSummaries, } - case version.Electra: + case version.Electra, version.Fulu: return ðpb.BeaconStateElectra{ GenesisTime: b.genesisTime, GenesisValidatorsRoot: gvrCopy[:], @@ -195,10 +205,10 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint, CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint, FinalizedCheckpoint: b.finalizedCheckpoint, - InactivityScores: b.inactivityScoresVal(), + InactivityScores: inactivityScores, CurrentSyncCommittee: b.currentSyncCommittee, NextSyncCommittee: b.nextSyncCommittee, - LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderElectra, + LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderDeneb, NextWithdrawalIndex: b.nextWithdrawalIndex, NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex, HistoricalSummaries: b.historicalSummaries, @@ -208,7 +218,7 @@ func (b *BeaconState) ToProtoUnsafe() interface{} { EarliestExitEpoch: b.earliestExitEpoch, ConsolidationBalanceToConsume: b.consolidationBalanceToConsume, EarliestConsolidationEpoch: b.earliestConsolidationEpoch, - PendingBalanceDeposits: b.pendingBalanceDeposits, + PendingDeposits: b.pendingDeposits, PendingPartialWithdrawals: b.pendingPartialWithdrawals, PendingConsolidations: b.pendingConsolidations, } @@ -378,7 +388,7 @@ func (b *BeaconState) ToProto() interface{} { NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex, HistoricalSummaries: b.historicalSummariesVal(), } - case version.Electra: + case version.Electra, version.Fulu: return ðpb.BeaconStateElectra{ GenesisTime: b.genesisTime, GenesisValidatorsRoot: gvrCopy[:], @@ -404,7 +414,7 @@ func (b *BeaconState) ToProto() interface{} { InactivityScores: b.inactivityScoresVal(), CurrentSyncCommittee: b.currentSyncCommitteeVal(), NextSyncCommittee: b.nextSyncCommitteeVal(), - LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderElectra.Copy(), + LatestExecutionPayloadHeader: b.latestExecutionPayloadHeaderDeneb.Copy(), NextWithdrawalIndex: b.nextWithdrawalIndex, NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex, HistoricalSummaries: b.historicalSummariesVal(), @@ -414,7 +424,7 @@ func (b *BeaconState) ToProto() interface{} { EarliestExitEpoch: b.earliestExitEpoch, ConsolidationBalanceToConsume: b.consolidationBalanceToConsume, EarliestConsolidationEpoch: b.earliestConsolidationEpoch, - PendingBalanceDeposits: b.pendingBalanceDepositsVal(), + PendingDeposits: b.pendingDepositsVal(), PendingPartialWithdrawals: b.pendingPartialWithdrawalsVal(), PendingConsolidations: b.pendingConsolidationsVal(), } @@ -543,3 +553,5 @@ func ProtobufBeaconStateElectra(s interface{}) (*ethpb.BeaconStateElectra, error } return pbState, nil } + +var ProtobufBeaconStateFulu = ProtobufBeaconStateElectra diff --git a/beacon-chain/state/state-native/getters_validator.go b/beacon-chain/state/state-native/getters_validator.go index 6acac6100040..dc874bf16ccd 100644 --- a/beacon-chain/state/state-native/getters_validator.go +++ b/beacon-chain/state/state-native/getters_validator.go @@ -2,7 +2,6 @@ package state_native import ( "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/features" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" @@ -151,6 +150,10 @@ func (b *BeaconState) ValidatorAtIndexReadOnly(idx primitives.ValidatorIndex) (s b.lock.RLock() defer b.lock.RUnlock() + return b.validatorAtIndexReadOnly(idx) +} + +func (b *BeaconState) validatorAtIndexReadOnly(idx primitives.ValidatorIndex) (state.ReadOnlyValidator, error) { if features.Get().EnableExperimentalState { if b.validatorsMultiValue == nil { return nil, state.ErrNilValidatorsInState @@ -180,10 +183,6 @@ func (b *BeaconState) ValidatorIndexByPubkey(key [fieldparams.BLSPubkeyLength]by b.lock.RLock() defer b.lock.RUnlock() - if b.Version() >= version.Electra { - return b.getValidatorIndex(key) - } - var numOfVals int if features.Get().EnableExperimentalState { numOfVals = b.validatorsMultiValue.Len(b) @@ -446,34 +445,6 @@ func (b *BeaconState) inactivityScoresVal() []uint64 { return res } -// ActiveBalanceAtIndex returns the active balance for the given validator. -// -// Spec definition: -// -// def get_active_balance(state: BeaconState, validator_index: ValidatorIndex) -> Gwei: -// max_effective_balance = get_validator_max_effective_balance(state.validators[validator_index]) -// return min(state.balances[validator_index], max_effective_balance) -func (b *BeaconState) ActiveBalanceAtIndex(i primitives.ValidatorIndex) (uint64, error) { - if b.version < version.Electra { - return 0, errNotSupported("ActiveBalanceAtIndex", b.version) - } - - b.lock.RLock() - defer b.lock.RUnlock() - - v, err := b.validatorAtIndex(i) - if err != nil { - return 0, err - } - - bal, err := b.balanceAtIndex(i) - if err != nil { - return 0, err - } - - return min(bal, helpers.ValidatorMaxEffectiveBalance(v)), nil -} - // PendingBalanceToWithdraw returns the sum of all pending withdrawals for the given validator. // // Spec definition: diff --git a/beacon-chain/state/state-native/getters_validator_test.go b/beacon-chain/state/state-native/getters_validator_test.go index fed0359806e3..0a9cce57202e 100644 --- a/beacon-chain/state/state-native/getters_validator_test.go +++ b/beacon-chain/state/state-native/getters_validator_test.go @@ -1,15 +1,12 @@ package state_native_test import ( - "math" "testing" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" statenative "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" testtmpl "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/testing" - "github.com/prysmaticlabs/prysm/v5/config/params" - consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" "github.com/prysmaticlabs/prysm/v5/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/assert" @@ -72,60 +69,6 @@ func TestValidatorIndexes(t *testing.T) { }) } -func TestActiveBalanceAtIndex(t *testing.T) { - // Test setup with a state with 4 validators. - // Validators 0 & 1 have compounding withdrawal credentials while validators 2 & 3 have BLS withdrawal credentials. - pb := ðpb.BeaconStateElectra{ - Validators: []*ethpb.Validator{ - { - WithdrawalCredentials: []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte}, - }, - { - WithdrawalCredentials: []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte}, - }, - { - WithdrawalCredentials: []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}, - }, - { - WithdrawalCredentials: []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}, - }, - }, - Balances: []uint64{ - 55, - math.MaxUint64, - 55, - math.MaxUint64, - }, - } - state, err := statenative.InitializeFromProtoUnsafeElectra(pb) - require.NoError(t, err) - - ab, err := state.ActiveBalanceAtIndex(0) - require.NoError(t, err) - require.Equal(t, uint64(55), ab) - - ab, err = state.ActiveBalanceAtIndex(1) - require.NoError(t, err) - require.Equal(t, params.BeaconConfig().MaxEffectiveBalanceElectra, ab) - - ab, err = state.ActiveBalanceAtIndex(2) - require.NoError(t, err) - require.Equal(t, uint64(55), ab) - - ab, err = state.ActiveBalanceAtIndex(3) - require.NoError(t, err) - require.Equal(t, params.BeaconConfig().MinActivationBalance, ab) - - // Accessing a validator index out of bounds should error. - _, err = state.ActiveBalanceAtIndex(4) - require.ErrorIs(t, err, consensus_types.ErrOutOfBounds) - - // Accessing a validator wwhere balance slice is out of bounds for some reason. - require.NoError(t, state.SetBalances([]uint64{})) - _, err = state.ActiveBalanceAtIndex(0) - require.ErrorIs(t, err, consensus_types.ErrOutOfBounds) -} - func TestPendingBalanceToWithdraw(t *testing.T) { pb := ðpb.BeaconStateElectra{ PendingPartialWithdrawals: []*ethpb.PendingPartialWithdrawal{ diff --git a/beacon-chain/state/state-native/getters_withdrawal.go b/beacon-chain/state/state-native/getters_withdrawal.go index e2a26d029673..2c53c1c39920 100644 --- a/beacon-chain/state/state-native/getters_withdrawal.go +++ b/beacon-chain/state/state-native/getters_withdrawal.go @@ -49,56 +49,59 @@ func (b *BeaconState) NextWithdrawalValidatorIndex() (primitives.ValidatorIndex, // Spec definition: // // def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64]: -// epoch = get_current_epoch(state) -// withdrawal_index = state.next_withdrawal_index -// validator_index = state.next_withdrawal_validator_index -// withdrawals: List[Withdrawal] = [] +// epoch = get_current_epoch(state) +// withdrawal_index = state.next_withdrawal_index +// validator_index = state.next_withdrawal_validator_index +// withdrawals: List[Withdrawal] = [] +// processed_partial_withdrawals_count = 0 // -// # [New in Electra:EIP7251] Consume pending partial withdrawals -// for withdrawal in state.pending_partial_withdrawals: -// if withdrawal.withdrawable_epoch > epoch or len(withdrawals) == MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: -// break +// # [New in Electra:EIP7251] Consume pending partial withdrawals +// for withdrawal in state.pending_partial_withdrawals: +// if withdrawal.withdrawable_epoch > epoch or len(withdrawals) == MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: +// break // -// validator = state.validators[withdrawal.index] -// has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE -// has_excess_balance = state.balances[withdrawal.index] > MIN_ACTIVATION_BALANCE -// if validator.exit_epoch == FAR_FUTURE_EPOCH and has_sufficient_effective_balance and has_excess_balance: -// withdrawable_balance = min(state.balances[withdrawal.index] - MIN_ACTIVATION_BALANCE, withdrawal.amount) -// withdrawals.append(Withdrawal( -// index=withdrawal_index, -// validator_index=withdrawal.index, -// address=ExecutionAddress(validator.withdrawal_credentials[12:]), -// amount=withdrawable_balance, -// )) -// withdrawal_index += WithdrawalIndex(1) +// validator = state.validators[withdrawal.index] +// has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE +// has_excess_balance = state.balances[withdrawal.index] > MIN_ACTIVATION_BALANCE +// if validator.exit_epoch == FAR_FUTURE_EPOCH and has_sufficient_effective_balance and has_excess_balance: +// withdrawable_balance = min(state.balances[withdrawal.index] - MIN_ACTIVATION_BALANCE, withdrawal.amount) +// withdrawals.append(Withdrawal( +// index=withdrawal_index, +// validator_index=withdrawal.index, +// address=ExecutionAddress(validator.withdrawal_credentials[12:]), +// amount=withdrawable_balance, +// )) +// withdrawal_index += WithdrawalIndex(1) // -// partial_withdrawals_count = len(withdrawals) +// processed_partial_withdrawals_count += 1 // -// # Sweep for remaining. -// bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) -// for _ in range(bound): -// validator = state.validators[validator_index] -// balance = state.balances[validator_index] -// if is_fully_withdrawable_validator(validator, balance, epoch): -// withdrawals.append(Withdrawal( -// index=withdrawal_index, -// validator_index=validator_index, -// address=ExecutionAddress(validator.withdrawal_credentials[12:]), -// amount=balance, -// )) -// withdrawal_index += WithdrawalIndex(1) -// elif is_partially_withdrawable_validator(validator, balance): -// withdrawals.append(Withdrawal( -// index=withdrawal_index, -// validator_index=validator_index, -// address=ExecutionAddress(validator.withdrawal_credentials[12:]), -// amount=balance - get_validator_max_effective_balance(validator), # [Modified in Electra:EIP7251] -// )) -// withdrawal_index += WithdrawalIndex(1) -// if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD: -// break -// validator_index = ValidatorIndex((validator_index + 1) % len(state.validators)) -// return withdrawals, partial_withdrawals_count +// # Sweep for remaining. +// bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) +// for _ in range(bound): +// validator = state.validators[validator_index] +// # [Modified in Electra:EIP7251] +// partially_withdrawn_balance = sum(withdrawal.amount for withdrawal in withdrawals if withdrawal.validator_index == validator_index) +// balance = state.balances[validator_index] - partially_withdrawn_balance +// if is_fully_withdrawable_validator(validator, balance, epoch): +// withdrawals.append(Withdrawal( +// index=withdrawal_index, +// validator_index=validator_index, +// address=ExecutionAddress(validator.withdrawal_credentials[12:]), +// amount=balance, +// )) +// withdrawal_index += WithdrawalIndex(1) +// elif is_partially_withdrawable_validator(validator, balance): +// withdrawals.append(Withdrawal( +// index=withdrawal_index, +// validator_index=validator_index, +// address=ExecutionAddress(validator.withdrawal_credentials[12:]), +// amount=balance - get_max_effective_balance(validator), # [Modified in Electra:EIP7251] +// )) +// withdrawal_index += WithdrawalIndex(1) +// if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD: +// break +// validator_index = ValidatorIndex((validator_index + 1) % len(state.validators)) +// return withdrawals, processed_partial_withdrawals_count func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, error) { if b.version < version.Capella { return nil, 0, errNotSupported("ExpectedWithdrawals", b.version) @@ -113,13 +116,14 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err epoch := slots.ToEpoch(b.slot) // Electra partial withdrawals functionality. + var processedPartialWithdrawalsCount uint64 if b.version >= version.Electra { for _, w := range b.pendingPartialWithdrawals { if w.WithdrawableEpoch > epoch || len(withdrawals) >= int(params.BeaconConfig().MaxPendingPartialsPerWithdrawalsSweep) { break } - v, err := b.validatorAtIndex(w.Index) + v, err := b.validatorAtIndexReadOnly(w.Index) if err != nil { return nil, 0, fmt.Errorf("failed to determine withdrawals at index %d: %w", w.Index, err) } @@ -127,26 +131,26 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err if err != nil { return nil, 0, fmt.Errorf("could not retrieve balance at index %d: %w", w.Index, err) } - hasSufficientEffectiveBalance := v.EffectiveBalance >= params.BeaconConfig().MinActivationBalance + hasSufficientEffectiveBalance := v.EffectiveBalance() >= params.BeaconConfig().MinActivationBalance hasExcessBalance := vBal > params.BeaconConfig().MinActivationBalance - if v.ExitEpoch == params.BeaconConfig().FarFutureEpoch && hasSufficientEffectiveBalance && hasExcessBalance { + if v.ExitEpoch() == params.BeaconConfig().FarFutureEpoch && hasSufficientEffectiveBalance && hasExcessBalance { amount := min(vBal-params.BeaconConfig().MinActivationBalance, w.Amount) withdrawals = append(withdrawals, &enginev1.Withdrawal{ Index: withdrawalIndex, ValidatorIndex: w.Index, - Address: v.WithdrawalCredentials[12:], + Address: v.GetWithdrawalCredentials()[12:], Amount: amount, }) withdrawalIndex++ } + processedPartialWithdrawalsCount++ } } - partialWithdrawalsCount := uint64(len(withdrawals)) validatorsLen := b.validatorsLen() bound := mathutil.Min(uint64(validatorsLen), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep) for i := uint64(0); i < bound; i++ { - val, err := b.validatorAtIndex(validatorIndex) + val, err := b.validatorAtIndexReadOnly(validatorIndex) if err != nil { return nil, 0, errors.Wrapf(err, "could not retrieve validator at index %d", validatorIndex) } @@ -154,6 +158,15 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err if err != nil { return nil, 0, errors.Wrapf(err, "could not retrieve balance at index %d", validatorIndex) } + if b.version >= version.Electra { + var partiallyWithdrawnBalance uint64 + for _, w := range withdrawals { + if w.ValidatorIndex == validatorIndex { + partiallyWithdrawnBalance += w.Amount + } + } + balance = balance - partiallyWithdrawnBalance + } if helpers.IsFullyWithdrawableValidator(val, balance, epoch, b.version) { withdrawals = append(withdrawals, &enginev1.Withdrawal{ Index: withdrawalIndex, @@ -180,7 +193,16 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err } } - return withdrawals, partialWithdrawalsCount, nil + return withdrawals, processedPartialWithdrawalsCount, nil +} + +func (b *BeaconState) PendingPartialWithdrawals() ([]*ethpb.PendingPartialWithdrawal, error) { + if b.version < version.Electra { + return nil, errNotSupported("PendingPartialWithdrawals", b.version) + } + b.lock.RLock() + defer b.lock.RUnlock() + return b.pendingPartialWithdrawalsVal(), nil } func (b *BeaconState) pendingPartialWithdrawalsVal() []*ethpb.PendingPartialWithdrawal { diff --git a/beacon-chain/state/state-native/getters_withdrawal_test.go b/beacon-chain/state/state-native/getters_withdrawal_test.go index 2b247c255bf8..1fc8f188a743 100644 --- a/beacon-chain/state/state-native/getters_withdrawal_test.go +++ b/beacon-chain/state/state-native/getters_withdrawal_test.go @@ -64,7 +64,7 @@ func TestNextWithdrawalValidatorIndex(t *testing.T) { } func TestExpectedWithdrawals(t *testing.T) { - for _, stateVersion := range []int{version.Capella, version.Deneb, version.Electra} { + for _, stateVersion := range []int{version.Capella, version.Deneb, version.Electra, version.Fulu} { t.Run(version.String(stateVersion), func(t *testing.T) { t.Run("no withdrawals", func(t *testing.T) { s := state_native.EmptyStateFromVersion(t, stateVersion) @@ -343,10 +343,76 @@ func TestExpectedWithdrawals(t *testing.T) { require.NoError(t, pb.UnmarshalSSZ(serializedSSZ)) s, err := state_native.InitializeFromProtoElectra(pb) require.NoError(t, err) - t.Log(s.NumPendingPartialWithdrawals()) expected, partialWithdrawalsCount, err := s.ExpectedWithdrawals() require.NoError(t, err) require.Equal(t, 8, len(expected)) require.Equal(t, uint64(8), partialWithdrawalsCount) }) + + t.Run("electra some pending partial withdrawals", func(t *testing.T) { + // Load a serialized Electra state from disk. + // This spectest has a fully hydrated beacon state with partial pending withdrawals. + serializedBytes, err := util.BazelFileBytes("tests/mainnet/electra/operations/withdrawal_request/pyspec_tests/pending_withdrawals_consume_all_excess_balance/pre.ssz_snappy") + require.NoError(t, err) + serializedSSZ, err := snappy.Decode(nil /* dst */, serializedBytes) + require.NoError(t, err) + pb := ðpb.BeaconStateElectra{} + require.NoError(t, pb.UnmarshalSSZ(serializedSSZ)) + s, err := state_native.InitializeFromProtoElectra(pb) + require.NoError(t, err) + p, err := s.PendingPartialWithdrawals() + require.NoError(t, err) + require.NoError(t, s.UpdateBalancesAtIndex(p[0].Index, 0)) // This should still count as partial withdrawal. + _, partialWithdrawalsCount, err := s.ExpectedWithdrawals() + require.NoError(t, err) + require.Equal(t, uint64(10), partialWithdrawalsCount) + }) + t.Run("electra same validator has one partially and one fully withdrawable", func(t *testing.T) { + s, _ := util.DeterministicGenesisStateElectra(t, 1) + vals := make([]*ethpb.Validator, 100) + balances := make([]uint64, 100) + for i := range vals { + balances[i] = params.BeaconConfig().MaxEffectiveBalance + val := ðpb.Validator{ + WithdrawalCredentials: make([]byte, 32), + EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, + WithdrawableEpoch: primitives.Epoch(1), + ExitEpoch: params.BeaconConfig().FarFutureEpoch, + } + val.WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + val.WithdrawalCredentials[31] = byte(i) + vals[i] = val + } + balances[1] += params.BeaconConfig().MinDepositAmount + vals[1].WithdrawableEpoch = primitives.Epoch(0) + require.NoError(t, s.SetValidators(vals)) + require.NoError(t, s.SetBalances(balances)) + // Give validator a pending balance to withdraw. + require.NoError(t, s.AppendPendingPartialWithdrawal(ðpb.PendingPartialWithdrawal{ + Index: 1, + Amount: balances[1], // will only deduct excess even though balance is more that minimum activation + WithdrawableEpoch: primitives.Epoch(0), + })) + p, err := s.PendingPartialWithdrawals() + require.NoError(t, err) + require.Equal(t, 1, len(p)) + expected, _, err := s.ExpectedWithdrawals() + require.NoError(t, err) + require.Equal(t, 2, len(expected)) + + withdrawalFull := &enginev1.Withdrawal{ + Index: 1, + ValidatorIndex: 1, + Address: vals[1].WithdrawalCredentials[12:], + Amount: balances[1] - params.BeaconConfig().MinDepositAmount, // subtract the partial from this + } + withdrawalPartial := &enginev1.Withdrawal{ + Index: 0, + ValidatorIndex: 1, + Address: vals[1].WithdrawalCredentials[12:], + Amount: params.BeaconConfig().MinDepositAmount, + } + require.DeepEqual(t, withdrawalPartial, expected[0]) + require.DeepEqual(t, withdrawalFull, expected[1]) + }) } diff --git a/beacon-chain/state/state-native/hasher.go b/beacon-chain/state/state-native/hasher.go index c4e3254c49df..781b244827f5 100644 --- a/beacon-chain/state/state-native/hasher.go +++ b/beacon-chain/state/state-native/hasher.go @@ -12,8 +12,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/ssz" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" ) // ComputeFieldRootsWithHasher hashes the provided state and returns its respective field roots. @@ -41,6 +41,8 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateDenebFieldCount) case version.Electra: fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateElectraFieldCount) + case version.Fulu: + fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateFuluFieldCount) default: return nil, fmt.Errorf("unknown state version %s", version.String(state.version)) } @@ -243,7 +245,7 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b fieldRoots[types.LatestExecutionPayloadHeaderCapella.RealPosition()] = executionPayloadRoot[:] } - if state.version == version.Deneb { + if state.version >= version.Deneb { // Execution payload root. executionPayloadRoot, err := state.latestExecutionPayloadHeaderDeneb.HashTreeRoot() if err != nil { @@ -252,15 +254,6 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b fieldRoots[types.LatestExecutionPayloadHeaderDeneb.RealPosition()] = executionPayloadRoot[:] } - if state.version == version.Electra { - // Execution payload root. - executionPayloadRoot, err := state.latestExecutionPayloadHeaderElectra.HashTreeRoot() - if err != nil { - return nil, err - } - fieldRoots[types.LatestExecutionPayloadHeaderElectra.RealPosition()] = executionPayloadRoot[:] - } - if state.version >= version.Capella { // Next withdrawal index root. nextWithdrawalIndexRoot := make([]byte, 32) @@ -305,12 +298,12 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b eceRoot := ssz.Uint64Root(uint64(state.earliestConsolidationEpoch)) fieldRoots[types.EarliestConsolidationEpoch.RealPosition()] = eceRoot[:] - // PendingBalanceDeposits root. - pbdRoot, err := stateutil.PendingBalanceDepositsRoot(state.pendingBalanceDeposits) + // PendingDeposits root. + pbdRoot, err := stateutil.PendingDepositsRoot(state.pendingDeposits) if err != nil { return nil, errors.Wrap(err, "could not compute pending balance deposits merkleization") } - fieldRoots[types.PendingBalanceDeposits.RealPosition()] = pbdRoot[:] + fieldRoots[types.PendingDeposits.RealPosition()] = pbdRoot[:] // PendingPartialWithdrawals root. ppwRoot, err := stateutil.PendingPartialWithdrawalsRoot(state.pendingPartialWithdrawals) diff --git a/beacon-chain/state/state-native/proofs.go b/beacon-chain/state/state-native/proofs.go index c08fcd8b29ed..c1b12c4e388f 100644 --- a/beacon-chain/state/state-native/proofs.go +++ b/beacon-chain/state/state-native/proofs.go @@ -4,8 +4,8 @@ import ( "context" "encoding/binary" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/fieldtrie" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types" + "github.com/prysmaticlabs/prysm/v5/container/trie" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/runtime/version" ) @@ -56,7 +56,7 @@ func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte, if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.CurrentSyncCommittee.RealPosition()), nil + return trie.ProofFromMerkleLayers(b.merkleLayers, types.CurrentSyncCommittee.RealPosition()), nil } // NextSyncCommitteeProof from the state's Merkle trie representation. @@ -74,7 +74,7 @@ func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, err if err := b.recomputeDirtyFields(ctx); err != nil { return nil, err } - return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.NextSyncCommittee.RealPosition()), nil + return trie.ProofFromMerkleLayers(b.merkleLayers, types.NextSyncCommittee.RealPosition()), nil } // FinalizedRootProof crafts a Merkle proof for the finalized root @@ -102,7 +102,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error) epochRoot := bytesutil.ToBytes32(epochBuf) proof := make([][]byte, 0) proof = append(proof, epochRoot[:]) - branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.FinalizedCheckpoint.RealPosition()) + branch := trie.ProofFromMerkleLayers(b.merkleLayers, types.FinalizedCheckpoint.RealPosition()) proof = append(proof, branch...) return proof, nil } diff --git a/beacon-chain/state/state-native/readonly_validator.go b/beacon-chain/state/state-native/readonly_validator.go index f5029049eda9..b7ea3f2da1a0 100644 --- a/beacon-chain/state/state-native/readonly_validator.go +++ b/beacon-chain/state/state-native/readonly_validator.go @@ -4,6 +4,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) @@ -70,11 +71,6 @@ func (v readOnlyValidator) PublicKey() [fieldparams.BLSPubkeyLength]byte { return pubkey } -// publicKeySlice returns the public key in the slice form for the read only validator. -func (v readOnlyValidator) publicKeySlice() []byte { - return v.validator.PublicKey -} - // WithdrawalCredentials returns the withdrawal credentials of the // read only validator. func (v readOnlyValidator) GetWithdrawalCredentials() []byte { @@ -92,3 +88,40 @@ func (v readOnlyValidator) Slashed() bool { func (v readOnlyValidator) IsNil() bool { return v.validator == nil } + +// HasETH1WithdrawalCredentials returns true if the validator has an ETH1 withdrawal credentials. +func (v readOnlyValidator) HasETH1WithdrawalCredentials() bool { + if v.IsNil() { + return false + } + return v.validator.WithdrawalCredentials[0] == params.BeaconConfig().ETH1AddressWithdrawalPrefixByte +} + +// HasCompoundingWithdrawalCredentials returns true if the validator has a compounding withdrawal credentials. +func (v readOnlyValidator) HasCompoundingWithdrawalCredentials() bool { + if v.IsNil() { + return false + } + return v.validator.WithdrawalCredentials[0] == params.BeaconConfig().CompoundingWithdrawalPrefixByte +} + +// HasExecutionWithdrawalCredentials returns true if the validator has an execution withdrawal credentials. +func (v readOnlyValidator) HasExecutionWithdrawalCredentials() bool { + return v.HasETH1WithdrawalCredentials() || v.HasCompoundingWithdrawalCredentials() +} + +// Copy returns a new validator from the read only validator +func (v readOnlyValidator) Copy() *ethpb.Validator { + pubKey := v.PublicKey() + withdrawalCreds := v.GetWithdrawalCredentials() + return ðpb.Validator{ + PublicKey: pubKey[:], + WithdrawalCredentials: withdrawalCreds, + EffectiveBalance: v.EffectiveBalance(), + Slashed: v.Slashed(), + ActivationEligibilityEpoch: v.ActivationEligibilityEpoch(), + ActivationEpoch: v.ActivationEpoch(), + ExitEpoch: v.ExitEpoch(), + WithdrawableEpoch: v.WithdrawableEpoch(), + } +} diff --git a/beacon-chain/state/state-native/references_test.go b/beacon-chain/state/state-native/references_test.go index 82596e11ccf3..d58f43e99113 100644 --- a/beacon-chain/state/state-native/references_test.go +++ b/beacon-chain/state/state-native/references_test.go @@ -865,8 +865,8 @@ func TestValidatorReferences_RemainsConsistent_Phase0(t *testing.T) { assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") // Modify all validators from copied state. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error) { + return ðpb.Validator{PublicKey: []byte{'V'}}, nil })) // Ensure reference is properly accounted for. @@ -900,8 +900,8 @@ func TestValidatorReferences_RemainsConsistent_Altair(t *testing.T) { assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") // Modify all validators from copied state. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error) { + return ðpb.Validator{PublicKey: []byte{'V'}}, nil })) // Ensure reference is properly accounted for. @@ -935,8 +935,8 @@ func TestValidatorReferences_RemainsConsistent_Capella(t *testing.T) { assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") // Modify all validators from copied state. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error) { + return ðpb.Validator{PublicKey: []byte{'V'}}, nil })) // Ensure reference is properly accounted for. @@ -970,8 +970,8 @@ func TestValidatorReferences_RemainsConsistent_Deneb(t *testing.T) { assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") // Modify all validators from copied state. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error) { + return ðpb.Validator{PublicKey: []byte{'V'}}, nil })) // Ensure reference is properly accounted for. @@ -1005,8 +1005,8 @@ func TestValidatorReferences_RemainsConsistent_Bellatrix(t *testing.T) { assert.DeepNotEqual(t, a.Validators()[0], b.Validators()[0], "validators are equal when they are supposed to be different") // Modify all validators from copied state. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { - return true, ðpb.Validator{PublicKey: []byte{'V'}}, nil + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error) { + return ðpb.Validator{PublicKey: []byte{'V'}}, nil })) // Ensure reference is properly accounted for. @@ -1041,15 +1041,14 @@ func TestValidatorReferences_ApplyValidator_BalancesRead(t *testing.T) { require.Equal(t, true, ok) // Modify all validators from copied state, it should not deadlock. - assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { + assert.NoError(t, b.ApplyToEveryValidator(func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error) { b, err := b.BalanceAtIndex(0) if err != nil { - return false, nil, err + return nil, err } - newVal := ethpb.CopyValidator(val) + newVal := val.Copy() newVal.EffectiveBalance += b - val.EffectiveBalance += b - return true, val, nil + return newVal, nil })) } diff --git a/beacon-chain/state/state-native/setters_churn.go b/beacon-chain/state/state-native/setters_churn.go index fdcf547fdcd1..c04f2dee175d 100644 --- a/beacon-chain/state/state-native/setters_churn.go +++ b/beacon-chain/state/state-native/setters_churn.go @@ -71,9 +71,7 @@ func (b *BeaconState) ExitEpochAndUpdateChurn(exitBalance primitives.Gwei) (prim b.earliestExitEpoch = earliestExitEpoch b.markFieldAsDirty(types.ExitBalanceToConsume) - b.rebuildTrie[types.ExitBalanceToConsume] = true b.markFieldAsDirty(types.EarliestExitEpoch) - b.rebuildTrie[types.EarliestExitEpoch] = true return b.earliestExitEpoch, nil } diff --git a/beacon-chain/state/state-native/setters_consolidation.go b/beacon-chain/state/state-native/setters_consolidation.go index d814832dd72b..2eb09bbf8cfd 100644 --- a/beacon-chain/state/state-native/setters_consolidation.go +++ b/beacon-chain/state/state-native/setters_consolidation.go @@ -1,6 +1,8 @@ package state_native import ( + "errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -15,16 +17,23 @@ func (b *BeaconState) AppendPendingConsolidation(val *ethpb.PendingConsolidation if b.version < version.Electra { return errNotSupported("AppendPendingConsolidation", b.version) } + if val == nil { + return errors.New("cannot append nil pending consolidation") + } b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[types.PendingConsolidations].MinusRef() - b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) - - b.pendingConsolidations = append(b.pendingConsolidations, val) + pendingConsolidations := b.pendingConsolidations + if b.sharedFieldReferences[types.PendingConsolidations].Refs() > 1 { + pendingConsolidations = make([]*ethpb.PendingConsolidation, 0, len(b.pendingConsolidations)+1) + pendingConsolidations = append(pendingConsolidations, b.pendingConsolidations...) + b.sharedFieldReferences[types.PendingConsolidations].MinusRef() + b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) + } + b.pendingConsolidations = append(pendingConsolidations, val) b.markFieldAsDirty(types.PendingConsolidations) - b.rebuildTrie[types.PendingConsolidations] = true + return nil } @@ -44,7 +53,6 @@ func (b *BeaconState) SetPendingConsolidations(val []*ethpb.PendingConsolidation b.pendingConsolidations = val b.markFieldAsDirty(types.PendingConsolidations) - b.rebuildTrie[types.PendingConsolidations] = true return nil } @@ -61,7 +69,6 @@ func (b *BeaconState) SetEarliestConsolidationEpoch(epoch primitives.Epoch) erro b.earliestConsolidationEpoch = epoch b.markFieldAsDirty(types.EarliestConsolidationEpoch) - b.rebuildTrie[types.EarliestConsolidationEpoch] = true return nil } @@ -78,6 +85,5 @@ func (b *BeaconState) SetConsolidationBalanceToConsume(balance primitives.Gwei) b.consolidationBalanceToConsume = balance b.markFieldAsDirty(types.ConsolidationBalanceToConsume) - b.rebuildTrie[types.ConsolidationBalanceToConsume] = true return nil } diff --git a/beacon-chain/state/state-native/setters_consolidation_test.go b/beacon-chain/state/state-native/setters_consolidation_test.go index af8ced0ea22b..1113eab98be9 100644 --- a/beacon-chain/state/state-native/setters_consolidation_test.go +++ b/beacon-chain/state/state-native/setters_consolidation_test.go @@ -20,6 +20,21 @@ func TestAppendPendingConsolidation(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(1), num) + pc := make([]*eth.PendingConsolidation, 0, 4) + require.NoError(t, s.SetPendingConsolidations(pc)) + require.NoError(t, s.AppendPendingConsolidation(ð.PendingConsolidation{SourceIndex: 1})) + s2 := s.Copy() + require.NoError(t, s2.AppendPendingConsolidation(ð.PendingConsolidation{SourceIndex: 3})) + require.NoError(t, s.AppendPendingConsolidation(ð.PendingConsolidation{SourceIndex: 2})) + pc, err = s.PendingConsolidations() + require.NoError(t, err) + require.Equal(t, primitives.ValidatorIndex(1), pc[0].SourceIndex) + require.Equal(t, primitives.ValidatorIndex(2), pc[1].SourceIndex) + pc, err = s2.PendingConsolidations() + require.NoError(t, err) + require.Equal(t, primitives.ValidatorIndex(1), pc[0].SourceIndex) + require.Equal(t, primitives.ValidatorIndex(3), pc[1].SourceIndex) + // Fails for versions older than electra s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{}) require.NoError(t, err) diff --git a/beacon-chain/state/state-native/setters_deposit_requests.go b/beacon-chain/state/state-native/setters_deposit_requests.go index bd441c248e1d..a9e82f1d2f4d 100644 --- a/beacon-chain/state/state-native/setters_deposit_requests.go +++ b/beacon-chain/state/state-native/setters_deposit_requests.go @@ -16,6 +16,5 @@ func (b *BeaconState) SetDepositRequestsStartIndex(index uint64) error { b.depositRequestsStartIndex = index b.markFieldAsDirty(types.DepositRequestsStartIndex) - b.rebuildTrie[types.DepositRequestsStartIndex] = true return nil } diff --git a/beacon-chain/state/state-native/setters_balance_deposits.go b/beacon-chain/state/state-native/setters_deposits.go similarity index 53% rename from beacon-chain/state/state-native/setters_balance_deposits.go rename to beacon-chain/state/state-native/setters_deposits.go index 1be44219bc5a..dcb1655a1039 100644 --- a/beacon-chain/state/state-native/setters_balance_deposits.go +++ b/beacon-chain/state/state-native/setters_deposits.go @@ -1,6 +1,8 @@ package state_native import ( + "errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -8,43 +10,49 @@ import ( "github.com/prysmaticlabs/prysm/v5/runtime/version" ) -// AppendPendingBalanceDeposit is a mutating call to the beacon state to create and append a pending +// AppendPendingDeposit is a mutating call to the beacon state to create and append a pending // balance deposit object on to the state. This method requires access to the Lock on the state and // only applies in electra or later. -func (b *BeaconState) AppendPendingBalanceDeposit(index primitives.ValidatorIndex, amount uint64) error { +func (b *BeaconState) AppendPendingDeposit(pd *ethpb.PendingDeposit) error { if b.version < version.Electra { - return errNotSupported("AppendPendingBalanceDeposit", b.version) + return errNotSupported("AppendPendingDeposit", b.version) + } + if pd == nil { + return errors.New("cannot append nil pending deposit") } b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[types.PendingBalanceDeposits].MinusRef() - b.sharedFieldReferences[types.PendingBalanceDeposits] = stateutil.NewRef(1) + pendingDeposits := b.pendingDeposits + if b.sharedFieldReferences[types.PendingDeposits].Refs() > 1 { + pendingDeposits = make([]*ethpb.PendingDeposit, 0, len(b.pendingDeposits)+1) + pendingDeposits = append(pendingDeposits, b.pendingDeposits...) + b.sharedFieldReferences[types.PendingDeposits].MinusRef() + b.sharedFieldReferences[types.PendingDeposits] = stateutil.NewRef(1) + } - b.pendingBalanceDeposits = append(b.pendingBalanceDeposits, ðpb.PendingBalanceDeposit{Index: index, Amount: amount}) + b.pendingDeposits = append(pendingDeposits, pd) + b.markFieldAsDirty(types.PendingDeposits) - b.markFieldAsDirty(types.PendingBalanceDeposits) - b.rebuildTrie[types.PendingBalanceDeposits] = true return nil } -// SetPendingBalanceDeposits is a mutating call to the beacon state which replaces the pending +// SetPendingDeposits is a mutating call to the beacon state which replaces the pending // balance deposit slice with the provided value. This method requires access to the Lock on the // state and only applies in electra or later. -func (b *BeaconState) SetPendingBalanceDeposits(val []*ethpb.PendingBalanceDeposit) error { +func (b *BeaconState) SetPendingDeposits(val []*ethpb.PendingDeposit) error { if b.version < version.Electra { - return errNotSupported("SetPendingBalanceDeposits", b.version) + return errNotSupported("SetPendingDeposits", b.version) } b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[types.PendingBalanceDeposits].MinusRef() - b.sharedFieldReferences[types.PendingBalanceDeposits] = stateutil.NewRef(1) + b.sharedFieldReferences[types.PendingDeposits].MinusRef() + b.sharedFieldReferences[types.PendingDeposits] = stateutil.NewRef(1) - b.pendingBalanceDeposits = val + b.pendingDeposits = val - b.markFieldAsDirty(types.PendingBalanceDeposits) - b.rebuildTrie[types.PendingBalanceDeposits] = true + b.markFieldAsDirty(types.PendingDeposits) return nil } @@ -61,6 +69,5 @@ func (b *BeaconState) SetDepositBalanceToConsume(dbtc primitives.Gwei) error { b.depositBalanceToConsume = dbtc b.markFieldAsDirty(types.DepositBalanceToConsume) - b.rebuildTrie[types.DepositBalanceToConsume] = true return nil } diff --git a/beacon-chain/state/state-native/setters_balance_deposits_test.go b/beacon-chain/state/state-native/setters_deposits_test.go similarity index 50% rename from beacon-chain/state/state-native/setters_balance_deposits_test.go rename to beacon-chain/state/state-native/setters_deposits_test.go index 594943b712a9..2712cfd57b59 100644 --- a/beacon-chain/state/state-native/setters_balance_deposits_test.go +++ b/beacon-chain/state/state-native/setters_deposits_test.go @@ -9,40 +9,67 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/require" ) -func TestAppendPendingBalanceDeposit(t *testing.T) { +func TestAppendPendingDeposit(t *testing.T) { s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{}) require.NoError(t, err) - pbd, err := s.PendingBalanceDeposits() + pbd, err := s.PendingDeposits() require.NoError(t, err) require.Equal(t, 0, len(pbd)) - require.NoError(t, s.AppendPendingBalanceDeposit(1, 10)) - pbd, err = s.PendingBalanceDeposits() + creds := []byte{0xFA, 0xCC} + pubkey := []byte{0xAA, 0xBB} + sig := []byte{0xCC, 0xDD} + require.NoError(t, s.AppendPendingDeposit(ð.PendingDeposit{ + PublicKey: pubkey, + WithdrawalCredentials: creds, + Amount: 10, + Signature: sig, + Slot: 1, + })) + pbd, err = s.PendingDeposits() require.NoError(t, err) require.Equal(t, 1, len(pbd)) - require.Equal(t, primitives.ValidatorIndex(1), pbd[0].Index) + require.DeepEqual(t, pubkey, pbd[0].PublicKey) require.Equal(t, uint64(10), pbd[0].Amount) + require.DeepEqual(t, creds, pbd[0].WithdrawalCredentials) + require.Equal(t, primitives.Slot(1), pbd[0].Slot) + require.DeepEqual(t, sig, pbd[0].Signature) + + ds := make([]*eth.PendingDeposit, 0, 4) + require.NoError(t, s.SetPendingDeposits(ds)) + require.NoError(t, s.AppendPendingDeposit(ð.PendingDeposit{Amount: 1})) + s2 := s.Copy() + require.NoError(t, s2.AppendPendingDeposit(ð.PendingDeposit{Amount: 3})) + require.NoError(t, s.AppendPendingDeposit(ð.PendingDeposit{Amount: 2})) + d, err := s.PendingDeposits() + require.NoError(t, err) + require.Equal(t, uint64(1), d[0].Amount) + require.Equal(t, uint64(2), d[1].Amount) + d, err = s2.PendingDeposits() + require.NoError(t, err) + require.Equal(t, uint64(1), d[0].Amount) + require.Equal(t, uint64(3), d[1].Amount) // Fails for versions older than electra s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{}) require.NoError(t, err) - require.ErrorContains(t, "not supported", s.AppendPendingBalanceDeposit(1, 1)) + require.ErrorContains(t, "not supported", s.AppendPendingDeposit(ð.PendingDeposit{})) } -func TestSetPendingBalanceDeposits(t *testing.T) { +func TestSetPendingDeposits(t *testing.T) { s, err := state_native.InitializeFromProtoElectra(ð.BeaconStateElectra{}) require.NoError(t, err) - pbd, err := s.PendingBalanceDeposits() + pbd, err := s.PendingDeposits() require.NoError(t, err) require.Equal(t, 0, len(pbd)) - require.NoError(t, s.SetPendingBalanceDeposits([]*eth.PendingBalanceDeposit{{}, {}, {}})) - pbd, err = s.PendingBalanceDeposits() + require.NoError(t, s.SetPendingDeposits([]*eth.PendingDeposit{{}, {}, {}})) + pbd, err = s.PendingDeposits() require.NoError(t, err) require.Equal(t, 3, len(pbd)) // Fails for versions older than electra s, err = state_native.InitializeFromProtoDeneb(ð.BeaconStateDeneb{}) require.NoError(t, err) - require.ErrorContains(t, "not supported", s.SetPendingBalanceDeposits([]*eth.PendingBalanceDeposit{{}, {}, {}})) + require.ErrorContains(t, "not supported", s.SetPendingDeposits([]*eth.PendingDeposit{{}, {}, {}})) } func TestSetDepositBalanceToConsume(t *testing.T) { diff --git a/beacon-chain/state/state-native/setters_eth1_test.go b/beacon-chain/state/state-native/setters_eth1_test.go index a42a93c14eda..ccfa745f6b5b 100644 --- a/beacon-chain/state/state-native/setters_eth1_test.go +++ b/beacon-chain/state/state-native/setters_eth1_test.go @@ -5,7 +5,6 @@ import ( state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/config/params" - eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -32,7 +31,7 @@ func BenchmarkAppendEth1DataVotes(b *testing.B) { ref := st.Copy() for i := 0; i < b.N; i++ { - err := ref.AppendEth1DataVotes(ð.Eth1Data{DepositCount: uint64(i)}) + err := ref.AppendEth1DataVotes(ðpb.Eth1Data{DepositCount: uint64(i)}) require.NoError(b, err) ref = st.Copy() } diff --git a/beacon-chain/state/state-native/setters_misc.go b/beacon-chain/state/state-native/setters_misc.go index affd7ef520be..e5c4b4e65a43 100644 --- a/beacon-chain/state/state-native/setters_misc.go +++ b/beacon-chain/state/state-native/setters_misc.go @@ -107,22 +107,6 @@ func (b *BeaconState) SetHistoricalRoots(val [][]byte) error { return nil } -// SaveValidatorIndices save validator indices of beacon chain to cache -func (b *BeaconState) SaveValidatorIndices() { - if b.Version() < version.Electra { - return - } - - b.lock.Lock() - defer b.lock.Unlock() - - if b.validatorIndexCache == nil { - b.validatorIndexCache = newFinalizedValidatorIndexCache() - } - - b.saveValidatorIndices() -} - // AppendHistoricalRoots for the beacon state. Appends the new value // to the end of list. func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error { diff --git a/beacon-chain/state/state-native/setters_participation.go b/beacon-chain/state/state-native/setters_participation.go index 6017d677693d..92750d95c061 100644 --- a/beacon-chain/state/state-native/setters_participation.go +++ b/beacon-chain/state/state-native/setters_participation.go @@ -22,7 +22,6 @@ func (b *BeaconState) SetPreviousParticipationBits(val []byte) error { b.previousEpochParticipation = val b.markFieldAsDirty(types.PreviousEpochParticipationBits) - b.rebuildTrie[types.PreviousEpochParticipationBits] = true return nil } @@ -41,7 +40,6 @@ func (b *BeaconState) SetCurrentParticipationBits(val []byte) error { b.currentEpochParticipation = val b.markFieldAsDirty(types.CurrentEpochParticipationBits) - b.rebuildTrie[types.CurrentEpochParticipationBits] = true return nil } @@ -126,7 +124,6 @@ func (b *BeaconState) ModifyPreviousParticipationBits(mutator func(val []byte) ( defer b.lock.Unlock() b.previousEpochParticipation = participation b.markFieldAsDirty(types.PreviousEpochParticipationBits) - b.rebuildTrie[types.PreviousEpochParticipationBits] = true return nil } @@ -161,6 +158,5 @@ func (b *BeaconState) ModifyCurrentParticipationBits(mutator func(val []byte) ([ defer b.lock.Unlock() b.currentEpochParticipation = participation b.markFieldAsDirty(types.CurrentEpochParticipationBits) - b.rebuildTrie[types.CurrentEpochParticipationBits] = true return nil } diff --git a/beacon-chain/state/state-native/setters_payload_header.go b/beacon-chain/state/state-native/setters_payload_header.go index 9187aec5ba0c..535af82065e3 100644 --- a/beacon-chain/state/state-native/setters_payload_header.go +++ b/beacon-chain/state/state-native/setters_payload_header.go @@ -45,7 +45,7 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa b.markFieldAsDirty(types.LatestExecutionPayloadHeaderCapella) return nil case *enginev1.ExecutionPayloadDeneb: - if b.version != version.Deneb { + if !(b.version >= version.Deneb) { return fmt.Errorf("wrong state version (%s) for deneb execution payload", version.String(b.version)) } latest, err := consensusblocks.PayloadToHeaderDeneb(val) @@ -55,21 +55,6 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa b.latestExecutionPayloadHeaderDeneb = latest b.markFieldAsDirty(types.LatestExecutionPayloadHeaderDeneb) return nil - case *enginev1.ExecutionPayloadElectra: - if b.version != version.Electra { - return fmt.Errorf("wrong state version (%s) for electra execution payload", version.String(b.version)) - } - eVal, ok := val.(interfaces.ExecutionDataElectra) - if !ok { - return fmt.Errorf("could not cast %T to ExecutionDataElectra: %w", val, interfaces.ErrInvalidCast) - } - latest, err := consensusblocks.PayloadToHeaderElectra(eVal) - if err != nil { - return errors.Wrap(err, "could not convert payload to header") - } - b.latestExecutionPayloadHeaderElectra = latest - b.markFieldAsDirty(types.LatestExecutionPayloadHeaderElectra) - return nil case *enginev1.ExecutionPayloadHeader: if b.version != version.Bellatrix { return fmt.Errorf("wrong state version (%s) for bellatrix execution payload header", version.String(b.version)) @@ -85,19 +70,12 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa b.markFieldAsDirty(types.LatestExecutionPayloadHeaderCapella) return nil case *enginev1.ExecutionPayloadHeaderDeneb: - if b.version != version.Deneb { + if !(b.version >= version.Deneb) { return fmt.Errorf("wrong state version (%s) for deneb execution payload header", version.String(b.version)) } b.latestExecutionPayloadHeaderDeneb = header b.markFieldAsDirty(types.LatestExecutionPayloadHeaderDeneb) return nil - case *enginev1.ExecutionPayloadHeaderElectra: - if b.version != version.Electra { - return fmt.Errorf("wrong state version (%s) for electra execution payload header", version.String(b.version)) - } - b.latestExecutionPayloadHeaderElectra = header - b.markFieldAsDirty(types.LatestExecutionPayloadHeaderElectra) - return nil default: return errors.New("value must be an execution payload header") } diff --git a/beacon-chain/state/state-native/setters_payload_header_test.go b/beacon-chain/state/state-native/setters_payload_header_test.go index 8e49ccdfb3ec..74dda536a19c 100644 --- a/beacon-chain/state/state-native/setters_payload_header_test.go +++ b/beacon-chain/state/state-native/setters_payload_header_test.go @@ -35,7 +35,7 @@ func TestSetLatestExecutionPayloadHeader(t *testing.T) { }(), func() interfaces.ExecutionData { e := util.NewBeaconBlockElectra().Block.Body.ExecutionPayload - ee, err := blocks.WrappedExecutionPayloadElectra(e) + ee, err := blocks.WrappedExecutionPayloadDeneb(e) require.NoError(t, err) return ee }(), @@ -62,7 +62,7 @@ func TestSetLatestExecutionPayloadHeader(t *testing.T) { }(), func() interfaces.ExecutionData { e := util.NewBlindedBeaconBlockElectra().Message.Body.ExecutionPayloadHeader - ee, err := blocks.WrappedExecutionPayloadHeaderElectra(e) + ee, err := blocks.WrappedExecutionPayloadHeaderDeneb(e) require.NoError(t, err) return ee }(), @@ -93,6 +93,13 @@ func TestSetLatestExecutionPayloadHeader(t *testing.T) { if i == j { continue } + // Skip Deneb-Electra combinations + if i == len(payloads)-1 && j == len(payloads)-2 { + continue + } + if i == len(payloads)-2 && j == len(payloads)-1 { + continue + } t.Run(fmt.Sprintf("%s state with %s payload", version.String(i+versionOffset), version.String(j+versionOffset)), func(t *testing.T) { s := state_native.EmptyStateFromVersion(t, i+versionOffset) p := payloads[j] diff --git a/beacon-chain/state/state-native/setters_validator.go b/beacon-chain/state/state-native/setters_validator.go index a30986c9ccf3..6569a080653c 100644 --- a/beacon-chain/state/state-native/setters_validator.go +++ b/beacon-chain/state/state-native/setters_validator.go @@ -2,6 +2,7 @@ package state_native import ( "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil" "github.com/prysmaticlabs/prysm/v5/config/features" @@ -38,7 +39,7 @@ func (b *BeaconState) SetValidators(val []*ethpb.Validator) error { // ApplyToEveryValidator applies the provided callback function to each validator in the // validator registry. -func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error)) error { +func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error)) error { var changedVals []uint64 if features.Get().EnableExperimentalState { l := b.validatorsMultiValue.Len(b) @@ -47,11 +48,15 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator if err != nil { return err } - changed, newVal, err := f(i, v) + ro, err := NewValidator(v) if err != nil { return err } - if changed { + newVal, err := f(i, ro) + if err != nil { + return err + } + if newVal != nil { changedVals = append(changedVals, uint64(i)) if err = b.validatorsMultiValue.UpdateAt(b, uint64(i), newVal); err != nil { return errors.Wrapf(err, "could not update validator at index %d", i) @@ -71,11 +76,15 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator b.lock.Unlock() for i, val := range v { - changed, newVal, err := f(i, val) + ro, err := NewValidator(val) + if err != nil { + return err + } + newVal, err := f(i, ro) if err != nil { return err } - if changed { + if newVal != nil { changedVals = append(changedVals, uint64(i)) v[i] = newVal } @@ -89,8 +98,10 @@ func (b *BeaconState) ApplyToEveryValidator(f func(idx int, val *ethpb.Validator b.lock.Lock() defer b.lock.Unlock() - b.markFieldAsDirty(types.Validators) - b.addDirtyIndices(types.Validators, changedVals) + if len(changedVals) > 0 { + b.markFieldAsDirty(types.Validators) + b.addDirtyIndices(types.Validators, changedVals) + } return nil } diff --git a/beacon-chain/state/state-native/setters_withdrawal.go b/beacon-chain/state/state-native/setters_withdrawal.go index 36b97a826768..84326095167d 100644 --- a/beacon-chain/state/state-native/setters_withdrawal.go +++ b/beacon-chain/state/state-native/setters_withdrawal.go @@ -54,20 +54,24 @@ func (b *BeaconState) AppendPendingPartialWithdrawal(ppw *eth.PendingPartialWith b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[types.PendingPartialWithdrawals].MinusRef() - b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) - - b.pendingPartialWithdrawals = append(b.pendingPartialWithdrawals, ppw) + pendingPartialWithdrawals := b.pendingPartialWithdrawals + if b.sharedFieldReferences[types.PendingPartialWithdrawals].Refs() > 1 { + pendingPartialWithdrawals = make([]*eth.PendingPartialWithdrawal, 0, len(b.pendingPartialWithdrawals)+1) + pendingPartialWithdrawals = append(pendingPartialWithdrawals, b.pendingPartialWithdrawals...) + b.sharedFieldReferences[types.PendingPartialWithdrawals].MinusRef() + b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) + } + b.pendingPartialWithdrawals = append(pendingPartialWithdrawals, ppw) b.markFieldAsDirty(types.PendingPartialWithdrawals) - b.rebuildTrie[types.PendingPartialWithdrawals] = true + return nil } -// DequeuePartialWithdrawals removes the partial withdrawals from the beginning of the partial withdrawals list. -func (b *BeaconState) DequeuePartialWithdrawals(n uint64) error { +// DequeuePendingPartialWithdrawals removes the partial withdrawals from the beginning of the partial withdrawals list. +func (b *BeaconState) DequeuePendingPartialWithdrawals(n uint64) error { if b.version < version.Electra { - return errNotSupported("DequeuePartialWithdrawals", b.version) + return errNotSupported("DequeuePendingPartialWithdrawals", b.version) } if n > uint64(len(b.pendingPartialWithdrawals)) { @@ -81,8 +85,13 @@ func (b *BeaconState) DequeuePartialWithdrawals(n uint64) error { b.lock.Lock() defer b.lock.Unlock() - b.sharedFieldReferences[types.PendingPartialWithdrawals].MinusRef() - b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) + if b.sharedFieldReferences[types.PendingPartialWithdrawals].Refs() > 1 { + pendingPartialWithdrawals := make([]*eth.PendingPartialWithdrawal, len(b.pendingPartialWithdrawals)) + copy(pendingPartialWithdrawals, b.pendingPartialWithdrawals) + b.pendingPartialWithdrawals = pendingPartialWithdrawals + b.sharedFieldReferences[types.PendingPartialWithdrawals].MinusRef() + b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) + } b.pendingPartialWithdrawals = b.pendingPartialWithdrawals[n:] diff --git a/beacon-chain/state/state-native/setters_withdrawal_test.go b/beacon-chain/state/state-native/setters_withdrawal_test.go index d7627d397547..5aa033aa3cd8 100644 --- a/beacon-chain/state/state-native/setters_withdrawal_test.go +++ b/beacon-chain/state/state-native/setters_withdrawal_test.go @@ -68,22 +68,23 @@ func TestDequeuePendingWithdrawals(t *testing.T) { num, err := s.NumPendingPartialWithdrawals() require.NoError(t, err) require.Equal(t, uint64(3), num) - require.NoError(t, s.DequeuePartialWithdrawals(2)) + s2 := s.Copy() + require.NoError(t, s.DequeuePendingPartialWithdrawals(2)) num, err = s.NumPendingPartialWithdrawals() require.NoError(t, err) require.Equal(t, uint64(1), num) + num, err = s2.NumPendingPartialWithdrawals() + require.NoError(t, err) + require.Equal(t, uint64(3), num) // 2 of 1 exceeds the limit and an error should be returned - num, err = s.NumPendingPartialWithdrawals() - require.NoError(t, err) - require.Equal(t, uint64(1), num) - require.ErrorContains(t, "cannot dequeue more withdrawals than are in the queue", s.DequeuePartialWithdrawals(2)) + require.ErrorContains(t, "cannot dequeue more withdrawals than are in the queue", s.DequeuePendingPartialWithdrawals(2)) // Removing all pending partial withdrawals should be OK. num, err = s.NumPendingPartialWithdrawals() require.NoError(t, err) require.Equal(t, uint64(1), num) - require.NoError(t, s.DequeuePartialWithdrawals(1)) + require.NoError(t, s.DequeuePendingPartialWithdrawals(1)) num, err = s.Copy().NumPendingPartialWithdrawals() require.NoError(t, err) require.Equal(t, uint64(0), num) @@ -91,7 +92,7 @@ func TestDequeuePendingWithdrawals(t *testing.T) { s, err = InitializeFromProtoDeneb(ð.BeaconStateDeneb{}) require.NoError(t, err) - require.ErrorContains(t, "is not supported", s.DequeuePartialWithdrawals(0)) + require.ErrorContains(t, "is not supported", s.DequeuePendingPartialWithdrawals(0)) } func TestAppendPendingWithdrawals(t *testing.T) { @@ -111,6 +112,19 @@ func TestAppendPendingWithdrawals(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(4), num) + require.NoError(t, s.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{Index: 1})) + s2 := s.Copy() + require.NoError(t, s2.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{Index: 3})) + require.NoError(t, s.AppendPendingPartialWithdrawal(ð.PendingPartialWithdrawal{Index: 2})) + w, err := s.PendingPartialWithdrawals() + require.NoError(t, err) + require.Equal(t, primitives.ValidatorIndex(1), w[4].Index) + require.Equal(t, primitives.ValidatorIndex(2), w[5].Index) + w, err = s2.PendingPartialWithdrawals() + require.NoError(t, err) + require.Equal(t, primitives.ValidatorIndex(1), w[4].Index) + require.Equal(t, primitives.ValidatorIndex(3), w[5].Index) + require.ErrorContains(t, "cannot append nil pending partial withdrawal", s.AppendPendingPartialWithdrawal(nil)) s, err = InitializeFromProtoDeneb(ð.BeaconStateDeneb{}) diff --git a/beacon-chain/state/state-native/spec_parameters.go b/beacon-chain/state/state-native/spec_parameters.go index 1612a71efbdf..c82fe42d83ef 100644 --- a/beacon-chain/state/state-native/spec_parameters.go +++ b/beacon-chain/state/state-native/spec_parameters.go @@ -6,25 +6,33 @@ import ( ) func (b *BeaconState) ProportionalSlashingMultiplier() (uint64, error) { - switch b.version { - case version.Bellatrix, version.Capella, version.Deneb, version.Electra: + if b.version >= version.Bellatrix { return params.BeaconConfig().ProportionalSlashingMultiplierBellatrix, nil - case version.Altair: + } + + if b.version >= version.Altair { return params.BeaconConfig().ProportionalSlashingMultiplierAltair, nil - case version.Phase0: + } + + if b.version >= version.Phase0 { return params.BeaconConfig().ProportionalSlashingMultiplier, nil } - return 0, errNotSupported("ProportionalSlashingMultiplier()", b.version) + + return 0, errNotSupported("ProportionalSlashingMultiplier", b.version) } func (b *BeaconState) InactivityPenaltyQuotient() (uint64, error) { - switch b.version { - case version.Bellatrix, version.Capella, version.Deneb, version.Electra: + if b.version >= version.Bellatrix { return params.BeaconConfig().InactivityPenaltyQuotientBellatrix, nil - case version.Altair: + } + + if b.version >= version.Altair { return params.BeaconConfig().InactivityPenaltyQuotientAltair, nil - case version.Phase0: + } + + if b.version >= version.Phase0 { return params.BeaconConfig().InactivityPenaltyQuotient, nil } - return 0, errNotSupported("InactivityPenaltyQuotient()", b.version) + + return 0, errNotSupported("InactivityPenaltyQuotient", b.version) } diff --git a/beacon-chain/state/state-native/state_trie.go b/beacon-chain/state/state-native/state_trie.go index 29ba8c0abb21..90039dd8973e 100644 --- a/beacon-chain/state/state-native/state_trie.go +++ b/beacon-chain/state/state-native/state_trie.go @@ -19,96 +19,96 @@ import ( "github.com/prysmaticlabs/prysm/v5/container/slice" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/ssz" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) -var phase0Fields = []types.FieldIndex{ - types.GenesisTime, - types.GenesisValidatorsRoot, - types.Slot, - types.Fork, - types.LatestBlockHeader, - types.BlockRoots, - types.StateRoots, - types.HistoricalRoots, - types.Eth1Data, - types.Eth1DataVotes, - types.Eth1DepositIndex, - types.Validators, - types.Balances, - types.RandaoMixes, - types.Slashings, - types.PreviousEpochAttestations, - types.CurrentEpochAttestations, - types.JustificationBits, - types.PreviousJustifiedCheckpoint, - types.CurrentJustifiedCheckpoint, - types.FinalizedCheckpoint, -} - -var altairFields = []types.FieldIndex{ - types.GenesisTime, - types.GenesisValidatorsRoot, - types.Slot, - types.Fork, - types.LatestBlockHeader, - types.BlockRoots, - types.StateRoots, - types.HistoricalRoots, - types.Eth1Data, - types.Eth1DataVotes, - types.Eth1DepositIndex, - types.Validators, - types.Balances, - types.RandaoMixes, - types.Slashings, - types.PreviousEpochParticipationBits, - types.CurrentEpochParticipationBits, - types.JustificationBits, - types.PreviousJustifiedCheckpoint, - types.CurrentJustifiedCheckpoint, - types.FinalizedCheckpoint, - types.InactivityScores, - types.CurrentSyncCommittee, - types.NextSyncCommittee, -} - -var bellatrixFields = append(altairFields, types.LatestExecutionPayloadHeader) - -var capellaFields = append( - altairFields, - types.LatestExecutionPayloadHeaderCapella, - types.NextWithdrawalIndex, - types.NextWithdrawalValidatorIndex, - types.HistoricalSummaries, -) - -var denebFields = append( - altairFields, - types.LatestExecutionPayloadHeaderDeneb, - types.NextWithdrawalIndex, - types.NextWithdrawalValidatorIndex, - types.HistoricalSummaries, -) - -var electraFields = append( - altairFields, - types.NextWithdrawalIndex, - types.NextWithdrawalValidatorIndex, - types.HistoricalSummaries, - types.LatestExecutionPayloadHeaderElectra, - types.DepositRequestsStartIndex, - types.DepositBalanceToConsume, - types.ExitBalanceToConsume, - types.EarliestExitEpoch, - types.ConsolidationBalanceToConsume, - types.EarliestConsolidationEpoch, - types.PendingBalanceDeposits, - types.PendingPartialWithdrawals, - types.PendingConsolidations, +var ( + phase0Fields = []types.FieldIndex{ + types.GenesisTime, + types.GenesisValidatorsRoot, + types.Slot, + types.Fork, + types.LatestBlockHeader, + types.BlockRoots, + types.StateRoots, + types.HistoricalRoots, + types.Eth1Data, + types.Eth1DataVotes, + types.Eth1DepositIndex, + types.Validators, + types.Balances, + types.RandaoMixes, + types.Slashings, + types.PreviousEpochAttestations, + types.CurrentEpochAttestations, + types.JustificationBits, + types.PreviousJustifiedCheckpoint, + types.CurrentJustifiedCheckpoint, + types.FinalizedCheckpoint, + } + + altairFields = []types.FieldIndex{ + types.GenesisTime, + types.GenesisValidatorsRoot, + types.Slot, + types.Fork, + types.LatestBlockHeader, + types.BlockRoots, + types.StateRoots, + types.HistoricalRoots, + types.Eth1Data, + types.Eth1DataVotes, + types.Eth1DepositIndex, + types.Validators, + types.Balances, + types.RandaoMixes, + types.Slashings, + types.PreviousEpochParticipationBits, + types.CurrentEpochParticipationBits, + types.JustificationBits, + types.PreviousJustifiedCheckpoint, + types.CurrentJustifiedCheckpoint, + types.FinalizedCheckpoint, + types.InactivityScores, + types.CurrentSyncCommittee, + types.NextSyncCommittee, + } + + bellatrixFields = append(altairFields, types.LatestExecutionPayloadHeader) + + capellaFields = append( + altairFields, + types.LatestExecutionPayloadHeaderCapella, + types.NextWithdrawalIndex, + types.NextWithdrawalValidatorIndex, + types.HistoricalSummaries, + ) + + denebFields = append( + altairFields, + types.LatestExecutionPayloadHeaderDeneb, + types.NextWithdrawalIndex, + types.NextWithdrawalValidatorIndex, + types.HistoricalSummaries, + ) + + electraFields = append( + denebFields, + types.DepositRequestsStartIndex, + types.DepositBalanceToConsume, + types.ExitBalanceToConsume, + types.EarliestExitEpoch, + types.ConsolidationBalanceToConsume, + types.EarliestConsolidationEpoch, + types.PendingDeposits, + types.PendingPartialWithdrawals, + types.PendingConsolidations, + ) + + fuluFields = electraFields ) const ( @@ -118,12 +118,14 @@ const ( capellaSharedFieldRefCount = 13 denebSharedFieldRefCount = 13 electraSharedFieldRefCount = 16 + fuluSharedFieldRefCount = 16 experimentalStatePhase0SharedFieldRefCount = 5 experimentalStateAltairSharedFieldRefCount = 5 experimentalStateBellatrixSharedFieldRefCount = 6 experimentalStateCapellaSharedFieldRefCount = 7 experimentalStateDenebSharedFieldRefCount = 7 experimentalStateElectraSharedFieldRefCount = 10 + experimentalStateFuluSharedFieldRefCount = 10 ) // InitializeFromProtoPhase0 the beacon state from a protobuf representation. @@ -151,10 +153,16 @@ func InitializeFromProtoDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconState, er return InitializeFromProtoUnsafeDeneb(proto.Clone(st).(*ethpb.BeaconStateDeneb)) } +// InitializeFromProtoElectra the beacon state from a protobuf representation. func InitializeFromProtoElectra(st *ethpb.BeaconStateElectra) (state.BeaconState, error) { return InitializeFromProtoUnsafeElectra(proto.Clone(st).(*ethpb.BeaconStateElectra)) } +// InitializeFromProtoFulu the beacon state from a protobuf representation. +func InitializeFromProtoFulu(st *ethpb.BeaconStateElectra) (state.BeaconState, error) { + return InitializeFromProtoUnsafeFulu(proto.Clone(st).(*ethpb.BeaconStateElectra)) +} + // InitializeFromProtoUnsafePhase0 directly uses the beacon state protobuf fields // and sets them as fields of the BeaconState type. func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState, error) { @@ -189,12 +197,11 @@ func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState, id: types.Enumerator.Inc(), - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - validatorIndexCache: newFinalizedValidatorIndexCache(), + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), } if features.Get().EnableExperimentalState { @@ -296,12 +303,11 @@ func InitializeFromProtoUnsafeAltair(st *ethpb.BeaconStateAltair) (state.BeaconS id: types.Enumerator.Inc(), - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - validatorIndexCache: newFinalizedValidatorIndexCache(), + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), } if features.Get().EnableExperimentalState { @@ -407,12 +413,11 @@ func InitializeFromProtoUnsafeBellatrix(st *ethpb.BeaconStateBellatrix) (state.B id: types.Enumerator.Inc(), - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - validatorIndexCache: newFinalizedValidatorIndexCache(), + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), } if features.Get().EnableExperimentalState { @@ -522,12 +527,11 @@ func InitializeFromProtoUnsafeCapella(st *ethpb.BeaconStateCapella) (state.Beaco id: types.Enumerator.Inc(), - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - validatorIndexCache: newFinalizedValidatorIndexCache(), + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), } if features.Get().EnableExperimentalState { @@ -636,12 +640,11 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex, historicalSummaries: st.HistoricalSummaries, - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - validatorIndexCache: newFinalizedValidatorIndexCache(), + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), } if features.Get().EnableExperimentalState { @@ -696,7 +699,7 @@ func InitializeFromProtoUnsafeDeneb(st *ethpb.BeaconStateDeneb) (state.BeaconSta b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1) b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1) b.sharedFieldReferences[types.LatestExecutionPayloadHeaderDeneb] = stateutil.NewRef(1) // New in Deneb. - b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) // New in Capella. + b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) if !features.Get().EnableExperimentalState { b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) @@ -726,45 +729,44 @@ func InitializeFromProtoUnsafeElectra(st *ethpb.BeaconStateElectra) (state.Beaco fieldCount := params.BeaconConfig().BeaconStateElectraFieldCount b := &BeaconState{ - version: version.Electra, - genesisTime: st.GenesisTime, - genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), - slot: st.Slot, - fork: st.Fork, - latestBlockHeader: st.LatestBlockHeader, - historicalRoots: hRoots, - eth1Data: st.Eth1Data, - eth1DataVotes: st.Eth1DataVotes, - eth1DepositIndex: st.Eth1DepositIndex, - slashings: st.Slashings, - previousEpochParticipation: st.PreviousEpochParticipation, - currentEpochParticipation: st.CurrentEpochParticipation, - justificationBits: st.JustificationBits, - previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, - currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, - finalizedCheckpoint: st.FinalizedCheckpoint, - currentSyncCommittee: st.CurrentSyncCommittee, - nextSyncCommittee: st.NextSyncCommittee, - latestExecutionPayloadHeaderElectra: st.LatestExecutionPayloadHeader, - nextWithdrawalIndex: st.NextWithdrawalIndex, - nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex, - historicalSummaries: st.HistoricalSummaries, - depositRequestsStartIndex: st.DepositRequestsStartIndex, - depositBalanceToConsume: st.DepositBalanceToConsume, - exitBalanceToConsume: st.ExitBalanceToConsume, - earliestExitEpoch: st.EarliestExitEpoch, - consolidationBalanceToConsume: st.ConsolidationBalanceToConsume, - earliestConsolidationEpoch: st.EarliestConsolidationEpoch, - pendingBalanceDeposits: st.PendingBalanceDeposits, - pendingPartialWithdrawals: st.PendingPartialWithdrawals, - pendingConsolidations: st.PendingConsolidations, - - dirtyFields: make(map[types.FieldIndex]bool, fieldCount), - dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), - stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), - rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), - valMapHandler: stateutil.NewValMapHandler(st.Validators), - validatorIndexCache: newFinalizedValidatorIndexCache(), //only used in post-electra and only populates when finalizing, otherwise it falls back to processing the full validator set + version: version.Electra, + genesisTime: st.GenesisTime, + genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), + slot: st.Slot, + fork: st.Fork, + latestBlockHeader: st.LatestBlockHeader, + historicalRoots: hRoots, + eth1Data: st.Eth1Data, + eth1DataVotes: st.Eth1DataVotes, + eth1DepositIndex: st.Eth1DepositIndex, + slashings: st.Slashings, + previousEpochParticipation: st.PreviousEpochParticipation, + currentEpochParticipation: st.CurrentEpochParticipation, + justificationBits: st.JustificationBits, + previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, + currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, + finalizedCheckpoint: st.FinalizedCheckpoint, + currentSyncCommittee: st.CurrentSyncCommittee, + nextSyncCommittee: st.NextSyncCommittee, + latestExecutionPayloadHeaderDeneb: st.LatestExecutionPayloadHeader, + nextWithdrawalIndex: st.NextWithdrawalIndex, + nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex, + historicalSummaries: st.HistoricalSummaries, + depositRequestsStartIndex: st.DepositRequestsStartIndex, + depositBalanceToConsume: st.DepositBalanceToConsume, + exitBalanceToConsume: st.ExitBalanceToConsume, + earliestExitEpoch: st.EarliestExitEpoch, + consolidationBalanceToConsume: st.ConsolidationBalanceToConsume, + earliestConsolidationEpoch: st.EarliestConsolidationEpoch, + pendingDeposits: st.PendingDeposits, + pendingPartialWithdrawals: st.PendingPartialWithdrawals, + pendingConsolidations: st.PendingConsolidations, + + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), } if features.Get().EnableExperimentalState { @@ -818,11 +820,136 @@ func InitializeFromProtoUnsafeElectra(st *ethpb.BeaconStateElectra) (state.Beaco b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1) b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1) b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1) - b.sharedFieldReferences[types.LatestExecutionPayloadHeaderElectra] = stateutil.NewRef(1) // New in Electra. - b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) // New in Capella. - b.sharedFieldReferences[types.PendingBalanceDeposits] = stateutil.NewRef(1) // New in Electra. - b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) // New in Electra. - b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) // New in Electra. + b.sharedFieldReferences[types.LatestExecutionPayloadHeaderDeneb] = stateutil.NewRef(1) + b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) + b.sharedFieldReferences[types.PendingDeposits] = stateutil.NewRef(1) // New in Electra. + b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) // New in Electra. + b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) // New in Electra. + if !features.Get().EnableExperimentalState { + b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1) + b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1) + b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1) + b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1) + } + + state.Count.Inc() + // Finalizer runs when dst is being destroyed in garbage collection. + runtime.SetFinalizer(b, finalizerCleanup) + return b, nil +} + +// InitializeFromProtoUnsafeFulu directly uses the beacon state protobuf fields +// and sets them as fields of the BeaconState type. +func InitializeFromProtoUnsafeFulu(st *ethpb.BeaconStateElectra) (state.BeaconState, error) { + if st == nil { + return nil, errors.New("received nil state") + } + + hRoots := customtypes.HistoricalRoots(make([][32]byte, len(st.HistoricalRoots))) + for i, r := range st.HistoricalRoots { + hRoots[i] = bytesutil.ToBytes32(r) + } + + fieldCount := params.BeaconConfig().BeaconStateFuluFieldCount + b := &BeaconState{ + version: version.Fulu, + genesisTime: st.GenesisTime, + genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot), + slot: st.Slot, + fork: st.Fork, + latestBlockHeader: st.LatestBlockHeader, + historicalRoots: hRoots, + eth1Data: st.Eth1Data, + eth1DataVotes: st.Eth1DataVotes, + eth1DepositIndex: st.Eth1DepositIndex, + slashings: st.Slashings, + previousEpochParticipation: st.PreviousEpochParticipation, + currentEpochParticipation: st.CurrentEpochParticipation, + justificationBits: st.JustificationBits, + previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint, + currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint, + finalizedCheckpoint: st.FinalizedCheckpoint, + currentSyncCommittee: st.CurrentSyncCommittee, + nextSyncCommittee: st.NextSyncCommittee, + latestExecutionPayloadHeaderDeneb: st.LatestExecutionPayloadHeader, + nextWithdrawalIndex: st.NextWithdrawalIndex, + nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex, + historicalSummaries: st.HistoricalSummaries, + depositRequestsStartIndex: st.DepositRequestsStartIndex, + depositBalanceToConsume: st.DepositBalanceToConsume, + exitBalanceToConsume: st.ExitBalanceToConsume, + earliestExitEpoch: st.EarliestExitEpoch, + consolidationBalanceToConsume: st.ConsolidationBalanceToConsume, + earliestConsolidationEpoch: st.EarliestConsolidationEpoch, + pendingDeposits: st.PendingDeposits, + pendingPartialWithdrawals: st.PendingPartialWithdrawals, + pendingConsolidations: st.PendingConsolidations, + + dirtyFields: make(map[types.FieldIndex]bool, fieldCount), + dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), + stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), + rebuildTrie: make(map[types.FieldIndex]bool, fieldCount), + valMapHandler: stateutil.NewValMapHandler(st.Validators), + } + + if features.Get().EnableExperimentalState { + b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots) + b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots) + b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes) + b.balancesMultiValue = NewMultiValueBalances(st.Balances) + b.validatorsMultiValue = NewMultiValueValidators(st.Validators) + b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores) + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateFuluSharedFieldRefCount) + } else { + bRoots := make([][32]byte, fieldparams.BlockRootsLength) + for i, r := range st.BlockRoots { + bRoots[i] = bytesutil.ToBytes32(r) + } + b.blockRoots = bRoots + + sRoots := make([][32]byte, fieldparams.StateRootsLength) + for i, r := range st.StateRoots { + sRoots[i] = bytesutil.ToBytes32(r) + } + b.stateRoots = sRoots + + mixes := make([][32]byte, fieldparams.RandaoMixesLength) + for i, m := range st.RandaoMixes { + mixes[i] = bytesutil.ToBytes32(m) + } + b.randaoMixes = mixes + + b.balances = st.Balances + b.validators = st.Validators + b.inactivityScores = st.InactivityScores + + b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, fuluSharedFieldRefCount) + } + + for _, f := range fuluFields { + b.dirtyFields[f] = true + b.rebuildTrie[f] = true + b.dirtyIndices[f] = []uint64{} + trie, err := fieldtrie.NewFieldTrie(f, types.BasicArray, nil, 0) + if err != nil { + return nil, err + } + b.stateFieldLeaves[f] = trie + } + + // Initialize field reference tracking for shared data. + b.sharedFieldReferences[types.HistoricalRoots] = stateutil.NewRef(1) + b.sharedFieldReferences[types.Eth1DataVotes] = stateutil.NewRef(1) + b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1) + b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1) + b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1) + b.sharedFieldReferences[types.LatestExecutionPayloadHeaderDeneb] = stateutil.NewRef(1) + b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1) + b.sharedFieldReferences[types.PendingDeposits] = stateutil.NewRef(1) + b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) + b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) if !features.Get().EnableExperimentalState { b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1) b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1) @@ -857,6 +984,8 @@ func (b *BeaconState) Copy() state.BeaconState { fieldCount = params.BeaconConfig().BeaconStateDenebFieldCount case version.Electra: fieldCount = params.BeaconConfig().BeaconStateElectraFieldCount + case version.Fulu: + fieldCount = params.BeaconConfig().BeaconStateFuluFieldCount } dst := &BeaconState{ @@ -898,7 +1027,7 @@ func (b *BeaconState) Copy() state.BeaconState { currentEpochParticipation: b.currentEpochParticipation, inactivityScores: b.inactivityScores, inactivityScoresMultiValue: b.inactivityScoresMultiValue, - pendingBalanceDeposits: b.pendingBalanceDeposits, + pendingDeposits: b.pendingDeposits, pendingPartialWithdrawals: b.pendingPartialWithdrawals, pendingConsolidations: b.pendingConsolidations, @@ -916,7 +1045,6 @@ func (b *BeaconState) Copy() state.BeaconState { latestExecutionPayloadHeader: b.latestExecutionPayloadHeader.Copy(), latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapella.Copy(), latestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDeneb.Copy(), - latestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectra.Copy(), id: types.Enumerator.Inc(), @@ -926,8 +1054,7 @@ func (b *BeaconState) Copy() state.BeaconState { stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), // Share the reference to validator index map. - valMapHandler: b.valMapHandler, - validatorIndexCache: b.validatorIndexCache, + valMapHandler: b.valMapHandler, } if features.Get().EnableExperimentalState { @@ -955,6 +1082,8 @@ func (b *BeaconState) Copy() state.BeaconState { dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateDenebSharedFieldRefCount) case version.Electra: dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateElectraSharedFieldRefCount) + case version.Fulu: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateFuluSharedFieldRefCount) } } else { switch b.version { @@ -970,6 +1099,8 @@ func (b *BeaconState) Copy() state.BeaconState { dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount) case version.Electra: dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, electraSharedFieldRefCount) + case version.Fulu: + dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, fuluSharedFieldRefCount) } } @@ -1064,6 +1195,8 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error { b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateDenebFieldCount) case version.Electra: b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateElectraFieldCount) + case version.Fulu: + b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateFuluFieldCount) default: return fmt.Errorf("unknown state version (%s) when computing dirty fields in merklization", version.String(b.version)) } @@ -1179,7 +1312,7 @@ func (b *BeaconState) IsNil() bool { func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) { _, span := trace.StartSpan(ctx, "beaconState.rootSelector") defer span.End() - span.AddAttributes(trace.StringAttribute("field", field.String())) + span.SetAttributes(trace.StringAttribute("field", field.String())) switch field { case types.GenesisTime: @@ -1284,8 +1417,6 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) return b.latestExecutionPayloadHeaderCapella.HashTreeRoot() case types.LatestExecutionPayloadHeaderDeneb: return b.latestExecutionPayloadHeaderDeneb.HashTreeRoot() - case types.LatestExecutionPayloadHeaderElectra: - return b.latestExecutionPayloadHeaderElectra.HashTreeRoot() case types.NextWithdrawalIndex: return ssz.Uint64Root(b.nextWithdrawalIndex), nil case types.NextWithdrawalValidatorIndex: @@ -1304,8 +1435,8 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) return ssz.Uint64Root(uint64(b.consolidationBalanceToConsume)), nil case types.EarliestConsolidationEpoch: return ssz.Uint64Root(uint64(b.earliestConsolidationEpoch)), nil - case types.PendingBalanceDeposits: - return stateutil.PendingBalanceDepositsRoot(b.pendingBalanceDeposits) + case types.PendingDeposits: + return stateutil.PendingDepositsRoot(b.pendingDeposits) case types.PendingPartialWithdrawals: return stateutil.PendingPartialWithdrawalsRoot(b.pendingPartialWithdrawals) case types.PendingConsolidations: @@ -1356,8 +1487,7 @@ func (b *BeaconState) recomputeFieldTrie(index types.FieldIndex, elements interf if fTrie.FieldReference().Refs() > 1 { var newTrie *fieldtrie.FieldTrie // We choose to only copy the validator - // trie as it is pretty expensive to regenerate - // in the event of late blocks. + // trie as it is pretty expensive to regenerate. if index == types.Validators { newTrie = fTrie.CopyTrie() } else { diff --git a/beacon-chain/state/state-native/types/types.go b/beacon-chain/state/state-native/types/types.go index 43cb57c6a76a..1a93c58cb2e6 100644 --- a/beacon-chain/state/state-native/types/types.go +++ b/beacon-chain/state/state-native/types/types.go @@ -88,8 +88,6 @@ func (f FieldIndex) String() string { return "latestExecutionPayloadHeaderCapella" case LatestExecutionPayloadHeaderDeneb: return "latestExecutionPayloadHeaderDeneb" - case LatestExecutionPayloadHeaderElectra: - return "latestExecutionPayloadHeaderElectra" case NextWithdrawalIndex: return "nextWithdrawalIndex" case NextWithdrawalValidatorIndex: @@ -108,8 +106,8 @@ func (f FieldIndex) String() string { return "consolidationBalanceToConsume" case EarliestConsolidationEpoch: return "earliestConsolidationEpoch" - case PendingBalanceDeposits: - return "pendingBalanceDeposits" + case PendingDeposits: + return "pendingDeposits" case PendingPartialWithdrawals: return "pendingPartialWithdrawals" case PendingConsolidations: @@ -171,7 +169,7 @@ func (f FieldIndex) RealPosition() int { return 22 case NextSyncCommittee: return 23 - case LatestExecutionPayloadHeader, LatestExecutionPayloadHeaderCapella, LatestExecutionPayloadHeaderDeneb, LatestExecutionPayloadHeaderElectra: + case LatestExecutionPayloadHeader, LatestExecutionPayloadHeaderCapella, LatestExecutionPayloadHeaderDeneb: return 24 case NextWithdrawalIndex: return 25 @@ -191,7 +189,7 @@ func (f FieldIndex) RealPosition() int { return 32 case EarliestConsolidationEpoch: return 33 - case PendingBalanceDeposits: + case PendingDeposits: return 34 case PendingPartialWithdrawals: return 35 @@ -249,7 +247,6 @@ const ( LatestExecutionPayloadHeader LatestExecutionPayloadHeaderCapella LatestExecutionPayloadHeaderDeneb - LatestExecutionPayloadHeaderElectra NextWithdrawalIndex NextWithdrawalValidatorIndex HistoricalSummaries @@ -259,7 +256,7 @@ const ( EarliestExitEpoch // Electra: EIP-7251 ConsolidationBalanceToConsume // Electra: EIP-7251 EarliestConsolidationEpoch // Electra: EIP-7251 - PendingBalanceDeposits // Electra: EIP-7251 + PendingDeposits // Electra: EIP-7251 PendingPartialWithdrawals // Electra: EIP-7251 PendingConsolidations // Electra: EIP-7251 ) diff --git a/beacon-chain/state/state-native/validator_index_cache.go b/beacon-chain/state/state-native/validator_index_cache.go deleted file mode 100644 index dcb8ce33684f..000000000000 --- a/beacon-chain/state/state-native/validator_index_cache.go +++ /dev/null @@ -1,96 +0,0 @@ -package state_native - -import ( - "bytes" - "sync" - - "github.com/prysmaticlabs/prysm/v5/config/features" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" -) - -// finalizedValidatorIndexCache maintains a mapping from validator public keys to their indices within the beacon state. -// It includes a lastFinalizedIndex to track updates up to the last finalized validator index, -// and uses a mutex for concurrent read/write access to the cache. -type finalizedValidatorIndexCache struct { - indexMap map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex // Maps finalized BLS public keys to validator indices. - sync.RWMutex -} - -// newFinalizedValidatorIndexCache initializes a new validator index cache with an empty index map. -func newFinalizedValidatorIndexCache() *finalizedValidatorIndexCache { - return &finalizedValidatorIndexCache{ - indexMap: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), - } -} - -// getValidatorIndex retrieves the validator index for a given public key from the cache. -// If the public key is not found in the cache, it searches through the state starting from the last finalized index. -func (b *BeaconState) getValidatorIndex(pubKey [fieldparams.BLSPubkeyLength]byte) (primitives.ValidatorIndex, bool) { - b.validatorIndexCache.RLock() - index, found := b.validatorIndexCache.indexMap[pubKey] - b.validatorIndexCache.RUnlock() - if found { - return index, true - } - - validatorCount := len(b.validatorIndexCache.indexMap) - vals := b.validatorsReadOnlySinceIndex(validatorCount) - for i, val := range vals { - if bytes.Equal(bytesutil.PadTo(val.publicKeySlice(), 48), pubKey[:]) { - index := primitives.ValidatorIndex(validatorCount + i) - return index, true - } - } - return 0, false -} - -// saveValidatorIndices updates the validator index cache with new indices. -// It processes validator indices starting after the last finalized index and updates the tracker. -func (b *BeaconState) saveValidatorIndices() { - b.validatorIndexCache.Lock() - defer b.validatorIndexCache.Unlock() - - validatorCount := len(b.validatorIndexCache.indexMap) - vals := b.validatorsReadOnlySinceIndex(validatorCount) - for i, val := range vals { - b.validatorIndexCache.indexMap[val.PublicKey()] = primitives.ValidatorIndex(validatorCount + i) - } -} - -// validatorsReadOnlySinceIndex constructs a list of read only validator references after a specified index. -// The indices in the returned list correspond to their respective validator indices in the state. -// It returns nil if the specified index is out of bounds. This function is read-only and does not use locks. -func (b *BeaconState) validatorsReadOnlySinceIndex(index int) []readOnlyValidator { - totalValidators := b.validatorsLen() - if index >= totalValidators { - return nil - } - - var v []*ethpb.Validator - if features.Get().EnableExperimentalState { - if b.validatorsMultiValue == nil { - return nil - } - v = b.validatorsMultiValue.Value(b) - } else { - if b.validators == nil { - return nil - } - v = b.validators - } - - result := make([]readOnlyValidator, totalValidators-index) - for i := 0; i < len(result); i++ { - val := v[i+index] - if val == nil { - continue - } - result[i] = readOnlyValidator{ - validator: val, - } - } - return result -} diff --git a/beacon-chain/state/state-native/validator_index_cache_test.go b/beacon-chain/state/state-native/validator_index_cache_test.go deleted file mode 100644 index 85177f89ceeb..000000000000 --- a/beacon-chain/state/state-native/validator_index_cache_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package state_native - -import ( - "testing" - - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" -) - -func Test_FinalizedValidatorIndexCache(t *testing.T) { - c := newFinalizedValidatorIndexCache() - b := &BeaconState{validatorIndexCache: c} - - // What happens if you call getValidatorIndex with a public key that is not in the cache and state? - // The function will return 0 and false. - i, exists := b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{0}) - require.Equal(t, primitives.ValidatorIndex(0), i) - require.Equal(t, false, exists) - - // Validators are added to the state. They are [0, 1, 2] - b.validators = []*ethpb.Validator{ - {PublicKey: []byte{1}}, - {PublicKey: []byte{2}}, - {PublicKey: []byte{3}}, - } - // We should be able to retrieve these validators by public key even when they are not in the cache - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{1}) - require.Equal(t, primitives.ValidatorIndex(0), i) - require.Equal(t, true, exists) - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{2}) - require.Equal(t, primitives.ValidatorIndex(1), i) - require.Equal(t, true, exists) - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{3}) - require.Equal(t, primitives.ValidatorIndex(2), i) - require.Equal(t, true, exists) - - // State is finalized. We save [0, 1, 2 ] to the cache. - b.saveValidatorIndices() - require.Equal(t, 3, len(b.validatorIndexCache.indexMap)) - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{1}) - require.Equal(t, primitives.ValidatorIndex(0), i) - require.Equal(t, true, exists) - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{2}) - require.Equal(t, primitives.ValidatorIndex(1), i) - require.Equal(t, true, exists) - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{3}) - require.Equal(t, primitives.ValidatorIndex(2), i) - require.Equal(t, true, exists) - - // New validators are added to the state. They are [4, 5] - b.validators = []*ethpb.Validator{ - {PublicKey: []byte{1}}, - {PublicKey: []byte{2}}, - {PublicKey: []byte{3}}, - {PublicKey: []byte{4}}, - {PublicKey: []byte{5}}, - } - // We should be able to retrieve these validators by public key even when they are not in the cache - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{4}) - require.Equal(t, primitives.ValidatorIndex(3), i) - require.Equal(t, true, exists) - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{5}) - require.Equal(t, primitives.ValidatorIndex(4), i) - require.Equal(t, true, exists) - - // State is finalized. We save [4, 5] to the cache. - b.saveValidatorIndices() - require.Equal(t, 5, len(b.validatorIndexCache.indexMap)) - - // New validators are added to the state. They are [6] - b.validators = []*ethpb.Validator{ - {PublicKey: []byte{1}}, - {PublicKey: []byte{2}}, - {PublicKey: []byte{3}}, - {PublicKey: []byte{4}}, - {PublicKey: []byte{5}}, - {PublicKey: []byte{6}}, - } - // We should be able to retrieve these validators by public key even when they are not in the cache - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{6}) - require.Equal(t, primitives.ValidatorIndex(5), i) - require.Equal(t, true, exists) - - // State is finalized. We save [6] to the cache. - b.saveValidatorIndices() - require.Equal(t, 6, len(b.validatorIndexCache.indexMap)) - - // Save a few more times. - b.saveValidatorIndices() - b.saveValidatorIndices() - require.Equal(t, 6, len(b.validatorIndexCache.indexMap)) - - // Can still retrieve the validators from the cache - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{1}) - require.Equal(t, primitives.ValidatorIndex(0), i) - require.Equal(t, true, exists) - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{2}) - require.Equal(t, primitives.ValidatorIndex(1), i) - require.Equal(t, true, exists) - i, exists = b.getValidatorIndex([fieldparams.BLSPubkeyLength]byte{3}) - require.Equal(t, primitives.ValidatorIndex(2), i) - require.Equal(t, true, exists) -} diff --git a/beacon-chain/state/stategen/BUILD.bazel b/beacon-chain/state/stategen/BUILD.bazel index 294a6680db4c..d6d90003346c 100644 --- a/beacon-chain/state/stategen/BUILD.bazel +++ b/beacon-chain/state/stategen/BUILD.bazel @@ -35,6 +35,7 @@ go_library( "//consensus-types/primitives:go_default_library", "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//time/slots:go_default_library", "@com_github_hashicorp_golang_lru//:go_default_library", @@ -43,7 +44,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_k8s_client_go//tools/cache:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -72,18 +72,21 @@ go_test( "//beacon-chain/forkchoice/doubly-linked-tree:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", + "//beacon-chain/state/testing:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/blocks/testing:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/mock:go_default_library", "//consensus-types/primitives:go_default_library", + "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", + "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", diff --git a/beacon-chain/state/stategen/epoch_boundary_state_cache.go b/beacon-chain/state/stategen/epoch_boundary_state_cache.go index 9be422a87720..3ed39791d28e 100644 --- a/beacon-chain/state/stategen/epoch_boundary_state_cache.go +++ b/beacon-chain/state/stategen/epoch_boundary_state_cache.go @@ -184,7 +184,7 @@ func trim(queue *cache.FIFO, maxSize uint64) { } // popProcessNoopFunc is a no-op function that never returns an error. -func popProcessNoopFunc(_ interface{}) error { +func popProcessNoopFunc(_ interface{}, _ bool) error { return nil } diff --git a/beacon-chain/state/stategen/getter.go b/beacon-chain/state/stategen/getter.go index 6f3cc3eaf772..c1033a5a7c0d 100644 --- a/beacon-chain/state/stategen/getter.go +++ b/beacon-chain/state/stategen/getter.go @@ -12,8 +12,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) var ErrNoDataForSlot = errors.New("cannot retrieve data for slot") diff --git a/beacon-chain/state/stategen/history.go b/beacon-chain/state/stategen/history.go index 5a4f2adfc511..6e33d8a480ae 100644 --- a/beacon-chain/state/stategen/history.go +++ b/beacon-chain/state/stategen/history.go @@ -11,7 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) func WithCache(c CachedGetter) CanonicalHistoryOption { diff --git a/beacon-chain/state/stategen/migrate.go b/beacon-chain/state/stategen/migrate.go index 32e0d0db4fcb..21e697160890 100644 --- a/beacon-chain/state/stategen/migrate.go +++ b/beacon-chain/state/stategen/migrate.go @@ -7,8 +7,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // MigrateToCold advances the finalized info in between the cold and hot state sections. diff --git a/beacon-chain/state/stategen/replay.go b/beacon-chain/state/stategen/replay.go index 12b64d0fed62..ef8c3e1089d7 100644 --- a/beacon-chain/state/stategen/replay.go +++ b/beacon-chain/state/stategen/replay.go @@ -12,8 +12,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // ReplayBlocks replays the input blocks on the input state until the target slot is reached. diff --git a/beacon-chain/state/stategen/replay_test.go b/beacon-chain/state/stategen/replay_test.go index 768b84e59a52..eac26cfc1ecf 100644 --- a/beacon-chain/state/stategen/replay_test.go +++ b/beacon-chain/state/stategen/replay_test.go @@ -4,15 +4,18 @@ import ( "context" "testing" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" testDB "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" doublylinkedtree "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/doubly-linked-tree" + stateTesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/testing" "github.com/prysmaticlabs/prysm/v5/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" @@ -155,6 +158,8 @@ func TestReplayBlocks_ThroughFutureForkBoundaries(t *testing.T) { bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.DenebForkVersion)] = 4 bCfg.ElectraForkEpoch = 5 bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.ElectraForkVersion)] = 5 + bCfg.FuluForkEpoch = 6 + bCfg.ForkVersionSchedule[bytesutil.ToBytes4(bCfg.FuluForkVersion)] = 6 params.OverrideBeaconConfig(bCfg) beaconState, _ := util.DeterministicGenesisState(t, 32) @@ -209,13 +214,29 @@ func TestReplayBlocks_ProcessEpoch_Electra(t *testing.T) { beaconState, _ := util.DeterministicGenesisStateElectra(t, 1) require.NoError(t, beaconState.SetDepositBalanceToConsume(100)) amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9) - require.NoError(t, beaconState.SetPendingBalanceDeposits([]*ethpb.PendingBalanceDeposit{ + genesisBlock := util.NewBeaconBlockElectra() + + sk, err := bls.RandKey() + require.NoError(t, err) + ethAddress, err := hexutil.Decode("0x967646dCD8d34F4E02204faeDcbAe0cC96fB9245") + require.NoError(t, err) + newCredentials := make([]byte, 12) + newCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte + withdrawalCredentials := append(newCredentials, ethAddress...) + ffe := params.BeaconConfig().FarFutureEpoch + require.NoError(t, beaconState.SetValidators([]*ethpb.Validator{ { - Amount: uint64(amountAvailForProcessing) / 10, - Index: primitives.ValidatorIndex(0), + PublicKey: sk.PublicKey().Marshal(), + WithdrawalCredentials: withdrawalCredentials, + ExitEpoch: ffe, + EffectiveBalance: params.BeaconConfig().MinActivationBalance, }, })) - genesisBlock := util.NewBeaconBlockElectra() + + require.NoError(t, beaconState.SetPendingDeposits([]*ethpb.PendingDeposit{ + stateTesting.GeneratePendingDeposit(t, sk, uint64(amountAvailForProcessing)/10, bytesutil.ToBytes32(withdrawalCredentials), genesisBlock.Block.Slot), + })) + bodyRoot, err := genesisBlock.Block.HashTreeRoot() require.NoError(t, err) err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ @@ -238,7 +259,7 @@ func TestReplayBlocks_ProcessEpoch_Electra(t *testing.T) { require.NoError(t, err) require.Equal(t, primitives.Gwei(0), res) - remaining, err := newState.PendingBalanceDeposits() + remaining, err := newState.PendingDeposits() require.NoError(t, err) require.Equal(t, 0, len(remaining)) diff --git a/beacon-chain/state/stategen/replayer.go b/beacon-chain/state/stategen/replayer.go index aa6ea3eb3a1d..beff7a1a438e 100644 --- a/beacon-chain/state/stategen/replayer.go +++ b/beacon-chain/state/stategen/replayer.go @@ -9,8 +9,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) var ErrFutureSlotRequested = errors.New("cannot replay to future slots") diff --git a/beacon-chain/state/stategen/service.go b/beacon-chain/state/stategen/service.go index 6fc26cf6852e..3fa8011907c2 100644 --- a/beacon-chain/state/stategen/service.go +++ b/beacon-chain/state/stategen/service.go @@ -19,8 +19,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) var defaultHotStateDBInterval primitives.Slot = 128 diff --git a/beacon-chain/state/stategen/setter.go b/beacon-chain/state/stategen/setter.go index 9804bcc7d044..88c29356035b 100644 --- a/beacon-chain/state/stategen/setter.go +++ b/beacon-chain/state/stategen/setter.go @@ -9,10 +9,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // SaveState saves the state in the cache and/or DB. diff --git a/beacon-chain/state/stateutil/BUILD.bazel b/beacon-chain/state/stateutil/BUILD.bazel index 05d2c998151a..b9270e81c7e8 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state/stateutil/BUILD.bazel @@ -12,8 +12,8 @@ go_library( "historical_summaries_root.go", "participation_bit_root.go", "pending_attestation_root.go", - "pending_balance_deposits_root.go", "pending_consolidations_root.go", + "pending_deposits_root.go", "pending_partial_withdrawals_root.go", "reference.go", "sync_committee.root.go", diff --git a/beacon-chain/state/stateutil/pending_balance_deposits_root.go b/beacon-chain/state/stateutil/pending_deposits_root.go similarity index 57% rename from beacon-chain/state/stateutil/pending_balance_deposits_root.go rename to beacon-chain/state/stateutil/pending_deposits_root.go index 04d9b23f10b4..6d79759e4599 100644 --- a/beacon-chain/state/stateutil/pending_balance_deposits_root.go +++ b/beacon-chain/state/stateutil/pending_deposits_root.go @@ -6,6 +6,6 @@ import ( ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) -func PendingBalanceDepositsRoot(slice []*ethpb.PendingBalanceDeposit) ([32]byte, error) { - return ssz.SliceRoot(slice, fieldparams.PendingBalanceDepositsLimit) +func PendingDepositsRoot(slice []*ethpb.PendingDeposit) ([32]byte, error) { + return ssz.SliceRoot(slice, fieldparams.PendingDepositsLimit) } diff --git a/beacon-chain/state/testing/BUILD.bazel b/beacon-chain/state/testing/BUILD.bazel index 3a2585f11847..0a053d670a2b 100644 --- a/beacon-chain/state/testing/BUILD.bazel +++ b/beacon-chain/state/testing/BUILD.bazel @@ -4,17 +4,25 @@ go_library( name = "go_default_library", testonly = True, srcs = [ + "generators.go", "getters.go", "getters_block.go", "getters_checkpoint.go", "getters_validator.go", ], importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/testing", - visibility = ["//beacon-chain/state:__subpackages__"], + visibility = [ + "//beacon-chain/core:__subpackages__", + "//beacon-chain/state:__subpackages__", + ], deps = [ + "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/core/signing:go_default_library", "//beacon-chain/state:go_default_library", "//config/fieldparams:go_default_library", + "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", + "//crypto/bls/common:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", diff --git a/beacon-chain/state/testing/generators.go b/beacon-chain/state/testing/generators.go new file mode 100644 index 000000000000..51dfb5c2d209 --- /dev/null +++ b/beacon-chain/state/testing/generators.go @@ -0,0 +1,44 @@ +package testing + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/crypto/bls/common" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +// GeneratePendingDeposit is used for testing and producing a signed pending deposit +func GeneratePendingDeposit(t *testing.T, key common.SecretKey, amount uint64, withdrawalCredentials [32]byte, slot primitives.Slot) *ethpb.PendingDeposit { + dm := ðpb.DepositMessage{ + PublicKey: key.PublicKey().Marshal(), + WithdrawalCredentials: withdrawalCredentials[:], + Amount: amount, + } + domain, err := signing.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil) + require.NoError(t, err) + sr, err := signing.ComputeSigningRoot(dm, domain) + require.NoError(t, err) + sig := key.Sign(sr[:]) + depositData := ðpb.Deposit_Data{ + PublicKey: bytesutil.SafeCopyBytes(dm.PublicKey), + WithdrawalCredentials: bytesutil.SafeCopyBytes(dm.WithdrawalCredentials), + Amount: dm.Amount, + Signature: sig.Marshal(), + } + valid, err := blocks.IsValidDepositSignature(depositData) + require.NoError(t, err) + require.Equal(t, true, valid) + return ðpb.PendingDeposit{ + PublicKey: bytesutil.SafeCopyBytes(dm.PublicKey), + WithdrawalCredentials: bytesutil.SafeCopyBytes(dm.WithdrawalCredentials), + Amount: dm.Amount, + Signature: sig.Marshal(), + Slot: slot, + } +} diff --git a/beacon-chain/sync/BUILD.bazel b/beacon-chain/sync/BUILD.bazel index cba397bcf1bf..85a0317be3eb 100644 --- a/beacon-chain/sync/BUILD.bazel +++ b/beacon-chain/sync/BUILD.bazel @@ -44,7 +44,6 @@ go_library( "validate_aggregate_proof.go", "validate_attester_slashing.go", "validate_beacon_attestation.go", - "validate_beacon_attestation_electra.go", "validate_beacon_blocks.go", "validate_blob.go", "validate_bls_to_execution_change.go", @@ -112,6 +111,7 @@ go_library( "//encoding/ssz/equality:go_default_library", "//io/file:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/forks:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", @@ -138,7 +138,7 @@ go_library( "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_trailofbits_go_mutexasserts//:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@io_opentelemetry_go_otel_trace//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) @@ -178,7 +178,6 @@ go_test( "sync_test.go", "validate_aggregate_proof_test.go", "validate_attester_slashing_test.go", - "validate_beacon_attestation_electra_test.go", "validate_beacon_attestation_test.go", "validate_beacon_blocks_test.go", "validate_blob_test.go", @@ -239,10 +238,10 @@ go_test( "//encoding/ssz/equality:go_default_library", "//network/forks:go_default_library", "//proto/engine/v1:go_default_library", - "//proto/eth/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/attestation:go_default_library", "//proto/prysm/v1alpha1/metadata:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", @@ -253,10 +252,12 @@ go_test( "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_ethereum_go_ethereum//p2p/enr:go_default_library", "@com_github_golang_snappy//:go_default_library", + "@com_github_libp2p_go_libp2p//:go_default_library", "@com_github_libp2p_go_libp2p//core:go_default_library", "@com_github_libp2p_go_libp2p//core/network:go_default_library", "@com_github_libp2p_go_libp2p//core/peer:go_default_library", "@com_github_libp2p_go_libp2p//core/protocol:go_default_library", + "@com_github_libp2p_go_libp2p//p2p/transport/quic:go_default_library", "@com_github_libp2p_go_libp2p_pubsub//:go_default_library", "@com_github_libp2p_go_libp2p_pubsub//pb:go_default_library", "@com_github_patrickmn_go_cache//:go_default_library", diff --git a/beacon-chain/sync/backfill/blobs.go b/beacon-chain/sync/backfill/blobs.go index 1f7da626844b..0808f48ae8bd 100644 --- a/beacon-chain/sync/backfill/blobs.go +++ b/beacon-chain/sync/backfill/blobs.go @@ -9,6 +9,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" @@ -44,7 +45,7 @@ func newBlobSync(current primitives.Slot, vbs verifiedROBlocks, cfg *blobSyncCon return &blobSync{current: current, expected: expected, bbv: bbv, store: as}, nil } -type blobVerifierMap map[[32]byte][fieldparams.MaxBlobsPerBlock]verification.BlobVerifier +type blobVerifierMap map[[32]byte][]verification.BlobVerifier type blobSync struct { store das.AvailabilityStore @@ -106,8 +107,11 @@ type blobBatchVerifier struct { } func (bbv *blobBatchVerifier) newVerifier(rb blocks.ROBlob) verification.BlobVerifier { - m := bbv.verifiers[rb.BlockRoot()] - m[rb.Index] = bbv.newBlobVerifier(rb, verification.BackfillSidecarRequirements) + m, ok := bbv.verifiers[rb.BlockRoot()] + if !ok { + m = make([]verification.BlobVerifier, params.BeaconConfig().MaxBlobsPerBlock(rb.Slot())) + } + m[rb.Index] = bbv.newBlobVerifier(rb, verification.BackfillBlobSidecarRequirements) bbv.verifiers[rb.BlockRoot()] = m return m[rb.Index] } diff --git a/beacon-chain/sync/backfill/service.go b/beacon-chain/sync/backfill/service.go index 0dc0df6dddd0..414ed2082755 100644 --- a/beacon-chain/sync/backfill/service.go +++ b/beacon-chain/sync/backfill/service.go @@ -39,6 +39,7 @@ type Service struct { batchImporter batchImporter blobStore *filesystem.BlobStorage initSyncWaiter func() error + complete chan struct{} } var _ runtime.Service = (*Service)(nil) @@ -148,6 +149,7 @@ func NewService(ctx context.Context, su *Store, bStore *filesystem.BlobStorage, p2p: p, pa: pa, batchImporter: defaultBatchImporter, + complete: make(chan struct{}), } for _, o := range opts { if err := o(s); err != nil { @@ -250,6 +252,7 @@ func (s *Service) scheduleTodos() { func (s *Service) Start() { if !s.enabled { log.Info("Backfill service not enabled") + s.markComplete() return } ctx, cancel := context.WithCancel(s.ctx) @@ -273,6 +276,7 @@ func (s *Service) Start() { if s.store.isGenesisSync() { log.Info("Backfill short-circuit; node synced from genesis") + s.markComplete() return } status := s.store.status() @@ -281,6 +285,7 @@ func (s *Service) Start() { log.WithField("minimumRequiredSlot", s.ms(s.clock.CurrentSlot())). WithField("backfillLowestSlot", status.LowSlot). Info("Exiting backfill service; minimum block retention slot > lowest backfilled block") + s.markComplete() return } s.verifier, s.ctxMap, err = s.initVerifier(ctx) @@ -308,6 +313,7 @@ func (s *Service) Start() { return } if s.updateComplete() { + s.markComplete() return } s.importBatches(ctx) @@ -363,3 +369,17 @@ func newBlobVerifierFromInitializer(ini *verification.Initializer) verification. return ini.NewBlobVerifier(b, reqs) } } + +func (s *Service) markComplete() { + close(s.complete) + log.Info("Backfill service marked as complete") +} + +func (s *Service) WaitForCompletion() error { + select { + case <-s.ctx.Done(): + return s.ctx.Err() + case <-s.complete: + return nil + } +} diff --git a/beacon-chain/sync/backfill/verify_test.go b/beacon-chain/sync/backfill/verify_test.go index 19253ba7fcfe..f5e86003cdd2 100644 --- a/beacon-chain/sync/backfill/verify_test.go +++ b/beacon-chain/sync/backfill/verify_test.go @@ -1,6 +1,7 @@ package backfill import ( + "math" "testing" "github.com/ethereum/go-ethereum/common/hexutil" @@ -19,14 +20,21 @@ import ( ) func TestDomainCache(t *testing.T) { - cfg := params.MainnetConfig() + cfg := params.MainnetConfig().Copy() + // This hack is needed not to have both Electra and Fulu fork epoch both set to the future max epoch. + // It can be removed once the Electra fork version has been set to a real value. + for version := range cfg.ForkVersionSchedule { + if cfg.ForkVersionNames[version] == "electra" { + cfg.ForkVersionSchedule[version] = math.MaxUint64 - 1 + } + } + vRoot, err := hexutil.Decode("0x0011223344556677889900112233445566778899001122334455667788990011") dType := cfg.DomainBeaconProposer require.NoError(t, err) require.Equal(t, 32, len(vRoot)) fsched := forks.NewOrderedSchedule(cfg) - dc, err := newDomainCache(vRoot, - dType, fsched) + dc, err := newDomainCache(vRoot, dType, fsched) require.NoError(t, err) require.Equal(t, len(fsched), len(dc.forkDomains)) for i := range fsched { diff --git a/beacon-chain/sync/batch_verifier.go b/beacon-chain/sync/batch_verifier.go index e2a275accbb7..0edb70524553 100644 --- a/beacon-chain/sync/batch_verifier.go +++ b/beacon-chain/sync/batch_verifier.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) const signatureVerificationInterval = 50 * time.Millisecond diff --git a/beacon-chain/sync/blobs_test.go b/beacon-chain/sync/blobs_test.go index e05e6f7ed204..25cfe9c43f94 100644 --- a/beacon-chain/sync/blobs_test.go +++ b/beacon-chain/sync/blobs_test.go @@ -180,7 +180,7 @@ func (c *blobsTestCase) setup(t *testing.T) (*Service, []blocks.ROBlob, func()) cleanup := func() { params.OverrideBeaconConfig(cfg) } - maxBlobs := fieldparams.MaxBlobsPerBlock + maxBlobs := int(params.BeaconConfig().MaxBlobsPerBlock(0)) chain, clock := defaultMockChain(t) if c.chain == nil { c.chain = chain @@ -218,8 +218,8 @@ func (c *blobsTestCase) setup(t *testing.T) (*Service, []blocks.ROBlob, func()) rateLimiter: newRateLimiter(client), } - byRootRate := params.BeaconConfig().MaxRequestBlobSidecars * fieldparams.MaxBlobsPerBlock - byRangeRate := params.BeaconConfig().MaxRequestBlobSidecars * fieldparams.MaxBlobsPerBlock + byRootRate := params.BeaconConfig().MaxRequestBlobSidecars * uint64(params.BeaconConfig().MaxBlobsPerBlock(0)) + byRangeRate := params.BeaconConfig().MaxRequestBlobSidecars * uint64(params.BeaconConfig().MaxBlobsPerBlock(0)) s.setRateCollector(p2p.RPCBlobSidecarsByRootTopicV1, leakybucket.NewCollector(0.000001, int64(byRootRate), time.Second, false)) s.setRateCollector(p2p.RPCBlobSidecarsByRangeTopicV1, leakybucket.NewCollector(0.000001, int64(byRangeRate), time.Second, false)) @@ -250,8 +250,7 @@ func (c *blobsTestCase) run(t *testing.T) { } } for _, blobSidecars := range m { - v, err := verification.BlobSidecarSliceNoop(blobSidecars) - require.NoError(t, err) + v := verification.FakeVerifySliceForTest(t, blobSidecars) for i := range v { require.NoError(t, s.cfg.blobStorage.Save(v[i])) } @@ -310,7 +309,7 @@ func TestTestcaseSetup_BlocksAndBlobs(t *testing.T) { req := blobRootRequestFromSidecars(sidecars) expect := c.filterExpectedByRoot(t, sidecars, req) defer cleanup() - maxed := nblocks * fieldparams.MaxBlobsPerBlock + maxed := nblocks * params.BeaconConfig().MaxBlobsPerBlock(0) require.Equal(t, maxed, len(sidecars)) require.Equal(t, maxed, len(expect)) for _, sc := range sidecars { diff --git a/beacon-chain/sync/checkpoint/BUILD.bazel b/beacon-chain/sync/checkpoint/BUILD.bazel index 1e55272536ee..f5c5789fcd30 100644 --- a/beacon-chain/sync/checkpoint/BUILD.bazel +++ b/beacon-chain/sync/checkpoint/BUILD.bazel @@ -1,4 +1,4 @@ -load("@prysm//tools/go:def.bzl", "go_library") +load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", @@ -6,15 +6,52 @@ go_library( "api.go", "file.go", "log.go", + "weak-subjectivity.go", ], importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/checkpoint", visibility = ["//visibility:public"], deps = [ + "//api/client:go_default_library", "//api/client/beacon:go_default_library", + "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/db:go_default_library", + "//beacon-chain/state:go_default_library", "//config/params:go_default_library", + "//consensus-types/interfaces:go_default_library", + "//consensus-types/primitives:go_default_library", + "//encoding/bytesutil:go_default_library", + "//encoding/ssz/detect:go_default_library", "//io/file:go_default_library", + "//runtime/version:go_default_library", + "//time/slots:go_default_library", + "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", ], ) + +go_test( + name = "go_default_test", + srcs = [ + "api_test.go", + "weak-subjectivity_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//api/client:go_default_library", + "//api/client/beacon:go_default_library", + "//beacon-chain/state:go_default_library", + "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/blocks/testing:go_default_library", + "//consensus-types/primitives:go_default_library", + "//encoding/ssz/detect:go_default_library", + "//network/forks:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", + "//testing/require:go_default_library", + "//testing/util:go_default_library", + "//time/slots:go_default_library", + "@com_github_pkg_errors//:go_default_library", + ], +) diff --git a/beacon-chain/sync/checkpoint/api.go b/beacon-chain/sync/checkpoint/api.go index 4ed9dc65870a..6f201bd5020c 100644 --- a/beacon-chain/sync/checkpoint/api.go +++ b/beacon-chain/sync/checkpoint/api.go @@ -2,13 +2,27 @@ package checkpoint import ( "context" + "fmt" + "path" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api/client" "github.com/prysmaticlabs/prysm/v5/api/client/beacon" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/encoding/ssz/detect" + "github.com/prysmaticlabs/prysm/v5/io/file" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/sirupsen/logrus" ) +var errCheckpointBlockMismatch = errors.New("mismatch between checkpoint sync state and block") + // APIInitializer manages initializing the beacon node using checkpoint sync, retrieving the checkpoint state and root // from the remote beacon node api. type APIInitializer struct { @@ -18,7 +32,7 @@ type APIInitializer struct { // NewAPIInitializer creates an APIInitializer, handling the set up of a beacon node api client // using the provided host string. func NewAPIInitializer(beaconNodeHost string) (*APIInitializer, error) { - c, err := beacon.NewClient(beaconNodeHost) + c, err := beacon.NewClient(beaconNodeHost, client.WithMaxBodySize(client.MaxBodySizeState)) if err != nil { return nil, errors.Wrapf(err, "unable to parse beacon node url or hostname - %s", beaconNodeHost) } @@ -32,14 +46,119 @@ func (dl *APIInitializer) Initialize(ctx context.Context, d db.Database) error { if err == nil && origin != params.BeaconConfig().ZeroHash { log.Warnf("Origin checkpoint root %#x found in db, ignoring checkpoint sync flags", origin) return nil - } else { - if !errors.Is(err, db.ErrNotFound) { - return errors.Wrap(err, "error while checking database for origin root") - } } - od, err := beacon.DownloadFinalizedData(ctx, dl.c) + if err != nil && !errors.Is(err, db.ErrNotFound) { + return errors.Wrap(err, "error while checking database for origin root") + } + od, err := DownloadFinalizedData(ctx, dl.c) if err != nil { return errors.Wrap(err, "Error retrieving checkpoint origin state and block") } return d.SaveOrigin(ctx, od.StateBytes(), od.BlockBytes()) } + +// OriginData represents the BeaconState and ReadOnlySignedBeaconBlock necessary to start an empty Beacon Node +// using Checkpoint Sync. +type OriginData struct { + sb []byte + bb []byte + st state.BeaconState + b interfaces.ReadOnlySignedBeaconBlock + vu *detect.VersionedUnmarshaler + br [32]byte + sr [32]byte +} + +// SaveBlock saves the downloaded block to a unique file in the given path. +// For readability and collision avoidance, the file name includes: type, config name, slot and root +func (o *OriginData) SaveBlock(dir string) (string, error) { + blockPath := path.Join(dir, fname("block", o.vu, o.b.Block().Slot(), o.br)) + return blockPath, file.WriteFile(blockPath, o.BlockBytes()) +} + +// SaveState saves the downloaded state to a unique file in the given path. +// For readability and collision avoidance, the file name includes: type, config name, slot and root +func (o *OriginData) SaveState(dir string) (string, error) { + statePath := path.Join(dir, fname("state", o.vu, o.st.Slot(), o.sr)) + return statePath, file.WriteFile(statePath, o.StateBytes()) +} + +// StateBytes returns the ssz-encoded bytes of the downloaded BeaconState value. +func (o *OriginData) StateBytes() []byte { + return o.sb +} + +// BlockBytes returns the ssz-encoded bytes of the downloaded ReadOnlySignedBeaconBlock value. +func (o *OriginData) BlockBytes() []byte { + return o.bb +} + +func fname(prefix string, vu *detect.VersionedUnmarshaler, slot primitives.Slot, root [32]byte) string { + return fmt.Sprintf("%s_%s_%s_%d-%#x.ssz", prefix, vu.Config.ConfigName, version.String(vu.Fork), slot, root) +} + +// DownloadFinalizedData downloads the most recently finalized state, and the block most recently applied to that state. +// This pair can be used to initialize a new beacon node via checkpoint sync. +func DownloadFinalizedData(ctx context.Context, client *beacon.Client) (*OriginData, error) { + sb, err := client.GetState(ctx, beacon.IdFinalized) + if err != nil { + return nil, err + } + vu, err := detect.FromState(sb) + if err != nil { + return nil, errors.Wrap(err, "error detecting chain config for finalized state") + } + + log.WithFields(logrus.Fields{ + "name": vu.Config.ConfigName, + "fork": version.String(vu.Fork), + }).Info("Detected supported config in remote finalized state") + + s, err := vu.UnmarshalBeaconState(sb) + if err != nil { + return nil, errors.Wrap(err, "error unmarshaling finalized state to correct version") + } + + slot := s.LatestBlockHeader().Slot + bb, err := client.GetBlock(ctx, beacon.IdFromSlot(slot)) + if err != nil { + return nil, errors.Wrapf(err, "error requesting block by slot = %d", slot) + } + b, err := vu.UnmarshalBeaconBlock(bb) + if err != nil { + return nil, errors.Wrap(err, "unable to unmarshal block to a supported type using the detected fork schedule") + } + br, err := b.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "error computing hash_tree_root of retrieved block") + } + bodyRoot, err := b.Block().Body().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "error computing hash_tree_root of retrieved block body") + } + + sbr := bytesutil.ToBytes32(s.LatestBlockHeader().BodyRoot) + if sbr != bodyRoot { + return nil, errors.Wrapf(errCheckpointBlockMismatch, "state body root = %#x, block body root = %#x", sbr, bodyRoot) + } + sr, err := s.HashTreeRoot(ctx) + if err != nil { + return nil, errors.Wrapf(err, "failed to compute htr for finalized state at slot=%d", s.Slot()) + } + + log. + WithField("blockSlot", b.Block().Slot()). + WithField("stateSlot", s.Slot()). + WithField("stateRoot", hexutil.Encode(sr[:])). + WithField("blockRoot", hexutil.Encode(br[:])). + Info("Downloaded checkpoint sync state and block.") + return &OriginData{ + st: s, + b: b, + sb: sb, + bb: bb, + vu: vu, + br: br, + sr: sr, + }, nil +} diff --git a/beacon-chain/sync/checkpoint/api_test.go b/beacon-chain/sync/checkpoint/api_test.go new file mode 100644 index 000000000000..67ed35fe2c7b --- /dev/null +++ b/beacon-chain/sync/checkpoint/api_test.go @@ -0,0 +1,127 @@ +package checkpoint + +import ( + "bytes" + "context" + "io" + "net/http" + "testing" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api/client" + "github.com/prysmaticlabs/prysm/v5/api/client/beacon" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + blocktest "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks/testing" + "github.com/prysmaticlabs/prysm/v5/encoding/ssz/detect" + "github.com/prysmaticlabs/prysm/v5/network/forks" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/prysmaticlabs/prysm/v5/time/slots" +) + +func TestDownloadFinalizedData(t *testing.T) { + ctx := context.Background() + cfg := params.MainnetConfig().Copy() + + // avoid the altair zone because genesis tests are easier to set up + epoch := cfg.AltairForkEpoch - 1 + // set up checkpoint state, using the epoch that will be computed as the ws checkpoint state based on the head state + slot, err := slots.EpochStart(epoch) + require.NoError(t, err) + st, err := util.NewBeaconState() + require.NoError(t, err) + fork, err := forks.ForkForEpochFromConfig(cfg, epoch) + require.NoError(t, err) + require.NoError(t, st.SetFork(fork)) + require.NoError(t, st.SetSlot(slot)) + + // set up checkpoint block + b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) + require.NoError(t, err) + b, err = blocktest.SetBlockParentRoot(b, cfg.ZeroHash) + require.NoError(t, err) + b, err = blocktest.SetBlockSlot(b, slot) + require.NoError(t, err) + b, err = blocktest.SetProposerIndex(b, 0) + require.NoError(t, err) + + // set up state header pointing at checkpoint block - this is how the block is downloaded by root + header, err := b.Header() + require.NoError(t, err) + require.NoError(t, st.SetLatestBlockHeader(header.Header)) + + // order of operations can be confusing here: + // - when computing the state root, make sure block header is complete, EXCEPT the state root should be zero-value + // - before computing the block root (to match the request route), the block should include the state root + // *computed from the state with a header that does not have a state root set yet* + sr, err := st.HashTreeRoot(ctx) + require.NoError(t, err) + + b, err = blocktest.SetBlockStateRoot(b, sr) + require.NoError(t, err) + mb, err := b.MarshalSSZ() + require.NoError(t, err) + br, err := b.Block().HashTreeRoot() + require.NoError(t, err) + + ms, err := st.MarshalSSZ() + require.NoError(t, err) + + trans := &testRT{rt: func(req *http.Request) (*http.Response, error) { + res := &http.Response{Request: req} + switch req.URL.Path { + case beacon.RenderGetStatePath(beacon.IdFinalized): + res.StatusCode = http.StatusOK + res.Body = io.NopCloser(bytes.NewBuffer(ms)) + case beacon.RenderGetBlockPath(beacon.IdFromSlot(b.Block().Slot())): + res.StatusCode = http.StatusOK + res.Body = io.NopCloser(bytes.NewBuffer(mb)) + default: + res.StatusCode = http.StatusInternalServerError + res.Body = io.NopCloser(bytes.NewBufferString("")) + } + + return res, nil + }} + c, err := beacon.NewClient("http://localhost:3500", client.WithRoundTripper(trans)) + require.NoError(t, err) + // sanity check before we go through checkpoint + // make sure we can download the state and unmarshal it with the VersionedUnmarshaler + sb, err := c.GetState(ctx, beacon.IdFinalized) + require.NoError(t, err) + require.Equal(t, true, bytes.Equal(sb, ms)) + vu, err := detect.FromState(sb) + require.NoError(t, err) + us, err := vu.UnmarshalBeaconState(sb) + require.NoError(t, err) + ushtr, err := us.HashTreeRoot(ctx) + require.NoError(t, err) + require.Equal(t, sr, ushtr) + + expected := &OriginData{ + sb: ms, + bb: mb, + br: br, + sr: sr, + } + od, err := DownloadFinalizedData(ctx, c) + require.NoError(t, err) + require.Equal(t, true, bytes.Equal(expected.sb, od.sb)) + require.Equal(t, true, bytes.Equal(expected.bb, od.bb)) + require.Equal(t, expected.br, od.br) + require.Equal(t, expected.sr, od.sr) +} + +type testRT struct { + rt func(*http.Request) (*http.Response, error) +} + +func (rt *testRT) RoundTrip(req *http.Request) (*http.Response, error) { + if rt.rt != nil { + return rt.rt(req) + } + return nil, errors.New("RoundTripper not implemented") +} + +var _ http.RoundTripper = &testRT{} diff --git a/beacon-chain/sync/checkpoint/weak-subjectivity.go b/beacon-chain/sync/checkpoint/weak-subjectivity.go new file mode 100644 index 000000000000..1666d36f872d --- /dev/null +++ b/beacon-chain/sync/checkpoint/weak-subjectivity.go @@ -0,0 +1,128 @@ +package checkpoint + +import ( + "context" + + "github.com/pkg/errors" + base "github.com/prysmaticlabs/prysm/v5/api/client" + "github.com/prysmaticlabs/prysm/v5/api/client/beacon" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/encoding/ssz/detect" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/time/slots" +) + +// ComputeWeakSubjectivityCheckpoint attempts to use the prysm weak_subjectivity api +// to obtain the current weak_subjectivity checkpoint. +// For non-prysm nodes, the same computation will be performed with extra steps, +// using the head state downloaded from the beacon node api. +func ComputeWeakSubjectivityCheckpoint(ctx context.Context, client *beacon.Client) (*beacon.WeakSubjectivityData, error) { + ws, err := client.GetWeakSubjectivity(ctx) + if err != nil { + // a 404/405 is expected if querying an endpoint that doesn't support the weak subjectivity checkpoint api + if !errors.Is(err, base.ErrNotOK) { + return nil, errors.Wrap(err, "unexpected API response for prysm-only weak subjectivity checkpoint API") + } + // fall back to vanilla Beacon Node API method + return computeBackwardsCompatible(ctx, client) + } + log.Printf("server weak subjectivity checkpoint response - epoch=%d, block_root=%#x, state_root=%#x", ws.Epoch, ws.BlockRoot, ws.StateRoot) + return ws, nil +} + +// for clients that do not support the weak_subjectivity api method we gather the necessary data for a checkpoint sync by: +// - inspecting the remote server's head state and computing the weak subjectivity epoch locally +// - requesting the state at the first slot of the epoch +// - using hash_tree_root(state.latest_block_header) to compute the block the state integrates +// - requesting that block by its root +func computeBackwardsCompatible(ctx context.Context, client *beacon.Client) (*beacon.WeakSubjectivityData, error) { + log.Print("falling back to generic checkpoint derivation, weak_subjectivity API not supported by server") + epoch, err := getWeakSubjectivityEpochFromHead(ctx, client) + if err != nil { + return nil, errors.Wrap(err, "error computing weak subjectivity epoch via head state inspection") + } + + // use first slot of the epoch for the state slot + slot, err := slots.EpochStart(epoch) + if err != nil { + return nil, errors.Wrapf(err, "error computing first slot of epoch=%d", epoch) + } + + log.Printf("requesting checkpoint state at slot %d", slot) + // get the state at the first slot of the epoch + sb, err := client.GetState(ctx, beacon.IdFromSlot(slot)) + if err != nil { + return nil, errors.Wrapf(err, "failed to request state by slot from api, slot=%d", slot) + } + + // ConfigFork is used to unmarshal the BeaconState so we can read the block root in latest_block_header + vu, err := detect.FromState(sb) + if err != nil { + return nil, errors.Wrap(err, "error detecting chain config for beacon state") + } + log.Printf("detected supported config in checkpoint state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork)) + + s, err := vu.UnmarshalBeaconState(sb) + if err != nil { + return nil, errors.Wrap(err, "error using detected config fork to unmarshal state bytes") + } + + // compute state and block roots + sr, err := s.HashTreeRoot(ctx) + if err != nil { + return nil, errors.Wrap(err, "error computing hash_tree_root of state") + } + + h := s.LatestBlockHeader() + h.StateRoot = sr[:] + br, err := h.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "error while computing block root using state data") + } + + bb, err := client.GetBlock(ctx, beacon.IdFromRoot(br)) + if err != nil { + return nil, errors.Wrapf(err, "error requesting block by root = %d", br) + } + b, err := vu.UnmarshalBeaconBlock(bb) + if err != nil { + return nil, errors.Wrap(err, "unable to unmarshal block to a supported type using the detected fork schedule") + } + br, err = b.Block().HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "error computing hash_tree_root for block obtained via root") + } + + return &beacon.WeakSubjectivityData{ + Epoch: epoch, + BlockRoot: br, + StateRoot: sr, + }, nil +} + +// this method downloads the head state, which can be used to find the correct chain config +// and use prysm's helper methods to compute the latest weak subjectivity epoch. +func getWeakSubjectivityEpochFromHead(ctx context.Context, client *beacon.Client) (primitives.Epoch, error) { + headBytes, err := client.GetState(ctx, beacon.IdHead) + if err != nil { + return 0, err + } + vu, err := detect.FromState(headBytes) + if err != nil { + return 0, errors.Wrap(err, "error detecting chain config for beacon state") + } + log.Printf("detected supported config in remote head state, name=%s, fork=%s", vu.Config.ConfigName, version.String(vu.Fork)) + headState, err := vu.UnmarshalBeaconState(headBytes) + if err != nil { + return 0, errors.Wrap(err, "error unmarshaling state to correct version") + } + + epoch, err := helpers.LatestWeakSubjectivityEpoch(ctx, headState, vu.Config) + if err != nil { + return 0, errors.Wrap(err, "error computing the weak subjectivity epoch from head state") + } + + log.Printf("(computed client-side) weak subjectivity epoch = %d", epoch) + return epoch, nil +} diff --git a/api/client/beacon/checkpoint_test.go b/beacon-chain/sync/checkpoint/weak-subjectivity_test.go similarity index 68% rename from api/client/beacon/checkpoint_test.go rename to beacon-chain/sync/checkpoint/weak-subjectivity_test.go index 250608ebf99d..e090f8cec134 100644 --- a/api/client/beacon/checkpoint_test.go +++ b/beacon-chain/sync/checkpoint/weak-subjectivity_test.go @@ -1,4 +1,4 @@ -package beacon +package checkpoint import ( "bytes" @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/client" + "github.com/prysmaticlabs/prysm/v5/api/client/beacon" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" @@ -25,19 +26,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/time/slots" ) -type testRT struct { - rt func(*http.Request) (*http.Response, error) -} - -func (rt *testRT) RoundTrip(req *http.Request) (*http.Response, error) { - if rt.rt != nil { - return rt.rt(req) - } - return nil, errors.New("RoundTripper not implemented") -} - -var _ http.RoundTripper = &testRT{} - func marshalToEnvelope(val interface{}) ([]byte, error) { raw, err := json.Marshal(val) if err != nil { @@ -63,35 +51,6 @@ func TestMarshalToEnvelope(t *testing.T) { require.Equal(t, expected, string(encoded)) } -func TestFallbackVersionCheck(t *testing.T) { - trans := &testRT{rt: func(req *http.Request) (*http.Response, error) { - res := &http.Response{Request: req} - switch req.URL.Path { - case getNodeVersionPath: - res.StatusCode = http.StatusOK - b := bytes.NewBuffer(nil) - d := struct { - Version string `json:"version"` - }{ - Version: "Prysm/v2.0.5 (linux amd64)", - } - encoded, err := marshalToEnvelope(d) - require.NoError(t, err) - b.Write(encoded) - res.Body = io.NopCloser(b) - case getWeakSubjectivityPath: - res.StatusCode = http.StatusNotFound - } - return res, nil - }} - - c, err := NewClient("http://localhost:3500", client.WithRoundTripper(trans)) - require.NoError(t, err) - ctx := context.Background() - _, err = ComputeWeakSubjectivityCheckpoint(ctx, c) - require.ErrorIs(t, err, errUnsupportedPrysmCheckpointVersion) -} - func TestFname(t *testing.T) { vu := &detect.VersionedUnmarshaler{ Config: params.MainnetConfig(), @@ -160,7 +119,7 @@ func TestDownloadWeakSubjectivityCheckpoint(t *testing.T) { wsSerialized, err := wst.MarshalSSZ() require.NoError(t, err) - expectedWSD := WeakSubjectivityData{ + expectedWSD := beacon.WeakSubjectivityData{ BlockRoot: bRoot, StateRoot: wRoot, Epoch: epoch, @@ -169,7 +128,7 @@ func TestDownloadWeakSubjectivityCheckpoint(t *testing.T) { trans := &testRT{rt: func(req *http.Request) (*http.Response, error) { res := &http.Response{Request: req} switch req.URL.Path { - case getWeakSubjectivityPath: + case beacon.GetWeakSubjectivityPath: res.StatusCode = http.StatusOK cp := struct { Epoch string `json:"epoch"` @@ -188,10 +147,10 @@ func TestDownloadWeakSubjectivityCheckpoint(t *testing.T) { rb, err := marshalToEnvelope(wsr) require.NoError(t, err) res.Body = io.NopCloser(bytes.NewBuffer(rb)) - case renderGetStatePath(IdFromSlot(wSlot)): + case beacon.RenderGetStatePath(beacon.IdFromSlot(wSlot)): res.StatusCode = http.StatusOK res.Body = io.NopCloser(bytes.NewBuffer(wsSerialized)) - case renderGetBlockPath(IdFromRoot(bRoot)): + case beacon.RenderGetBlockPath(beacon.IdFromRoot(bRoot)): res.StatusCode = http.StatusOK res.Body = io.NopCloser(bytes.NewBuffer(serBlock)) } @@ -199,7 +158,7 @@ func TestDownloadWeakSubjectivityCheckpoint(t *testing.T) { return res, nil }} - c, err := NewClient("http://localhost:3500", client.WithRoundTripper(trans)) + c, err := beacon.NewClient("http://localhost:3500", client.WithRoundTripper(trans)) require.NoError(t, err) wsd, err := ComputeWeakSubjectivityCheckpoint(ctx, c) @@ -263,7 +222,7 @@ func TestDownloadBackwardsCompatibleCombined(t *testing.T) { trans := &testRT{rt: func(req *http.Request) (*http.Response, error) { res := &http.Response{Request: req} switch req.URL.Path { - case getNodeVersionPath: + case beacon.GetNodeVersionPath: res.StatusCode = http.StatusOK b := bytes.NewBuffer(nil) d := struct { @@ -275,15 +234,15 @@ func TestDownloadBackwardsCompatibleCombined(t *testing.T) { require.NoError(t, err) b.Write(encoded) res.Body = io.NopCloser(b) - case getWeakSubjectivityPath: + case beacon.GetWeakSubjectivityPath: res.StatusCode = http.StatusNotFound - case renderGetStatePath(IdHead): + case beacon.RenderGetStatePath(beacon.IdHead): res.StatusCode = http.StatusOK res.Body = io.NopCloser(bytes.NewBuffer(serialized)) - case renderGetStatePath(IdFromSlot(wSlot)): + case beacon.RenderGetStatePath(beacon.IdFromSlot(wSlot)): res.StatusCode = http.StatusOK res.Body = io.NopCloser(bytes.NewBuffer(wsSerialized)) - case renderGetBlockPath(IdFromRoot(bRoot)): + case beacon.RenderGetBlockPath(beacon.IdFromRoot(bRoot)): res.StatusCode = http.StatusOK res.Body = io.NopCloser(bytes.NewBuffer(serBlock)) } @@ -291,7 +250,7 @@ func TestDownloadBackwardsCompatibleCombined(t *testing.T) { return res, nil }} - c, err := NewClient("http://localhost:3500", client.WithRoundTripper(trans)) + c, err := beacon.NewClient("http://localhost:3500", client.WithRoundTripper(trans)) require.NoError(t, err) wsPub, err := ComputeWeakSubjectivityCheckpoint(ctx, c) @@ -308,13 +267,13 @@ func TestGetWeakSubjectivityEpochFromHead(t *testing.T) { require.NoError(t, err) trans := &testRT{rt: func(req *http.Request) (*http.Response, error) { res := &http.Response{Request: req} - if req.URL.Path == renderGetStatePath(IdHead) { + if req.URL.Path == beacon.RenderGetStatePath(beacon.IdHead) { res.StatusCode = http.StatusOK res.Body = io.NopCloser(bytes.NewBuffer(serialized)) } return res, nil }} - c, err := NewClient("http://localhost:3500", client.WithRoundTripper(trans)) + c, err := beacon.NewClient("http://localhost:3500", client.WithRoundTripper(trans)) require.NoError(t, err) actualEpoch, err := getWeakSubjectivityEpochFromHead(context.Background(), c) require.NoError(t, err) @@ -386,96 +345,3 @@ func populateValidators(cfg *params.BeaconChainConfig, st state.BeaconState, val } return st.SetBalances(balances) } - -func TestDownloadFinalizedData(t *testing.T) { - ctx := context.Background() - cfg := params.MainnetConfig().Copy() - - // avoid the altair zone because genesis tests are easier to set up - epoch := cfg.AltairForkEpoch - 1 - // set up checkpoint state, using the epoch that will be computed as the ws checkpoint state based on the head state - slot, err := slots.EpochStart(epoch) - require.NoError(t, err) - st, err := util.NewBeaconState() - require.NoError(t, err) - fork, err := forkForEpoch(cfg, epoch) - require.NoError(t, err) - require.NoError(t, st.SetFork(fork)) - require.NoError(t, st.SetSlot(slot)) - - // set up checkpoint block - b, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlock()) - require.NoError(t, err) - b, err = blocktest.SetBlockParentRoot(b, cfg.ZeroHash) - require.NoError(t, err) - b, err = blocktest.SetBlockSlot(b, slot) - require.NoError(t, err) - b, err = blocktest.SetProposerIndex(b, 0) - require.NoError(t, err) - - // set up state header pointing at checkpoint block - this is how the block is downloaded by root - header, err := b.Header() - require.NoError(t, err) - require.NoError(t, st.SetLatestBlockHeader(header.Header)) - - // order of operations can be confusing here: - // - when computing the state root, make sure block header is complete, EXCEPT the state root should be zero-value - // - before computing the block root (to match the request route), the block should include the state root - // *computed from the state with a header that does not have a state root set yet* - sr, err := st.HashTreeRoot(ctx) - require.NoError(t, err) - - b, err = blocktest.SetBlockStateRoot(b, sr) - require.NoError(t, err) - mb, err := b.MarshalSSZ() - require.NoError(t, err) - br, err := b.Block().HashTreeRoot() - require.NoError(t, err) - - ms, err := st.MarshalSSZ() - require.NoError(t, err) - - trans := &testRT{rt: func(req *http.Request) (*http.Response, error) { - res := &http.Response{Request: req} - switch req.URL.Path { - case renderGetStatePath(IdFinalized): - res.StatusCode = http.StatusOK - res.Body = io.NopCloser(bytes.NewBuffer(ms)) - case renderGetBlockPath(IdFromSlot(b.Block().Slot())): - res.StatusCode = http.StatusOK - res.Body = io.NopCloser(bytes.NewBuffer(mb)) - default: - res.StatusCode = http.StatusInternalServerError - res.Body = io.NopCloser(bytes.NewBufferString("")) - } - - return res, nil - }} - c, err := NewClient("http://localhost:3500", client.WithRoundTripper(trans)) - require.NoError(t, err) - // sanity check before we go through checkpoint - // make sure we can download the state and unmarshal it with the VersionedUnmarshaler - sb, err := c.GetState(ctx, IdFinalized) - require.NoError(t, err) - require.Equal(t, true, bytes.Equal(sb, ms)) - vu, err := detect.FromState(sb) - require.NoError(t, err) - us, err := vu.UnmarshalBeaconState(sb) - require.NoError(t, err) - ushtr, err := us.HashTreeRoot(ctx) - require.NoError(t, err) - require.Equal(t, sr, ushtr) - - expected := &OriginData{ - sb: ms, - bb: mb, - br: br, - sr: sr, - } - od, err := DownloadFinalizedData(ctx, c) - require.NoError(t, err) - require.Equal(t, true, bytes.Equal(expected.sb, od.sb)) - require.Equal(t, true, bytes.Equal(expected.bb, od.bb)) - require.Equal(t, expected.br, od.br) - require.Equal(t, expected.sr, od.sr) -} diff --git a/beacon-chain/sync/decode_pubsub_test.go b/beacon-chain/sync/decode_pubsub_test.go index 1638a2305890..ba8e3007fcaa 100644 --- a/beacon-chain/sync/decode_pubsub_test.go +++ b/beacon-chain/sync/decode_pubsub_test.go @@ -129,6 +129,8 @@ func TestExtractDataType(t *testing.T) { require.NoError(t, err) electraDigest, err := signing.ComputeForkDigest(params.BeaconConfig().ElectraForkVersion, params.BeaconConfig().ZeroHash[:]) require.NoError(t, err) + fuluDigest, err := signing.ComputeForkDigest(params.BeaconConfig().FuluForkVersion, params.BeaconConfig().ZeroHash[:]) + require.NoError(t, err) type args struct { digest []byte @@ -269,12 +271,28 @@ func TestExtractDataType(t *testing.T) { chain: &mock.ChainService{ValidatorsRoot: [32]byte{}}, }, wantBlock: func() interfaces.ReadOnlySignedBeaconBlock { - wsb, err := blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockElectra{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadElectra{}}}}) + wsb, err := blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockElectra{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadDeneb{}}}}) + require.NoError(t, err) + return wsb + }(), + wantMd: wrapper.WrappedMetadataV1(ðpb.MetaDataV1{}), + wantAtt: ðpb.SingleAttestation{}, + wantAggregate: ðpb.SignedAggregateAttestationAndProofElectra{}, + wantErr: false, + }, + { + name: "fulu fork version", + args: args{ + digest: fuluDigest[:], + chain: &mock.ChainService{ValidatorsRoot: [32]byte{}}, + }, + wantBlock: func() interfaces.ReadOnlySignedBeaconBlock { + wsb, err := blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockFulu{Block: ðpb.BeaconBlockElectra{Body: ðpb.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadDeneb{}}}}) require.NoError(t, err) return wsb }(), wantMd: wrapper.WrappedMetadataV1(ðpb.MetaDataV1{}), - wantAtt: ðpb.AttestationElectra{}, + wantAtt: ðpb.SingleAttestation{}, wantAggregate: ðpb.SignedAggregateAttestationAndProofElectra{}, wantErr: false, }, diff --git a/beacon-chain/sync/fork_watcher.go b/beacon-chain/sync/fork_watcher.go index cc3d50d76f7b..54702d5109c4 100644 --- a/beacon-chain/sync/fork_watcher.go +++ b/beacon-chain/sync/fork_watcher.go @@ -1,6 +1,7 @@ package sync import ( + "github.com/libp2p/go-libp2p/core/protocol" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -39,87 +40,129 @@ func (s *Service) forkWatcher() { } } -// Checks if there is a fork in the next epoch and if there is -// it registers the appropriate gossip and rpc topics. -func (s *Service) registerForUpcomingFork(currEpoch primitives.Epoch) error { - genRoot := s.cfg.clock.GenesisValidatorsRoot() - isNextForkEpoch, err := forks.IsForkNextEpoch(s.cfg.clock.GenesisTime(), genRoot[:]) +// registerForUpcomingFork registers appropriate gossip and RPC topic if there is a fork in the next epoch. +func (s *Service) registerForUpcomingFork(currentEpoch primitives.Epoch) error { + // Get the genesis validators root. + genesisValidatorsRoot := s.cfg.clock.GenesisValidatorsRoot() + + // Check if there is a fork in the next epoch. + isForkNextEpoch, err := forks.IsForkNextEpoch(s.cfg.clock.GenesisTime(), genesisValidatorsRoot[:]) if err != nil { return errors.Wrap(err, "Could not retrieve next fork epoch") } - // In preparation for the upcoming fork - // in the following epoch, the node - // will subscribe the new topics in advance. - if isNextForkEpoch { - nextEpoch := currEpoch + 1 - digest, err := forks.ForkDigestFromEpoch(nextEpoch, genRoot[:]) - if err != nil { - return errors.Wrap(err, "could not retrieve fork digest") - } - if s.subHandler.digestExists(digest) { - return nil - } - s.registerSubscribers(nextEpoch, digest) - if nextEpoch == params.BeaconConfig().AltairForkEpoch { - s.registerRPCHandlersAltair() - } - if nextEpoch == params.BeaconConfig().DenebForkEpoch { - s.registerRPCHandlersDeneb() - } + + // Exit early if there is no fork in the next epoch. + if !isForkNextEpoch { + return nil + } + + beforeForkEpoch := currentEpoch + forkEpoch := beforeForkEpoch + 1 + + // Get the fork afterForkDigest for the next epoch. + afterForkDigest, err := forks.ForkDigestFromEpoch(forkEpoch, genesisValidatorsRoot[:]) + if err != nil { + return errors.Wrap(err, "could not retrieve fork digest") + } + + // Exit early if the topics for the next epoch are already registered. + // It likely to be the case for all slots of the epoch that are not the first one. + if s.subHandler.digestExists(afterForkDigest) { + return nil + } + + // Register the subscribers (gossipsub) for the next epoch. + s.registerSubscribers(forkEpoch, afterForkDigest) + + // Get the handlers for the current and next fork. + beforeForkHandlerByTopic, err := s.rpcHandlerByTopicFromEpoch(beforeForkEpoch) + if err != nil { + return errors.Wrap(err, "RPC handler by topic from before fork epoch") + } + + forkHandlerByTopic, err := s.rpcHandlerByTopicFromEpoch(forkEpoch) + if err != nil { + return errors.Wrap(err, "RPC handler by topic from fork epoch") + } + + // Compute newly added topics. + newRPCHandlerByTopic := addedRPCHandlerByTopic(beforeForkHandlerByTopic, forkHandlerByTopic) + + // Register the new RPC handlers. + for topic, handler := range newRPCHandlerByTopic { + s.registerRPC(topic, handler) } + return nil } -// Checks if there was a fork in the previous epoch, and if there -// was then we deregister the topics from that particular fork. -func (s *Service) deregisterFromPastFork(currEpoch primitives.Epoch) error { - genRoot := s.cfg.clock.GenesisValidatorsRoot() - // This method takes care of the de-registration of - // old gossip pubsub handlers. Once we are at the epoch - // after the fork, we de-register from all the outdated topics. - currFork, err := forks.Fork(currEpoch) +// deregisterFromPastFork deregisters appropriate gossip and RPC topic if there is a fork in the current epoch. +func (s *Service) deregisterFromPastFork(currentEpoch primitives.Epoch) error { + // Extract the genesis validators root. + genesisValidatorsRoot := s.cfg.clock.GenesisValidatorsRoot() + + // Get the fork. + currentFork, err := forks.Fork(currentEpoch) if err != nil { - return err + return errors.Wrap(err, "genesis validators root") } - // If we are still in our genesis fork version then - // we simply exit early. - if currFork.Epoch == params.BeaconConfig().GenesisEpoch { + + // If we are still in our genesis fork version then exit early. + if currentFork.Epoch == params.BeaconConfig().GenesisEpoch { return nil } - epochAfterFork := currFork.Epoch + 1 - // If we are in the epoch after the fork, we start de-registering. - if epochAfterFork == currEpoch { - // Look at the previous fork's digest. - epochBeforeFork := currFork.Epoch - 1 - prevDigest, err := forks.ForkDigestFromEpoch(epochBeforeFork, genRoot[:]) - if err != nil { - return errors.Wrap(err, "Failed to determine previous epoch fork digest") - } - // Exit early if there are no topics with that particular - // digest. - if !s.subHandler.digestExists(prevDigest) { - return nil - } - prevFork, err := forks.Fork(epochBeforeFork) + // Get the epoch after the fork epoch. + afterForkEpoch := currentFork.Epoch + 1 + + // Start de-registering if the current epoch is after the fork epoch. + if currentEpoch != afterForkEpoch { + return nil + } + + // Look at the previous fork's digest. + beforeForkEpoch := currentFork.Epoch - 1 + + beforeForkDigest, err := forks.ForkDigestFromEpoch(beforeForkEpoch, genesisValidatorsRoot[:]) + if err != nil { + return errors.Wrap(err, "fork digest from epoch") + } + + // Exit early if there are no topics with that particular digest. + if !s.subHandler.digestExists(beforeForkDigest) { + return nil + } + + // Compute the RPC handlers that are no longer needed. + beforeForkHandlerByTopic, err := s.rpcHandlerByTopicFromEpoch(beforeForkEpoch) + if err != nil { + return errors.Wrap(err, "RPC handler by topic from before fork epoch") + } + + forkHandlerByTopic, err := s.rpcHandlerByTopicFromEpoch(currentFork.Epoch) + if err != nil { + return errors.Wrap(err, "RPC handler by topic from fork epoch") + } + + topicsToRemove := removedRPCTopics(beforeForkHandlerByTopic, forkHandlerByTopic) + for topic := range topicsToRemove { + fullTopic := topic + s.cfg.p2p.Encoding().ProtocolSuffix() + s.cfg.p2p.Host().RemoveStreamHandler(protocol.ID(fullTopic)) + log.WithField("topic", fullTopic).Debug("Removed RPC handler") + } + + // Run through all our current active topics and see + // if there are any subscriptions to be removed. + for _, t := range s.subHandler.allTopics() { + retDigest, err := p2p.ExtractGossipDigest(t) if err != nil { - return errors.Wrap(err, "failed to determine previous epoch fork data") - } - if prevFork.Epoch == params.BeaconConfig().GenesisEpoch { - s.unregisterPhase0Handlers() + log.WithError(err).Error("Could not retrieve digest") + continue } - // Run through all our current active topics and see - // if there are any subscriptions to be removed. - for _, t := range s.subHandler.allTopics() { - retDigest, err := p2p.ExtractGossipDigest(t) - if err != nil { - log.WithError(err).Error("Could not retrieve digest") - continue - } - if retDigest == prevDigest { - s.unSubscribeFromTopic(t) - } + if retDigest == beforeForkDigest { + s.unSubscribeFromTopic(t) } } + return nil } diff --git a/beacon-chain/sync/fork_watcher_test.go b/beacon-chain/sync/fork_watcher_test.go index 3f97fbd86eac..223117a6bc70 100644 --- a/beacon-chain/sync/fork_watcher_test.go +++ b/beacon-chain/sync/fork_watcher_test.go @@ -14,6 +14,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/network/forks" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" ) @@ -187,6 +188,94 @@ func TestService_CheckForNextEpochFork(t *testing.T) { assert.Equal(t, true, rpcMap[p2p.RPCBlobSidecarsByRootTopicV1+s.cfg.p2p.Encoding().ProtocolSuffix()], "topic doesn't exist") }, }, + { + name: "electra fork in the next epoch", + svcCreator: func(t *testing.T) *Service { + peer2peer := p2ptest.NewTestP2P(t) + gt := time.Now().Add(-4 * oneEpoch()) + vr := [32]byte{'A'} + chainService := &mockChain.ChainService{ + Genesis: gt, + ValidatorsRoot: vr, + } + bCfg := params.BeaconConfig().Copy() + bCfg.ElectraForkEpoch = 5 + params.OverrideBeaconConfig(bCfg) + params.BeaconConfig().InitializeForkSchedule() + ctx, cancel := context.WithCancel(context.Background()) + r := &Service{ + ctx: ctx, + cancel: cancel, + cfg: &config{ + p2p: peer2peer, + chain: chainService, + clock: startup.NewClock(gt, vr), + initialSync: &mockSync.Sync{IsSyncing: false}, + }, + chainStarted: abool.New(), + subHandler: newSubTopicHandler(), + } + return r + }, + currEpoch: 4, + wantErr: false, + postSvcCheck: func(t *testing.T, s *Service) { + genRoot := s.cfg.clock.GenesisValidatorsRoot() + digest, err := forks.ForkDigestFromEpoch(5, genRoot[:]) + assert.NoError(t, err) + assert.Equal(t, true, s.subHandler.digestExists(digest)) + rpcMap := make(map[string]bool) + for _, p := range s.cfg.p2p.Host().Mux().Protocols() { + rpcMap[string(p)] = true + } + assert.Equal(t, true, rpcMap[p2p.RPCBlobSidecarsByRangeTopicV1+s.cfg.p2p.Encoding().ProtocolSuffix()], "topic doesn't exist") + assert.Equal(t, true, rpcMap[p2p.RPCBlobSidecarsByRootTopicV1+s.cfg.p2p.Encoding().ProtocolSuffix()], "topic doesn't exist") + }, + }, + { + name: "fulu fork in the next epoch", + svcCreator: func(t *testing.T) *Service { + peer2peer := p2ptest.NewTestP2P(t) + gt := time.Now().Add(-4 * oneEpoch()) + vr := [32]byte{'A'} + chainService := &mockChain.ChainService{ + Genesis: gt, + ValidatorsRoot: vr, + } + bCfg := params.BeaconConfig().Copy() + bCfg.FuluForkEpoch = 5 + params.OverrideBeaconConfig(bCfg) + params.BeaconConfig().InitializeForkSchedule() + ctx, cancel := context.WithCancel(context.Background()) + r := &Service{ + ctx: ctx, + cancel: cancel, + cfg: &config{ + p2p: peer2peer, + chain: chainService, + clock: startup.NewClock(gt, vr), + initialSync: &mockSync.Sync{IsSyncing: false}, + }, + chainStarted: abool.New(), + subHandler: newSubTopicHandler(), + } + return r + }, + currEpoch: 4, + wantErr: false, + postSvcCheck: func(t *testing.T, s *Service) { + genRoot := s.cfg.clock.GenesisValidatorsRoot() + digest, err := forks.ForkDigestFromEpoch(5, genRoot[:]) + assert.NoError(t, err) + assert.Equal(t, true, s.subHandler.digestExists(digest)) + rpcMap := make(map[string]bool) + for _, p := range s.cfg.p2p.Host().Mux().Protocols() { + rpcMap[string(p)] = true + } + assert.Equal(t, true, rpcMap[p2p.RPCBlobSidecarsByRangeTopicV1+s.cfg.p2p.Encoding().ProtocolSuffix()], "topic doesn't exist") + assert.Equal(t, true, rpcMap[p2p.RPCBlobSidecarsByRootTopicV1+s.cfg.p2p.Encoding().ProtocolSuffix()], "topic doesn't exist") + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -230,7 +319,8 @@ func TestService_CheckForPreviousEpochFork(t *testing.T) { chainStarted: abool.New(), subHandler: newSubTopicHandler(), } - r.registerRPCHandlers() + err := r.registerRPCHandlers() + assert.NoError(t, err) return r }, currEpoch: 10, @@ -278,10 +368,21 @@ func TestService_CheckForPreviousEpochFork(t *testing.T) { prevGenesis := chainService.Genesis // To allow registration of v1 handlers chainService.Genesis = time.Now().Add(-1 * oneEpoch()) - r.registerRPCHandlers() + err := r.registerRPCHandlers() + assert.NoError(t, err) chainService.Genesis = prevGenesis - r.registerRPCHandlersAltair() + previous, err := r.rpcHandlerByTopicFromFork(version.Phase0) + assert.NoError(t, err) + + next, err := r.rpcHandlerByTopicFromFork(version.Altair) + assert.NoError(t, err) + + handlerByTopic := addedRPCHandlerByTopic(previous, next) + + for topic, handler := range handlerByTopic { + r.registerRPC(topic, handler) + } genRoot := r.cfg.clock.GenesisValidatorsRoot() digest, err := forks.ForkDigestFromEpoch(0, genRoot[:]) @@ -388,6 +489,7 @@ func TestService_CheckForPreviousEpochFork(t *testing.T) { } } +// oneEpoch returns the duration of one epoch. func oneEpoch() time.Duration { return time.Duration(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot)) * time.Second } diff --git a/beacon-chain/sync/genesis/BUILD.bazel b/beacon-chain/sync/genesis/BUILD.bazel index 22a55a88e5b0..5f6ae4840908 100644 --- a/beacon-chain/sync/genesis/BUILD.bazel +++ b/beacon-chain/sync/genesis/BUILD.bazel @@ -10,6 +10,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/genesis", visibility = ["//visibility:public"], deps = [ + "//api/client:go_default_library", "//api/client/beacon:go_default_library", "//beacon-chain/db:go_default_library", "//crypto/hash:go_default_library", diff --git a/beacon-chain/sync/genesis/api.go b/beacon-chain/sync/genesis/api.go index 643f857dba82..d34e18ef9290 100644 --- a/beacon-chain/sync/genesis/api.go +++ b/beacon-chain/sync/genesis/api.go @@ -4,6 +4,7 @@ import ( "context" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/api/client" "github.com/prysmaticlabs/prysm/v5/api/client/beacon" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db" ) @@ -17,7 +18,7 @@ type APIInitializer struct { // NewAPIInitializer creates an APIInitializer, handling the set up of a beacon node api client // using the provided host string. func NewAPIInitializer(beaconNodeHost string) (*APIInitializer, error) { - c, err := beacon.NewClient(beaconNodeHost) + c, err := beacon.NewClient(beaconNodeHost, client.WithMaxBodySize(client.MaxBodySizeState)) if err != nil { return nil, errors.Wrapf(err, "unable to parse beacon node url or hostname - %s", beaconNodeHost) } diff --git a/beacon-chain/sync/initial-sync/BUILD.bazel b/beacon-chain/sync/initial-sync/BUILD.bazel index 3d4ab052ec1e..7926aae88d06 100644 --- a/beacon-chain/sync/initial-sync/BUILD.bazel +++ b/beacon-chain/sync/initial-sync/BUILD.bazel @@ -39,6 +39,7 @@ go_library( "//container/leaky-bucket:go_default_library", "//crypto/rand:go_default_library", "//math:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime:go_default_library", "//runtime/version:go_default_library", @@ -48,7 +49,6 @@ go_library( "@com_github_paulbellamy_ratecounter//:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) @@ -85,7 +85,6 @@ go_test( "//beacon-chain/verification:go_default_library", "//cmd/beacon-chain/flags:go_default_library", "//config/features:go_default_library", - "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher.go b/beacon-chain/sync/initial-sync/blocks_fetcher.go index 915826801ed7..b79352bbff2c 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher.go @@ -20,17 +20,16 @@ import ( "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - blocks2 "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" leakybucket "github.com/prysmaticlabs/prysm/v5/container/leaky-bucket" "github.com/prysmaticlabs/prysm/v5/crypto/rand" "github.com/prysmaticlabs/prysm/v5/math" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" p2ppb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) const ( @@ -123,7 +122,7 @@ type fetchRequestResponse struct { pid peer.ID start primitives.Slot count uint64 - bwb []blocks2.BlockWithROBlobs + bwb []blocks.BlockWithROBlobs err error } @@ -289,7 +288,7 @@ func (f *blocksFetcher) handleRequest(ctx context.Context, start primitives.Slot response := &fetchRequestResponse{ start: start, count: count, - bwb: []blocks2.BlockWithROBlobs{}, + bwb: []blocks.BlockWithROBlobs{}, err: nil, } @@ -330,7 +329,7 @@ func (f *blocksFetcher) fetchBlocksFromPeer( ctx context.Context, start primitives.Slot, count uint64, peers []peer.ID, -) ([]blocks2.BlockWithROBlobs, peer.ID, error) { +) ([]blocks.BlockWithROBlobs, peer.ID, error) { ctx, span := trace.StartSpan(ctx, "initialsync.fetchBlocksFromPeer") defer span.End() @@ -363,16 +362,16 @@ func (f *blocksFetcher) fetchBlocksFromPeer( return nil, "", errNoPeersAvailable } -func sortedBlockWithVerifiedBlobSlice(blocks []interfaces.ReadOnlySignedBeaconBlock) ([]blocks2.BlockWithROBlobs, error) { - rb := make([]blocks2.BlockWithROBlobs, len(blocks)) - for i, b := range blocks { - ro, err := blocks2.NewROBlock(b) +func sortedBlockWithVerifiedBlobSlice(bs []interfaces.ReadOnlySignedBeaconBlock) ([]blocks.BlockWithROBlobs, error) { + rb := make([]blocks.BlockWithROBlobs, len(bs)) + for i, b := range bs { + ro, err := blocks.NewROBlock(b) if err != nil { return nil, err } - rb[i] = blocks2.BlockWithROBlobs{Block: ro} + rb[i] = blocks.BlockWithROBlobs{Block: ro} } - sort.Sort(blocks2.BlockWithROBlobsSlice(rb)) + sort.Sort(blocks.BlockWithROBlobsSlice(rb)) return rb, nil } @@ -386,7 +385,7 @@ type commitmentCountList []commitmentCount // countCommitments makes a list of all blocks that have commitments that need to be satisfied. // This gives us a representation to finish building the request that is lightweight and readable for testing. -func countCommitments(bwb []blocks2.BlockWithROBlobs, retentionStart primitives.Slot) commitmentCountList { +func countCommitments(bwb []blocks.BlockWithROBlobs, retentionStart primitives.Slot) commitmentCountList { if len(bwb) == 0 { return nil } @@ -468,7 +467,7 @@ func (r *blobRange) Request() *p2ppb.BlobSidecarsByRangeRequest { var errBlobVerification = errors.New("peer unable to serve aligned BlobSidecarsByRange and BeaconBlockSidecarsByRange responses") var errMissingBlobsForBlockCommitments = errors.Wrap(errBlobVerification, "blobs unavailable for processing block with kzg commitments") -func verifyAndPopulateBlobs(bwb []blocks2.BlockWithROBlobs, blobs []blocks.ROBlob, req *p2ppb.BlobSidecarsByRangeRequest, bss filesystem.BlobStorageSummarizer) ([]blocks2.BlockWithROBlobs, error) { +func verifyAndPopulateBlobs(bwb []blocks.BlockWithROBlobs, blobs []blocks.ROBlob, req *p2ppb.BlobSidecarsByRangeRequest, bss filesystem.BlobStorageSummarizer) ([]blocks.BlockWithROBlobs, error) { blobsByRoot := make(map[[32]byte][]blocks.ROBlob) for i := range blobs { if blobs[i].Slot() < req.StartSlot { @@ -492,7 +491,7 @@ func verifyAndPopulateBlobs(bwb []blocks2.BlockWithROBlobs, blobs []blocks.ROBlo var errDidntPopulate = errors.New("skipping population of block") -func populateBlock(bw blocks2.BlockWithROBlobs, blobs []blocks.ROBlob, req *p2ppb.BlobSidecarsByRangeRequest, bss filesystem.BlobStorageSummarizer) (blocks2.BlockWithROBlobs, error) { +func populateBlock(bw blocks.BlockWithROBlobs, blobs []blocks.ROBlob, req *p2ppb.BlobSidecarsByRangeRequest, bss filesystem.BlobStorageSummarizer) (blocks.BlockWithROBlobs, error) { blk := bw.Block if blk.Version() < version.Deneb || blk.Block().Slot() < req.StartSlot { return bw, errDidntPopulate @@ -530,7 +529,7 @@ func missingCommitError(root [32]byte, slot primitives.Slot, missing [][]byte) e } // fetchBlobsFromPeer fetches blocks from a single randomly selected peer. -func (f *blocksFetcher) fetchBlobsFromPeer(ctx context.Context, bwb []blocks2.BlockWithROBlobs, pid peer.ID, peers []peer.ID) ([]blocks2.BlockWithROBlobs, error) { +func (f *blocksFetcher) fetchBlobsFromPeer(ctx context.Context, bwb []blocks.BlockWithROBlobs, pid peer.ID, peers []peer.ID) ([]blocks.BlockWithROBlobs, error) { ctx, span := trace.StartSpan(ctx, "initialsync.fetchBlobsFromPeer") defer span.End() if slots.ToEpoch(f.clock.CurrentSlot()) < params.BeaconConfig().DenebForkEpoch { diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher_peers.go b/beacon-chain/sync/initial-sync/blocks_fetcher_peers.go index fd83ead9c585..ddb9c39cfd36 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher_peers.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher_peers.go @@ -11,10 +11,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/v5/config/params" mathutil "github.com/prysmaticlabs/prysm/v5/math" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" prysmTime "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // peerLock returns peer lock for a given peer. If lock is not found, it is created. diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher_test.go b/beacon-chain/sync/initial-sync/blocks_fetcher_test.go index e60f951b51a5..5a890f7c20d2 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher_test.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher_test.go @@ -20,7 +20,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" beaconsync "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" @@ -1083,7 +1082,7 @@ func TestCommitmentCountList(t *testing.T) { name: "nil bss, sparse slots", cc: []commitmentCount{ {slot: 11235, count: 1}, - {slot: 11240, count: fieldparams.MaxBlobsPerBlock}, + {slot: 11240, count: params.BeaconConfig().MaxBlobsPerBlock(0)}, {slot: 11250, count: 3}, }, expected: &blobRange{low: 11235, high: 11250}, @@ -1100,7 +1099,7 @@ func TestCommitmentCountList(t *testing.T) { }, cc: []commitmentCount{ {slot: 0, count: 3, root: bytesutil.ToBytes32([]byte("0"))}, - {slot: 5, count: fieldparams.MaxBlobsPerBlock, root: bytesutil.ToBytes32([]byte("1"))}, + {slot: 5, count: params.BeaconConfig().MaxBlobsPerBlock(0), root: bytesutil.ToBytes32([]byte("1"))}, {slot: 15, count: 3}, }, expected: &blobRange{low: 0, high: 15}, @@ -1118,7 +1117,7 @@ func TestCommitmentCountList(t *testing.T) { cc: []commitmentCount{ {slot: 0, count: 2, root: bytesutil.ToBytes32([]byte("0"))}, {slot: 5, count: 3}, - {slot: 15, count: fieldparams.MaxBlobsPerBlock, root: bytesutil.ToBytes32([]byte("2"))}, + {slot: 15, count: params.BeaconConfig().MaxBlobsPerBlock(0), root: bytesutil.ToBytes32([]byte("2"))}, }, expected: &blobRange{low: 5, high: 5}, request: ðpb.BlobSidecarsByRangeRequest{StartSlot: 5, Count: 1}, @@ -1136,7 +1135,7 @@ func TestCommitmentCountList(t *testing.T) { {slot: 0, count: 2, root: bytesutil.ToBytes32([]byte("0"))}, {slot: 5, count: 3}, {slot: 6, count: 3}, - {slot: 15, count: fieldparams.MaxBlobsPerBlock, root: bytesutil.ToBytes32([]byte("2"))}, + {slot: 15, count: params.BeaconConfig().MaxBlobsPerBlock(0), root: bytesutil.ToBytes32([]byte("2"))}, }, expected: &blobRange{low: 5, high: 6}, request: ðpb.BlobSidecarsByRangeRequest{StartSlot: 5, Count: 2}, @@ -1155,7 +1154,7 @@ func TestCommitmentCountList(t *testing.T) { {slot: 0, count: 2, root: bytesutil.ToBytes32([]byte("0"))}, {slot: 5, count: 3, root: bytesutil.ToBytes32([]byte("1"))}, {slot: 10, count: 3}, - {slot: 15, count: fieldparams.MaxBlobsPerBlock, root: bytesutil.ToBytes32([]byte("2"))}, + {slot: 15, count: params.BeaconConfig().MaxBlobsPerBlock(0), root: bytesutil.ToBytes32([]byte("2"))}, }, expected: &blobRange{low: 5, high: 10}, request: ðpb.BlobSidecarsByRangeRequest{StartSlot: 5, Count: 6}, diff --git a/beacon-chain/sync/initial-sync/blocks_fetcher_utils.go b/beacon-chain/sync/initial-sync/blocks_fetcher_utils.go index dcdaf161ab94..e1ebb8f2e218 100644 --- a/beacon-chain/sync/initial-sync/blocks_fetcher_utils.go +++ b/beacon-chain/sync/initial-sync/blocks_fetcher_utils.go @@ -12,10 +12,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" p2ppb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // forkData represents alternative chain path supported by a given peer. diff --git a/beacon-chain/sync/initial-sync/blocks_queue_test.go b/beacon-chain/sync/initial-sync/blocks_queue_test.go index 8a2ba65f517a..0d96cef82ab4 100644 --- a/beacon-chain/sync/initial-sync/blocks_queue_test.go +++ b/beacon-chain/sync/initial-sync/blocks_queue_test.go @@ -1094,7 +1094,7 @@ func TestBlocksQueue_stuckInUnfavourableFork(t *testing.T) { // its claims with actual blocks. emptyPeer := connectPeerHavingBlocks(t, p2p, chain1, finalizedSlot, p2p.Peers()) defer func() { - p2p.Peers().SetConnectionState(emptyPeer, peers.PeerDisconnected) + p2p.Peers().SetConnectionState(emptyPeer, peers.Disconnected) }() chainState, err := p2p.Peers().ChainState(emptyPeer) require.NoError(t, err) @@ -1291,7 +1291,7 @@ func TestBlocksQueue_stuckWhenHeadIsSetToOrphanedBlock(t *testing.T) { // Connect peer that has all the blocks available. allBlocksPeer := connectPeerHavingBlocks(t, p2p, chain, finalizedSlot, p2p.Peers()) defer func() { - p2p.Peers().SetConnectionState(allBlocksPeer, peers.PeerDisconnected) + p2p.Peers().SetConnectionState(allBlocksPeer, peers.Disconnected) }() // Queue should be able to fetch whole chain (including slot which comes before the currently set head). diff --git a/beacon-chain/sync/initial-sync/initial_sync_test.go b/beacon-chain/sync/initial-sync/initial_sync_test.go index 306370f279f4..30d72bb6944f 100644 --- a/beacon-chain/sync/initial-sync/initial_sync_test.go +++ b/beacon-chain/sync/initial-sync/initial_sync_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "os" "sync" "testing" "time" @@ -70,7 +71,7 @@ func TestMain(m *testing.M) { flags.Init(resetFlags) }() - m.Run() + os.Exit(m.Run()) } func initializeTestServices(t *testing.T, slots []primitives.Slot, peers []*peerData) (*mock.ChainService, *p2pt.TestP2P, db.Database) { @@ -227,7 +228,7 @@ func connectPeer(t *testing.T, host *p2pt.TestP2P, datum *peerData, peerStatus * p.Connect(host) peerStatus.Add(new(enr.Record), p.PeerID(), nil, network.DirOutbound) - peerStatus.SetConnectionState(p.PeerID(), peers.PeerConnected) + peerStatus.SetConnectionState(p.PeerID(), peers.Connected) peerStatus.SetChainState(p.PeerID(), ðpb.Status{ ForkDigest: params.BeaconConfig().GenesisForkVersion, FinalizedRoot: []byte(fmt.Sprintf("finalized_root %d", datum.finalizedEpoch)), @@ -326,7 +327,7 @@ func connectPeerHavingBlocks( require.NoError(t, err) peerStatus.Add(new(enr.Record), p.PeerID(), nil, network.DirOutbound) - peerStatus.SetConnectionState(p.PeerID(), peers.PeerConnected) + peerStatus.SetConnectionState(p.PeerID(), peers.Connected) peerStatus.SetChainState(p.PeerID(), ðpb.Status{ ForkDigest: params.BeaconConfig().GenesisForkVersion, FinalizedRoot: []byte(fmt.Sprintf("finalized_root %d", finalizedEpoch)), diff --git a/beacon-chain/sync/initial-sync/round_robin.go b/beacon-chain/sync/initial-sync/round_robin.go index 5d96478148f5..220527336cb0 100644 --- a/beacon-chain/sync/initial-sync/round_robin.go +++ b/beacon-chain/sync/initial-sync/round_robin.go @@ -11,7 +11,6 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v5/beacon-chain/das" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" @@ -70,14 +69,6 @@ func (s *Service) startBlocksQueue(ctx context.Context, highestSlot primitives.S return nil, errors.Wrapf(err, "unable to initialize context version map using genesis validator root = %#x", vr) } - summarizer, err := s.cfg.BlobStorage.WaitForSummarizer(ctx) - if err != nil { - // The summarizer is an optional optimization, we can continue without, only stop if there is a different error. - if !errors.Is(err, filesystem.ErrBlobStorageSummarizerUnavailable) { - return nil, err - } - summarizer = nil // This should already be nil, but we'll set it just to be safe. - } cfg := &blocksQueueConfig{ p2p: s.cfg.P2P, db: s.cfg.DB, @@ -86,7 +77,7 @@ func (s *Service) startBlocksQueue(ctx context.Context, highestSlot primitives.S ctxMap: ctxMap, highestExpectedSlot: highestSlot, mode: mode, - bs: summarizer, + bs: s.cfg.BlobStorage, } queue := newBlocksQueue(ctx, cfg) if err := queue.start(); err != nil { @@ -172,7 +163,7 @@ func (s *Service) processFetchedDataRegSync( if len(bwb) == 0 { return } - bv := verification.NewBlobBatchVerifier(s.newBlobVerifier, verification.InitsyncSidecarRequirements) + bv := verification.NewBlobBatchVerifier(s.newBlobVerifier, verification.InitsyncBlobSidecarRequirements) avs := das.NewLazilyPersistentStore(s.cfg.BlobStorage, bv) batchFields := logrus.Fields{ "firstSlot": data.bwb[0].Block.Block().Slot(), @@ -331,7 +322,7 @@ func (s *Service) processBatchedBlocks(ctx context.Context, genesis time.Time, errParentDoesNotExist, first.Block().ParentRoot(), first.Block().Slot()) } - bv := verification.NewBlobBatchVerifier(s.newBlobVerifier, verification.InitsyncSidecarRequirements) + bv := verification.NewBlobBatchVerifier(s.newBlobVerifier, verification.InitsyncBlobSidecarRequirements) avs := das.NewLazilyPersistentStore(s.cfg.BlobStorage, bv) s.logBatchSyncStatus(genesis, first, len(bwb)) for _, bb := range bwb { diff --git a/beacon-chain/sync/initial-sync/service.go b/beacon-chain/sync/initial-sync/service.go index e79b22a07720..0fa2bf6f336c 100644 --- a/beacon-chain/sync/initial-sync/service.go +++ b/beacon-chain/sync/initial-sync/service.go @@ -292,13 +292,10 @@ func missingBlobRequest(blk blocks.ROBlock, store *filesystem.BlobStorage) (p2pt if len(cmts) == 0 { return nil, nil } - onDisk, err := store.Indices(r) - if err != nil { - return nil, errors.Wrapf(err, "error checking existing blobs for checkpoint sync block root %#x", r) - } + onDisk := store.Summary(r) req := make(p2ptypes.BlobSidecarsByRootReq, 0, len(cmts)) for i := range cmts { - if onDisk[i] { + if onDisk.HasIndex(uint64(i)) { continue } req = append(req, ð.BlobIdentifier{BlockRoot: r[:], Index: uint64(i)}) @@ -333,14 +330,14 @@ func (s *Service) fetchOriginBlobs(pids []peer.ID) error { } shufflePeers(pids) for i := range pids { - sidecars, err := sync.SendBlobSidecarByRoot(s.ctx, s.clock, s.cfg.P2P, pids[i], s.ctxMap, &req) + sidecars, err := sync.SendBlobSidecarByRoot(s.ctx, s.clock, s.cfg.P2P, pids[i], s.ctxMap, &req, rob.Block().Slot()) if err != nil { continue } if len(sidecars) != len(req) { continue } - bv := verification.NewBlobBatchVerifier(s.newBlobVerifier, verification.InitsyncSidecarRequirements) + bv := verification.NewBlobBatchVerifier(s.newBlobVerifier, verification.InitsyncBlobSidecarRequirements) avs := das.NewLazilyPersistentStore(s.cfg.BlobStorage, bv) current := s.clock.CurrentSlot() if err := avs.Persist(current, sidecars...); err != nil { diff --git a/beacon-chain/sync/initial-sync/service_test.go b/beacon-chain/sync/initial-sync/service_test.go index cccb99bc080b..612e3b865bb2 100644 --- a/beacon-chain/sync/initial-sync/service_test.go +++ b/beacon-chain/sync/initial-sync/service_test.go @@ -464,7 +464,7 @@ func TestMissingBlobRequest(t *testing.T) { setup: func(t *testing.T) (blocks.ROBlock, *filesystem.BlobStorage) { bk, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 2) bm, fs := filesystem.NewEphemeralBlobStorageWithMocker(t) - require.NoError(t, bm.CreateFakeIndices(bk.Root(), 1)) + require.NoError(t, bm.CreateFakeIndices(bk.Root(), bk.Block().Slot(), 1)) return bk, fs }, nReq: 1, @@ -474,7 +474,7 @@ func TestMissingBlobRequest(t *testing.T) { setup: func(t *testing.T) (blocks.ROBlock, *filesystem.BlobStorage) { bk, _ := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 2) bm, fs := filesystem.NewEphemeralBlobStorageWithMocker(t) - require.NoError(t, bm.CreateFakeIndices(bk.Root(), 0, 1)) + require.NoError(t, bm.CreateFakeIndices(bk.Root(), bk.Block().Slot(), 0, 1)) return bk, fs }, nReq: 0, @@ -495,8 +495,8 @@ func TestOriginOutsideRetention(t *testing.T) { bdb := dbtest.SetupDB(t) genesis := time.Unix(0, 0) secsPerEpoch := params.BeaconConfig().SecondsPerSlot * uint64(params.BeaconConfig().SlotsPerEpoch) - retentionSeconds := time.Second * time.Duration(uint64(params.BeaconConfig().MinEpochsForBlobsSidecarsRequest+1)*secsPerEpoch) - outsideRetention := genesis.Add(retentionSeconds) + retentionPeriod := time.Second * time.Duration(uint64(params.BeaconConfig().MinEpochsForBlobsSidecarsRequest+1)*secsPerEpoch) + outsideRetention := genesis.Add(retentionPeriod) now := func() time.Time { return outsideRetention } diff --git a/beacon-chain/sync/metrics.go b/beacon-chain/sync/metrics.go index 07502117a458..af7a73d1a5c8 100644 --- a/beacon-chain/sync/metrics.go +++ b/beacon-chain/sync/metrics.go @@ -170,6 +170,20 @@ var ( Help: "The number of blob sidecars that were dropped due to missing parent block", }, ) + + blobRecoveredFromELTotal = promauto.NewCounter( + prometheus.CounterOpts{ + Name: "blob_recovered_from_el_total", + Help: "Count the number of times blobs have been recovered from the execution layer.", + }, + ) + + blobExistedInDBTotal = promauto.NewCounter( + prometheus.CounterOpts{ + Name: "blob_existed_in_db_total", + Help: "Count the number of times blobs have been found in the database.", + }, + ) ) func (s *Service) updateMetrics() { diff --git a/beacon-chain/sync/options.go b/beacon-chain/sync/options.go index 9b0281ea667f..e29903f9312c 100644 --- a/beacon-chain/sync/options.go +++ b/beacon-chain/sync/options.go @@ -2,6 +2,7 @@ package sync import ( "github.com/prysmaticlabs/prysm/v5/async/event" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" blockfeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/block" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" @@ -43,6 +44,13 @@ func WithDatabase(db db.NoHeadAccessDatabase) Option { } } +func WithAttestationCache(c *cache.AttestationCache) Option { + return func(s *Service) error { + s.cfg.attestationCache = c + return nil + } +} + func WithAttestationPool(attPool attestations.Pool) Option { return func(s *Service) error { s.cfg.attPool = attPool @@ -127,9 +135,9 @@ func WithSlasherBlockHeadersFeed(slasherBlockHeadersFeed *event.Feed) Option { } } -func WithPayloadReconstructor(r execution.PayloadReconstructor) Option { +func WithReconstructor(r execution.Reconstructor) Option { return func(s *Service) error { - s.cfg.executionPayloadReconstructor = r + s.cfg.executionReconstructor = r return nil } } diff --git a/beacon-chain/sync/pending_attestations_queue.go b/beacon-chain/sync/pending_attestations_queue.go index f827d4fd6b11..7d9d3137e182 100644 --- a/beacon-chain/sync/pending_attestations_queue.go +++ b/beacon-chain/sync/pending_attestations_queue.go @@ -9,16 +9,19 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/prysmaticlabs/prysm/v5/async" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/rand" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // This defines how often a node cleans up and processes pending attestations in the queue. @@ -90,71 +93,146 @@ func (s *Service) processPendingAtts(ctx context.Context) error { func (s *Service) processAttestations(ctx context.Context, attestations []ethpb.SignedAggregateAttAndProof) { for _, signedAtt := range attestations { - aggregate := signedAtt.AggregateAttestationAndProof().AggregateVal() - data := aggregate.GetData() + att := signedAtt.AggregateAttestationAndProof().AggregateVal() // The pending attestations can arrive in both aggregated and unaggregated forms, // each from has distinct validation steps. - if helpers.IsAggregated(aggregate) { - // Save the pending aggregated attestation to the pool if it passes the aggregated - // validation steps. - valRes, err := s.validateAggregatedAtt(ctx, signedAtt) - if err != nil { - log.WithError(err).Debug("Pending aggregated attestation failed validation") - } - aggValid := pubsub.ValidationAccept == valRes - if s.validateBlockInAttestation(ctx, signedAtt) && aggValid { - if err := s.cfg.attPool.SaveAggregatedAttestation(aggregate); err != nil { - log.WithError(err).Debug("Could not save aggregate attestation") - continue - } - s.setAggregatorIndexEpochSeen(data.Target.Epoch, signedAtt.AggregateAttestationAndProof().GetAggregatorIndex()) - - // Broadcasting the signed attestation again once a node is able to process it. - if err := s.cfg.p2p.Broadcast(ctx, signedAtt); err != nil { - log.WithError(err).Debug("Could not broadcast") - } - } + if att.IsAggregated() { + s.processAggregated(ctx, signedAtt) } else { - // This is an important validation before retrieving attestation pre state to defend against - // attestation's target intentionally reference checkpoint that's long ago. - // Verify current finalized checkpoint is an ancestor of the block defined by the attestation's beacon block root. - if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { - log.WithError(blockchain.ErrNotDescendantOfFinalized).Debug("Could not verify finalized consistency") - continue - } - if err := s.cfg.chain.VerifyLmdFfgConsistency(ctx, aggregate); err != nil { - log.WithError(err).Debug("Could not verify FFG consistency") - continue + s.processUnaggregated(ctx, att) + } + } +} + +func (s *Service) processAggregated(ctx context.Context, att ethpb.SignedAggregateAttAndProof) { + aggregate := att.AggregateAttestationAndProof().AggregateVal() + + // Save the pending aggregated attestation to the pool if it passes the aggregated + // validation steps. + valRes, err := s.validateAggregatedAtt(ctx, att) + if err != nil { + log.WithError(err).Debug("Pending aggregated attestation failed validation") + } + aggValid := pubsub.ValidationAccept == valRes + if s.validateBlockInAttestation(ctx, att) && aggValid { + if features.Get().EnableExperimentalAttestationPool { + if err = s.cfg.attestationCache.Add(aggregate); err != nil { + log.WithError(err).Debug("Could not save aggregate attestation") + return } - preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) - if err != nil { - log.WithError(err).Debug("Could not retrieve attestation prestate") - continue + } else { + if err := s.cfg.attPool.SaveAggregatedAttestation(aggregate); err != nil { + log.WithError(err).Debug("Could not save aggregate attestation") + return } + } - valid, err := s.validateUnaggregatedAttWithState(ctx, aggregate, preState) - if err != nil { - log.WithError(err).Debug("Pending unaggregated attestation failed validation") - continue + s.setAggregatorIndexEpochSeen(aggregate.GetData().Target.Epoch, att.AggregateAttestationAndProof().GetAggregatorIndex()) + + // Broadcasting the signed attestation again once a node is able to process it. + if err := s.cfg.p2p.Broadcast(ctx, att); err != nil { + log.WithError(err).Debug("Could not broadcast") + } + } +} + +func (s *Service) processUnaggregated(ctx context.Context, att ethpb.Att) { + data := att.GetData() + + // This is an important validation before retrieving attestation pre state to defend against + // attestation's target intentionally reference checkpoint that's long ago. + // Verify current finalized checkpoint is an ancestor of the block defined by the attestation's beacon block root. + if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { + log.WithError(blockchain.ErrNotDescendantOfFinalized).Debug("Could not verify finalized consistency") + return + } + if err := s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { + log.WithError(err).Debug("Could not verify FFG consistency") + return + } + preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) + if err != nil { + log.WithError(err).Debug("Could not retrieve attestation prestate") + return + } + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, data.Slot, att.GetCommitteeIndex()) + if err != nil { + log.WithError(err).Debug("Could not retrieve committee from state") + return + } + valid, err := validateAttesterData(ctx, att, committee) + if err != nil { + log.WithError(err).Debug("Could not validate attester data") + return + } else if valid != pubsub.ValidationAccept { + log.Debug("Attestation failed attester data validation") + return + } + + var singleAtt *ethpb.SingleAttestation + if att.Version() >= version.Electra { + var ok bool + singleAtt, ok = att.(*ethpb.SingleAttestation) + if !ok { + log.Debugf("Attestation has wrong type (expected %T, got %T)", ðpb.SingleAttestation{}, att) + return + } + att = singleAtt.ToAttestationElectra(committee) + } + + valid, err = s.validateUnaggregatedAttWithState(ctx, att, preState) + if err != nil { + log.WithError(err).Debug("Pending unaggregated attestation failed validation") + return + } + if valid == pubsub.ValidationAccept { + if features.Get().EnableExperimentalAttestationPool { + if err = s.cfg.attestationCache.Add(att); err != nil { + log.WithError(err).Debug("Could not save unaggregated attestation") + return } - if valid == pubsub.ValidationAccept { - if err := s.cfg.attPool.SaveUnaggregatedAttestation(aggregate); err != nil { - log.WithError(err).Debug("Could not save unaggregated attestation") - continue - } - s.setSeenCommitteeIndicesSlot(data.Slot, data.CommitteeIndex, aggregate.GetAggregationBits()) - - valCount, err := helpers.ActiveValidatorCount(ctx, preState, slots.ToEpoch(data.Slot)) - if err != nil { - log.WithError(err).Debug("Could not retrieve active validator count") - continue - } - // Broadcasting the signed attestation again once a node is able to process it. - if err := s.cfg.p2p.BroadcastAttestation(ctx, helpers.ComputeSubnetForAttestation(valCount, aggregate), aggregate); err != nil { - log.WithError(err).Debug("Could not broadcast") - } + } else { + if err := s.cfg.attPool.SaveUnaggregatedAttestation(att); err != nil { + log.WithError(err).Debug("Could not save unaggregated attestation") + return } } + s.setSeenCommitteeIndicesSlot(data.Slot, data.CommitteeIndex, att.GetAggregationBits()) + + valCount, err := helpers.ActiveValidatorCount(ctx, preState, slots.ToEpoch(data.Slot)) + if err != nil { + log.WithError(err).Debug("Could not retrieve active validator count") + return + } + + // Broadcasting the signed attestation again once a node is able to process it. + var attToBroadcast ethpb.Att + if singleAtt != nil { + attToBroadcast = singleAtt + } else { + attToBroadcast = att + } + if err := s.cfg.p2p.BroadcastAttestation(ctx, helpers.ComputeSubnetForAttestation(valCount, attToBroadcast), attToBroadcast); err != nil { + log.WithError(err).Debug("Could not broadcast") + } + + // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node + // of a received unaggregated attestation. + if singleAtt != nil { + s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.SingleAttReceived, + Data: &operation.SingleAttReceivedData{ + Attestation: singleAtt, + }, + }) + } else { + s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.UnaggregatedAttReceived, + Data: &operation.UnAggregatedAttReceivedData{ + Attestation: att, + }, + }) + } } } @@ -195,6 +273,10 @@ func (s *Service) savePendingAtt(att ethpb.SignedAggregateAttAndProof) { } func attsAreEqual(a, b ethpb.SignedAggregateAttAndProof) bool { + if a.Version() != b.Version() { + return false + } + if a.GetSignature() != nil { return b.GetSignature() != nil && a.AggregateAttestationAndProof().GetAggregatorIndex() == b.AggregateAttestationAndProof().GetAggregatorIndex() } @@ -212,6 +294,12 @@ func attsAreEqual(a, b ethpb.SignedAggregateAttAndProof) bool { } if a.Version() >= version.Electra { + if aAggregate.IsSingle() != bAggregate.IsSingle() { + return false + } + if aAggregate.IsSingle() && aAggregate.GetAttestingIndex() != bAggregate.GetAttestingIndex() { + return false + } if !bytes.Equal(aAggregate.CommitteeBitsVal().Bytes(), bAggregate.CommitteeBitsVal().Bytes()) { return false } diff --git a/beacon-chain/sync/pending_attestations_queue_test.go b/beacon-chain/sync/pending_attestations_queue_test.go index 6a7e7077a116..551f2e21784b 100644 --- a/beacon-chain/sync/pending_attestations_queue_test.go +++ b/beacon-chain/sync/pending_attestations_queue_test.go @@ -2,6 +2,7 @@ package sync import ( "context" + "sync" "testing" "time" @@ -10,6 +11,8 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/async/abool" mock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" dbtest "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" @@ -40,7 +43,7 @@ func TestProcessPendingAtts_NoBlockRequestBlock(t *testing.T) { p1.Connect(p2) assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected") p1.Peers().Add(new(enr.Record), p2.PeerID(), nil, network.DirOutbound) - p1.Peers().SetConnectionState(p2.PeerID(), peers.PeerConnected) + p1.Peers().SetConnectionState(p2.PeerID(), peers.Connected) p1.Peers().SetChainState(p2.PeerID(), ðpb.Status{}) chain := &mock.ChainService{Genesis: prysmTime.Now(), FinalizedCheckPoint: ðpb.Checkpoint{}} @@ -92,18 +95,9 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) { att.Signature = privKeys[i].Sign(hashTreeRoot[:]).Marshal() } - // Arbitrary aggregator index for testing purposes. - aggregatorIndex := committee[0] - sszUint := primitives.SSZUint64(att.Data.Slot) - sig, err := signing.ComputeDomainAndSign(beaconState, 0, &sszUint, params.BeaconConfig().DomainSelectionProof, privKeys[aggregatorIndex]) - require.NoError(t, err) aggregateAndProof := ðpb.AggregateAttestationAndProof{ - SelectionProof: sig, - Aggregate: att, - AggregatorIndex: aggregatorIndex, + Aggregate: att, } - aggreSig, err := signing.ComputeDomainAndSign(beaconState, 0, aggregateAndProof, params.BeaconConfig().DomainAggregateAndProof, privKeys[aggregatorIndex]) - require.NoError(t, err) require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix()))) @@ -114,15 +108,22 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) { Epoch: 0, }, } + + done := make(chan *feed.Event, 1) + defer close(done) + opn := mock.NewEventFeedWrapper() + sub := opn.Subscribe(done) + defer sub.Unsubscribe() ctx, cancel := context.WithCancel(context.Background()) r := &Service{ ctx: ctx, cfg: &config{ - p2p: p1, - beaconDB: db, - chain: chain, - clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), - attPool: attestations.NewPool(), + p2p: p1, + beaconDB: db, + chain: chain, + clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), + attPool: attestations.NewPool(), + attestationNotifier: &mock.SimpleNotifier{Feed: opn}, }, blkRootToPendingAtts: make(map[[32]byte][]ethpb.SignedAggregateAttAndProof), seenUnAggregatedAttestationCache: lruwrpr.New(10), @@ -134,15 +135,126 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) { require.NoError(t, err) require.NoError(t, r.cfg.beaconDB.SaveState(context.Background(), s, root)) - r.blkRootToPendingAtts[root] = []ethpb.SignedAggregateAttAndProof{ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof, Signature: aggreSig}} + r.blkRootToPendingAtts[root] = []ethpb.SignedAggregateAttAndProof{ðpb.SignedAggregateAttestationAndProof{Message: aggregateAndProof}} require.NoError(t, r.processPendingAtts(context.Background())) + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case received := <-done: + // make sure a single att was sent + require.Equal(t, operation.UnaggregatedAttReceived, int(received.Type)) + return + case <-ctx.Done(): + return + } + } + }() atts, err := r.cfg.attPool.UnaggregatedAttestations() require.NoError(t, err) assert.Equal(t, 1, len(atts), "Did not save unaggregated att") assert.DeepEqual(t, att, atts[0], "Incorrect saved att") assert.Equal(t, 0, len(r.cfg.attPool.AggregatedAttestations()), "Did save aggregated att") require.LogsContain(t, hook, "Verified and saved pending attestations to pool") + wg.Wait() + cancel() +} + +func TestProcessPendingAtts_HasBlockSaveUnAggregatedAttElectra(t *testing.T) { + hook := logTest.NewGlobal() + db := dbtest.SetupDB(t) + p1 := p2ptest.NewTestP2P(t) + validators := uint64(256) + + beaconState, privKeys := util.DeterministicGenesisStateElectra(t, validators) + + sb := util.NewBeaconBlockElectra() + util.SaveBlock(t, context.Background(), db, sb) + root, err := sb.Block.HashTreeRoot() + require.NoError(t, err) + + att := ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + BeaconBlockRoot: root[:], + Source: ðpb.Checkpoint{Epoch: 0, Root: bytesutil.PadTo([]byte("hello-world"), 32)}, + Target: ðpb.Checkpoint{Epoch: 0, Root: root[:]}, + }, + } + aggregateAndProof := ðpb.AggregateAttestationAndProofSingle{ + Aggregate: att, + } + + committee, err := helpers.BeaconCommitteeFromState(context.Background(), beaconState, att.Data.Slot, att.Data.CommitteeIndex) + assert.NoError(t, err) + att.AttesterIndex = committee[0] + attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot()) + require.NoError(t, err) + hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain) + assert.NoError(t, err) + att.Signature = privKeys[committee[0]].Sign(hashTreeRoot[:]).Marshal() + + require.NoError(t, beaconState.SetGenesisTime(uint64(time.Now().Unix()))) + + chain := &mock.ChainService{Genesis: time.Now(), + State: beaconState, + FinalizedCheckPoint: ðpb.Checkpoint{ + Root: aggregateAndProof.Aggregate.Data.BeaconBlockRoot, + Epoch: 0, + }, + } + done := make(chan *feed.Event, 1) + defer close(done) + opn := mock.NewEventFeedWrapper() + sub := opn.Subscribe(done) + defer sub.Unsubscribe() + ctx, cancel := context.WithCancel(context.Background()) + r := &Service{ + ctx: ctx, + cfg: &config{ + p2p: p1, + beaconDB: db, + chain: chain, + clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), + attPool: attestations.NewPool(), + attestationNotifier: &mock.SimpleNotifier{Feed: opn}, + }, + blkRootToPendingAtts: make(map[[32]byte][]ethpb.SignedAggregateAttAndProof), + seenUnAggregatedAttestationCache: lruwrpr.New(10), + signatureChan: make(chan *signatureVerifier, verifierLimit), + } + go r.verifierRoutine() + + s, err := util.NewBeaconStateElectra() + require.NoError(t, err) + require.NoError(t, r.cfg.beaconDB.SaveState(context.Background(), s, root)) + + r.blkRootToPendingAtts[root] = []ethpb.SignedAggregateAttAndProof{ðpb.SignedAggregateAttestationAndProofSingle{Message: aggregateAndProof}} + require.NoError(t, r.processPendingAtts(context.Background())) + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case received := <-done: + // make sure a single att was sent + require.Equal(t, operation.SingleAttReceived, int(received.Type)) + return + case <-ctx.Done(): + return + } + } + }() + atts, err := r.cfg.attPool.UnaggregatedAttestations() + require.NoError(t, err) + require.Equal(t, 1, len(atts), "Did not save unaggregated att") + assert.DeepEqual(t, att.ToAttestationElectra(committee), atts[0], "Incorrect saved att") + assert.Equal(t, 0, len(r.cfg.attPool.AggregatedAttestations()), "Did save aggregated att") + require.LogsContain(t, hook, "Verified and saved pending attestations to pool") + wg.Wait() cancel() } @@ -239,11 +351,12 @@ func TestProcessPendingAtts_NoBroadcastWithBadSignature(t *testing.T) { r = &Service{ ctx: ctx, cfg: &config{ - p2p: p1, - beaconDB: db, - chain: chain2, - clock: startup.NewClock(chain2.Genesis, chain2.ValidatorsRoot), - attPool: attestations.NewPool(), + p2p: p1, + beaconDB: db, + chain: chain2, + clock: startup.NewClock(chain2.Genesis, chain2.ValidatorsRoot), + attPool: attestations.NewPool(), + attestationNotifier: &mock.MockOperationNotifier{}, }, blkRootToPendingAtts: make(map[[32]byte][]ethpb.SignedAggregateAttAndProof), seenUnAggregatedAttestationCache: lruwrpr.New(10), @@ -465,12 +578,12 @@ func Test_attsAreEqual_Committee(t *testing.T) { Message: ðpb.AggregateAttestationAndProof{ Aggregate: ðpb.Attestation{ Data: ðpb.AttestationData{ - CommitteeIndex: 123}}}} + CommitteeIndex: 0}}}} att2 := ðpb.SignedAggregateAttestationAndProof{ Message: ðpb.AggregateAttestationAndProof{ Aggregate: ðpb.Attestation{ Data: ðpb.AttestationData{ - CommitteeIndex: 123}}}} + CommitteeIndex: 0}}}} assert.Equal(t, true, attsAreEqual(att1, att2)) }) t.Run("Phase 0 not equal", func(t *testing.T) { @@ -478,12 +591,12 @@ func Test_attsAreEqual_Committee(t *testing.T) { Message: ðpb.AggregateAttestationAndProof{ Aggregate: ðpb.Attestation{ Data: ðpb.AttestationData{ - CommitteeIndex: 123}}}} + CommitteeIndex: 0}}}} att2 := ðpb.SignedAggregateAttestationAndProof{ Message: ðpb.AggregateAttestationAndProof{ Aggregate: ðpb.Attestation{ Data: ðpb.AttestationData{ - CommitteeIndex: 456}}}} + CommitteeIndex: 1}}}} assert.Equal(t, false, attsAreEqual(att1, att2)) }) t.Run("Electra equal", func(t *testing.T) { @@ -524,4 +637,72 @@ func Test_attsAreEqual_Committee(t *testing.T) { }}} assert.Equal(t, false, attsAreEqual(att1, att2)) }) + t.Run("Single and Electra not equal", func(t *testing.T) { + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(0, true) + att1 := ðpb.SignedAggregateAttestationAndProofElectra{ + Message: ðpb.AggregateAttestationAndProofElectra{ + Aggregate: ðpb.AttestationElectra{ + Data: ðpb.AttestationData{}, + CommitteeBits: cb, + }}} + att2 := ðpb.SignedAggregateAttestationAndProofSingle{ + Message: ðpb.AggregateAttestationAndProofSingle{ + Aggregate: ðpb.SingleAttestation{ + CommitteeId: 0, + AttesterIndex: 0, + Data: ðpb.AttestationData{}, + }, + }, + } + assert.Equal(t, false, attsAreEqual(att1, att2)) + }) + t.Run("Single equal", func(t *testing.T) { + att1 := ðpb.SignedAggregateAttestationAndProofSingle{ + Message: ðpb.AggregateAttestationAndProofSingle{ + Aggregate: ðpb.SingleAttestation{ + CommitteeId: 0, + AttesterIndex: 0, + Data: ðpb.AttestationData{}, + }, + }, + } + att2 := ðpb.SignedAggregateAttestationAndProofSingle{ + Message: ðpb.AggregateAttestationAndProofSingle{ + Aggregate: ðpb.SingleAttestation{ + CommitteeId: 0, + AttesterIndex: 0, + Data: ðpb.AttestationData{}, + }, + }, + } + assert.Equal(t, true, attsAreEqual(att1, att2)) + }) + t.Run("Single not equal", func(t *testing.T) { + // Same AttesterIndex but different CommitteeId + att1 := ðpb.SignedAggregateAttestationAndProofSingle{ + Message: ðpb.AggregateAttestationAndProofSingle{ + Aggregate: ðpb.SingleAttestation{ + CommitteeId: 0, + AttesterIndex: 0, + Data: ðpb.AttestationData{}, + }, + }, + } + att2 := ðpb.SignedAggregateAttestationAndProofSingle{ + Message: ðpb.AggregateAttestationAndProofSingle{ + Aggregate: ðpb.SingleAttestation{ + CommitteeId: 1, + AttesterIndex: 0, + Data: ðpb.AttestationData{}, + }, + }, + } + assert.Equal(t, false, attsAreEqual(att1, att2)) + + // Same CommitteeId but different AttesterIndex + att2.Message.Aggregate.CommitteeId = 0 + att2.Message.Aggregate.AttesterIndex = 1 + assert.Equal(t, false, attsAreEqual(att1, att2)) + }) } diff --git a/beacon-chain/sync/pending_blocks_queue.go b/beacon-chain/sync/pending_blocks_queue.go index 698ee4572654..0268e0765c36 100644 --- a/beacon-chain/sync/pending_blocks_queue.go +++ b/beacon-chain/sync/pending_blocks_queue.go @@ -21,10 +21,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/encoding/ssz/equality" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + prysmTrace "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" "github.com/trailofbits/go-mutexasserts" - "go.opencensus.io/trace" + "go.opentelemetry.io/otel/trace" ) var processPendingBlocksPeriod = slots.DivideSlotBy(3 /* times per slot */) @@ -52,7 +53,7 @@ func (s *Service) processPendingBlocksQueue() { // processPendingBlocks validates, processes, and broadcasts pending blocks. func (s *Service) processPendingBlocks(ctx context.Context) error { - ctx, span := trace.StartSpan(ctx, "processPendingBlocks") + ctx, span := prysmTrace.StartSpan(ctx, "processPendingBlocks") defer span.End() // Remove old blocks from our expiration cache. @@ -66,7 +67,7 @@ func (s *Service) processPendingBlocks(ctx context.Context) error { // Sort slots for ordered processing. sortedSlots := s.sortedPendingSlots() - span.AddAttributes(trace.Int64Attribute("numSlots", int64(len(sortedSlots))), trace.Int64Attribute("numPeers", int64(len(s.cfg.p2p.Peers().Connected())))) + span.SetAttributes(prysmTrace.Int64Attribute("numSlots", int64(len(sortedSlots))), prysmTrace.Int64Attribute("numPeers", int64(len(s.cfg.p2p.Peers().Connected())))) randGen := rand.NewGenerator() var parentRoots [][32]byte @@ -157,9 +158,9 @@ func (s *Service) processPendingBlocks(ctx context.Context) error { } // startInnerSpan starts a new tracing span for an inner loop and returns the new context and span. -func startInnerSpan(ctx context.Context, slot primitives.Slot) (context.Context, *trace.Span) { - ctx, span := trace.StartSpan(ctx, "processPendingBlocks.InnerLoop") - span.AddAttributes(trace.Int64Attribute("slot", int64(slot))) // lint:ignore uintcast -- This conversion is OK for tracing. +func startInnerSpan(ctx context.Context, slot primitives.Slot) (context.Context, trace.Span) { + ctx, span := prysmTrace.StartSpan(ctx, "processPendingBlocks.InnerLoop") + span.SetAttributes(prysmTrace.Int64Attribute("slot", int64(slot))) // lint:ignore uintcast -- This conversion is OK for tracing. return ctx, span } @@ -254,7 +255,7 @@ func (s *Service) getBestPeers() []core.PeerID { func (s *Service) checkIfBlockIsBad( ctx context.Context, - span *trace.Span, + span trace.Span, slot primitives.Slot, b interfaces.ReadOnlySignedBeaconBlock, blkRoot [32]byte, @@ -282,7 +283,7 @@ func (s *Service) checkIfBlockIsBad( } func (s *Service) sendBatchRootRequest(ctx context.Context, roots [][32]byte, randGen *rand.Rand) error { - ctx, span := trace.StartSpan(ctx, "sendBatchRootRequest") + ctx, span := prysmTrace.StartSpan(ctx, "sendBatchRootRequest") defer span.End() roots = dedupRoots(roots) @@ -314,7 +315,7 @@ func (s *Service) sendBatchRootRequest(ctx context.Context, roots [][32]byte, ra if uint64(len(roots)) > maxReqBlock { req = roots[:maxReqBlock] } - if err := s.sendRecentBeaconBlocksRequest(ctx, &req, pid); err != nil { + if err := s.sendBeaconBlocksRequest(ctx, &req, pid); err != nil { tracing.AnnotateError(span, err) log.WithError(err).Debug("Could not send recent block request") } diff --git a/beacon-chain/sync/pending_blocks_queue_test.go b/beacon-chain/sync/pending_blocks_queue_test.go index 3e367b214691..6eef5bcac80b 100644 --- a/beacon-chain/sync/pending_blocks_queue_test.go +++ b/beacon-chain/sync/pending_blocks_queue_test.go @@ -406,7 +406,7 @@ func TestRegularSyncBeaconBlockSubscriber_ProcessPendingBlocks_2Chains(t *testin r.initCaches() p1.Peers().Add(new(enr.Record), p2.PeerID(), nil, network.DirOutbound) - p1.Peers().SetConnectionState(p2.PeerID(), peers.PeerConnected) + p1.Peers().SetConnectionState(p2.PeerID(), peers.Connected) p1.Peers().SetChainState(p2.PeerID(), ðpb.Status{}) b0 := util.NewBeaconBlock() @@ -505,7 +505,7 @@ func TestRegularSyncBeaconBlockSubscriber_PruneOldPendingBlocks(t *testing.T) { r.initCaches() p1.Peers().Add(new(enr.Record), p1.PeerID(), nil, network.DirOutbound) - p1.Peers().SetConnectionState(p1.PeerID(), peers.PeerConnected) + p1.Peers().SetConnectionState(p1.PeerID(), peers.Connected) p1.Peers().SetChainState(p1.PeerID(), ðpb.Status{}) b0 := util.NewBeaconBlock() @@ -611,7 +611,7 @@ func TestService_BatchRootRequest(t *testing.T) { r.initCaches() p1.Peers().Add(new(enr.Record), p2.PeerID(), nil, network.DirOutbound) - p1.Peers().SetConnectionState(p2.PeerID(), peers.PeerConnected) + p1.Peers().SetConnectionState(p2.PeerID(), peers.Connected) p1.Peers().SetChainState(p2.PeerID(), ðpb.Status{FinalizedEpoch: 2}) b0 := util.NewBeaconBlock() diff --git a/beacon-chain/sync/rate_limiter.go b/beacon-chain/sync/rate_limiter.go index 636fe54c685e..5d088f5002a1 100644 --- a/beacon-chain/sync/rate_limiter.go +++ b/beacon-chain/sync/rate_limiter.go @@ -7,12 +7,13 @@ import ( "github.com/libp2p/go-libp2p/core/network" "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/trailofbits/go-mutexasserts" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" p2ptypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/types" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" leakybucket "github.com/prysmaticlabs/prysm/v5/container/leaky-bucket" - "github.com/sirupsen/logrus" - "github.com/trailofbits/go-mutexasserts" ) const defaultBurstLimit = 5 @@ -98,19 +99,20 @@ func (l *limiter) validateRequest(stream network.Stream, amt uint64) error { defer l.RUnlock() topic := string(stream.Protocol()) + remotePeer := stream.Conn().RemotePeer() collector, err := l.retrieveCollector(topic) if err != nil { return err } - key := stream.Conn().RemotePeer().String() - remaining := collector.Remaining(key) + + remaining := collector.Remaining(remotePeer.String()) // Treat each request as a minimum of 1. if amt == 0 { amt = 1 } if amt > uint64(remaining) { - l.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) + l.p2p.Peers().Scorers().BadResponsesScorer().Increment(remotePeer) writeErrorResponseToStream(responseCodeInvalidRequest, p2ptypes.ErrRateLimited.Error(), stream, l.p2p) return p2ptypes.ErrRateLimited } diff --git a/beacon-chain/sync/rate_limiter_test.go b/beacon-chain/sync/rate_limiter_test.go index a45d769bb654..653581103147 100644 --- a/beacon-chain/sync/rate_limiter_test.go +++ b/beacon-chain/sync/rate_limiter_test.go @@ -97,7 +97,7 @@ func TestRateLimiter_ExceedRawCapacity(t *testing.T) { for i := 0; i < defaultBurstLimit; i++ { assert.ErrorContains(t, p2ptypes.ErrRateLimited.Error(), rlimiter.validateRawRpcRequest(stream)) } - assert.Equal(t, true, p1.Peers().IsBad(p2.PeerID()), "peer is not marked as a bad peer") + assert.NotNil(t, p1.Peers().IsBad(p2.PeerID()), "peer is not marked as a bad peer") require.NoError(t, stream.Close(), "could not close stream") if util.WaitTimeout(&wg, 1*time.Second) { diff --git a/beacon-chain/sync/rpc.go b/beacon-chain/sync/rpc.go index 7ada5cc609f3..956803f9d401 100644 --- a/beacon-chain/sync/rpc.go +++ b/beacon-chain/sync/rpc.go @@ -9,116 +9,168 @@ import ( libp2pcore "github.com/libp2p/go-libp2p/core" "github.com/libp2p/go-libp2p/core/network" - "github.com/libp2p/go-libp2p/core/protocol" "github.com/pkg/errors" ssz "github.com/prysmaticlabs/fastssz" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" p2ptypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/types" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) -// Time to first byte timeout. The maximum time to wait for first byte of -// request response (time-to-first-byte). The client is expected to give up if -// they don't receive the first byte within 5 seconds. -var ttfbTimeout = params.BeaconConfig().TtfbTimeoutDuration() +var ( + // Time to first byte timeout. The maximum time to wait for first byte of + // request response (time-to-first-byte). The client is expected to give up if + // they don't receive the first byte within 5 seconds. + ttfbTimeout = params.BeaconConfig().TtfbTimeoutDuration() -// respTimeout is the maximum time for complete response transfer. -var respTimeout = params.BeaconConfig().RespTimeoutDuration() + // respTimeout is the maximum time for complete response transfer. + respTimeout = params.BeaconConfig().RespTimeoutDuration() +) // rpcHandler is responsible for handling and responding to any incoming message. // This method may return an error to internal monitoring, but the error will // not be relayed to the peer. type rpcHandler func(context.Context, interface{}, libp2pcore.Stream) error -// registerRPCHandlers for p2p RPC. -func (s *Service) registerRPCHandlers() { - currEpoch := slots.ToEpoch(s.cfg.clock.CurrentSlot()) - // Register V2 handlers if we are past altair fork epoch. - if currEpoch >= params.BeaconConfig().AltairForkEpoch { - s.registerRPC( - p2p.RPCStatusTopicV1, - s.statusRPCHandler, - ) - s.registerRPC( - p2p.RPCGoodByeTopicV1, - s.goodbyeRPCHandler, - ) - s.registerRPC( - p2p.RPCPingTopicV1, - s.pingHandler, - ) - s.registerRPCHandlersAltair() - if currEpoch >= params.BeaconConfig().DenebForkEpoch { - s.registerRPCHandlersDeneb() - } - return +// rpcHandlerByTopicFromFork returns the RPC handlers for a given fork index. +func (s *Service) rpcHandlerByTopicFromFork(forkIndex int) (map[string]rpcHandler, error) { + // Electra: https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/p2p-interface.md#messages + if forkIndex >= version.Electra { + return map[string]rpcHandler{ + p2p.RPCStatusTopicV1: s.statusRPCHandler, + p2p.RPCGoodByeTopicV1: s.goodbyeRPCHandler, + p2p.RPCBlocksByRangeTopicV2: s.beaconBlocksByRangeRPCHandler, + p2p.RPCBlocksByRootTopicV2: s.beaconBlocksRootRPCHandler, + p2p.RPCPingTopicV1: s.pingHandler, + p2p.RPCMetaDataTopicV2: s.metaDataHandler, + p2p.RPCBlobSidecarsByRootTopicV1: s.blobSidecarByRootRPCHandler, // Modified in Electra + p2p.RPCBlobSidecarsByRangeTopicV1: s.blobSidecarsByRangeRPCHandler, // Modified in Electra + }, nil + } + + // Deneb: https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/p2p-interface.md#messages + if forkIndex >= version.Deneb { + return map[string]rpcHandler{ + p2p.RPCStatusTopicV1: s.statusRPCHandler, + p2p.RPCGoodByeTopicV1: s.goodbyeRPCHandler, + p2p.RPCBlocksByRangeTopicV2: s.beaconBlocksByRangeRPCHandler, // Modified in Deneb + p2p.RPCBlocksByRootTopicV2: s.beaconBlocksRootRPCHandler, // Modified in Deneb + p2p.RPCPingTopicV1: s.pingHandler, + p2p.RPCMetaDataTopicV2: s.metaDataHandler, + p2p.RPCBlobSidecarsByRootTopicV1: s.blobSidecarByRootRPCHandler, // Added in Deneb + p2p.RPCBlobSidecarsByRangeTopicV1: s.blobSidecarsByRangeRPCHandler, // Added in Deneb + }, nil + } + + // Capella: https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/p2p-interface.md#messages + // Bellatrix: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/p2p-interface.md#messages + // Altair: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/p2p-interface.md#messages + if forkIndex >= version.Altair { + return map[string]rpcHandler{ + p2p.RPCStatusTopicV1: s.statusRPCHandler, + p2p.RPCGoodByeTopicV1: s.goodbyeRPCHandler, + p2p.RPCBlocksByRangeTopicV2: s.beaconBlocksByRangeRPCHandler, // Updated in Altair and modified in Capella + p2p.RPCBlocksByRootTopicV2: s.beaconBlocksRootRPCHandler, // Updated in Altair and modified in Capella + p2p.RPCPingTopicV1: s.pingHandler, + p2p.RPCMetaDataTopicV2: s.metaDataHandler, // Updated in Altair + }, nil + } + + // PhaseO: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#messages + if forkIndex >= version.Phase0 { + return map[string]rpcHandler{ + p2p.RPCStatusTopicV1: s.statusRPCHandler, + p2p.RPCGoodByeTopicV1: s.goodbyeRPCHandler, + p2p.RPCBlocksByRangeTopicV1: s.beaconBlocksByRangeRPCHandler, + p2p.RPCBlocksByRootTopicV1: s.beaconBlocksRootRPCHandler, + p2p.RPCPingTopicV1: s.pingHandler, + p2p.RPCMetaDataTopicV1: s.metaDataHandler, + }, nil + } + + return nil, errors.Errorf("RPC handler not found for fork index %d", forkIndex) +} + +// rpcHandlerByTopic returns the RPC handlers for a given epoch. +func (s *Service) rpcHandlerByTopicFromEpoch(epoch primitives.Epoch) (map[string]rpcHandler, error) { + // Get the beacon config. + beaconConfig := params.BeaconConfig() + + if epoch >= beaconConfig.FuluForkEpoch { + return s.rpcHandlerByTopicFromFork(version.Fulu) + } + + if epoch >= beaconConfig.ElectraForkEpoch { + return s.rpcHandlerByTopicFromFork(version.Electra) + } + + if epoch >= beaconConfig.DenebForkEpoch { + return s.rpcHandlerByTopicFromFork(version.Deneb) + } + + if epoch >= beaconConfig.CapellaForkEpoch { + return s.rpcHandlerByTopicFromFork(version.Capella) + } + + if epoch >= beaconConfig.BellatrixForkEpoch { + return s.rpcHandlerByTopicFromFork(version.Bellatrix) + } + + if epoch >= beaconConfig.AltairForkEpoch { + return s.rpcHandlerByTopicFromFork(version.Altair) } - s.registerRPC( - p2p.RPCStatusTopicV1, - s.statusRPCHandler, - ) - s.registerRPC( - p2p.RPCGoodByeTopicV1, - s.goodbyeRPCHandler, - ) - s.registerRPC( - p2p.RPCBlocksByRangeTopicV1, - s.beaconBlocksByRangeRPCHandler, - ) - s.registerRPC( - p2p.RPCBlocksByRootTopicV1, - s.beaconBlocksRootRPCHandler, - ) - s.registerRPC( - p2p.RPCPingTopicV1, - s.pingHandler, - ) - s.registerRPC( - p2p.RPCMetaDataTopicV1, - s.metaDataHandler, - ) + + return s.rpcHandlerByTopicFromFork(version.Phase0) } -// registerRPCHandlers for altair. -func (s *Service) registerRPCHandlersAltair() { - s.registerRPC( - p2p.RPCBlocksByRangeTopicV2, - s.beaconBlocksByRangeRPCHandler, - ) - s.registerRPC( - p2p.RPCBlocksByRootTopicV2, - s.beaconBlocksRootRPCHandler, - ) - s.registerRPC( - p2p.RPCMetaDataTopicV2, - s.metaDataHandler, - ) +// addedRPCHandlerByTopic returns the RPC handlers that are added in the new map that are not present in the old map. +func addedRPCHandlerByTopic(previous, next map[string]rpcHandler) map[string]rpcHandler { + added := make(map[string]rpcHandler) + + for topic, handler := range next { + if _, ok := previous[topic]; !ok { + added[topic] = handler + } + } + + return added } -func (s *Service) registerRPCHandlersDeneb() { - s.registerRPC( - p2p.RPCBlobSidecarsByRangeTopicV1, - s.blobSidecarsByRangeRPCHandler, - ) - s.registerRPC( - p2p.RPCBlobSidecarsByRootTopicV1, - s.blobSidecarByRootRPCHandler, - ) +// removedTopics returns the topics that are removed in the new map that are not present in the old map. +func removedRPCTopics(previous, next map[string]rpcHandler) map[string]bool { + removed := make(map[string]bool) + + for topic := range previous { + if _, ok := next[topic]; !ok { + removed[topic] = true + } + } + + return removed } -// Remove all v1 Stream handlers that are no longer supported -// from altair onwards. -func (s *Service) unregisterPhase0Handlers() { - fullBlockRangeTopic := p2p.RPCBlocksByRangeTopicV1 + s.cfg.p2p.Encoding().ProtocolSuffix() - fullBlockRootTopic := p2p.RPCBlocksByRootTopicV1 + s.cfg.p2p.Encoding().ProtocolSuffix() - fullMetadataTopic := p2p.RPCMetaDataTopicV1 + s.cfg.p2p.Encoding().ProtocolSuffix() +// registerRPCHandlers for p2p RPC. +func (s *Service) registerRPCHandlers() error { + // Get the current epoch. + currentSlot := s.cfg.clock.CurrentSlot() + currentEpoch := slots.ToEpoch(currentSlot) + + // Get the RPC handlers for the current epoch. + handlerByTopic, err := s.rpcHandlerByTopicFromEpoch(currentEpoch) + if err != nil { + return errors.Wrap(err, "rpc handler by topic from epoch") + } - s.cfg.p2p.Host().RemoveStreamHandler(protocol.ID(fullBlockRangeTopic)) - s.cfg.p2p.Host().RemoveStreamHandler(protocol.ID(fullBlockRootTopic)) - s.cfg.p2p.Host().RemoveStreamHandler(protocol.ID(fullMetadataTopic)) + // Register the RPC handlers for the current epoch. + for topic, handler := range handlerByTopic { + s.registerRPC(topic, handler) + } + + return nil } // registerRPC for a given topic with an expected protobuf message type. @@ -138,6 +190,9 @@ func (s *Service) registerRPC(baseTopic string, handle rpcHandler) { ctx, cancel := context.WithTimeout(s.ctx, ttfbTimeout) defer cancel() + conn := stream.Conn() + remotePeer := conn.RemotePeer() + // Resetting after closing is a no-op so defer a reset in case something goes wrong. // It's up to the handler to Close the stream (send an EOF) if // it successfully writes a response. We don't blindly call @@ -156,13 +211,13 @@ func (s *Service) registerRPC(baseTopic string, handle rpcHandler) { ctx, span := trace.StartSpan(ctx, "sync.rpc") defer span.End() - span.AddAttributes(trace.StringAttribute("topic", topic)) - span.AddAttributes(trace.StringAttribute("peer", stream.Conn().RemotePeer().String())) + span.SetAttributes(trace.StringAttribute("topic", topic)) + span.SetAttributes(trace.StringAttribute("peer", remotePeer.String())) log := log.WithField("peer", stream.Conn().RemotePeer().String()).WithField("topic", string(stream.Protocol())) // Check before hand that peer is valid. - if s.cfg.p2p.Peers().IsBad(stream.Conn().RemotePeer()) { - if err := s.sendGoodByeAndDisconnect(ctx, p2ptypes.GoodbyeCodeBanned, stream.Conn().RemotePeer()); err != nil { + if err := s.cfg.p2p.Peers().IsBad(remotePeer); err != nil { + if err := s.sendGoodByeAndDisconnect(ctx, p2ptypes.GoodbyeCodeBanned, remotePeer); err != nil { log.WithError(err).Debug("Could not disconnect from peer") } return @@ -248,6 +303,7 @@ func (s *Service) registerRPC(baseTopic string, handle rpcHandler) { } } }) + log.Debug("Registered new RPC handler") } func logStreamErrors(err error, topic string) { diff --git a/beacon-chain/sync/rpc_beacon_blocks_by_range.go b/beacon-chain/sync/rpc_beacon_blocks_by_range.go index 0236b22681d7..77ab4a19f705 100644 --- a/beacon-chain/sync/rpc_beacon_blocks_by_range.go +++ b/beacon-chain/sync/rpc_beacon_blocks_by_range.go @@ -13,9 +13,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" + "github.com/sirupsen/logrus" ) // beaconBlocksByRangeRPCHandler looks up the request blocks from the database from a given start block. @@ -26,21 +27,34 @@ func (s *Service) beaconBlocksByRangeRPCHandler(ctx context.Context, msg interfa defer cancel() SetRPCStreamDeadlines(stream) + remotePeer := stream.Conn().RemotePeer() + m, ok := msg.(*pb.BeaconBlocksByRangeRequest) if !ok { return errors.New("message is not type *pb.BeaconBlockByRangeRequest") } - log.WithField("startSlot", m.StartSlot).WithField("count", m.Count).Debug("Serving block by range request") + + log.WithFields(logrus.Fields{ + "startSlot": m.StartSlot, + "count": m.Count, + "peer": remotePeer, + }).Debug("Serving block by range request") + rp, err := validateRangeRequest(m, s.cfg.clock.CurrentSlot()) if err != nil { s.writeErrorResponseToStream(responseCodeInvalidRequest, err.Error(), stream) - s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) + s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(remotePeer) tracing.AnnotateError(span, err) return err } available := s.validateRangeAvailability(rp) if !available { - log.Debug("error in validating range availability") + log.WithFields(logrus.Fields{ + "startSlot": rp.start, + "endSlot": rp.end, + "size": rp.size, + "current": s.cfg.clock.CurrentSlot(), + }).Debug("error in validating range availability") s.writeErrorResponseToStream(responseCodeResourceUnavailable, p2ptypes.ErrResourceUnavailable.Error(), stream) tracing.AnnotateError(span, err) return nil @@ -50,12 +64,12 @@ func (s *Service) beaconBlocksByRangeRPCHandler(ctx context.Context, msg interfa if err != nil { return err } - remainingBucketCapacity := blockLimiter.Remaining(stream.Conn().RemotePeer().String()) - span.AddAttributes( + remainingBucketCapacity := blockLimiter.Remaining(remotePeer.String()) + span.SetAttributes( trace.Int64Attribute("start", int64(rp.start)), // lint:ignore uintcast -- This conversion is OK for tracing. trace.Int64Attribute("end", int64(rp.end)), // lint:ignore uintcast -- This conversion is OK for tracing. trace.Int64Attribute("count", int64(m.Count)), - trace.StringAttribute("peer", stream.Conn().RemotePeer().String()), + trace.StringAttribute("peer", remotePeer.String()), trace.Int64Attribute("remaining_capacity", remainingBucketCapacity), ) @@ -82,12 +96,19 @@ func (s *Service) beaconBlocksByRangeRPCHandler(ctx context.Context, msg interfa } rpcBlocksByRangeResponseLatency.Observe(float64(time.Since(batchStart).Milliseconds())) } + if err := batch.error(); err != nil { - log.WithError(err).Debug("error in BlocksByRange batch") - s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream) + log.WithError(err).Debug("Serving block by range request - BlocksByRange batch") + + // If a rate limit is hit, it means an error response has already been sent and the stream has been closed. + if !errors.Is(err, p2ptypes.ErrRateLimited) { + s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream) + } + tracing.AnnotateError(span, err) return err } + closeStream(stream, log) return nil } @@ -160,7 +181,7 @@ func (s *Service) writeBlockBatchToStream(ctx context.Context, batch blockBatch, return nil } - reconstructed, err := s.cfg.executionPayloadReconstructor.ReconstructFullBellatrixBlockBatch(ctx, blinded) + reconstructed, err := s.cfg.executionReconstructor.ReconstructFullBellatrixBlockBatch(ctx, blinded) if err != nil { log.WithError(err).Error("Could not reconstruct full bellatrix block batch from blinded bodies") return err diff --git a/beacon-chain/sync/rpc_beacon_blocks_by_range_test.go b/beacon-chain/sync/rpc_beacon_blocks_by_range_test.go index 55e838718ab0..0178425a2c28 100644 --- a/beacon-chain/sync/rpc_beacon_blocks_by_range_test.go +++ b/beacon-chain/sync/rpc_beacon_blocks_by_range_test.go @@ -239,11 +239,11 @@ func TestRPCBeaconBlocksByRange_ReconstructsPayloads(t *testing.T) { // Start service with 160 as allowed blocks capacity (and almost zero capacity recovery). r := &Service{ cfg: &config{ - p2p: p1, - beaconDB: d, - chain: &chainMock.ChainService{}, - clock: clock, - executionPayloadReconstructor: mockEngine, + p2p: p1, + beaconDB: d, + chain: &chainMock.ChainService{}, + clock: clock, + executionReconstructor: mockEngine, }, rateLimiter: newRateLimiter(p1), availableBlocker: mockBlocker{avail: true}, @@ -433,11 +433,12 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) { } sendRequest := func(p1, p2 *p2ptest.TestP2P, r *Service, req *ethpb.BeaconBlocksByRangeRequest, validateBlocks bool, success bool) error { - var wg sync.WaitGroup - wg.Add(1) pcl := protocol.ID(p2p.RPCBlocksByRangeTopicV1) + reqAnswered := false p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) { - defer wg.Done() + defer func() { + reqAnswered = true + }() if !validateBlocks { return } @@ -458,9 +459,8 @@ func TestRPCBeaconBlocksByRange_RPCHandlerRateLimitOverflow(t *testing.T) { if err := r.beaconBlocksByRangeRPCHandler(context.Background(), req, stream); err != nil { return err } - if util.WaitTimeout(&wg, 1*time.Second) { - t.Fatal("Did not receive stream within 1 sec") - } + time.Sleep(100 * time.Millisecond) + assert.Equal(t, reqAnswered, true) return nil } diff --git a/beacon-chain/sync/rpc_beacon_blocks_by_root.go b/beacon-chain/sync/rpc_beacon_blocks_by_root.go index ad1ffe83d292..b95c59716af7 100644 --- a/beacon-chain/sync/rpc_beacon_blocks_by_root.go +++ b/beacon-chain/sync/rpc_beacon_blocks_by_root.go @@ -7,11 +7,11 @@ import ( libp2pcore "github.com/libp2p/go-libp2p/core" "github.com/libp2p/go-libp2p/core/peer" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/verify" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" @@ -20,9 +20,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/time/slots" ) -// sendRecentBeaconBlocksRequest sends a recent beacon blocks request to a peer to get +// sendBeaconBlocksRequest sends a recent beacon blocks request to a peer to get // those corresponding blocks from that peer. -func (s *Service) sendRecentBeaconBlocksRequest(ctx context.Context, requests *types.BeaconBlockByRootsReq, id peer.ID) error { +func (s *Service) sendBeaconBlocksRequest(ctx context.Context, requests *types.BeaconBlockByRootsReq, id peer.ID) error { ctx, cancel := context.WithTimeout(ctx, respTimeout) defer cancel() @@ -112,7 +112,7 @@ func (s *Service) beaconBlocksRootRPCHandler(ctx context.Context, msg interface{ } if blk.Block().IsBlinded() { - blk, err = s.cfg.executionPayloadReconstructor.ReconstructFullBlock(ctx, blk) + blk, err = s.cfg.executionReconstructor.ReconstructFullBlock(ctx, blk) if err != nil { if errors.Is(err, execution.ErrEmptyBlockHash) { log.WithError(err).Warn("Could not reconstruct block from header with syncing execution client. Waiting to complete syncing") @@ -139,7 +139,7 @@ func (s *Service) sendAndSaveBlobSidecars(ctx context.Context, request types.Blo return nil } - sidecars, err := SendBlobSidecarByRoot(ctx, s.cfg.clock, s.cfg.p2p, peerID, s.ctxMap, &request) + sidecars, err := SendBlobSidecarByRoot(ctx, s.cfg.clock, s.cfg.p2p, peerID, s.ctxMap, &request, block.Block().Slot()) if err != nil { return err } @@ -151,7 +151,7 @@ func (s *Service) sendAndSaveBlobSidecars(ctx context.Context, request types.Blo if len(sidecars) != len(request) { return fmt.Errorf("received %d blob sidecars, expected %d for RPC", len(sidecars), len(request)) } - bv := verification.NewBlobBatchVerifier(s.newBlobVerifier, verification.PendingQueueSidecarRequirements) + bv := verification.NewBlobBatchVerifier(s.newBlobVerifier, verification.PendingQueueBlobSidecarRequirements) for _, sidecar := range sidecars { if err := verify.BlobAlignsWithBlock(sidecar, RoBlock); err != nil { return err @@ -189,21 +189,18 @@ func (s *Service) constructPendingBlobsRequest(root [32]byte, commitments int) ( if commitments == 0 { return nil, nil } - stored, err := s.cfg.blobStorage.Indices(root) - if err != nil { - return nil, err - } + summary := s.cfg.blobStorage.Summary(root) - return requestsForMissingIndices(stored, commitments, root), nil + return requestsForMissingIndices(summary, commitments, root), nil } // requestsForMissingIndices constructs a slice of BlobIdentifiers that are missing from // local storage, based on a mapping that represents which indices are locally stored, // and the highest expected index. -func requestsForMissingIndices(storedIndices [fieldparams.MaxBlobsPerBlock]bool, commitments int, root [32]byte) []*eth.BlobIdentifier { +func requestsForMissingIndices(stored filesystem.BlobStorageSummary, commitments int, root [32]byte) []*eth.BlobIdentifier { var ids []*eth.BlobIdentifier for i := uint64(0); i < uint64(commitments); i++ { - if !storedIndices[i] { + if !stored.HasIndex(i) { ids = append(ids, ð.BlobIdentifier{Index: i, BlockRoot: root[:]}) } } diff --git a/beacon-chain/sync/rpc_beacon_blocks_by_root_test.go b/beacon-chain/sync/rpc_beacon_blocks_by_root_test.go index d95306297025..328e0c66d957 100644 --- a/beacon-chain/sync/rpc_beacon_blocks_by_root_test.go +++ b/beacon-chain/sync/rpc_beacon_blocks_by_root_test.go @@ -31,7 +31,6 @@ import ( leakybucket "github.com/prysmaticlabs/prysm/v5/container/leaky-bucket" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" - eth "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -151,11 +150,11 @@ func TestRecentBeaconBlocksRPCHandler_ReturnsBlocks_ReconstructsPayload(t *testi }, } r := &Service{cfg: &config{ - p2p: p1, - beaconDB: d, - executionPayloadReconstructor: mockEngine, - chain: &mock.ChainService{ValidatorsRoot: [32]byte{}}, - clock: startup.NewClock(time.Unix(0, 0), [32]byte{}), + p2p: p1, + beaconDB: d, + executionReconstructor: mockEngine, + chain: &mock.ChainService{ValidatorsRoot: [32]byte{}}, + clock: startup.NewClock(time.Unix(0, 0), [32]byte{}), }, rateLimiter: newRateLimiter(p1)} pcl := protocol.ID(p2p.RPCBlocksByRootTopicV1) topic := string(pcl) @@ -253,7 +252,7 @@ func TestRecentBeaconBlocks_RPCRequestSent(t *testing.T) { }) p1.Connect(p2) - require.NoError(t, r.sendRecentBeaconBlocksRequest(context.Background(), &expectedRoots, p2.PeerID())) + require.NoError(t, r.sendBeaconBlocksRequest(context.Background(), &expectedRoots, p2.PeerID())) if util.WaitTimeout(&wg, 1*time.Second) { t.Fatal("Did not receive stream within 1 sec") @@ -328,7 +327,7 @@ func TestRecentBeaconBlocks_RPCRequestSent_IncorrectRoot(t *testing.T) { }) p1.Connect(p2) - require.ErrorContains(t, "received unexpected block with root", r.sendRecentBeaconBlocksRequest(context.Background(), &expectedRoots, p2.PeerID())) + require.ErrorContains(t, "received unexpected block with root", r.sendBeaconBlocksRequest(context.Background(), &expectedRoots, p2.PeerID())) } func TestRecentBeaconBlocksRPCHandler_HandleZeroBlocks(t *testing.T) { @@ -395,7 +394,7 @@ func TestRequestPendingBlobs(t *testing.T) { Genesis: time.Now(), } p1.Peers().Add(new(enr.Record), p2.PeerID(), nil, network.DirOutbound) - p1.Peers().SetConnectionState(p2.PeerID(), peers.PeerConnected) + p1.Peers().SetConnectionState(p2.PeerID(), peers.Connected) p1.Peers().SetChainState(p2.PeerID(), ðpb.Status{FinalizedEpoch: 1}) s := &Service{ cfg: &config{ @@ -445,13 +444,12 @@ func TestConstructPendingBlobsRequest(t *testing.T) { util.GenerateTestDenebBlobSidecar(t, root, header, 0, bytesutil.PadTo([]byte{}, 48), make([][]byte, 0)), util.GenerateTestDenebBlobSidecar(t, root, header, 2, bytesutil.PadTo([]byte{}, 48), make([][]byte, 0)), } - vscs, err := verification.BlobSidecarSliceNoop(blobSidecars) - require.NoError(t, err) + vscs := verification.FakeVerifySliceForTest(t, blobSidecars) for i := range vscs { require.NoError(t, bs.Save(vscs[i])) } - expected := []*eth.BlobIdentifier{ + expected := []*ethpb.BlobIdentifier{ {Index: 1, BlockRoot: root[:]}, } actual, err = s.constructPendingBlobsRequest(root, count) @@ -461,17 +459,19 @@ func TestConstructPendingBlobsRequest(t *testing.T) { } func TestFilterUnknownIndices(t *testing.T) { - haveIndices := [fieldparams.MaxBlobsPerBlock]bool{true, true, true, false, false, false} - blockRoot := [32]byte{} count := 5 - expected := []*eth.BlobIdentifier{ + expected := []*ethpb.BlobIdentifier{ {Index: 3, BlockRoot: blockRoot[:]}, {Index: 4, BlockRoot: blockRoot[:]}, } - actual := requestsForMissingIndices(haveIndices, count, blockRoot) + sum, err := filesystem.NewBlobStorageSummary( + params.BeaconConfig().DenebForkEpoch, + []bool{true, true, true, false, false, false}) + require.NoError(t, err) + actual := requestsForMissingIndices(sum, count, blockRoot) require.Equal(t, len(expected), len(actual)) require.Equal(t, expected[0].Index, actual[0].Index) require.DeepEqual(t, actual[0].BlockRoot, expected[0].BlockRoot) diff --git a/beacon-chain/sync/rpc_blob_sidecars_by_range.go b/beacon-chain/sync/rpc_blob_sidecars_by_range.go index 7de9ad03e5ad..01433c8d96b6 100644 --- a/beacon-chain/sync/rpc_blob_sidecars_by_range.go +++ b/beacon-chain/sync/rpc_blob_sidecars_by_range.go @@ -10,13 +10,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" p2ptypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/types" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) func (s *Service) streamBlobBatch(ctx context.Context, batch blockBatch, wQuota uint64, stream libp2pcore.Stream) (uint64, error) { @@ -28,14 +27,10 @@ func (s *Service) streamBlobBatch(ctx context.Context, batch blockBatch, wQuota defer span.End() for _, b := range batch.canonical() { root := b.Root() - idxs, err := s.cfg.blobStorage.Indices(b.Root()) - if err != nil { - s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream) - return wQuota, errors.Wrapf(err, "could not retrieve sidecars for block root %#x", root) - } - for i, l := uint64(0), uint64(len(idxs)); i < l; i++ { + idxs := s.cfg.blobStorage.Summary(root) + for i := range idxs.MaxBlobsForEpoch() { // index not available, skip - if !idxs[i] { + if !idxs.HasIndex(i) { continue } // We won't check for file not found since the .Indices method should normally prevent that from happening. @@ -99,7 +94,11 @@ func (s *Service) blobSidecarsByRangeRPCHandler(ctx context.Context, msg interfa } var batch blockBatch + wQuota := params.BeaconConfig().MaxRequestBlobSidecars + if slots.ToEpoch(s.cfg.chain.CurrentSlot()) >= params.BeaconConfig().ElectraForkEpoch { + wQuota = params.BeaconConfig().MaxRequestBlobSidecarsElectra + } for batch, ok = batcher.next(ctx, stream); ok; batch, ok = batcher.next(ctx, stream) { batchStart := time.Now() wQuota, err = s.streamBlobBatch(ctx, batch, wQuota, stream) @@ -114,7 +113,12 @@ func (s *Service) blobSidecarsByRangeRPCHandler(ctx context.Context, msg interfa } if err := batch.error(); err != nil { log.WithError(err).Debug("error in BlobSidecarsByRange batch") - s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream) + + // If a rate limit is hit, it means an error response has already been sent and the stream has been closed. + if !errors.Is(err, p2ptypes.ErrRateLimited) { + s.writeErrorResponseToStream(responseCodeServerError, p2ptypes.ErrGeneric.Error(), stream) + } + tracing.AnnotateError(span, err) return err } @@ -140,8 +144,14 @@ func BlobRPCMinValidSlot(current primitives.Slot) (primitives.Slot, error) { return slots.EpochStart(minStart) } -func blobBatchLimit() uint64 { - return uint64(flags.Get().BlockBatchLimit / fieldparams.MaxBlobsPerBlock) +// This function is used to derive what is the ideal block batch size we can serve +// blobs to the remote peer for. We compute the current limit which is the maximum +// blobs to be served to the peer every period. And then using the maximum blobs per +// block determine the block batch size satisfying this limit. +func blobBatchLimit(slot primitives.Slot) uint64 { + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(slot) + maxPossibleBlobs := flags.Get().BlobBatchLimit * flags.Get().BlobBatchLimitBurstFactor + return uint64(maxPossibleBlobs / maxBlobsPerBlock) } func validateBlobsByRange(r *pb.BlobSidecarsByRangeRequest, current primitives.Slot) (rangeParams, error) { @@ -194,7 +204,7 @@ func validateBlobsByRange(r *pb.BlobSidecarsByRangeRequest, current primitives.S rp.end = rp.start } - limit := blobBatchLimit() + limit := blobBatchLimit(current) if limit > maxRequest { limit = maxRequest } diff --git a/beacon-chain/sync/rpc_blob_sidecars_by_range_test.go b/beacon-chain/sync/rpc_blob_sidecars_by_range_test.go index 3e2418850eb0..18c471bab25a 100644 --- a/beacon-chain/sync/rpc_blob_sidecars_by_range_test.go +++ b/beacon-chain/sync/rpc_blob_sidecars_by_range_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" types "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -25,7 +24,7 @@ func (c *blobsTestCase) defaultOldestSlotByRange(t *testing.T) types.Slot { } func blobRangeRequestFromSidecars(scs []blocks.ROBlob) interface{} { - maxBlobs := fieldparams.MaxBlobsPerBlock + maxBlobs := params.BeaconConfig().MaxBlobsPerBlock(scs[0].Slot()) count := uint64(len(scs) / maxBlobs) return ðpb.BlobSidecarsByRangeRequest{ StartSlot: scs[0].Slot(), @@ -135,7 +134,7 @@ func TestBlobByRangeOK(t *testing.T) { Count: 20, } }, - total: func() *int { x := fieldparams.MaxBlobsPerBlock * 10; return &x }(), // 10 blocks * 4 blobs = 40 + total: func() *int { x := params.BeaconConfig().MaxBlobsPerBlock(0) * 10; return &x }(), // 10 blocks * 4 blobs = 40 }, { name: "when request count > MAX_REQUEST_BLOCKS_DENEB, MAX_REQUEST_BLOBS_SIDECARS sidecars in response", @@ -233,7 +232,7 @@ func TestBlobsByRangeValidation(t *testing.T) { }, start: defaultMinStart, end: defaultMinStart + 9, - batch: blobBatchLimit(), + batch: blobBatchLimit(100), }, { name: "count > MAX_REQUEST_BLOB_SIDECARS", @@ -245,7 +244,7 @@ func TestBlobsByRangeValidation(t *testing.T) { start: defaultMinStart, end: defaultMinStart - 10 + 999, // a large count is ok, we just limit the amount of actual responses - batch: blobBatchLimit(), + batch: blobBatchLimit(100), }, { name: "start + count > current", @@ -267,7 +266,7 @@ func TestBlobsByRangeValidation(t *testing.T) { }, start: denebSlot, end: denebSlot + 89, - batch: blobBatchLimit(), + batch: blobBatchLimit(100), }, } for _, c := range cases { diff --git a/beacon-chain/sync/rpc_blob_sidecars_by_root.go b/beacon-chain/sync/rpc_blob_sidecars_by_root.go index 57ffa5754438..ab3b5c6bb9a9 100644 --- a/beacon-chain/sync/rpc_blob_sidecars_by_root.go +++ b/beacon-chain/sync/rpc_blob_sidecars_by_root.go @@ -13,10 +13,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/types" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" + "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // blobSidecarByRootRPCHandler handles the /eth2/beacon_chain/req/blob_sidecars_by_root/1/ RPC request. @@ -34,7 +36,8 @@ func (s *Service) blobSidecarByRootRPCHandler(ctx context.Context, msg interface } blobIdents := *ref - if err := validateBlobByRootRequest(blobIdents); err != nil { + cs := s.cfg.clock.CurrentSlot() + if err := validateBlobByRootRequest(blobIdents, cs); err != nil { s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) s.writeErrorResponseToStream(responseCodeInvalidRequest, err.Error(), stream) return err @@ -49,7 +52,6 @@ func (s *Service) blobSidecarByRootRPCHandler(ctx context.Context, msg interface } // Compute the oldest slot we'll allow a peer to request, based on the current slot. - cs := s.cfg.clock.CurrentSlot() minReqSlot, err := BlobRPCMinValidSlot(cs) if err != nil { return errors.Wrapf(err, "unexpected error computing min valid blob request slot, current_slot=%d", cs) @@ -104,9 +106,15 @@ func (s *Service) blobSidecarByRootRPCHandler(ctx context.Context, msg interface return nil } -func validateBlobByRootRequest(blobIdents types.BlobSidecarsByRootReq) error { - if uint64(len(blobIdents)) > params.BeaconConfig().MaxRequestBlobSidecars { - return types.ErrMaxBlobReqExceeded +func validateBlobByRootRequest(blobIdents types.BlobSidecarsByRootReq, slot primitives.Slot) error { + if slots.ToEpoch(slot) >= params.BeaconConfig().ElectraForkEpoch { + if uint64(len(blobIdents)) > params.BeaconConfig().MaxRequestBlobSidecarsElectra { + return types.ErrMaxBlobReqExceeded + } + } else { + if uint64(len(blobIdents)) > params.BeaconConfig().MaxRequestBlobSidecars { + return types.ErrMaxBlobReqExceeded + } } return nil } diff --git a/beacon-chain/sync/rpc_blob_sidecars_by_root_test.go b/beacon-chain/sync/rpc_blob_sidecars_by_root_test.go index 49abe6dc35ff..9789f6ab416a 100644 --- a/beacon-chain/sync/rpc_blob_sidecars_by_root_test.go +++ b/beacon-chain/sync/rpc_blob_sidecars_by_root_test.go @@ -8,7 +8,6 @@ import ( "github.com/libp2p/go-libp2p/core/network" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" p2pTypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/types" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" types "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -223,7 +222,7 @@ func TestBlobsByRootValidation(t *testing.T) { name: "block with all indices missing between 2 full blocks", nblocks: 3, missing: map[int]bool{1: true}, - total: func(i int) *int { return &i }(2 * fieldparams.MaxBlobsPerBlock), + total: func(i int) *int { return &i }(2 * int(params.BeaconConfig().MaxBlobsPerBlock(0))), }, { name: "exceeds req max", diff --git a/beacon-chain/sync/rpc_chunked_response.go b/beacon-chain/sync/rpc_chunked_response.go index 6eac6fc8ff3d..762b8d0f42ae 100644 --- a/beacon-chain/sync/rpc_chunked_response.go +++ b/beacon-chain/sync/rpc_chunked_response.go @@ -69,6 +69,12 @@ func WriteBlockChunk(stream libp2pcore.Stream, tor blockchain.TemporalOracle, en return err } obtainedCtx = digest[:] + case version.Fulu: + digest, err := forks.ForkDigestFromEpoch(params.BeaconConfig().FuluForkEpoch, valRoot[:]) + if err != nil { + return err + } + obtainedCtx = digest[:] default: return errors.Wrapf(ErrUnrecognizedVersion, "block version %d is not recognized", blk.Version()) } diff --git a/beacon-chain/sync/rpc_goodbye.go b/beacon-chain/sync/rpc_goodbye.go index 4c27e0b55cf8..03f0789c87cf 100644 --- a/beacon-chain/sync/rpc_goodbye.go +++ b/beacon-chain/sync/rpc_goodbye.go @@ -55,10 +55,7 @@ func (s *Service) goodbyeRPCHandler(_ context.Context, msg interface{}, stream l // disconnectBadPeer checks whether peer is considered bad by some scorer, and tries to disconnect // the peer, if that is the case. Additionally, disconnection reason is obtained from scorer. -func (s *Service) disconnectBadPeer(ctx context.Context, id peer.ID) { - if !s.cfg.p2p.Peers().IsBad(id) { - return - } +func (s *Service) disconnectBadPeer(ctx context.Context, id peer.ID, badPeerErr error) { err := s.cfg.p2p.Peers().Scorers().ValidationError(id) goodbyeCode := p2ptypes.ErrToGoodbyeCode(err) if err == nil { @@ -67,6 +64,8 @@ func (s *Service) disconnectBadPeer(ctx context.Context, id peer.ID) { if err := s.sendGoodByeAndDisconnect(ctx, goodbyeCode, id); err != nil { log.WithError(err).Debug("Error when disconnecting with bad peer") } + + log.WithError(badPeerErr).WithField("peerID", id).Debug("Initiate peer disconnection") } // A custom goodbye method that is used by our connection handler, in the diff --git a/beacon-chain/sync/rpc_metadata.go b/beacon-chain/sync/rpc_metadata.go index 65fb0003d896..b7953f882253 100644 --- a/beacon-chain/sync/rpc_metadata.go +++ b/beacon-chain/sync/rpc_metadata.go @@ -21,97 +21,148 @@ import ( func (s *Service) metaDataHandler(_ context.Context, _ interface{}, stream libp2pcore.Stream) error { SetRPCStreamDeadlines(stream) + // Validate the incoming request regarding rate limiting. if err := s.rateLimiter.validateRequest(stream, 1); err != nil { - return err + return errors.Wrap(err, "validate request") } + s.rateLimiter.add(stream, 1) - if s.cfg.p2p.Metadata() == nil || s.cfg.p2p.Metadata().IsNil() { + // Retrieve our metadata. + metadata := s.cfg.p2p.Metadata() + + // Handle the case our metadata is nil. + if metadata == nil || metadata.IsNil() { nilErr := errors.New("nil metadata stored for host") + resp, err := s.generateErrorResponse(responseCodeServerError, types.ErrGeneric.Error()) if err != nil { log.WithError(err).Debug("Could not generate a response error") - } else if _, err := stream.Write(resp); err != nil { + return nilErr + } + + if _, err := stream.Write(resp); err != nil { log.WithError(err).Debug("Could not write to stream") } + return nilErr } + + // Get the stream version from the protocol. _, _, streamVersion, err := p2p.TopicDeconstructor(string(stream.Protocol())) if err != nil { + wrappedErr := errors.Wrap(err, "topic deconstructor") + resp, genErr := s.generateErrorResponse(responseCodeServerError, types.ErrGeneric.Error()) if genErr != nil { log.WithError(genErr).Debug("Could not generate a response error") - } else if _, wErr := stream.Write(resp); wErr != nil { + return wrappedErr + } + + if _, wErr := stream.Write(resp); wErr != nil { log.WithError(wErr).Debug("Could not write to stream") } - return err + return wrappedErr } - currMd := s.cfg.p2p.Metadata() + + // Handle the case where the stream version is not recognized. + metadataVersion := metadata.Version() switch streamVersion { case p2p.SchemaVersionV1: - // We have a v1 metadata object saved locally, so we - // convert it back to a v0 metadata object. - if currMd.Version() != version.Phase0 { - currMd = wrapper.WrappedMetadataV0( + switch metadataVersion { + case version.Altair, version.Deneb: + metadata = wrapper.WrappedMetadataV0( &pb.MetaDataV0{ - Attnets: currMd.AttnetsBitfield(), - SeqNumber: currMd.SequenceNumber(), + Attnets: metadata.AttnetsBitfield(), + SeqNumber: metadata.SequenceNumber(), }) } + case p2p.SchemaVersionV2: - // We have a v0 metadata object saved locally, so we - // convert it to a v1 metadata object. - if currMd.Version() != version.Altair { - currMd = wrapper.WrappedMetadataV1( + switch metadataVersion { + case version.Phase0: + metadata = wrapper.WrappedMetadataV1( &pb.MetaDataV1{ - Attnets: currMd.AttnetsBitfield(), - SeqNumber: currMd.SequenceNumber(), + Attnets: metadata.AttnetsBitfield(), + SeqNumber: metadata.SequenceNumber(), Syncnets: bitfield.Bitvector4{byte(0x00)}, }) + case version.Deneb: + metadata = wrapper.WrappedMetadataV1( + &pb.MetaDataV1{ + Attnets: metadata.AttnetsBitfield(), + SeqNumber: metadata.SequenceNumber(), + Syncnets: metadata.SyncnetsBitfield(), + }) } } + + // Write the METADATA response into the stream. if _, err := stream.Write([]byte{responseCodeSuccess}); err != nil { - return err + return errors.Wrap(err, "write metadata response") } - _, err = s.cfg.p2p.Encoding().EncodeWithMaxLength(stream, currMd) + + // Encode the metadata and write it to the stream. + _, err = s.cfg.p2p.Encoding().EncodeWithMaxLength(stream, metadata) if err != nil { - return err + return errors.Wrap(err, "encode metadata") } - closeStream(stream, log) + + closeStreamAndWait(stream, log) return nil } -func (s *Service) sendMetaDataRequest(ctx context.Context, id peer.ID) (metadata.Metadata, error) { +// sendMetaDataRequest sends a METADATA request to the peer and return the response. +func (s *Service) sendMetaDataRequest(ctx context.Context, peerID peer.ID) (metadata.Metadata, error) { ctx, cancel := context.WithTimeout(ctx, respTimeout) defer cancel() - topic, err := p2p.TopicFromMessage(p2p.MetadataMessageName, slots.ToEpoch(s.cfg.clock.CurrentSlot())) + // Compute the current epoch. + currentSlot := s.cfg.clock.CurrentSlot() + currentEpoch := slots.ToEpoch(currentSlot) + + // Compute the topic for the metadata request regarding the current epoch. + topic, err := p2p.TopicFromMessage(p2p.MetadataMessageName, currentEpoch) if err != nil { - return nil, err + return nil, errors.Wrap(err, "topic from message") } - stream, err := s.cfg.p2p.Send(ctx, new(interface{}), topic, id) + + // Send the METADATA request to the peer. + message := new(interface{}) + stream, err := s.cfg.p2p.Send(ctx, message, topic, peerID) if err != nil { - return nil, err + return nil, errors.Wrap(err, "send metadata request") } - defer closeStream(stream, log) + + defer closeStreamAndWait(stream, log) + + // Read the METADATA response from the peer. code, errMsg, err := ReadStatusCode(stream, s.cfg.p2p.Encoding()) if err != nil { - s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) - return nil, err + s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(peerID) + return nil, errors.Wrap(err, "read status code") } + if code != 0 { - s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) + s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(peerID) return nil, errors.New(errMsg) } + + // Get the genesis validators root. valRoot := s.cfg.clock.GenesisValidatorsRoot() - rpcCtx, err := forks.ForkDigestFromEpoch(slots.ToEpoch(s.cfg.clock.CurrentSlot()), valRoot[:]) + + // Get the fork digest from the current epoch and the genesis validators root. + rpcCtx, err := forks.ForkDigestFromEpoch(currentEpoch, valRoot[:]) if err != nil { - return nil, err + return nil, errors.Wrap(err, "fork digest from epoch") } + + // Instantiate zero value of the metadata. msg, err := extractDataTypeFromTypeMap(types.MetaDataMap, rpcCtx[:], s.cfg.clock) if err != nil { - return nil, err + return nil, errors.Wrap(err, "extract data type from type map") } + // Defensive check to ensure valid objects are being sent. topicVersion := "" switch msg.Version() { @@ -120,12 +171,17 @@ func (s *Service) sendMetaDataRequest(ctx context.Context, id peer.ID) (metadata case version.Altair: topicVersion = p2p.SchemaVersionV2 } + + // Validate the version of the topic. if err := validateVersion(topicVersion, stream); err != nil { return nil, err } + + // Decode the metadata from the peer. if err := s.cfg.p2p.Encoding().DecodeWithMaxLength(stream, msg); err != nil { s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) return nil, err } + return msg, nil } diff --git a/beacon-chain/sync/rpc_metadata_test.go b/beacon-chain/sync/rpc_metadata_test.go index 23eb74041f0b..813f28e95e29 100644 --- a/beacon-chain/sync/rpc_metadata_test.go +++ b/beacon-chain/sync/rpc_metadata_test.go @@ -6,8 +6,10 @@ import ( "testing" "time" + "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/protocol" + libp2pquic "github.com/libp2p/go-libp2p/p2p/transport/quic" mock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" db "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" @@ -229,3 +231,95 @@ func TestMetadataRPCHandler_SendsMetadataAltair(t *testing.T) { t.Error("Peer is disconnected despite receiving a valid ping") } } + +func TestMetadataRPCHandler_SendsMetadataQUIC(t *testing.T) { + params.SetupTestConfigCleanup(t) + bCfg := params.BeaconConfig().Copy() + bCfg.AltairForkEpoch = 5 + params.OverrideBeaconConfig(bCfg) + params.BeaconConfig().InitializeForkSchedule() + + p1 := p2ptest.NewTestP2P(t, libp2p.Transport(libp2pquic.NewTransport)) + p2 := p2ptest.NewTestP2P(t, libp2p.Transport(libp2pquic.NewTransport)) + p1.Connect(p2) + assert.Equal(t, 1, len(p1.BHost.Network().Peers()), "Expected peers to be connected") + bitfield := [8]byte{'A', 'B'} + p2.LocalMetadata = wrapper.WrappedMetadataV0(&pb.MetaDataV0{ + SeqNumber: 2, + Attnets: bitfield[:], + }) + + // Set up a head state in the database with data we expect. + d := db.SetupDB(t) + chain := &mock.ChainService{Genesis: time.Now().Add(-5 * oneEpoch()), ValidatorsRoot: [32]byte{}} + r := &Service{ + cfg: &config{ + beaconDB: d, + p2p: p1, + chain: chain, + clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), + }, + rateLimiter: newRateLimiter(p1), + } + + chain2 := &mock.ChainService{Genesis: time.Now().Add(-5 * oneEpoch()), ValidatorsRoot: [32]byte{}} + r2 := &Service{ + cfg: &config{ + beaconDB: d, + p2p: p2, + chain: chain2, + clock: startup.NewClock(chain2.Genesis, chain2.ValidatorsRoot), + }, + rateLimiter: newRateLimiter(p2), + } + + // Setup streams + pcl := protocol.ID(p2p.RPCMetaDataTopicV2 + r.cfg.p2p.Encoding().ProtocolSuffix()) + topic := string(pcl) + r.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(2, 2, time.Second, false) + r2.rateLimiter.limiterMap[topic] = leakybucket.NewCollector(2, 2, time.Second, false) + + var wg sync.WaitGroup + wg.Add(1) + p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) { + defer wg.Done() + err := r2.metaDataHandler(context.Background(), new(interface{}), stream) + assert.NoError(t, err) + }) + + _, err := r.sendMetaDataRequest(context.Background(), p2.BHost.ID()) + assert.NoError(t, err) + + if util.WaitTimeout(&wg, 1*time.Second) { + t.Fatal("Did not receive stream within 1 sec") + } + + // Fix up peer with the correct metadata. + p2.LocalMetadata = wrapper.WrappedMetadataV1(&pb.MetaDataV1{ + SeqNumber: 2, + Attnets: bitfield[:], + Syncnets: []byte{0x0}, + }) + + wg.Add(1) + p2.BHost.SetStreamHandler(pcl, func(stream network.Stream) { + defer wg.Done() + assert.NoError(t, r2.metaDataHandler(context.Background(), new(interface{}), stream)) + }) + + md, err := r.sendMetaDataRequest(context.Background(), p2.BHost.ID()) + assert.NoError(t, err) + + if !equality.DeepEqual(md.InnerObject(), p2.LocalMetadata.InnerObject()) { + t.Fatalf("MetadataV1 unequal, received %v but wanted %v", md, p2.LocalMetadata) + } + + if util.WaitTimeout(&wg, 1*time.Second) { + t.Fatal("Did not receive stream within 1 sec") + } + + conns := p1.BHost.Network().ConnsToPeer(p2.BHost.ID()) + if len(conns) == 0 { + t.Error("Peer is disconnected despite receiving a valid ping") + } +} diff --git a/beacon-chain/sync/rpc_ping.go b/beacon-chain/sync/rpc_ping.go index e082b5cbab63..ec7e2c448a8d 100644 --- a/beacon-chain/sync/rpc_ping.go +++ b/beacon-chain/sync/rpc_ping.go @@ -2,12 +2,12 @@ package sync import ( "context" - "errors" "fmt" "strings" libp2pcore "github.com/libp2p/go-libp2p/core" "github.com/libp2p/go-libp2p/core/peer" + "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" p2ptypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/types" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -16,127 +16,191 @@ import ( ) // pingHandler reads the incoming ping rpc message from the peer. +// If the peer's sequence number is higher than the one stored locally, +// a METADATA request is sent to the peer to retrieve and update the latest metadata. +// Note: This function is misnamed, as it performs more than just reading a ping message. func (s *Service) pingHandler(_ context.Context, msg interface{}, stream libp2pcore.Stream) error { SetRPCStreamDeadlines(stream) + // Convert the message to SSW Uint64 type. m, ok := msg.(*primitives.SSZUint64) if !ok { return fmt.Errorf("wrong message type for ping, got %T, wanted *uint64", msg) } + + // Validate the incoming request regarding rate limiting. if err := s.rateLimiter.validateRequest(stream, 1); err != nil { - return err + return errors.Wrap(err, "validate request") } + s.rateLimiter.add(stream, 1) - valid, err := s.validateSequenceNum(*m, stream.Conn().RemotePeer()) + + // Retrieve the peer ID. + peerID := stream.Conn().RemotePeer() + + // Check if the peer sequence number is higher than the one we have in our store. + valid, err := s.validateSequenceNum(*m, peerID) if err != nil { // Descore peer for giving us a bad sequence number. if errors.Is(err, p2ptypes.ErrInvalidSequenceNum) { - s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) + s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(peerID) s.writeErrorResponseToStream(responseCodeInvalidRequest, p2ptypes.ErrInvalidSequenceNum.Error(), stream) } - return err + + return errors.Wrap(err, "validate sequence number") } + + // We can already prepare a success response to the peer. if _, err := stream.Write([]byte{responseCodeSuccess}); err != nil { - return err + return errors.Wrap(err, "write response") } - sq := primitives.SSZUint64(s.cfg.p2p.MetadataSeq()) - if _, err := s.cfg.p2p.Encoding().EncodeWithMaxLength(stream, &sq); err != nil { + + // Retrieve our own sequence number. + seqNumber := s.cfg.p2p.MetadataSeq() + + // SSZ encode our sequence number. + seqNumberSSZ := primitives.SSZUint64(seqNumber) + + // Send our sequence number back to the peer. + if _, err := s.cfg.p2p.Encoding().EncodeWithMaxLength(stream, &seqNumberSSZ); err != nil { return err } closeStream(stream, log) if valid { - // If the sequence number was valid we're done. + // If the peer's sequence numberwas valid we're done. return nil } - // The sequence number was not valid. Start our own ping back to the peer. + // The peer's sequence number was not valid. We ask the peer for its metadata. go func() { - // New context so the calling function doesn't cancel on us. + // Define a new context so the calling function doesn't cancel on us. ctx, cancel := context.WithTimeout(context.Background(), ttfbTimeout) defer cancel() - md, err := s.sendMetaDataRequest(ctx, stream.Conn().RemotePeer()) + + // Send a METADATA request to the peer. + peerMetadata, err := s.sendMetaDataRequest(ctx, peerID) if err != nil { // We cannot compare errors directly as the stream muxer error // type isn't compatible with the error we have, so a direct // equality checks fails. if !strings.Contains(err.Error(), p2ptypes.ErrIODeadline.Error()) { - log.WithField("peer", stream.Conn().RemotePeer()).WithError(err).Debug("Could not send metadata request") + log.WithField("peer", peerID).WithError(err).Debug("Could not send metadata request") } + return } - // update metadata if there is no error - s.cfg.p2p.Peers().SetMetadata(stream.Conn().RemotePeer(), md) + + // Update peer's metadata. + s.cfg.p2p.Peers().SetMetadata(peerID, peerMetadata) }() return nil } -func (s *Service) sendPingRequest(ctx context.Context, id peer.ID) error { +// sendPingRequest first sends a PING request to the peer. +// If the peer responds with a sequence number higher than latest one for it we have in our store, +// then this function sends a METADATA request to the peer, and stores the metadata received. +// This function is actually poorly named, since it does more than just sending a ping request. +func (s *Service) sendPingRequest(ctx context.Context, peerID peer.ID) error { ctx, cancel := context.WithTimeout(ctx, respTimeout) defer cancel() - metadataSeq := primitives.SSZUint64(s.cfg.p2p.MetadataSeq()) - topic, err := p2p.TopicFromMessage(p2p.PingMessageName, slots.ToEpoch(s.cfg.clock.CurrentSlot())) + // Get the current epoch. + currentSlot := s.cfg.clock.CurrentSlot() + currentEpoch := slots.ToEpoch(currentSlot) + + // SSZ encode our metadata sequence number. + metadataSeq := s.cfg.p2p.MetadataSeq() + encodedMetadataSeq := primitives.SSZUint64(metadataSeq) + + // Get the PING topic for the current epoch. + topic, err := p2p.TopicFromMessage(p2p.PingMessageName, currentEpoch) if err != nil { - return err + return errors.Wrap(err, "topic from message") } - stream, err := s.cfg.p2p.Send(ctx, &metadataSeq, topic, id) + + // Send the PING request to the peer. + stream, err := s.cfg.p2p.Send(ctx, &encodedMetadataSeq, topic, peerID) if err != nil { - return err + return errors.Wrap(err, "send ping request") } - currentTime := time.Now() defer closeStream(stream, log) + startTime := time.Now() + + // Read the response from the peer. code, errMsg, err := ReadStatusCode(stream, s.cfg.p2p.Encoding()) if err != nil { - return err + return errors.Wrap(err, "read status code") } - // Records the latency of the ping request for that peer. - s.cfg.p2p.Host().Peerstore().RecordLatency(id, time.Now().Sub(currentTime)) + // Record the latency of the ping request for that peer. + s.cfg.p2p.Host().Peerstore().RecordLatency(peerID, time.Now().Sub(startTime)) + + // If the peer responded with an error, increment the bad responses scorer. if code != 0 { - s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) - return errors.New(errMsg) + s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(peerID) + return errors.Errorf("code: %d - %s", code, errMsg) } + + // Decode the sequence number from the peer. msg := new(primitives.SSZUint64) if err := s.cfg.p2p.Encoding().DecodeWithMaxLength(stream, msg); err != nil { - return err + return errors.Wrap(err, "decode sequence number") } - valid, err := s.validateSequenceNum(*msg, stream.Conn().RemotePeer()) + + // Determine if the peer's sequence number returned by the peer is higher than the one we have in our store. + valid, err := s.validateSequenceNum(*msg, peerID) if err != nil { // Descore peer for giving us a bad sequence number. if errors.Is(err, p2ptypes.ErrInvalidSequenceNum) { - s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(stream.Conn().RemotePeer()) + s.cfg.p2p.Peers().Scorers().BadResponsesScorer().Increment(peerID) } - return err + + return errors.Wrap(err, "validate sequence number") } + + // The sequence number have in our store for this peer is the same as the one returned by the peer, all good. if valid { return nil } - md, err := s.sendMetaDataRequest(ctx, stream.Conn().RemotePeer()) + + // We need to send a METADATA request to the peer to get its latest metadata. + md, err := s.sendMetaDataRequest(ctx, peerID) if err != nil { - // do not increment bad responses, as its - // already done in the request method. - return err + // do not increment bad responses, as its already done in the request method. + return errors.Wrap(err, "send metadata request") } - s.cfg.p2p.Peers().SetMetadata(stream.Conn().RemotePeer(), md) + + // Update the metadata for the peer. + s.cfg.p2p.Peers().SetMetadata(peerID, md) + return nil } -// validates the peer's sequence number. +// validateSequenceNum validates the peer's sequence number. +// - If the peer's sequence number is greater than the sequence number we have in our store for the peer, return false. +// - If the peer's sequence number is equal to the sequence number we have in our store for the peer, return true. +// - If the peer's sequence number is less than the sequence number we have in our store for the peer, return an error. func (s *Service) validateSequenceNum(seq primitives.SSZUint64, id peer.ID) (bool, error) { + // Retrieve the metadata for the peer we got in our store. md, err := s.cfg.p2p.Peers().Metadata(id) if err != nil { - return false, err + return false, errors.Wrap(err, "get metadata") } + + // If we have no metadata for the peer, return false. if md == nil || md.IsNil() { return false, nil } - // Return error on invalid sequence number. + + // The peer's sequence number must be less than or equal to the sequence number we have in our store. if md.SequenceNumber() > uint64(seq) { return false, p2ptypes.ErrInvalidSequenceNum } + + // Return true if the peer's sequence number is equal to the sequence number we have in our store. return md.SequenceNumber() == uint64(seq), nil } diff --git a/beacon-chain/sync/rpc_send_request.go b/beacon-chain/sync/rpc_send_request.go index 30edbb09cf51..1be89a9cebfb 100644 --- a/beacon-chain/sync/rpc_send_request.go +++ b/beacon-chain/sync/rpc_send_request.go @@ -12,14 +12,12 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p" "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/encoder" p2ptypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/types" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" @@ -49,7 +47,7 @@ type BeaconBlockProcessor func(block interfaces.ReadOnlySignedBeaconBlock) error // SendBeaconBlocksByRangeRequest sends BeaconBlocksByRange and returns fetched blocks, if any. func SendBeaconBlocksByRangeRequest( ctx context.Context, tor blockchain.TemporalOracle, p2pProvider p2p.SenderEncoder, pid peer.ID, - req *pb.BeaconBlocksByRangeRequest, blockProcessor BeaconBlockProcessor, + req *ethpb.BeaconBlocksByRangeRequest, blockProcessor BeaconBlockProcessor, ) ([]interfaces.ReadOnlySignedBeaconBlock, error) { topic, err := p2p.TopicFromMessage(p2p.BeaconBlocksByRangeMessageName, slots.ToEpoch(tor.CurrentSlot())) if err != nil { @@ -155,7 +153,7 @@ func SendBeaconBlocksByRootRequest( return blocks, nil } -func SendBlobsByRangeRequest(ctx context.Context, tor blockchain.TemporalOracle, p2pApi p2p.SenderEncoder, pid peer.ID, ctxMap ContextByteVersions, req *pb.BlobSidecarsByRangeRequest, bvs ...BlobResponseValidation) ([]blocks.ROBlob, error) { +func SendBlobsByRangeRequest(ctx context.Context, tor blockchain.TemporalOracle, p2pApi p2p.SenderEncoder, pid peer.ID, ctxMap ContextByteVersions, req *ethpb.BlobSidecarsByRangeRequest, bvs ...BlobResponseValidation) ([]blocks.ROBlob, error) { topic, err := p2p.TopicFromMessage(p2p.BlobSidecarsByRangeName, slots.ToEpoch(tor.CurrentSlot())) if err != nil { return nil, err @@ -171,9 +169,13 @@ func SendBlobsByRangeRequest(ctx context.Context, tor blockchain.TemporalOracle, } defer closeStream(stream, log) + maxBlobsPerBlock := uint64(params.BeaconConfig().MaxBlobsPerBlock(req.StartSlot + primitives.Slot(req.Count))) max := params.BeaconConfig().MaxRequestBlobSidecars - if max > req.Count*fieldparams.MaxBlobsPerBlock { - max = req.Count * fieldparams.MaxBlobsPerBlock + if slots.ToEpoch(req.StartSlot) >= params.BeaconConfig().ElectraForkEpoch { + max = params.BeaconConfig().MaxRequestBlobSidecarsElectra + } + if max > req.Count*maxBlobsPerBlock { + max = req.Count * maxBlobsPerBlock } vfuncs := []BlobResponseValidation{blobValidatorFromRangeReq(req), newSequentialBlobValidator()} if len(bvs) > 0 { @@ -184,7 +186,7 @@ func SendBlobsByRangeRequest(ctx context.Context, tor blockchain.TemporalOracle, func SendBlobSidecarByRoot( ctx context.Context, tor blockchain.TemporalOracle, p2pApi p2p.P2P, pid peer.ID, - ctxMap ContextByteVersions, req *p2ptypes.BlobSidecarsByRootReq, + ctxMap ContextByteVersions, req *p2ptypes.BlobSidecarsByRootReq, slot primitives.Slot, ) ([]blocks.ROBlob, error) { if uint64(len(*req)) > params.BeaconConfig().MaxRequestBlobSidecars { return nil, errors.Wrapf(p2ptypes.ErrMaxBlobReqExceeded, "length=%d", len(*req)) @@ -202,8 +204,12 @@ func SendBlobSidecarByRoot( defer closeStream(stream, log) max := params.BeaconConfig().MaxRequestBlobSidecars - if max > uint64(len(*req))*fieldparams.MaxBlobsPerBlock { - max = uint64(len(*req)) * fieldparams.MaxBlobsPerBlock + if slots.ToEpoch(slot) >= params.BeaconConfig().ElectraForkEpoch { + max = params.BeaconConfig().MaxRequestBlobSidecarsElectra + } + maxBlobCount := params.BeaconConfig().MaxBlobsPerBlock(slot) + if max > uint64(len(*req)*maxBlobCount) { + max = uint64(len(*req) * maxBlobCount) } return readChunkEncodedBlobs(stream, p2pApi.Encoding(), ctxMap, blobValidatorFromRootReq(req), max) } @@ -228,7 +234,8 @@ type seqBlobValid struct { } func (sbv *seqBlobValid) nextValid(blob blocks.ROBlob) error { - if blob.Index >= fieldparams.MaxBlobsPerBlock { + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(blob.Slot()) + if blob.Index >= uint64(maxBlobsPerBlock) { return errBlobIndexOutOfBounds } if sbv.prev == nil { @@ -298,7 +305,7 @@ func blobValidatorFromRootReq(req *p2ptypes.BlobSidecarsByRootReq) BlobResponseV } } -func blobValidatorFromRangeReq(req *pb.BlobSidecarsByRangeRequest) BlobResponseValidation { +func blobValidatorFromRangeReq(req *ethpb.BlobSidecarsByRangeRequest) BlobResponseValidation { end := req.StartSlot + primitives.Slot(req.Count) return func(sc blocks.ROBlob) error { if sc.Slot() < req.StartSlot || sc.Slot() >= end { @@ -354,7 +361,7 @@ func readChunkedBlobSidecar(stream network.Stream, encoding encoder.NetworkEncod v, found := ctxMap[bytesutil.ToBytes4(ctxb)] if !found { - return b, errors.Wrapf(errBlobUnmarshal, fmt.Sprintf("unrecognized fork digest %#x", ctxb)) + return b, errors.Wrapf(errBlobUnmarshal, "unrecognized fork digest %#x", ctxb) } // Only deneb and electra are supported at this time, because we lack a fork-spanning interface/union type for blobs. // In electra, there's no changes to blob type. diff --git a/beacon-chain/sync/rpc_send_request_test.go b/beacon-chain/sync/rpc_send_request_test.go index 4fb2321e60e6..40b09c11fb49 100644 --- a/beacon-chain/sync/rpc_send_request_test.go +++ b/beacon-chain/sync/rpc_send_request_test.go @@ -23,6 +23,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/prysmaticlabs/prysm/v5/time/slots" ) func TestSendRequest_SendBeaconBlocksByRangeRequest(t *testing.T) { @@ -619,7 +620,7 @@ func TestSeqBlobValid(t *testing.T) { wrongRoot, err := blocks.NewROBlobWithRoot(oops[2].BlobSidecar, bytesutil.ToBytes32([]byte("parentderp"))) require.NoError(t, err) oob := oops[3] - oob.Index = fieldparams.MaxBlobsPerBlock + oob.Index = uint64(params.BeaconConfig().MaxBlobsPerBlock(0)) cases := []struct { name string @@ -691,3 +692,188 @@ func TestSeqBlobValid(t *testing.T) { }) } } + +func TestSendBlobsByRangeRequest(t *testing.T) { + topic := fmt.Sprintf("%s/ssz_snappy", p2p.RPCBlobSidecarsByRangeTopicV1) + ctx := context.Background() + + t.Run("single blob - Deneb", func(t *testing.T) { + // Setup genesis such that we are currently in deneb. + s := uint64(slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch)) * params.BeaconConfig().SecondsPerSlot + clock := startup.NewClock(time.Now().Add(-time.Second*time.Duration(s)), [32]byte{}) + ctxByte, err := ContextByteVersionsForValRoot(clock.GenesisValidatorsRoot()) + require.NoError(t, err) + // Setup peers + p1 := p2ptest.NewTestP2P(t) + p2 := p2ptest.NewTestP2P(t) + p1.Connect(p2) + // Set current slot to a deneb slot. + slot := slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch + 1) + // Create a simple handler that will return a valid response. + p2.SetStreamHandler(topic, func(stream network.Stream) { + defer func() { + assert.NoError(t, stream.Close()) + }() + + req := ðpb.BlobSidecarsByRangeRequest{} + assert.NoError(t, p2.Encoding().DecodeWithMaxLength(stream, req)) + assert.Equal(t, slot, req.StartSlot) + assert.Equal(t, uint64(1), req.Count) + + // Create a sequential set of blobs with the appropriate header information. + var prevRoot [32]byte + for i := req.StartSlot; i < req.StartSlot+primitives.Slot(req.Count); i++ { + b := util.HydrateBlobSidecar(ðpb.BlobSidecar{}) + b.SignedBlockHeader.Header.Slot = i + b.SignedBlockHeader.Header.ParentRoot = prevRoot[:] + ro, err := blocks.NewROBlob(b) + require.NoError(t, err) + vro := blocks.NewVerifiedROBlob(ro) + prevRoot = vro.BlockRoot() + assert.NoError(t, WriteBlobSidecarChunk(stream, clock, p2.Encoding(), vro)) + } + }) + req := ðpb.BlobSidecarsByRangeRequest{ + StartSlot: slot, + Count: 1, + } + + blobs, err := SendBlobsByRangeRequest(ctx, clock, p1, p2.PeerID(), ctxByte, req) + assert.NoError(t, err) + assert.Equal(t, 1, len(blobs)) + }) + + t.Run("Deneb - Electra epoch boundary crossing", func(t *testing.T) { + cfg := params.BeaconConfig() + cfg.ElectraForkEpoch = cfg.DenebForkEpoch + 1 + undo, err := params.SetActiveWithUndo(cfg) + require.NoError(t, err) + defer func() { + require.NoError(t, undo()) + }() + // Setup genesis such that we are currently in deneb. + s := uint64(slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch)) * params.BeaconConfig().SecondsPerSlot + clock := startup.NewClock(time.Now().Add(-time.Second*time.Duration(s)), [32]byte{}) + ctxByte, err := ContextByteVersionsForValRoot(clock.GenesisValidatorsRoot()) + require.NoError(t, err) + // Setup peers + p1 := p2ptest.NewTestP2P(t) + p2 := p2ptest.NewTestP2P(t) + p1.Connect(p2) + // Set current slot to the first slot of the last deneb epoch. + slot := slots.UnsafeEpochStart(params.BeaconConfig().DenebForkEpoch) + // Create a simple handler that will return a valid response. + p2.SetStreamHandler(topic, func(stream network.Stream) { + defer func() { + assert.NoError(t, stream.Close()) + }() + + req := ðpb.BlobSidecarsByRangeRequest{} + assert.NoError(t, p2.Encoding().DecodeWithMaxLength(stream, req)) + assert.Equal(t, slot, req.StartSlot) + assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch)*3, req.Count) + + // Create a sequential set of blobs with the appropriate header information. + var prevRoot [32]byte + for i := req.StartSlot; i < req.StartSlot+primitives.Slot(req.Count); i++ { + maxBlobsForSlot := cfg.MaxBlobsPerBlock(i) + parentRoot := prevRoot + header := util.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{}) + header.Header.Slot = i + header.Header.ParentRoot = parentRoot[:] + bRoot, err := header.Header.HashTreeRoot() + require.NoError(t, err) + prevRoot = bRoot + // Send the maximum possible blobs per slot. + for j := 0; j < maxBlobsForSlot; j++ { + b := util.HydrateBlobSidecar(ðpb.BlobSidecar{}) + b.SignedBlockHeader = header + b.Index = uint64(j) + ro, err := blocks.NewROBlob(b) + require.NoError(t, err) + vro := blocks.NewVerifiedROBlob(ro) + assert.NoError(t, WriteBlobSidecarChunk(stream, clock, p2.Encoding(), vro)) + } + } + }) + req := ðpb.BlobSidecarsByRangeRequest{ + StartSlot: slot, + Count: uint64(params.BeaconConfig().SlotsPerEpoch) * 3, + } + maxDenebBlobs := cfg.MaxBlobsPerBlockAtEpoch(cfg.DenebForkEpoch) + maxElectraBlobs := cfg.MaxBlobsPerBlockAtEpoch(cfg.ElectraForkEpoch) + totalDenebBlobs := primitives.Slot(maxDenebBlobs) * params.BeaconConfig().SlotsPerEpoch + totalElectraBlobs := primitives.Slot(maxElectraBlobs) * 2 * params.BeaconConfig().SlotsPerEpoch + totalExpectedBlobs := totalDenebBlobs + totalElectraBlobs + + blobs, err := SendBlobsByRangeRequest(ctx, clock, p1, p2.PeerID(), ctxByte, req) + assert.NoError(t, err) + assert.Equal(t, int(totalExpectedBlobs), len(blobs)) + }) + + t.Run("Starting from Electra", func(t *testing.T) { + cfg := params.BeaconConfig() + cfg.ElectraForkEpoch = cfg.DenebForkEpoch + 1 + undo, err := params.SetActiveWithUndo(cfg) + require.NoError(t, err) + defer func() { + require.NoError(t, undo()) + }() + + s := uint64(slots.UnsafeEpochStart(params.BeaconConfig().ElectraForkEpoch)) * params.BeaconConfig().SecondsPerSlot + clock := startup.NewClock(time.Now().Add(-time.Second*time.Duration(s)), [32]byte{}) + ctxByte, err := ContextByteVersionsForValRoot(clock.GenesisValidatorsRoot()) + require.NoError(t, err) + // Setup peers + p1 := p2ptest.NewTestP2P(t) + p2 := p2ptest.NewTestP2P(t) + p1.Connect(p2) + + slot := slots.UnsafeEpochStart(params.BeaconConfig().ElectraForkEpoch) + // Create a simple handler that will return a valid response. + p2.SetStreamHandler(topic, func(stream network.Stream) { + defer func() { + assert.NoError(t, stream.Close()) + }() + + req := ðpb.BlobSidecarsByRangeRequest{} + assert.NoError(t, p2.Encoding().DecodeWithMaxLength(stream, req)) + assert.Equal(t, slot, req.StartSlot) + assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch)*3, req.Count) + + // Create a sequential set of blobs with the appropriate header information. + var prevRoot [32]byte + for i := req.StartSlot; i < req.StartSlot+primitives.Slot(req.Count); i++ { + maxBlobsForSlot := cfg.MaxBlobsPerBlock(i) + parentRoot := prevRoot + header := util.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{}) + header.Header.Slot = i + header.Header.ParentRoot = parentRoot[:] + bRoot, err := header.Header.HashTreeRoot() + require.NoError(t, err) + prevRoot = bRoot + // Send the maximum possible blobs per slot. + for j := 0; j < maxBlobsForSlot; j++ { + b := util.HydrateBlobSidecar(ðpb.BlobSidecar{}) + b.SignedBlockHeader = header + b.Index = uint64(j) + ro, err := blocks.NewROBlob(b) + require.NoError(t, err) + vro := blocks.NewVerifiedROBlob(ro) + assert.NoError(t, WriteBlobSidecarChunk(stream, clock, p2.Encoding(), vro)) + } + } + }) + req := ðpb.BlobSidecarsByRangeRequest{ + StartSlot: slot, + Count: uint64(params.BeaconConfig().SlotsPerEpoch) * 3, + } + + maxElectraBlobs := cfg.MaxBlobsPerBlockAtEpoch(cfg.ElectraForkEpoch) + totalElectraBlobs := primitives.Slot(maxElectraBlobs) * 3 * params.BeaconConfig().SlotsPerEpoch + + blobs, err := SendBlobsByRangeRequest(ctx, clock, p1, p2.PeerID(), ctxByte, req) + assert.NoError(t, err) + assert.Equal(t, int(totalElectraBlobs), len(blobs)) + }) +} diff --git a/beacon-chain/sync/rpc_status.go b/beacon-chain/sync/rpc_status.go index e688301d66de..d12de6548241 100644 --- a/beacon-chain/sync/rpc_status.go +++ b/beacon-chain/sync/rpc_status.go @@ -25,7 +25,7 @@ import ( "github.com/sirupsen/logrus" ) -// maintainPeerStatuses by infrequently polling peers for their latest status. +// maintainPeerStatuses maintains peer statuses by polling peers for their latest status twice per epoch. func (s *Service) maintainPeerStatuses() { // Run twice per epoch. interval := time.Duration(params.BeaconConfig().SlotsPerEpoch.Div(2).Mul(params.BeaconConfig().SecondsPerSlot)) * time.Second @@ -38,16 +38,20 @@ func (s *Service) maintainPeerStatuses() { // If our peer status has not been updated correctly we disconnect over here // and set the connection state over here instead. if s.cfg.p2p.Host().Network().Connectedness(id) != network.Connected { - s.cfg.p2p.Peers().SetConnectionState(id, peers.PeerDisconnecting) + s.cfg.p2p.Peers().SetConnectionState(id, peers.Disconnecting) if err := s.cfg.p2p.Disconnect(id); err != nil { log.WithError(err).Debug("Error when disconnecting with peer") } - s.cfg.p2p.Peers().SetConnectionState(id, peers.PeerDisconnected) + s.cfg.p2p.Peers().SetConnectionState(id, peers.Disconnected) + log.WithFields(logrus.Fields{ + "peer": id, + "reason": "maintain peer statuses - peer is not connected", + }).Debug("Initiate peer disconnection") return } // Disconnect from peers that are considered bad by any of the registered scorers. - if s.cfg.p2p.Peers().IsBad(id) { - s.disconnectBadPeer(s.ctx, id) + if err := s.cfg.p2p.Peers().IsBad(id); err != nil { + s.disconnectBadPeer(s.ctx, id, err) return } // If the status hasn't been updated in the recent interval time. @@ -73,6 +77,11 @@ func (s *Service) maintainPeerStatuses() { if err := s.sendGoodByeAndDisconnect(s.ctx, p2ptypes.GoodbyeCodeTooManyPeers, id); err != nil { log.WithField("peer", id).WithError(err).Debug("Could not disconnect with peer") } + + log.WithFields(logrus.Fields{ + "peer": id, + "reason": "to be pruned", + }).Debug("Initiate peer disconnection") } }) } @@ -169,8 +178,8 @@ func (s *Service) sendRPCStatusRequest(ctx context.Context, id peer.ID) error { // If validation fails, validation error is logged, and peer status scorer will mark peer as bad. err = s.validateStatusMessage(ctx, msg) s.cfg.p2p.Peers().Scorers().PeerStatusScorer().SetPeerStatus(id, msg, err) - if s.cfg.p2p.Peers().IsBad(id) { - s.disconnectBadPeer(s.ctx, id) + if err := s.cfg.p2p.Peers().IsBad(id); err != nil { + s.disconnectBadPeer(s.ctx, id, err) } return err } @@ -182,7 +191,7 @@ func (s *Service) reValidatePeer(ctx context.Context, id peer.ID) error { } // Do not return an error for ping requests. if err := s.sendPingRequest(ctx, id); err != nil && !isUnwantedError(err) { - log.WithError(err).Debug("Could not ping peer") + log.WithError(err).WithField("pid", id).Debug("Could not ping peer") } return nil } @@ -286,7 +295,7 @@ func (s *Service) validateStatusMessage(ctx context.Context, msg *pb.Status) err return err } if !bytes.Equal(forkDigest[:], msg.ForkDigest) { - return p2ptypes.ErrWrongForkDigestVersion + return fmt.Errorf("mismatch fork digest: expected %#x, got %#x: %w", forkDigest[:], msg.ForkDigest, p2ptypes.ErrWrongForkDigestVersion) } genesis := s.cfg.clock.GenesisTime() cp := s.cfg.chain.FinalizedCheckpt() diff --git a/beacon-chain/sync/rpc_status_test.go b/beacon-chain/sync/rpc_status_test.go index 67323129d604..2aece63d6a93 100644 --- a/beacon-chain/sync/rpc_status_test.go +++ b/beacon-chain/sync/rpc_status_test.go @@ -413,7 +413,7 @@ func TestHandshakeHandlers_Roundtrip(t *testing.T) { assert.Equal(t, numActive1+1, numActive2, "Number of active peers unexpected") require.NoError(t, p2.Disconnect(p1.PeerID())) - p1.Peers().SetConnectionState(p2.PeerID(), peers.PeerDisconnected) + p1.Peers().SetConnectionState(p2.PeerID(), peers.Disconnected) // Wait for disconnect event to trigger. time.Sleep(200 * time.Millisecond) @@ -877,7 +877,7 @@ func TestStatusRPCRequest_BadPeerHandshake(t *testing.T) { require.NoError(t, cw.SetClock(startup.NewClock(chain.Genesis, chain.ValidatorsRoot))) - assert.Equal(t, false, p1.Peers().Scorers().IsBadPeer(p2.PeerID()), "Peer is marked as bad") + assert.NoError(t, p1.Peers().Scorers().IsBadPeer(p2.PeerID()), "Peer is marked as bad") p1.Connect(p2) if util.WaitTimeout(&wg, time.Second) { @@ -887,9 +887,9 @@ func TestStatusRPCRequest_BadPeerHandshake(t *testing.T) { connectionState, err := p1.Peers().ConnectionState(p2.PeerID()) require.NoError(t, err, "Could not obtain peer connection state") - assert.Equal(t, peers.PeerDisconnected, connectionState, "Expected peer to be disconnected") + assert.Equal(t, peers.Disconnected, connectionState, "Expected peer to be disconnected") - assert.Equal(t, true, p1.Peers().Scorers().IsBadPeer(p2.PeerID()), "Peer is not marked as bad") + assert.NotNil(t, p1.Peers().Scorers().IsBadPeer(p2.PeerID()), "Peer is not marked as bad") } func TestStatusRPC_ValidGenesisMessage(t *testing.T) { diff --git a/beacon-chain/sync/service.go b/beacon-chain/sync/service.go index 15196bf6ca74..16a243440c8d 100644 --- a/beacon-chain/sync/service.go +++ b/beacon-chain/sync/service.go @@ -15,10 +15,13 @@ import ( "github.com/libp2p/go-libp2p/core/peer" gcache "github.com/patrickmn/go-cache" "github.com/pkg/errors" + "github.com/trailofbits/go-mutexasserts" + "github.com/prysmaticlabs/prysm/v5/async" "github.com/prysmaticlabs/prysm/v5/async/abool" "github.com/prysmaticlabs/prysm/v5/async/event" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" blockfeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/block" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state" @@ -44,22 +47,24 @@ import ( "github.com/prysmaticlabs/prysm/v5/runtime" prysmTime "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" - "github.com/trailofbits/go-mutexasserts" ) var _ runtime.Service = (*Service)(nil) -const rangeLimit uint64 = 1024 -const seenBlockSize = 1000 -const seenBlobSize = seenBlockSize * 4 // Each block can have max 4 blobs. Worst case 164kB for cache. -const seenUnaggregatedAttSize = 20000 -const seenAggregatedAttSize = 16384 -const seenSyncMsgSize = 1000 // Maximum of 512 sync committee members, 1000 is a safe amount. -const seenSyncContributionSize = 512 // Maximum of SYNC_COMMITTEE_SIZE as specified by the spec. -const seenExitSize = 100 -const seenProposerSlashingSize = 100 -const badBlockSize = 1000 -const syncMetricsInterval = 10 * time.Second +const ( + rangeLimit uint64 = 1024 + seenBlockSize = 1000 + seenBlobSize = seenBlockSize * 6 // Each block can have max 6 blobs. + seenDataColumnSize = seenBlockSize * 128 // Each block can have max 128 data columns. + seenUnaggregatedAttSize = 20000 + seenAggregatedAttSize = 16384 + seenSyncMsgSize = 1000 // Maximum of 512 sync committee members, 1000 is a safe amount. + seenSyncContributionSize = 512 // Maximum of SYNC_COMMITTEE_SIZE as specified by the spec. + seenExitSize = 100 + seenProposerSlashingSize = 100 + badBlockSize = 1000 + syncMetricsInterval = 10 * time.Second +) var ( // Seconds in one epoch. @@ -77,25 +82,26 @@ type validationFn func(ctx context.Context) (pubsub.ValidationResult, error) // config to hold dependencies for the sync service. type config struct { - attestationNotifier operation.Notifier - p2p p2p.P2P - beaconDB db.NoHeadAccessDatabase - attPool attestations.Pool - exitPool voluntaryexits.PoolManager - slashingPool slashings.PoolManager - syncCommsPool synccommittee.Pool - blsToExecPool blstoexec.PoolManager - chain blockchainService - initialSync Checker - blockNotifier blockfeed.Notifier - operationNotifier operation.Notifier - executionPayloadReconstructor execution.PayloadReconstructor - stateGen *stategen.State - slasherAttestationsFeed *event.Feed - slasherBlockHeadersFeed *event.Feed - clock *startup.Clock - stateNotifier statefeed.Notifier - blobStorage *filesystem.BlobStorage + attestationNotifier operation.Notifier + p2p p2p.P2P + beaconDB db.NoHeadAccessDatabase + attestationCache *cache.AttestationCache + attPool attestations.Pool + exitPool voluntaryexits.PoolManager + slashingPool slashings.PoolManager + syncCommsPool synccommittee.Pool + blsToExecPool blstoexec.PoolManager + chain blockchainService + initialSync Checker + blockNotifier blockfeed.Notifier + operationNotifier operation.Notifier + executionReconstructor execution.Reconstructor + stateGen *stategen.State + slasherAttestationsFeed *event.Feed + slasherBlockHeadersFeed *event.Feed + clock *startup.Clock + stateNotifier statefeed.Notifier + blobStorage *filesystem.BlobStorage } // This defines the interface for interacting with block chain service @@ -162,18 +168,18 @@ type Service struct { // NewService initializes new regular sync service. func NewService(ctx context.Context, opts ...Option) *Service { - c := gcache.New(pendingBlockExpTime /* exp time */, 0 /* disable janitor */) ctx, cancel := context.WithCancel(ctx) r := &Service{ ctx: ctx, cancel: cancel, chainStarted: abool.New(), cfg: &config{clock: startup.NewClock(time.Unix(0, 0), [32]byte{})}, - slotToPendingBlocks: c, + slotToPendingBlocks: gcache.New(pendingBlockExpTime /* exp time */, 0 /* disable janitor */), seenPendingBlocks: make(map[[32]byte]bool), blkRootToPendingAtts: make(map[[32]byte][]ethpb.SignedAggregateAttAndProof), signatureChan: make(chan *signatureVerifier, verifierLimit), } + for _, opt := range opts { if err := opt(r); err != nil { return nil @@ -224,7 +230,7 @@ func (s *Service) Start() { s.newBlobVerifier = newBlobVerifierFromInitializer(v) go s.verifierRoutine() - go s.registerHandlers() + go s.startTasksPostInitialSync() s.cfg.p2p.AddConnectionHandler(s.reValidatePeer, s.sendGoodbye) s.cfg.p2p.AddDisconnectionHandler(func(_ context.Context, _ peer.ID) error { @@ -299,14 +305,21 @@ func (s *Service) waitForChainStart() { ctxMap, err := ContextByteVersionsForValRoot(clock.GenesisValidatorsRoot()) if err != nil { - log.WithError(err).WithField("genesisValidatorRoot", clock.GenesisValidatorsRoot()). + log. + WithError(err). + WithField("genesisValidatorRoot", clock.GenesisValidatorsRoot()). Error("sync service failed to initialize context version map") return } s.ctxMap = ctxMap // Register respective rpc handlers at state initialized event. - s.registerRPCHandlers() + err = s.registerRPCHandlers() + if err != nil { + log.WithError(err).Error("Could not register rpc handlers") + return + } + // Wait for chainstart in separate routine. if startTime.After(prysmTime.Now()) { time.Sleep(prysmTime.Until(startTime)) @@ -315,23 +328,31 @@ func (s *Service) waitForChainStart() { s.markForChainStart() } -func (s *Service) registerHandlers() { +func (s *Service) startTasksPostInitialSync() { + // Wait for the chain to start. s.waitForChainStart() + select { case <-s.initialSyncComplete: - // Register respective pubsub handlers at state synced event. - digest, err := s.currentForkDigest() + // Compute the current epoch. + currentSlot := slots.CurrentSlot(uint64(s.cfg.clock.GenesisTime().Unix())) + currentEpoch := slots.ToEpoch(currentSlot) + + // Compute the current fork forkDigest. + forkDigest, err := s.currentForkDigest() if err != nil { log.WithError(err).Error("Could not retrieve current fork digest") return } - currentEpoch := slots.ToEpoch(slots.CurrentSlot(uint64(s.cfg.clock.GenesisTime().Unix()))) - s.registerSubscribers(currentEpoch, digest) + + // Register respective pubsub handlers at state synced event. + s.registerSubscribers(currentEpoch, forkDigest) + + // Start the fork watcher. go s.forkWatcher() - return + case <-s.ctx.Done(): log.Debug("Context closed, exiting goroutine") - return } } diff --git a/beacon-chain/sync/service_test.go b/beacon-chain/sync/service_test.go index 637e3cea0f46..78f42589ae6e 100644 --- a/beacon-chain/sync/service_test.go +++ b/beacon-chain/sync/service_test.go @@ -62,7 +62,7 @@ func TestSyncHandlers_WaitToSync(t *testing.T) { } topic := "/eth2/%x/beacon_block" - go r.registerHandlers() + go r.startTasksPostInitialSync() time.Sleep(100 * time.Millisecond) var vr [32]byte @@ -143,7 +143,7 @@ func TestSyncHandlers_WaitTillSynced(t *testing.T) { syncCompleteCh := make(chan bool) go func() { - r.registerHandlers() + r.startTasksPostInitialSync() syncCompleteCh <- true }() @@ -200,7 +200,7 @@ func TestSyncService_StopCleanly(t *testing.T) { initialSyncComplete: make(chan struct{}), } - go r.registerHandlers() + go r.startTasksPostInitialSync() var vr [32]byte require.NoError(t, gs.SetClock(startup.NewClock(time.Now(), vr))) r.waitForChainStart() diff --git a/beacon-chain/sync/subscriber.go b/beacon-chain/sync/subscriber.go index 3b7f7def672c..69afe97eb06c 100644 --- a/beacon-chain/sync/subscriber.go +++ b/beacon-chain/sync/subscriber.go @@ -20,16 +20,17 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/peers" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" "github.com/prysmaticlabs/prysm/v5/config/features" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/container/slice" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/forks" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/messagehandler" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) @@ -52,6 +53,30 @@ func (s *Service) noopValidator(_ context.Context, _ peer.ID, msg *pubsub.Messag return pubsub.ValidationAccept, nil } +func sliceFromCount(count uint64) []uint64 { + result := make([]uint64, 0, count) + + for item := range count { + result = append(result, item) + } + + return result +} + +func (s *Service) activeSyncSubnetIndices(currentSlot primitives.Slot) []uint64 { + if flags.Get().SubscribeToAllSubnets { + return sliceFromCount(params.BeaconConfig().SyncCommitteeSubnetCount) + } + + // Get the current epoch. + currentEpoch := slots.ToEpoch(currentSlot) + + // Retrieve the subnets we want to subscribe to. + subs := cache.SyncSubnetIDs.GetAllSubnets(currentEpoch) + + return slice.SetUint64(subs) +} + // Register PubSub subscribers func (s *Service) registerSubscribers(epoch primitives.Epoch, digest [4]byte) { s.subscribe( @@ -84,49 +109,34 @@ func (s *Service) registerSubscribers(epoch primitives.Epoch, digest [4]byte) { s.attesterSlashingSubscriber, digest, ) - if flags.Get().SubscribeToAllSubnets { - s.subscribeStaticWithSubnets( - p2p.AttestationSubnetTopicFormat, - s.validateCommitteeIndexBeaconAttestation, /* validator */ - s.committeeIndexBeaconAttestationSubscriber, /* message handler */ - digest, - params.BeaconConfig().AttestationSubnetCount, - ) - } else { - s.subscribeDynamicWithSubnets( - p2p.AttestationSubnetTopicFormat, - s.validateCommitteeIndexBeaconAttestation, /* validator */ - s.committeeIndexBeaconAttestationSubscriber, /* message handler */ - digest, - ) - } - // Altair Fork Version - if epoch >= params.BeaconConfig().AltairForkEpoch { + s.subscribeWithParameters( + p2p.AttestationSubnetTopicFormat, + s.validateCommitteeIndexBeaconAttestation, + s.committeeIndexBeaconAttestationSubscriber, + digest, + s.persistentAndAggregatorSubnetIndices, + s.attesterSubnetIndices, + ) + // Altair fork version + if params.BeaconConfig().AltairForkEpoch <= epoch { s.subscribe( p2p.SyncContributionAndProofSubnetTopicFormat, s.validateSyncContributionAndProof, s.syncContributionAndProofSubscriber, digest, ) - if flags.Get().SubscribeToAllSubnets { - s.subscribeStaticWithSyncSubnets( - p2p.SyncCommitteeSubnetTopicFormat, - s.validateSyncCommitteeMessage, /* validator */ - s.syncCommitteeMessageSubscriber, /* message handler */ - digest, - ) - } else { - s.subscribeDynamicWithSyncSubnets( - p2p.SyncCommitteeSubnetTopicFormat, - s.validateSyncCommitteeMessage, /* validator */ - s.syncCommitteeMessageSubscriber, /* message handler */ - digest, - ) - } + s.subscribeWithParameters( + p2p.SyncCommitteeSubnetTopicFormat, + s.validateSyncCommitteeMessage, + s.syncCommitteeMessageSubscriber, + digest, + s.activeSyncSubnetIndices, + func(currentSlot primitives.Slot) []uint64 { return []uint64{} }, + ) } - // New Gossip Topic in Capella - if epoch >= params.BeaconConfig().CapellaForkEpoch { + // New gossip topic in Capella + if params.BeaconConfig().CapellaForkEpoch <= epoch { s.subscribe( p2p.BlsToExecutionChangeSubnetTopicFormat, s.validateBlsToExecutionChange, @@ -135,14 +145,31 @@ func (s *Service) registerSubscribers(epoch primitives.Epoch, digest [4]byte) { ) } - // New Gossip Topic in Deneb - if epoch >= params.BeaconConfig().DenebForkEpoch { - s.subscribeStaticWithSubnets( + // New gossip topic in Deneb, modified in Electra + if params.BeaconConfig().DenebForkEpoch <= epoch && epoch < params.BeaconConfig().ElectraForkEpoch { + s.subscribeWithParameters( + p2p.BlobSubnetTopicFormat, + s.validateBlob, + s.blobSubscriber, + digest, + func(currentSlot primitives.Slot) []uint64 { + return sliceFromCount(params.BeaconConfig().BlobsidecarSubnetCount) + }, + func(currentSlot primitives.Slot) []uint64 { return []uint64{} }, + ) + } + + // Modified gossip topic in Electra + if params.BeaconConfig().ElectraForkEpoch <= epoch { + s.subscribeWithParameters( p2p.BlobSubnetTopicFormat, - s.validateBlob, /* validator */ - s.blobSubscriber, /* message handler */ + s.validateBlob, + s.blobSubscriber, digest, - params.BeaconConfig().BlobsidecarSubnetCount, + func(currentSlot primitives.Slot) []uint64 { + return sliceFromCount(params.BeaconConfig().BlobsidecarSubnetCountElectra) + }, + func(currentSlot primitives.Slot) []uint64 { return []uint64{} }, ) } } @@ -171,7 +198,7 @@ func (s *Service) subscribeWithBase(topic string, validator wrappedVal, handle s // Do not resubscribe already seen subscriptions. ok := s.subHandler.topicExists(topic) if ok { - log.Debugf("Provided topic already has an active subscription running: %s", topic) + log.WithField("topic", topic).Debug("Provided topic already has an active subscription running") return nil } @@ -188,6 +215,7 @@ func (s *Service) subscribeWithBase(topic string, validator wrappedVal, handle s log.WithError(err).Error("Could not subscribe topic") return nil } + s.subHandler.addTopic(sub.Topic(), sub) // Pipeline decodes the incoming subscription data, runs the validation, and handles the @@ -195,6 +223,7 @@ func (s *Service) subscribeWithBase(topic string, validator wrappedVal, handle s pipeline := func(msg *pubsub.Message) { ctx, cancel := context.WithTimeout(s.ctx, pubsubMessageTimeout) defer cancel() + ctx, span := trace.StartSpan(ctx, "sync.pubsub") defer span.End() @@ -208,7 +237,7 @@ func (s *Service) subscribeWithBase(topic string, validator wrappedVal, handle s } }() - span.AddAttributes(trace.StringAttribute("topic", topic)) + span.SetAttributes(trace.StringAttribute("topic", topic)) if msg.ValidatorData == nil { log.Error("Received nil message on pubsub") @@ -312,8 +341,8 @@ func (s *Service) wrapAndReportValidation(topic string, v wrappedVal) (string, p "multiaddress": multiAddr(pid, s.cfg.p2p.Peers()), "peerID": pid.String(), "agent": agentString(pid, s.cfg.p2p.Host()), - "gossipScore": s.cfg.p2p.Peers().Scorers().GossipScorer().Score(pid), - }).Debugf("Gossip message was ignored") + "gossipScore": fmt.Sprintf("%.2f", s.cfg.p2p.Peers().Scorers().GossipScorer().Score(pid)), + }).Debug("Gossip message was ignored") } messageIgnoredValidationCounter.WithLabelValues(topic).Inc() } @@ -321,139 +350,15 @@ func (s *Service) wrapAndReportValidation(topic string, v wrappedVal) (string, p } } -// subscribe to a static subnet with the given topic and index. A given validator and subscription handler is -// used to handle messages from the subnet. The base protobuf message is used to initialize new messages for decoding. -func (s *Service) subscribeStaticWithSubnets(topic string, validator wrappedVal, handle subHandler, digest [4]byte, subnetCount uint64) { - genRoot := s.cfg.clock.GenesisValidatorsRoot() - _, e, err := forks.RetrieveForkDataFromDigest(digest, genRoot[:]) - if err != nil { - // Impossible condition as it would mean digest does not exist. - panic(err) - } - base := p2p.GossipTopicMappings(topic, e) - if base == nil { - // Impossible condition as it would mean topic does not exist. - panic(fmt.Sprintf("%s is not mapped to any message in GossipTopicMappings", topic)) - } - for i := uint64(0); i < subnetCount; i++ { - s.subscribeWithBase(s.addDigestAndIndexToTopic(topic, digest, i), validator, handle) - } - genesis := s.cfg.clock.GenesisTime() - ticker := slots.NewSlotTicker(genesis, params.BeaconConfig().SecondsPerSlot) - - go func() { - for { - select { - case <-s.ctx.Done(): - ticker.Done() - return - case <-ticker.C(): - if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() { - continue - } - valid, err := isDigestValid(digest, genesis, genRoot) - if err != nil { - log.Error(err) - continue - } - if !valid { - log.Warnf("Attestation subnets with digest %#x are no longer valid, unsubscribing from all of them.", digest) - // Unsubscribes from all our current subnets. - for i := uint64(0); i < subnetCount; i++ { - fullTopic := fmt.Sprintf(topic, digest, i) + s.cfg.p2p.Encoding().ProtocolSuffix() - s.unSubscribeFromTopic(fullTopic) - } - ticker.Done() - return - } - // Check every slot that there are enough peers - for i := uint64(0); i < subnetCount; i++ { - if !s.validPeersExist(s.addDigestAndIndexToTopic(topic, digest, i)) { - log.Debugf("No peers found subscribed to attestation gossip subnet with "+ - "committee index %d. Searching network for peers subscribed to the subnet.", i) - _, err := s.cfg.p2p.FindPeersWithSubnet( - s.ctx, - s.addDigestAndIndexToTopic(topic, digest, i), - i, - flags.Get().MinimumPeersPerSubnet, - ) - if err != nil { - log.WithError(err).Debug("Could not search for peers") - return - } - } - } - } - } - }() -} - -// subscribe to a dynamically changing list of subnets. This method expects a fmt compatible -// string for the topic name and the list of subnets for subscribed topics that should be -// maintained. -func (s *Service) subscribeDynamicWithSubnets( +// reValidateSubscriptions unsubscribe from topics we are currently subscribed to but that are +// not in the list of wanted subnets. +// TODO: Rename this functions as it does not only revalidate subscriptions. +func (s *Service) reValidateSubscriptions( + subscriptions map[uint64]*pubsub.Subscription, + wantedSubs []uint64, topicFormat string, - validate wrappedVal, - handle subHandler, digest [4]byte, ) { - genRoot := s.cfg.clock.GenesisValidatorsRoot() - _, e, err := forks.RetrieveForkDataFromDigest(digest, genRoot[:]) - if err != nil { - // Impossible condition as it would mean digest does not exist. - panic(err) - } - base := p2p.GossipTopicMappings(topicFormat, e) - if base == nil { - panic(fmt.Sprintf("%s is not mapped to any message in GossipTopicMappings", topicFormat)) - } - subscriptions := make(map[uint64]*pubsub.Subscription, params.BeaconConfig().MaxCommitteesPerSlot) - genesis := s.cfg.clock.GenesisTime() - ticker := slots.NewSlotTicker(genesis, params.BeaconConfig().SecondsPerSlot) - - go func() { - for { - select { - case <-s.ctx.Done(): - ticker.Done() - return - case currentSlot := <-ticker.C(): - if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() { - continue - } - valid, err := isDigestValid(digest, genesis, genRoot) - if err != nil { - log.Error(err) - continue - } - if !valid { - log.Warnf("Attestation subnets with digest %#x are no longer valid, unsubscribing from all of them.", digest) - // Unsubscribes from all our current subnets. - s.reValidateSubscriptions(subscriptions, []uint64{}, topicFormat, digest) - ticker.Done() - return - } - wantedSubs := s.retrievePersistentSubs(currentSlot) - // Resize as appropriate. - s.reValidateSubscriptions(subscriptions, wantedSubs, topicFormat, digest) - - // subscribe desired aggregator subnets. - for _, idx := range wantedSubs { - s.subscribeAggregatorSubnet(subscriptions, idx, digest, validate, handle) - } - // find desired subs for attesters - attesterSubs := s.attesterSubnetIndices(currentSlot) - for _, idx := range attesterSubs { - s.lookupAttesterSubnets(digest, idx) - } - } - } - }() -} - -// revalidate that our currently connected subnets are valid. -func (s *Service) reValidateSubscriptions(subscriptions map[uint64]*pubsub.Subscription, - wantedSubs []uint64, topicFormat string, digest [4]byte) { for k, v := range subscriptions { var wanted bool for _, idx := range wantedSubs { @@ -462,6 +367,7 @@ func (s *Service) reValidateSubscriptions(subscriptions map[uint64]*pubsub.Subsc break } } + if !wanted && v != nil { v.Cancel() fullTopic := fmt.Sprintf(topicFormat, digest, k) + s.cfg.p2p.Encoding().ProtocolSuffix() @@ -471,198 +377,180 @@ func (s *Service) reValidateSubscriptions(subscriptions map[uint64]*pubsub.Subsc } } -// subscribe missing subnets for our aggregators. -func (s *Service) subscribeAggregatorSubnet( - subscriptions map[uint64]*pubsub.Subscription, - idx uint64, +// searchForPeers searches for peers in the given subnets. +func (s *Service) searchForPeers( + ctx context.Context, + topicFormat string, digest [4]byte, - validate wrappedVal, - handle subHandler, + currentSlot primitives.Slot, + getSubnetsToSubscribe func(currentSlot primitives.Slot) []uint64, + getSubnetsToFindPeersOnly func(currentSlot primitives.Slot) []uint64, ) { - // do not subscribe if we have no peers in the same - // subnet - topic := p2p.GossipTypeMapping[reflect.TypeOf(ðpb.Attestation{})] - subnetTopic := fmt.Sprintf(topic, digest, idx) - // check if subscription exists and if not subscribe the relevant subnet. - if _, exists := subscriptions[idx]; !exists { - subscriptions[idx] = s.subscribeWithBase(subnetTopic, validate, handle) - } - if !s.validPeersExist(subnetTopic) { - log.Debugf("No peers found subscribed to attestation gossip subnet with "+ - "committee index %d. Searching network for peers subscribed to the subnet.", idx) - _, err := s.cfg.p2p.FindPeersWithSubnet(s.ctx, subnetTopic, idx, flags.Get().MinimumPeersPerSubnet) + // Retrieve the subnets we want to subscribe to. + subnetsToSubscribeIndex := getSubnetsToSubscribe(currentSlot) + + // Retrieve the subnets we want to find peers for. + subnetsToFindPeersOnlyIndex := getSubnetsToFindPeersOnly(currentSlot) + + // Combine the subnets to subscribe and the subnets to find peers for. + subnetsToFindPeersIndex := slice.SetUint64(append(subnetsToSubscribeIndex, subnetsToFindPeersOnlyIndex...)) + + // Find new peers for wanted subnets if needed. + for _, subnetIndex := range subnetsToFindPeersIndex { + topic := fmt.Sprintf(topicFormat, digest, subnetIndex) + + // Check if we have enough peers in the subnet. Skip if we do. + if s.enoughPeersAreConnected(topic) { + continue + } + + // Not enough peers in the subnet, we need to search for more. + _, err := s.cfg.p2p.FindPeersWithSubnet(ctx, topic, subnetIndex, flags.Get().MinimumPeersPerSubnet) if err != nil { log.WithError(err).Debug("Could not search for peers") } } } -// subscribe missing subnets for our sync committee members. -func (s *Service) subscribeSyncSubnet( - subscriptions map[uint64]*pubsub.Subscription, - idx uint64, +// subscribeToSubnets subscribes to needed subnets, unsubscribe from unneeded ones and search for more peers if needed. +// Returns `true` if the digest is valid (wrt. the current epoch), `false` otherwise. +func (s *Service) subscribeToSubnets( + topicFormat string, digest [4]byte, + genesisValidatorsRoot [fieldparams.RootLength]byte, + genesisTime time.Time, + subscriptions map[uint64]*pubsub.Subscription, + currentSlot primitives.Slot, validate wrappedVal, handle subHandler, -) { - // do not subscribe if we have no peers in the same - // subnet - topic := p2p.GossipTypeMapping[reflect.TypeOf(ðpb.SyncCommitteeMessage{})] - subnetTopic := fmt.Sprintf(topic, digest, idx) - // check if subscription exists and if not subscribe the relevant subnet. - if _, exists := subscriptions[idx]; !exists { - subscriptions[idx] = s.subscribeWithBase(subnetTopic, validate, handle) - } - if !s.validPeersExist(subnetTopic) { - log.Debugf("No peers found subscribed to sync gossip subnet with "+ - "committee index %d. Searching network for peers subscribed to the subnet.", idx) - _, err := s.cfg.p2p.FindPeersWithSubnet(s.ctx, subnetTopic, idx, flags.Get().MinimumPeersPerSubnet) - if err != nil { - log.WithError(err).Debug("Could not search for peers") - } + getSubnetsToSubscribe func(currentSlot primitives.Slot) []uint64, + getSubnetsToFindPeersOnly func(currentSlot primitives.Slot) []uint64, +) bool { + // Do not subscribe if not synced. + if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() { + return true } -} -// subscribe to a static subnet with the given topic and index. A given validator and subscription handler is -// used to handle messages from the subnet. The base protobuf message is used to initialize new messages for decoding. -func (s *Service) subscribeStaticWithSyncSubnets(topic string, validator wrappedVal, handle subHandler, digest [4]byte) { - genRoot := s.cfg.clock.GenesisValidatorsRoot() - _, e, err := forks.RetrieveForkDataFromDigest(digest, genRoot[:]) + // Check the validity of the digest. + valid, err := isDigestValid(digest, genesisTime, genesisValidatorsRoot) if err != nil { - panic(err) - } - base := p2p.GossipTopicMappings(topic, e) - if base == nil { - panic(fmt.Sprintf("%s is not mapped to any message in GossipTopicMappings", topic)) + log.Error(err) + return true } - for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { - s.subscribeWithBase(s.addDigestAndIndexToTopic(topic, digest, i), validator, handle) + + // Unsubscribe from all subnets if the digest is not valid. It's likely to be the case after a hard fork. + if !valid { + description := topicFormat + if pos := strings.LastIndex(topicFormat, "/"); pos != -1 { + description = topicFormat[pos+1:] + } + + if pos := strings.LastIndex(description, "_"); pos != -1 { + description = description[:pos] + } + + log.WithFields(logrus.Fields{ + "digest": fmt.Sprintf("%#x", digest), + "subnets": description, + }).Debug("Subnets with this digest are no longer valid, unsubscribing from all of them") + s.reValidateSubscriptions(subscriptions, []uint64{}, topicFormat, digest) + return false } - genesis := s.cfg.clock.GenesisTime() - ticker := slots.NewSlotTicker(genesis, params.BeaconConfig().SecondsPerSlot) - go func() { - for { - select { - case <-s.ctx.Done(): - ticker.Done() - return - case <-ticker.C(): - if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() { - continue - } - valid, err := isDigestValid(digest, genesis, genRoot) - if err != nil { - log.Error(err) - continue - } - if !valid { - log.Warnf("Sync subnets with digest %#x are no longer valid, unsubscribing from all of them.", digest) - // Unsubscribes from all our current subnets. - for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { - fullTopic := fmt.Sprintf(topic, digest, i) + s.cfg.p2p.Encoding().ProtocolSuffix() - s.unSubscribeFromTopic(fullTopic) - } - ticker.Done() - return - } - // Check every slot that there are enough peers - for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { - if !s.validPeersExist(s.addDigestAndIndexToTopic(topic, digest, i)) { - log.Debugf("No peers found subscribed to sync gossip subnet with "+ - "committee index %d. Searching network for peers subscribed to the subnet.", i) - _, err := s.cfg.p2p.FindPeersWithSubnet( - s.ctx, - s.addDigestAndIndexToTopic(topic, digest, i), - i, - flags.Get().MinimumPeersPerSubnet, - ) - if err != nil { - log.WithError(err).Debug("Could not search for peers") - return - } - } - } - } + // Retrieve the subnets we want to subscribe to. + subnetsToSubscribeIndex := getSubnetsToSubscribe(currentSlot) + + // Remove subscriptions that are no longer wanted. + s.reValidateSubscriptions(subscriptions, subnetsToSubscribeIndex, topicFormat, digest) + + // Subscribe to wanted subnets. + for _, subnetIndex := range subnetsToSubscribeIndex { + subnetTopic := fmt.Sprintf(topicFormat, digest, subnetIndex) + + // Check if subscription exists. + if _, exists := subscriptions[subnetIndex]; exists { + continue } - }() + + // We need to subscribe to the subnet. + subscription := s.subscribeWithBase(subnetTopic, validate, handle) + subscriptions[subnetIndex] = subscription + } + return true } -// subscribe to a dynamically changing list of subnets. This method expects a fmt compatible -// string for the topic name and the list of subnets for subscribed topics that should be -// maintained. -func (s *Service) subscribeDynamicWithSyncSubnets( +// subscribeWithParameters subscribes to a list of subnets. +func (s *Service) subscribeWithParameters( topicFormat string, validate wrappedVal, handle subHandler, digest [4]byte, + getSubnetsToSubscribe func(currentSlot primitives.Slot) []uint64, + getSubnetsToFindPeersOnly func(currentSlot primitives.Slot) []uint64, ) { - genRoot := s.cfg.clock.GenesisValidatorsRoot() - _, e, err := forks.RetrieveForkDataFromDigest(digest, genRoot[:]) + // Initialize the subscriptions map. + subscriptions := make(map[uint64]*pubsub.Subscription) + + // Retrieve the genesis validators root. + genesisValidatorsRoot := s.cfg.clock.GenesisValidatorsRoot() + + // Retrieve the epoch of the fork corresponding to the digest. + _, epoch, err := forks.RetrieveForkDataFromDigest(digest, genesisValidatorsRoot[:]) if err != nil { panic(err) } - base := p2p.GossipTopicMappings(topicFormat, e) + + // Retrieve the base protobuf message. + base := p2p.GossipTopicMappings(topicFormat, epoch) if base == nil { panic(fmt.Sprintf("%s is not mapped to any message in GossipTopicMappings", topicFormat)) } - subscriptions := make(map[uint64]*pubsub.Subscription, params.BeaconConfig().SyncCommitteeSubnetCount) - genesis := s.cfg.clock.GenesisTime() - ticker := slots.NewSlotTicker(genesis, params.BeaconConfig().SecondsPerSlot) + + // Retrieve the genesis time. + genesisTime := s.cfg.clock.GenesisTime() + + // Define a ticker ticking every slot. + secondsPerSlot := params.BeaconConfig().SecondsPerSlot + ticker := slots.NewSlotTicker(genesisTime, secondsPerSlot) + + // Retrieve the current slot. + currentSlot := s.cfg.clock.CurrentSlot() + + // Subscribe to subnets. + s.subscribeToSubnets(topicFormat, digest, genesisValidatorsRoot, genesisTime, subscriptions, currentSlot, validate, handle, getSubnetsToSubscribe, getSubnetsToFindPeersOnly) + + // Derive a new context and cancel function. + ctx, cancel := context.WithCancel(s.ctx) go func() { + // Search for peers. + s.searchForPeers(ctx, topicFormat, digest, currentSlot, getSubnetsToSubscribe, getSubnetsToFindPeersOnly) + for { select { - case <-s.ctx.Done(): - ticker.Done() - return case currentSlot := <-ticker.C(): - if s.chainStarted.IsSet() && s.cfg.initialSync.Syncing() { - continue - } - valid, err := isDigestValid(digest, genesis, genRoot) - if err != nil { - log.Error(err) - continue - } - if !valid { - log.Warnf("Sync subnets with digest %#x are no longer valid, unsubscribing from all of them.", digest) - // Unsubscribes from all our current subnets. - s.reValidateSubscriptions(subscriptions, []uint64{}, topicFormat, digest) + isDigestValid := s.subscribeToSubnets(topicFormat, digest, genesisValidatorsRoot, genesisTime, subscriptions, currentSlot, validate, handle, getSubnetsToSubscribe, getSubnetsToFindPeersOnly) + + // Stop the ticker if the digest is not valid. Likely to happen after a hard fork. + if !isDigestValid { ticker.Done() return } - wantedSubs := s.retrieveActiveSyncSubnets(slots.ToEpoch(currentSlot)) - // Resize as appropriate. - s.reValidateSubscriptions(subscriptions, wantedSubs, topicFormat, digest) + // Search for peers. + s.searchForPeers(ctx, topicFormat, digest, currentSlot, getSubnetsToSubscribe, getSubnetsToFindPeersOnly) - // subscribe desired aggregator subnets. - for _, idx := range wantedSubs { - s.subscribeSyncSubnet(subscriptions, idx, digest, validate, handle) - } + case <-s.ctx.Done(): + cancel() + ticker.Done() + return } } }() } -// lookup peers for attester specific subnets. -func (s *Service) lookupAttesterSubnets(digest [4]byte, idx uint64) { - topic := p2p.GossipTypeMapping[reflect.TypeOf(ðpb.Attestation{})] - subnetTopic := fmt.Sprintf(topic, digest, idx) - if !s.validPeersExist(subnetTopic) { - log.Debugf("No peers found subscribed to attestation gossip subnet with "+ - "committee index %d. Searching network for peers subscribed to the subnet.", idx) - // perform a search for peers with the desired committee index. - _, err := s.cfg.p2p.FindPeersWithSubnet(s.ctx, subnetTopic, idx, flags.Get().MinimumPeersPerSubnet) - if err != nil { - log.WithError(err).Debug("Could not search for peers") - } - } -} - func (s *Service) unSubscribeFromTopic(topic string) { - log.WithField("topic", topic).Debug("Unsubscribing from topic") + log.WithField("topic", topic).Info("Unsubscribed from") if err := s.cfg.p2p.PubSub().UnregisterTopicValidator(topic); err != nil { log.WithError(err).Error("Could not unregister topic validator") } @@ -676,25 +564,27 @@ func (s *Service) unSubscribeFromTopic(topic string) { } } -// find if we have peers who are subscribed to the same subnet -func (s *Service) validPeersExist(subnetTopic string) bool { - numOfPeers := s.cfg.p2p.PubSub().ListPeers(subnetTopic + s.cfg.p2p.Encoding().ProtocolSuffix()) - return len(numOfPeers) >= flags.Get().MinimumPeersPerSubnet -} +// enoughPeersAreConnected checks if we have enough peers which are subscribed to the same subnet. +func (s *Service) enoughPeersAreConnected(subnetTopic string) bool { + topic := subnetTopic + s.cfg.p2p.Encoding().ProtocolSuffix() + threshold := flags.Get().MinimumPeersPerSubnet -func (s *Service) retrievePersistentSubs(currSlot primitives.Slot) []uint64 { - // Persistent subscriptions from validators - persistentSubs := s.persistentSubnetIndices() - // Update desired topic indices for aggregator - wantedSubs := s.aggregatorSubnetIndices(currSlot) + peersWithSubnet := s.cfg.p2p.PubSub().ListPeers(topic) + peersWithSubnetCount := len(peersWithSubnet) - // Combine subscriptions to get all requested subscriptions - return slice.SetUint64(append(persistentSubs, wantedSubs...)) + return peersWithSubnetCount >= threshold } -func (*Service) retrieveActiveSyncSubnets(currEpoch primitives.Epoch) []uint64 { - subs := cache.SyncSubnetIDs.GetAllSubnets(currEpoch) - return slice.SetUint64(subs) +func (s *Service) persistentAndAggregatorSubnetIndices(currentSlot primitives.Slot) []uint64 { + if flags.Get().SubscribeToAllSubnets { + return sliceFromCount(params.BeaconConfig().AttestationSubnetCount) + } + + persistentSubnetIndices := s.persistentSubnetIndices() + aggregatorSubnetIndices := s.aggregatorSubnetIndices(currentSlot) + + // Combine subscriptions to get all requested subscriptions. + return slice.SetUint64(append(persistentSubnetIndices, aggregatorSubnetIndices...)) } // filters out required peers for the node to function, not @@ -710,7 +600,7 @@ func (s *Service) filterNeededPeers(pids []peer.ID) []peer.ID { return pids } currSlot := s.cfg.clock.CurrentSlot() - wantedSubs := s.retrievePersistentSubs(currSlot) + wantedSubs := s.persistentAndAggregatorSubnetIndices(currSlot) wantedSubs = slice.SetUint64(append(wantedSubs, s.attesterSubnetIndices(currSlot)...)) topic := p2p.GossipTypeMapping[reflect.TypeOf(ðpb.Attestation{})] diff --git a/beacon-chain/sync/subscriber_beacon_aggregate_proof.go b/beacon-chain/sync/subscriber_beacon_aggregate_proof.go index 06380ec948f2..439c9a46dd58 100644 --- a/beacon-chain/sync/subscriber_beacon_aggregate_proof.go +++ b/beacon-chain/sync/subscriber_beacon_aggregate_proof.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/config/features" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "google.golang.org/protobuf/proto" ) @@ -24,10 +24,13 @@ func (s *Service) beaconAggregateProofSubscriber(_ context.Context, msg proto.Me return errors.New("nil aggregate") } - // An unaggregated attestation can make it here. It’s valid, the aggregator it just itself, although it means poor performance for the subnet. - if !helpers.IsAggregated(aggregate) { - return s.cfg.attPool.SaveUnaggregatedAttestation(aggregate) + if features.Get().EnableExperimentalAttestationPool { + return s.cfg.attestationCache.Add(aggregate) + } else { + // An unaggregated attestation can make it here. It’s valid, the aggregator it just itself, although it means poor performance for the subnet. + if !aggregate.IsAggregated() { + return s.cfg.attPool.SaveUnaggregatedAttestation(aggregate) + } + return s.cfg.attPool.SaveAggregatedAttestation(aggregate) } - - return s.cfg.attPool.SaveAggregatedAttestation(aggregate) } diff --git a/beacon-chain/sync/subscriber_beacon_attestation.go b/beacon-chain/sync/subscriber_beacon_attestation.go index d6d280c38811..37c4c7972429 100644 --- a/beacon-chain/sync/subscriber_beacon_attestation.go +++ b/beacon-chain/sync/subscriber_beacon_attestation.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/cache" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/container/slice" @@ -25,17 +26,21 @@ func (s *Service) committeeIndexBeaconAttestationSubscriber(_ context.Context, m if data == nil { return errors.New("nil attestation") } - s.setSeenCommitteeIndicesSlot(data.Slot, data.CommitteeIndex, a.GetAggregationBits()) + committeeIndex := a.GetCommitteeIndex() + s.setSeenCommitteeIndicesSlot(data.Slot, committeeIndex, a.GetAggregationBits()) - exists, err := s.cfg.attPool.HasAggregatedAttestation(a) - if err != nil { - return errors.Wrap(err, "could not determine if attestation pool has this attestation") + if features.Get().EnableExperimentalAttestationPool { + return s.cfg.attestationCache.Add(a) + } else { + exists, err := s.cfg.attPool.HasAggregatedAttestation(a) + if err != nil { + return errors.Wrap(err, "could not determine if attestation pool has this attestation") + } + if exists { + return nil + } + return s.cfg.attPool.SaveUnaggregatedAttestation(a) } - if exists { - return nil - } - - return s.cfg.attPool.SaveUnaggregatedAttestation(a) } func (*Service) persistentSubnetIndices() []uint64 { diff --git a/beacon-chain/sync/subscriber_beacon_blocks.go b/beacon-chain/sync/subscriber_beacon_blocks.go index ff5f4c16457a..908d5370f505 100644 --- a/beacon-chain/sync/subscriber_beacon_blocks.go +++ b/beacon-chain/sync/subscriber_beacon_blocks.go @@ -12,6 +12,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/io/file" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/time/slots" "google.golang.org/protobuf/proto" ) @@ -33,6 +35,8 @@ func (s *Service) beaconBlockSubscriber(ctx context.Context, msg proto.Message) return err } + go s.reconstructAndBroadcastBlobs(ctx, signed) + if err := s.cfg.chain.ReceiveBlock(ctx, signed, root, nil); err != nil { if blockchain.IsInvalidBlock(err) { r := blockchain.InvalidBlockRoot(err) @@ -55,6 +59,80 @@ func (s *Service) beaconBlockSubscriber(ctx context.Context, msg proto.Message) return err } +// reconstructAndBroadcastBlobs processes and broadcasts blob sidecars for a given beacon block. +// This function reconstructs the blob sidecars from the EL using the block's KZG commitments, +// broadcasts the reconstructed blobs over P2P, and saves them into the blob storage. +func (s *Service) reconstructAndBroadcastBlobs(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock) { + if block.Version() < version.Deneb { + return + } + + startTime, err := slots.ToTime(uint64(s.cfg.chain.GenesisTime().Unix()), block.Block().Slot()) + if err != nil { + log.WithError(err).Error("Failed to convert slot to time") + } + + blockRoot, err := block.Block().HashTreeRoot() + if err != nil { + log.WithError(err).Error("Failed to calculate block root") + return + } + + if s.cfg.blobStorage == nil { + return + } + summary := s.cfg.blobStorage.Summary(blockRoot) + cmts, err := block.Block().Body().BlobKzgCommitments() + if err != nil { + log.WithError(err).Error("Failed to read commitments from block") + return + } + for i := range cmts { + if summary.HasIndex(uint64(i)) { + blobExistedInDBTotal.Inc() + } + } + + // Reconstruct blob sidecars from the EL + blobSidecars, err := s.cfg.executionReconstructor.ReconstructBlobSidecars(ctx, block, blockRoot, summary.HasIndex) + if err != nil { + log.WithError(err).Error("Failed to reconstruct blob sidecars") + return + } + if len(blobSidecars) == 0 { + return + } + + // Refresh indices as new blobs may have been added to the db + summary = s.cfg.blobStorage.Summary(blockRoot) + + // Broadcast blob sidecars first than save them to the db + for _, sidecar := range blobSidecars { + // Don't broadcast the blob if it has appeared on disk. + if summary.HasIndex(sidecar.Index) { + continue + } + if err := s.cfg.p2p.BroadcastBlob(ctx, sidecar.Index, sidecar.BlobSidecar); err != nil { + log.WithFields(blobFields(sidecar.ROBlob)).WithError(err).Error("Failed to broadcast blob sidecar") + } + } + + for _, sidecar := range blobSidecars { + if summary.HasIndex(sidecar.Index) { + continue + } + if err := s.subscribeBlob(ctx, sidecar); err != nil { + log.WithFields(blobFields(sidecar.ROBlob)).WithError(err).Error("Failed to receive blob") + continue + } + + blobRecoveredFromELTotal.Inc() + fields := blobFields(sidecar.ROBlob) + fields["sinceSlotStartTime"] = s.cfg.clock.Now().Sub(startTime) + log.WithFields(fields).Debug("Processed blob sidecar from EL") + } +} + // WriteInvalidBlockToDisk as a block ssz. Writes to temp directory. func saveInvalidBlockToTemp(block interfaces.ReadOnlySignedBeaconBlock) { if !features.Get().SaveInvalidBlock { diff --git a/beacon-chain/sync/subscriber_beacon_blocks_test.go b/beacon-chain/sync/subscriber_beacon_blocks_test.go index 626215144af6..8291c3e0a4eb 100644 --- a/beacon-chain/sync/subscriber_beacon_blocks_test.go +++ b/beacon-chain/sync/subscriber_beacon_blocks_test.go @@ -8,15 +8,20 @@ import ( "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" chainMock "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain/testing" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" dbtest "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution" + mockExecution "github.com/prysmaticlabs/prysm/v5/beacon-chain/execution/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations" + mockp2p "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" + "github.com/prysmaticlabs/prysm/v5/time" "google.golang.org/protobuf/proto" ) @@ -66,13 +71,15 @@ func TestService_beaconBlockSubscriber(t *testing.T) { DB: db, Root: make([]byte, 32), }, - attPool: attestations.NewPool(), + attPool: attestations.NewPool(), + blobStorage: filesystem.NewEphemeralBlobStorage(t), + executionReconstructor: &mockExecution.EngineClient{}, }, } s.initCaches() // Set up attestation pool. for _, att := range pooledAttestations { - if helpers.IsAggregated(att) { + if att.IsAggregated() { assert.NoError(t, s.cfg.attPool.SaveAggregatedAttestation(att)) } else { assert.NoError(t, s.cfg.attPool.SaveUnaggregatedAttestation(att)) @@ -124,3 +131,65 @@ func TestService_BeaconBlockSubscribe_UndefinedEeError(t *testing.T) { require.Equal(t, 0, len(s.badBlockCache.Keys())) require.Equal(t, 1, len(s.seenBlockCache.Keys())) } + +func TestReconstructAndBroadcastBlobs(t *testing.T) { + rob, err := blocks.NewROBlob( + ðpb.BlobSidecar{ + SignedBlockHeader: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + ParentRoot: make([]byte, 32), + BodyRoot: make([]byte, 32), + StateRoot: make([]byte, 32), + }, + Signature: []byte("signature"), + }, + }) + require.NoError(t, err) + + chainService := &chainMock.ChainService{ + Genesis: time.Now(), + } + + b := util.NewBeaconBlockDeneb() + sb, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + + tests := []struct { + name string + blobSidecars []blocks.VerifiedROBlob + expectedBlobCount int + }{ + { + name: "Constructed 0 blobs", + blobSidecars: nil, + expectedBlobCount: 0, + }, + { + name: "Constructed 6 blobs", + blobSidecars: []blocks.VerifiedROBlob{ + {ROBlob: rob}, {ROBlob: rob}, {ROBlob: rob}, {ROBlob: rob}, {ROBlob: rob}, {ROBlob: rob}, + }, + expectedBlobCount: 6, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := Service{ + cfg: &config{ + p2p: mockp2p.NewTestP2P(t), + chain: chainService, + clock: startup.NewClock(time.Now(), [32]byte{}), + blobStorage: filesystem.NewEphemeralBlobStorage(t), + executionReconstructor: &mockExecution.EngineClient{ + BlobSidecars: tt.blobSidecars, + }, + operationNotifier: &chainMock.MockOperationNotifier{}, + }, + seenBlobCache: lruwrpr.New(1), + } + s.reconstructAndBroadcastBlobs(context.Background(), sb) + require.Equal(t, tt.expectedBlobCount, len(chainService.Blobs)) + }) + } +} diff --git a/beacon-chain/sync/subscriber_blob_sidecar.go b/beacon-chain/sync/subscriber_blob_sidecar.go index e93638bdad10..c96288226c64 100644 --- a/beacon-chain/sync/subscriber_blob_sidecar.go +++ b/beacon-chain/sync/subscriber_blob_sidecar.go @@ -13,9 +13,13 @@ import ( func (s *Service) blobSubscriber(ctx context.Context, msg proto.Message) error { b, ok := msg.(blocks.VerifiedROBlob) if !ok { - return fmt.Errorf("message was not type blocks.ROBlob, type=%T", msg) + return fmt.Errorf("message was not type blocks.VerifiedROBlob, type=%T", msg) } + return s.subscribeBlob(ctx, b) +} + +func (s *Service) subscribeBlob(ctx context.Context, b blocks.VerifiedROBlob) error { s.setSeenBlobIndex(b.Slot(), b.ProposerIndex(), b.Index) if err := s.cfg.chain.ReceiveBlob(ctx, b); err != nil { diff --git a/beacon-chain/sync/subscriber_test.go b/beacon-chain/sync/subscriber_test.go index d0bae7fe4aa9..0840313c8013 100644 --- a/beacon-chain/sync/subscriber_test.go +++ b/beacon-chain/sync/subscriber_test.go @@ -312,37 +312,6 @@ func TestRevalidateSubscription_CorrectlyFormatsTopic(t *testing.T) { require.LogsDoNotContain(t, hook, "Could not unregister topic validator") } -func TestStaticSubnets(t *testing.T) { - p := p2ptest.NewTestP2P(t) - ctx, cancel := context.WithCancel(context.Background()) - chain := &mockChain.ChainService{ - Genesis: time.Now(), - ValidatorsRoot: [32]byte{'A'}, - } - r := Service{ - ctx: ctx, - cfg: &config{ - chain: chain, - clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), - p2p: p, - }, - chainStarted: abool.New(), - subHandler: newSubTopicHandler(), - } - defaultTopic := "/eth2/%x/beacon_attestation_%d" - d, err := r.currentForkDigest() - assert.NoError(t, err) - r.subscribeStaticWithSubnets(defaultTopic, r.noopValidator, func(_ context.Context, msg proto.Message) error { - // no-op - return nil - }, d, params.BeaconConfig().AttestationSubnetCount) - topics := r.cfg.p2p.PubSub().GetTopics() - if uint64(len(topics)) != params.BeaconConfig().AttestationSubnetCount { - t.Errorf("Wanted the number of subnet topics registered to be %d but got %d", params.BeaconConfig().AttestationSubnetCount, len(topics)) - } - cancel() -} - func Test_wrapAndReportValidation(t *testing.T) { mChain := &mockChain.ChainService{ Genesis: time.Now(), @@ -539,37 +508,6 @@ func TestFilterSubnetPeers(t *testing.T) { assert.Equal(t, 1, len(recPeers), "expected at least 1 suitable peer to prune") } -func TestSubscribeWithSyncSubnets_StaticOK(t *testing.T) { - params.SetupTestConfigCleanup(t) - cfg := params.MainnetTestConfig().Copy() - cfg.SecondsPerSlot = 1 - params.OverrideBeaconConfig(cfg) - - p := p2ptest.NewTestP2P(t) - ctx, cancel := context.WithCancel(context.Background()) - chain := &mockChain.ChainService{ - Genesis: time.Now(), - ValidatorsRoot: [32]byte{'A'}, - } - r := Service{ - ctx: ctx, - cfg: &config{ - chain: chain, - clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), - p2p: p, - }, - chainStarted: abool.New(), - subHandler: newSubTopicHandler(), - } - // Empty cache at the end of the test. - defer cache.SyncSubnetIDs.EmptyAllCaches() - digest, err := r.currentForkDigest() - assert.NoError(t, err) - r.subscribeStaticWithSyncSubnets(p2p.SyncCommitteeSubnetTopicFormat, nil, nil, digest) - assert.Equal(t, int(params.BeaconConfig().SyncCommitteeSubnetCount), len(r.cfg.p2p.PubSub().GetTopics())) - cancel() -} - func TestSubscribeWithSyncSubnets_DynamicOK(t *testing.T) { params.SetupTestConfigCleanup(t) cfg := params.MainnetConfig().Copy() @@ -600,7 +538,7 @@ func TestSubscribeWithSyncSubnets_DynamicOK(t *testing.T) { cache.SyncSubnetIDs.AddSyncCommitteeSubnets([]byte("pubkey"), currEpoch, []uint64{0, 1}, 10*time.Second) digest, err := r.currentForkDigest() assert.NoError(t, err) - r.subscribeDynamicWithSyncSubnets(p2p.SyncCommitteeSubnetTopicFormat, nil, nil, digest) + r.subscribeWithParameters(p2p.SyncCommitteeSubnetTopicFormat, nil, nil, digest, r.activeSyncSubnetIndices, func(currentSlot primitives.Slot) []uint64 { return []uint64{} }) time.Sleep(2 * time.Second) assert.Equal(t, 2, len(r.cfg.p2p.PubSub().GetTopics())) topicMap := map[string]bool{} @@ -615,46 +553,6 @@ func TestSubscribeWithSyncSubnets_DynamicOK(t *testing.T) { cancel() } -func TestSubscribeWithSyncSubnets_StaticSwitchFork(t *testing.T) { - p := p2ptest.NewTestP2P(t) - params.SetupTestConfigCleanup(t) - cfg := params.BeaconConfig() - cfg.AltairForkEpoch = 1 - cfg.SecondsPerSlot = 1 - params.OverrideBeaconConfig(cfg) - params.BeaconConfig().InitializeForkSchedule() - ctx, cancel := context.WithCancel(context.Background()) - currSlot := primitives.Slot(100) - chain := &mockChain.ChainService{ - Genesis: time.Now().Add(-time.Duration(uint64(params.BeaconConfig().SlotsPerEpoch)*params.BeaconConfig().SecondsPerSlot) * time.Second), - ValidatorsRoot: [32]byte{'A'}, - Slot: &currSlot, - } - r := Service{ - ctx: ctx, - cfg: &config{ - chain: chain, - clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), - p2p: p, - }, - chainStarted: abool.New(), - subHandler: newSubTopicHandler(), - } - // Empty cache at the end of the test. - defer cache.SyncSubnetIDs.EmptyAllCaches() - genRoot := r.cfg.clock.GenesisValidatorsRoot() - digest, err := signing.ComputeForkDigest(params.BeaconConfig().GenesisForkVersion, genRoot[:]) - assert.NoError(t, err) - r.subscribeStaticWithSyncSubnets(p2p.SyncCommitteeSubnetTopicFormat, nil, nil, digest) - assert.Equal(t, int(params.BeaconConfig().SyncCommitteeSubnetCount), len(r.cfg.p2p.PubSub().GetTopics())) - - // Expect that all old topics will be unsubscribed. - time.Sleep(2 * time.Second) - assert.Equal(t, 0, len(r.cfg.p2p.PubSub().GetTopics())) - - cancel() -} - func TestSubscribeWithSyncSubnets_DynamicSwitchFork(t *testing.T) { params.SetupTestConfigCleanup(t) p := p2ptest.NewTestP2P(t) @@ -689,7 +587,7 @@ func TestSubscribeWithSyncSubnets_DynamicSwitchFork(t *testing.T) { digest, err := signing.ComputeForkDigest(params.BeaconConfig().GenesisForkVersion, genRoot[:]) assert.NoError(t, err) - r.subscribeDynamicWithSyncSubnets(p2p.SyncCommitteeSubnetTopicFormat, nil, nil, digest) + r.subscribeWithParameters(p2p.SyncCommitteeSubnetTopicFormat, nil, nil, digest, r.activeSyncSubnetIndices, func(currentSlot primitives.Slot) []uint64 { return []uint64{} }) time.Sleep(2 * time.Second) assert.Equal(t, 2, len(r.cfg.p2p.PubSub().GetTopics())) topicMap := map[string]bool{} diff --git a/beacon-chain/sync/sync_test.go b/beacon-chain/sync/sync_test.go index 578c0b9e529d..6db83b5dd299 100644 --- a/beacon-chain/sync/sync_test.go +++ b/beacon-chain/sync/sync_test.go @@ -2,6 +2,7 @@ package sync import ( "io" + "os" "testing" "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags" @@ -16,11 +17,11 @@ func TestMain(m *testing.M) { flags.Init(&flags.GlobalFlags{ BlockBatchLimit: 64, BlockBatchLimitBurstFactor: 10, - BlobBatchLimit: 8, + BlobBatchLimit: 32, BlobBatchLimitBurstFactor: 2, }) defer func() { flags.Init(resetFlags) }() - m.Run() + os.Exit(m.Run()) } diff --git a/beacon-chain/sync/validate_aggregate_proof.go b/beacon-chain/sync/validate_aggregate_proof.go index 8c753b6eb7d8..b33f1f0193e5 100644 --- a/beacon-chain/sync/validate_aggregate_proof.go +++ b/beacon-chain/sync/validate_aggregate_proof.go @@ -14,16 +14,16 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/runtime/version" prysmTime "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // validateAggregateAndProof verifies the aggregated signature and the selection proof is valid before forwarding to the @@ -57,11 +57,10 @@ func (s *Service) validateAggregateAndProof(ctx context.Context, pid peer.ID, ms } aggregate := m.AggregateAttestationAndProof().AggregateVal() - data := aggregate.GetData() - if err := helpers.ValidateNilAttestation(aggregate); err != nil { return pubsub.ValidationReject, err } + data := aggregate.GetData() // Do not process slot 0 aggregates. if data.Slot == 0 { return pubsub.ValidationIgnore, nil @@ -69,18 +68,12 @@ func (s *Service) validateAggregateAndProof(ctx context.Context, pid peer.ID, ms // Broadcast the aggregated attestation on a feed to notify other services in the beacon node // of a received aggregated attestation. - // TODO: this will be extended to Electra in a later PR - if m.Version() == version.Phase0 { - phase0Att, ok := m.(*ethpb.SignedAggregateAttestationAndProof) - if ok { - s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ - Type: operation.AggregatedAttReceived, - Data: &operation.AggregatedAttReceivedData{ - Attestation: phase0Att.Message, - }, - }) - } - } + s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.AggregatedAttReceived, + Data: &operation.AggregatedAttReceivedData{ + Attestation: m.AggregateAttestationAndProof(), + }, + }) if err := helpers.ValidateSlotTargetEpoch(data); err != nil { return pubsub.ValidationReject, err @@ -109,15 +102,31 @@ func (s *Service) validateAggregateAndProof(ctx context.Context, pid peer.ID, ms return pubsub.ValidationReject, errors.New("bad block referenced in attestation data") } - // Verify aggregate attestation has not already been seen via aggregate gossip, within a block, or through the creation locally. - seen, err := s.cfg.attPool.HasAggregatedAttestation(aggregate) - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - if seen { - return pubsub.ValidationIgnore, nil + if features.Get().EnableExperimentalAttestationPool { + // It is possible that some aggregate in the pool already covers all bits + // of this aggregate, in which case we can ignore it. + isRedundant, err := s.cfg.attestationCache.AggregateIsRedundant(aggregate) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + if isRedundant { + return pubsub.ValidationIgnore, nil + } + } else { + // Verify aggregate attestation has not already been seen via aggregate gossip, within a block, or through the creation locally. + seen, err := s.cfg.attPool.HasAggregatedAttestation(aggregate) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + if seen { + return pubsub.ValidationIgnore, nil + } } + + // Verify the block being voted on is in the beacon chain. + // If not, store this attestation in the map of pending attestations. if !s.validateBlockInAttestation(ctx, m) { return pubsub.ValidationIgnore, nil } @@ -167,39 +176,39 @@ func (s *Service) validateAggregatedAtt(ctx context.Context, signed ethpb.Signed return pubsub.ValidationIgnore, err } + committeeIndex, _, result, err := s.validateCommitteeIndexAndCount(ctx, aggregate, bs) + if result != pubsub.ValidationAccept { + wrappedErr := errors.Wrapf(err, "could not validate committee index") + tracing.AnnotateError(span, wrappedErr) + return result, err + } + + committee, err := helpers.BeaconCommitteeFromState(ctx, bs, aggregate.GetData().Slot, committeeIndex) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + + // Verify number of aggregation bits matches the committee size. + if err = helpers.VerifyBitfieldLength(aggregate.GetAggregationBits(), uint64(len(committee))); err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationReject, err + } + // Verify validator index is within the beacon committee. - result, err := s.validateIndexInCommittee(ctx, bs, aggregate, aggregatorIndex) + result, err = s.validateIndexInCommittee(ctx, aggregate, aggregatorIndex, committee) if result != pubsub.ValidationAccept { wrappedErr := errors.Wrapf(err, "could not validate index in committee") tracing.AnnotateError(span, wrappedErr) return result, wrappedErr } - var committeeIndex primitives.CommitteeIndex - if signed.Version() >= version.Electra { - a, ok := aggregate.(*ethpb.AttestationElectra) - // This will never fail in practice because we asserted the version - if !ok { - err := fmt.Errorf("aggregate attestation has wrong type (expected %T, got %T)", ðpb.AttestationElectra{}, aggregate) - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - committeeIndex, result, err = validateCommitteeIndexElectra(ctx, a) - if result != pubsub.ValidationAccept { - wrappedErr := errors.Wrapf(err, "could not validate committee index for Electra version") - tracing.AnnotateError(span, wrappedErr) - return result, wrappedErr - } - } else { - committeeIndex = data.CommitteeIndex - } - // Verify selection proof reflects to the right validator. selectionSigSet, err := validateSelectionIndex( ctx, bs, data.Slot, - committeeIndex, + committee, aggregatorIndex, aggregateAndProof.GetSelectionProof(), ) @@ -230,6 +239,8 @@ func (s *Service) validateAggregatedAtt(ctx context.Context, signed ethpb.Signed return s.validateWithBatchVerifier(ctx, "aggregate", set) } +// validateBlocksInAttestation checks if the block being voted on is in the beaconDB. +// If not, it store this attestation in the map of pending attestations. func (s *Service) validateBlockInAttestation(ctx context.Context, satt ethpb.SignedAggregateAttAndProof) bool { // Verify the block being voted and the processed state is in beaconDB. The block should have passed validation if it's in the beaconDB. blockRoot := bytesutil.ToBytes32(satt.AggregateAttestationAndProof().AggregateVal().GetData().BeaconBlockRoot) @@ -266,20 +277,10 @@ func (s *Service) setAggregatorIndexEpochSeen(epoch primitives.Epoch, aggregator // - [REJECT] The aggregate attestation has participants -- that is, len(get_attesting_indices(state, aggregate.data, aggregate.aggregation_bits)) >= 1. // - [REJECT] The aggregator's validator index is within the committee -- // i.e. `aggregate_and_proof.aggregator_index in get_beacon_committee(state, aggregate.data.slot, aggregate.data.index)`. -func (s *Service) validateIndexInCommittee(ctx context.Context, bs state.ReadOnlyBeaconState, a ethpb.Att, validatorIndex primitives.ValidatorIndex) (pubsub.ValidationResult, error) { - ctx, span := trace.StartSpan(ctx, "sync.validateIndexInCommittee") +func (s *Service) validateIndexInCommittee(ctx context.Context, a ethpb.Att, validatorIndex primitives.ValidatorIndex, committee []primitives.ValidatorIndex) (pubsub.ValidationResult, error) { + _, span := trace.StartSpan(ctx, "sync.validateIndexInCommittee") defer span.End() - _, result, err := s.validateCommitteeIndex(ctx, a, bs) - if result != pubsub.ValidationAccept { - return result, err - } - - committee, result, err := s.validateBitLength(ctx, bs, a.GetData().Slot, a.GetData().CommitteeIndex, a.GetAggregationBits()) - if result != pubsub.ValidationAccept { - return result, err - } - if a.GetAggregationBits().Count() == 0 { return pubsub.ValidationReject, errors.New("no attesting indices") } @@ -304,17 +305,13 @@ func validateSelectionIndex( ctx context.Context, bs state.ReadOnlyBeaconState, slot primitives.Slot, - committeeIndex primitives.CommitteeIndex, + committee []primitives.ValidatorIndex, validatorIndex primitives.ValidatorIndex, proof []byte, ) (*bls.SignatureBatch, error) { - ctx, span := trace.StartSpan(ctx, "sync.validateSelectionIndex") + _, span := trace.StartSpan(ctx, "sync.validateSelectionIndex") defer span.End() - committee, err := helpers.BeaconCommitteeFromState(ctx, bs, slot, committeeIndex) - if err != nil { - return nil, err - } aggregator, err := helpers.IsAggregator(uint64(len(committee)), proof) if err != nil { return nil, err @@ -326,11 +323,12 @@ func validateSelectionIndex( domain := params.BeaconConfig().DomainSelectionProof epoch := slots.ToEpoch(slot) - v, err := bs.ValidatorAtIndex(validatorIndex) + v, err := bs.ValidatorAtIndexReadOnly(validatorIndex) if err != nil { return nil, err } - publicKey, err := bls.PublicKeyFromBytes(v.PublicKey) + pk := v.PublicKey() + publicKey, err := bls.PublicKeyFromBytes(pk[:]) if err != nil { return nil, err } @@ -356,11 +354,12 @@ func validateSelectionIndex( func aggSigSet(s state.ReadOnlyBeaconState, a ethpb.SignedAggregateAttAndProof) (*bls.SignatureBatch, error) { aggregateAndProof := a.AggregateAttestationAndProof() - v, err := s.ValidatorAtIndex(aggregateAndProof.GetAggregatorIndex()) + v, err := s.ValidatorAtIndexReadOnly(aggregateAndProof.GetAggregatorIndex()) if err != nil { return nil, err } - publicKey, err := bls.PublicKeyFromBytes(v.PublicKey) + pk := v.PublicKey() + publicKey, err := bls.PublicKeyFromBytes(pk[:]) if err != nil { return nil, err } diff --git a/beacon-chain/sync/validate_aggregate_proof_test.go b/beacon-chain/sync/validate_aggregate_proof_test.go index a8e5539aed13..b3e49fc8ac90 100644 --- a/beacon-chain/sync/validate_aggregate_proof_test.go +++ b/beacon-chain/sync/validate_aggregate_proof_test.go @@ -44,20 +44,19 @@ func TestVerifyIndexInCommittee_CanVerify(t *testing.T) { bf := bitfield.NewBitlist(validators / uint64(params.BeaconConfig().SlotsPerEpoch)) bf.SetBitAt(0, true) - att := ðpb.Attestation{Data: ðpb.AttestationData{ - Target: ðpb.Checkpoint{Epoch: 0}}, - AggregationBits: bf} + att := ðpb.Attestation{Data: ðpb.AttestationData{}, AggregationBits: bf} committee, err := helpers.BeaconCommitteeFromState(context.Background(), s, att.Data.Slot, att.Data.CommitteeIndex) assert.NoError(t, err) indices, err := attestation.AttestingIndices(att, committee) require.NoError(t, err) - result, err := service.validateIndexInCommittee(ctx, s, att, primitives.ValidatorIndex(indices[0])) + + result, err := service.validateIndexInCommittee(ctx, att, primitives.ValidatorIndex(indices[0]), committee) require.NoError(t, err) assert.Equal(t, pubsub.ValidationAccept, result) wanted := "validator index 1000 is not within the committee" - result, err = service.validateIndexInCommittee(ctx, s, att, 1000) + result, err = service.validateIndexInCommittee(ctx, att, 1000, committee) assert.ErrorContains(t, wanted, err) assert.Equal(t, pubsub.ValidationReject, result) } @@ -71,8 +70,7 @@ func TestVerifyIndexInCommittee_ExistsInBeaconCommittee(t *testing.T) { s, _ := util.DeterministicGenesisState(t, validators) require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch)) - att := ðpb.Attestation{Data: ðpb.AttestationData{ - Target: ðpb.Checkpoint{Epoch: 0}}} + att := ðpb.Attestation{Data: ðpb.AttestationData{}} committee, err := helpers.BeaconCommitteeFromState(context.Background(), s, att.Data.Slot, att.Data.CommitteeIndex) require.NoError(t, err) @@ -81,32 +79,45 @@ func TestVerifyIndexInCommittee_ExistsInBeaconCommittee(t *testing.T) { att.AggregationBits = bl service := &Service{} - result, err := service.validateIndexInCommittee(ctx, s, att, committee[0]) + result, err := service.validateIndexInCommittee(ctx, att, committee[0], committee) require.ErrorContains(t, "no attesting indices", err) assert.Equal(t, pubsub.ValidationReject, result) att.AggregationBits.SetBitAt(0, true) - result, err = service.validateIndexInCommittee(ctx, s, att, committee[0]) + result, err = service.validateIndexInCommittee(ctx, att, committee[0], committee) require.NoError(t, err) assert.Equal(t, pubsub.ValidationAccept, result) wanted := "validator index 1000 is not within the committee" - result, err = service.validateIndexInCommittee(ctx, s, att, 1000) + result, err = service.validateIndexInCommittee(ctx, att, 1000, committee) assert.ErrorContains(t, wanted, err) assert.Equal(t, pubsub.ValidationReject, result) - att.AggregationBits = bitfield.NewBitlist(1) - result, err = service.validateIndexInCommittee(ctx, s, att, committee[0]) - require.ErrorContains(t, "wanted participants bitfield length 4, got: 1", err) - assert.Equal(t, pubsub.ValidationReject, result) - att.Data.CommitteeIndex = 10000 - result, err = service.validateIndexInCommittee(ctx, s, att, committee[0]) + _, _, result, err = service.validateCommitteeIndexAndCount(ctx, att, s) require.ErrorContains(t, "committee index 10000 > 2", err) assert.Equal(t, pubsub.ValidationReject, result) } +func TestVerifyIndexInCommittee_Electra(t *testing.T) { + ctx := context.Background() + s, _ := util.DeterministicGenesisStateElectra(t, 64) + service := &Service{} + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(0, true) + att := ðpb.AttestationElectra{Data: ðpb.AttestationData{}, CommitteeBits: cb} + committee, err := helpers.BeaconCommitteeFromState(context.Background(), s, att.Data.Slot, att.Data.CommitteeIndex) + require.NoError(t, err) + bl := bitfield.NewBitlist(uint64(len(committee))) + bl.SetBitAt(0, true) + att.AggregationBits = bl + + result, err := service.validateIndexInCommittee(ctx, att, committee[0], committee) + require.NoError(t, err) + assert.Equal(t, pubsub.ValidationAccept, result) +} + func TestVerifySelection_NotAnAggregator(t *testing.T) { ctx := context.Background() params.SetupTestConfigCleanup(t) @@ -116,8 +127,9 @@ func TestVerifySelection_NotAnAggregator(t *testing.T) { sig := privKeys[0].Sign([]byte{'A'}) data := util.HydrateAttestationData(ðpb.AttestationData{}) - - _, err := validateSelectionIndex(ctx, beaconState, data.Slot, data.CommitteeIndex, 0, sig.Marshal()) + committee, err := helpers.BeaconCommitteeFromState(ctx, beaconState, data.Slot, data.CommitteeIndex) + require.NoError(t, err) + _, err = validateSelectionIndex(ctx, beaconState, data.Slot, committee, 0, sig.Marshal()) wanted := "validator is not an aggregator for slot" assert.ErrorContains(t, wanted, err) } diff --git a/beacon-chain/sync/validate_attester_slashing.go b/beacon-chain/sync/validate_attester_slashing.go index d854a94c0e96..1b752bd55dd7 100644 --- a/beacon-chain/sync/validate_attester_slashing.go +++ b/beacon-chain/sync/validate_attester_slashing.go @@ -13,9 +13,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/container/slice" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // Clients who receive an attester slashing on this topic MUST validate the conditions within VerifyAttesterSlashing before diff --git a/beacon-chain/sync/validate_attester_slashing_test.go b/beacon-chain/sync/validate_attester_slashing_test.go index 591dfffdb811..7234151306c3 100644 --- a/beacon-chain/sync/validate_attester_slashing_test.go +++ b/beacon-chain/sync/validate_attester_slashing_test.go @@ -3,7 +3,7 @@ package sync import ( "bytes" "context" - "math/rand" + "crypto/rand" "reflect" "testing" "time" diff --git a/beacon-chain/sync/validate_beacon_attestation.go b/beacon-chain/sync/validate_beacon_attestation.go index 2cea8638bbd4..7aaa943bbe5b 100644 --- a/beacon-chain/sync/validate_beacon_attestation.go +++ b/beacon-chain/sync/validate_beacon_attestation.go @@ -9,7 +9,6 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/peer" "github.com/pkg/errors" - "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed" @@ -22,11 +21,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" ) // Validation @@ -62,24 +61,15 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p if !ok { return pubsub.ValidationReject, errWrongMessage } - - data := att.GetData() - if err := helpers.ValidateNilAttestation(att); err != nil { return pubsub.ValidationReject, err } + data := att.GetData() + // Do not process slot 0 attestations. if data.Slot == 0 { return pubsub.ValidationIgnore, nil } - // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node - // of a received unaggregated attestation. - s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ - Type: operation.UnaggregatedAttReceived, - Data: &operation.UnAggregatedAttReceivedData{ - Attestation: att, - }, - }) // Attestation's slot is within ATTESTATION_PROPAGATION_SLOT_RANGE and early attestation // processing tolerance. @@ -92,25 +82,75 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p return pubsub.ValidationReject, err } + committeeIndex := att.GetCommitteeIndex() + + if !features.Get().EnableSlasher { + // Verify this the first attestation received for the participating validator for the slot. + if s.hasSeenCommitteeIndicesSlot(data.Slot, committeeIndex, att.GetAggregationBits()) { + return pubsub.ValidationIgnore, nil + } + + // Reject an attestation if it references an invalid block. + if s.hasBadBlock(bytesutil.ToBytes32(data.BeaconBlockRoot)) || + s.hasBadBlock(bytesutil.ToBytes32(data.Target.Root)) || + s.hasBadBlock(bytesutil.ToBytes32(data.Source.Root)) { + attBadBlockCount.Inc() + return pubsub.ValidationReject, errors.New("attestation data references bad block root") + } + } + var validationRes pubsub.ValidationResult - var committeeIndex primitives.CommitteeIndex + // Verify the block being voted and the processed state is in beaconDB and the block has passed validation if it's in the beaconDB. + blockRoot := bytesutil.ToBytes32(data.BeaconBlockRoot) + if !s.hasBlockAndState(ctx, blockRoot) { + return s.saveToPendingAttPool(att) + } + + if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { + tracing.AnnotateError(span, blockchain.ErrNotDescendantOfFinalized) + return pubsub.ValidationIgnore, blockchain.ErrNotDescendantOfFinalized + } + if err = s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { + tracing.AnnotateError(span, err) + attBadLmdConsistencyCount.Inc() + return pubsub.ValidationReject, err + } + + preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + + validationRes, err = s.validateUnaggregatedAttTopic(ctx, att, preState, *msg.Topic) + if validationRes != pubsub.ValidationAccept { + return validationRes, err + } + + committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.GetData().Slot, committeeIndex) + if err != nil { + tracing.AnnotateError(span, err) + return pubsub.ValidationIgnore, err + } + + validationRes, err = validateAttesterData(ctx, att, committee) + if validationRes != pubsub.ValidationAccept { + return validationRes, err + } + + var singleAtt *eth.SingleAttestation if att.Version() >= version.Electra { - a, ok := att.(*eth.AttestationElectra) - // This will never fail in practice because we asserted the version + singleAtt, ok = att.(*eth.SingleAttestation) if !ok { - err := fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.AttestationElectra{}, att) - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err + return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, att) } - committeeIndex, validationRes, err = validateCommitteeIndexElectra(ctx, a) - if validationRes != pubsub.ValidationAccept { - wrappedErr := errors.Wrapf(err, "could not validate committee index for Electra version") - tracing.AnnotateError(span, wrappedErr) - return validationRes, wrappedErr - } - } else { - committeeIndex = data.CommitteeIndex + att = singleAtt.ToAttestationElectra(committee) + } + + validationRes, err = s.validateUnaggregatedAttWithState(ctx, att, preState) + if validationRes != pubsub.ValidationAccept { + return validationRes, err } if features.Get().EnableSlasher { @@ -142,68 +182,25 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p }() } - // Verify this the first attestation received for the participating validator for the slot. - if s.hasSeenCommitteeIndicesSlot(data.Slot, data.CommitteeIndex, att.GetAggregationBits()) { - return pubsub.ValidationIgnore, nil - } - - // Reject an attestation if it references an invalid block. - if s.hasBadBlock(bytesutil.ToBytes32(data.BeaconBlockRoot)) || - s.hasBadBlock(bytesutil.ToBytes32(data.Target.Root)) || - s.hasBadBlock(bytesutil.ToBytes32(data.Source.Root)) { - attBadBlockCount.Inc() - return pubsub.ValidationReject, errors.New("attestation data references bad block root") - } - - // Verify the block being voted and the processed state is in beaconDB and the block has passed validation if it's in the beaconDB. - blockRoot := bytesutil.ToBytes32(data.BeaconBlockRoot) - if !s.hasBlockAndState(ctx, blockRoot) { - // A node doesn't have the block, it'll request from peer while saving the pending attestation to a queue. - if att.Version() >= version.Electra { - a, ok := att.(*eth.AttestationElectra) - // This will never fail in practice because we asserted the version - if !ok { - return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.AttestationElectra{}, att) - } - s.savePendingAtt(ð.SignedAggregateAttestationAndProofElectra{Message: ð.AggregateAttestationAndProofElectra{Aggregate: a}}) - } else { - a, ok := att.(*eth.Attestation) - // This will never fail in practice because we asserted the version - if !ok { - return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.Attestation{}, att) - } - s.savePendingAtt(ð.SignedAggregateAttestationAndProof{Message: ð.AggregateAttestationAndProof{Aggregate: a}}) - } - return pubsub.ValidationIgnore, nil - } - - if !s.cfg.chain.InForkchoice(bytesutil.ToBytes32(data.BeaconBlockRoot)) { - tracing.AnnotateError(span, blockchain.ErrNotDescendantOfFinalized) - return pubsub.ValidationIgnore, blockchain.ErrNotDescendantOfFinalized - } - if err := s.cfg.chain.VerifyLmdFfgConsistency(ctx, att); err != nil { - tracing.AnnotateError(span, err) - attBadLmdConsistencyCount.Inc() - return pubsub.ValidationReject, err - } - - preState, err := s.cfg.chain.AttestationTargetState(ctx, data.Target) - if err != nil { - tracing.AnnotateError(span, err) - return pubsub.ValidationIgnore, err - } - - validationRes, err = s.validateUnaggregatedAttTopic(ctx, att, preState, *msg.Topic) - if validationRes != pubsub.ValidationAccept { - return validationRes, err - } - - validationRes, err = s.validateUnaggregatedAttWithState(ctx, att, preState) - if validationRes != pubsub.ValidationAccept { - return validationRes, err + // Broadcast the unaggregated attestation on a feed to notify other services in the beacon node + // of a received unaggregated attestation. + if singleAtt != nil { + s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.SingleAttReceived, + Data: &operation.SingleAttReceivedData{ + Attestation: singleAtt, + }, + }) + } else { + s.cfg.attestationNotifier.OperationFeed().Send(&feed.Event{ + Type: operation.UnaggregatedAttReceived, + Data: &operation.UnAggregatedAttReceivedData{ + Attestation: att, + }, + }) } - s.setSeenCommitteeIndicesSlot(data.Slot, data.CommitteeIndex, att.GetAggregationBits()) + s.setSeenCommitteeIndicesSlot(data.Slot, committeeIndex, att.GetAggregationBits()) msg.ValidatorData = att @@ -215,7 +212,7 @@ func (s *Service) validateUnaggregatedAttTopic(ctx context.Context, a eth.Att, b ctx, span := trace.StartSpan(ctx, "sync.validateUnaggregatedAttTopic") defer span.End() - valCount, result, err := s.validateCommitteeIndex(ctx, a, bs) + _, valCount, result, err := s.validateCommitteeIndexAndCount(ctx, a, bs) if result != pubsub.ValidationAccept { return result, err } @@ -233,29 +230,44 @@ func (s *Service) validateUnaggregatedAttTopic(ctx context.Context, a eth.Att, b return pubsub.ValidationAccept, nil } -func (s *Service) validateCommitteeIndex(ctx context.Context, a eth.Att, bs state.ReadOnlyBeaconState) (uint64, pubsub.ValidationResult, error) { +func (s *Service) validateCommitteeIndexAndCount( + ctx context.Context, + a eth.Att, + bs state.ReadOnlyBeaconState, +) (primitives.CommitteeIndex, uint64, pubsub.ValidationResult, error) { + // - [REJECT] attestation.data.index == 0 + if a.Version() >= version.Electra && a.GetData().CommitteeIndex != 0 { + return 0, 0, pubsub.ValidationReject, errors.New("attestation data's committee index must be 0") + } valCount, err := helpers.ActiveValidatorCount(ctx, bs, slots.ToEpoch(a.GetData().Slot)) if err != nil { - return 0, pubsub.ValidationIgnore, err + return 0, 0, pubsub.ValidationIgnore, err } count := helpers.SlotCommitteeCount(valCount) - if uint64(a.GetData().CommitteeIndex) > count { - return 0, pubsub.ValidationReject, errors.Errorf("committee index %d > %d", a.GetData().CommitteeIndex, count) + ci := a.GetCommitteeIndex() + if uint64(ci) > count { + return 0, 0, pubsub.ValidationReject, fmt.Errorf("committee index %d > %d", ci, count) } - return valCount, pubsub.ValidationAccept, nil + return ci, valCount, pubsub.ValidationAccept, nil } -// This validates beacon unaggregated attestation using the given state, the validation consists of bitfield length and count consistency -// and signature verification. -func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.Att, bs state.ReadOnlyBeaconState) (pubsub.ValidationResult, error) { - ctx, span := trace.StartSpan(ctx, "sync.validateUnaggregatedAttWithState") - defer span.End() - - committee, result, err := s.validateBitLength(ctx, bs, a.GetData().Slot, a.GetData().CommitteeIndex, a.GetAggregationBits()) - if result != pubsub.ValidationAccept { - return result, err +func validateAttesterData( + ctx context.Context, + a eth.Att, + committee []primitives.ValidatorIndex, +) (pubsub.ValidationResult, error) { + if a.Version() >= version.Electra { + singleAtt, ok := a.(*eth.SingleAttestation) + if !ok { + return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, a) + } + return validateAttestingIndex(ctx, singleAtt.AttesterIndex, committee) } + // Verify number of aggregation bits matches the committee size. + if err := helpers.VerifyBitfieldLength(a.GetAggregationBits(), uint64(len(committee))); err != nil { + return pubsub.ValidationReject, err + } // Attestation must be unaggregated and the bit index must exist in the range of committee indices. // Note: The Ethereum Beacon chain spec suggests (len(get_attesting_indices(state, attestation.data, attestation.aggregation_bits)) == 1) // however this validation can be achieved without use of get_attesting_indices which is an O(n) lookup. @@ -263,33 +275,46 @@ func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.At return pubsub.ValidationReject, errors.New("attestation bitfield is invalid") } + return pubsub.ValidationAccept, nil +} + +// This validates beacon unaggregated attestation using the given state, the validation consists of signature verification. +func (s *Service) validateUnaggregatedAttWithState(ctx context.Context, a eth.Att, bs state.ReadOnlyBeaconState) (pubsub.ValidationResult, error) { + ctx, span := trace.StartSpan(ctx, "sync.validateUnaggregatedAttWithState") + defer span.End() + set, err := blocks.AttestationSignatureBatch(ctx, bs, []eth.Att{a}) if err != nil { tracing.AnnotateError(span, err) attBadSignatureBatchCount.Inc() return pubsub.ValidationReject, err } + return s.validateWithBatchVerifier(ctx, "attestation", set) } -func (s *Service) validateBitLength( +func validateAttestingIndex( ctx context.Context, - bs state.ReadOnlyBeaconState, - slot primitives.Slot, - committeeIndex primitives.CommitteeIndex, - aggregationBits bitfield.Bitlist, -) ([]primitives.ValidatorIndex, pubsub.ValidationResult, error) { - committee, err := helpers.BeaconCommitteeFromState(ctx, bs, slot, committeeIndex) - if err != nil { - return nil, pubsub.ValidationIgnore, err - } + attestingIndex primitives.ValidatorIndex, + committee []primitives.ValidatorIndex, +) (pubsub.ValidationResult, error) { + _, span := trace.StartSpan(ctx, "sync.validateAttestingIndex") + defer span.End() - // Verify number of aggregation bits matches the committee size. - if err := helpers.VerifyBitfieldLength(aggregationBits, uint64(len(committee))); err != nil { - return nil, pubsub.ValidationReject, err + // _[REJECT]_ The attester is a member of the committee -- i.e. + // `attestation.attester_index in get_beacon_committee(state, attestation.data.slot, index)`. + inCommittee := false + for _, ix := range committee { + if attestingIndex == ix { + inCommittee = true + break + } + } + if !inCommittee { + return pubsub.ValidationReject, errors.New("attester is not a member of the committee") } - return committee, pubsub.ValidationAccept, nil + return pubsub.ValidationAccept, nil } // Returns true if the attestation was already seen for the participating validator for the slot. @@ -318,3 +343,31 @@ func (s *Service) hasBlockAndState(ctx context.Context, blockRoot [32]byte) bool hasState := hasStateSummary || s.cfg.beaconDB.HasState(ctx, blockRoot) return hasState && s.cfg.chain.HasBlock(ctx, blockRoot) } + +func (s *Service) saveToPendingAttPool(att eth.Att) (pubsub.ValidationResult, error) { + // A node doesn't have the block, it'll request from peer while saving the pending attestation to a queue. + if att.Version() >= version.Electra { + a, ok := att.(*eth.SingleAttestation) + // This will never fail in practice because we asserted the version + if !ok { + return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.SingleAttestation{}, att) + } + // Even though there is no AggregateAndProof type to hold a single attestation, our design of pending atts pool + // requires to have an AggregateAndProof object, even for unaggregated attestations. + // Because of this we need to have a single attestation version of it to be able to save single attestations into the pool. + // It's not possible to convert the single attestation into an electra attestation before saving to the pool + // because crucial verification steps can't be performed without the block, and converting prior to these checks + // opens up DoS attacks. + // The AggregateAndProof object is discarded once we process the pending attestation and code paths dealing + // with "real" AggregateAndProof objects (ones that hold actual aggregates) don't use the single attestation version anywhere. + s.savePendingAtt(ð.SignedAggregateAttestationAndProofSingle{Message: ð.AggregateAttestationAndProofSingle{Aggregate: a}}) + } else { + a, ok := att.(*eth.Attestation) + // This will never fail in practice because we asserted the version + if !ok { + return pubsub.ValidationIgnore, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.Attestation{}, att) + } + s.savePendingAtt(ð.SignedAggregateAttestationAndProof{Message: ð.AggregateAttestationAndProof{Aggregate: a}}) + } + return pubsub.ValidationIgnore, nil +} diff --git a/beacon-chain/sync/validate_beacon_attestation_electra.go b/beacon-chain/sync/validate_beacon_attestation_electra.go deleted file mode 100644 index 3ed3fe9c1899..000000000000 --- a/beacon-chain/sync/validate_beacon_attestation_electra.go +++ /dev/null @@ -1,27 +0,0 @@ -package sync - -import ( - "context" - "fmt" - - pubsub "github.com/libp2p/go-libp2p-pubsub" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" -) - -func validateCommitteeIndexElectra(ctx context.Context, a *ethpb.AttestationElectra) (primitives.CommitteeIndex, pubsub.ValidationResult, error) { - _, span := trace.StartSpan(ctx, "sync.validateCommitteeIndexElectra") - defer span.End() - - ci := a.Data.CommitteeIndex - if ci != 0 { - return 0, pubsub.ValidationReject, fmt.Errorf("committee index must be 0 but was %d", ci) - } - committeeIndices := helpers.CommitteeIndices(a.CommitteeBits) - if len(committeeIndices) != 1 { - return 0, pubsub.ValidationReject, fmt.Errorf("exactly 1 committee index must be set but %d were set", len(committeeIndices)) - } - return committeeIndices[0], pubsub.ValidationAccept, nil -} diff --git a/beacon-chain/sync/validate_beacon_attestation_electra_test.go b/beacon-chain/sync/validate_beacon_attestation_electra_test.go deleted file mode 100644 index 81c8e2e9dff9..000000000000 --- a/beacon-chain/sync/validate_beacon_attestation_electra_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package sync - -import ( - "context" - "testing" - - pubsub "github.com/libp2p/go-libp2p-pubsub" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/assert" - "github.com/prysmaticlabs/prysm/v5/testing/require" -) - -func Test_validateCommitteeIndexElectra(t *testing.T) { - ctx := context.Background() - - t.Run("valid", func(t *testing.T) { - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(1, true) - ci, res, err := validateCommitteeIndexElectra(ctx, ðpb.AttestationElectra{Data: ðpb.AttestationData{}, CommitteeBits: cb}) - require.NoError(t, err) - assert.Equal(t, pubsub.ValidationAccept, res) - assert.Equal(t, primitives.CommitteeIndex(1), ci) - }) - t.Run("non-zero data committee index", func(t *testing.T) { - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(1, true) - _, res, err := validateCommitteeIndexElectra(ctx, ðpb.AttestationElectra{Data: ðpb.AttestationData{CommitteeIndex: 1}, CommitteeBits: cb}) - assert.NotNil(t, err) - assert.Equal(t, pubsub.ValidationReject, res) - }) - t.Run("no committee bits set", func(t *testing.T) { - cb := primitives.NewAttestationCommitteeBits() - _, res, err := validateCommitteeIndexElectra(ctx, ðpb.AttestationElectra{Data: ðpb.AttestationData{}, CommitteeBits: cb}) - assert.NotNil(t, err) - assert.Equal(t, pubsub.ValidationReject, res) - }) - t.Run("more than 1 committee bit set", func(t *testing.T) { - cb := primitives.NewAttestationCommitteeBits() - cb.SetBitAt(0, true) - cb.SetBitAt(1, true) - _, res, err := validateCommitteeIndexElectra(ctx, ðpb.AttestationElectra{Data: ðpb.AttestationData{}, CommitteeBits: cb}) - assert.NotNil(t, err) - assert.Equal(t, pubsub.ValidationReject, res) - }) -} diff --git a/beacon-chain/sync/validate_beacon_attestation_test.go b/beacon-chain/sync/validate_beacon_attestation_test.go index 2451352fb421..70adc55e8534 100644 --- a/beacon-chain/sync/validate_beacon_attestation_test.go +++ b/beacon-chain/sync/validate_beacon_attestation_test.go @@ -20,6 +20,7 @@ import ( lruwrpr "github.com/prysmaticlabs/prysm/v5/cache/lru" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -81,7 +82,7 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) { tests := []struct { name string - msg *ethpb.Attestation + msg ethpb.Att topic string validAttestationSignature bool want bool @@ -262,20 +263,20 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) { helpers.ClearCache() chain.ValidAttestation = tt.validAttestationSignature if tt.validAttestationSignature { - com, err := helpers.BeaconCommitteeFromState(context.Background(), savedState, tt.msg.Data.Slot, tt.msg.Data.CommitteeIndex) + com, err := helpers.BeaconCommitteeFromState(context.Background(), savedState, tt.msg.GetData().Slot, tt.msg.GetData().CommitteeIndex) require.NoError(t, err) - domain, err := signing.Domain(savedState.Fork(), tt.msg.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, savedState.GenesisValidatorsRoot()) + domain, err := signing.Domain(savedState.Fork(), tt.msg.GetData().Target.Epoch, params.BeaconConfig().DomainBeaconAttester, savedState.GenesisValidatorsRoot()) require.NoError(t, err) - attRoot, err := signing.ComputeSigningRoot(tt.msg.Data, domain) + attRoot, err := signing.ComputeSigningRoot(tt.msg.GetData(), domain) require.NoError(t, err) for i := 0; ; i++ { - if tt.msg.AggregationBits.BitAt(uint64(i)) { - tt.msg.Signature = keys[com[i]].Sign(attRoot[:]).Marshal() + if tt.msg.GetAggregationBits().BitAt(uint64(i)) { + tt.msg.SetSignature(keys[com[i]].Sign(attRoot[:]).Marshal()) break } } } else { - tt.msg.Signature = make([]byte, 96) + tt.msg.SetSignature(make([]byte, 96)) } buf := new(bytes.Buffer) _, err := p.Encoding().EncodeGossip(buf, tt.msg) @@ -305,6 +306,165 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) { } } +func TestService_validateCommitteeIndexBeaconAttestationElectra(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig() + fvs := map[[fieldparams.VersionLength]byte]primitives.Epoch{} + fvs[bytesutil.ToBytes4(cfg.GenesisForkVersion)] = 1 + fvs[bytesutil.ToBytes4(cfg.AltairForkVersion)] = 2 + fvs[bytesutil.ToBytes4(cfg.BellatrixForkVersion)] = 3 + fvs[bytesutil.ToBytes4(cfg.CapellaForkVersion)] = 4 + fvs[bytesutil.ToBytes4(cfg.DenebForkVersion)] = 5 + fvs[bytesutil.ToBytes4(cfg.FuluForkVersion)] = 6 + fvs[bytesutil.ToBytes4(cfg.ElectraForkVersion)] = 0 + cfg.ForkVersionSchedule = fvs + params.OverrideBeaconConfig(cfg) + + p := p2ptest.NewTestP2P(t) + db := dbtest.SetupDB(t) + chain := &mockChain.ChainService{ + // 1 slot ago. + Genesis: time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second), + ValidatorsRoot: [32]byte{'A'}, + ValidAttestation: true, + DB: db, + Optimistic: true, + } + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + s := &Service{ + ctx: ctx, + cfg: &config{ + initialSync: &mockSync.Sync{IsSyncing: false}, + p2p: p, + beaconDB: db, + chain: chain, + clock: startup.NewClock(chain.Genesis, chain.ValidatorsRoot), + attestationNotifier: (&mockChain.ChainService{}).OperationNotifier(), + }, + blkRootToPendingAtts: make(map[[32]byte][]ethpb.SignedAggregateAttAndProof), + seenUnAggregatedAttestationCache: lruwrpr.New(10), + signatureChan: make(chan *signatureVerifier, verifierLimit), + } + s.initCaches() + go s.verifierRoutine() + + digest, err := s.currentForkDigest() + require.NoError(t, err) + + blk := util.NewBeaconBlock() + blk.Block.Slot = 1 + util.SaveBlock(t, ctx, db, blk) + + validBlockRoot, err := blk.Block.HashTreeRoot() + require.NoError(t, err) + chain.FinalizedCheckPoint = ðpb.Checkpoint{ + Root: validBlockRoot[:], + Epoch: 0, + } + + validators := uint64(64) + savedState, keys := util.DeterministicGenesisState(t, validators) + require.NoError(t, savedState.SetSlot(1)) + require.NoError(t, db.SaveState(context.Background(), savedState, validBlockRoot)) + chain.State = savedState + committee, err := helpers.BeaconCommitteeFromState(ctx, savedState, 1, 0) + require.NoError(t, err) + + tests := []struct { + name string + msg ethpb.Att + want bool + }{ + { + name: "valid", + msg: ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + BeaconBlockRoot: validBlockRoot[:], + CommitteeIndex: 0, + Slot: 1, + Target: ðpb.Checkpoint{ + Epoch: 0, + Root: validBlockRoot[:], + }, + Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + }, + AttesterIndex: committee[0], + }, + want: true, + }, + { + name: "non-zero committee index in att data", + msg: ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + BeaconBlockRoot: validBlockRoot[:], + CommitteeIndex: 1, + Slot: 1, + Target: ðpb.Checkpoint{ + Epoch: 0, + Root: validBlockRoot[:], + }, + Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + }, + AttesterIndex: committee[0], + }, + want: false, + }, + { + name: "attesting index not in committee", + msg: ðpb.SingleAttestation{ + Data: ðpb.AttestationData{ + BeaconBlockRoot: validBlockRoot[:], + CommitteeIndex: 1, + Slot: 1, + Target: ðpb.Checkpoint{ + Epoch: 0, + Root: validBlockRoot[:], + }, + Source: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + }, + AttesterIndex: 999999, + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + helpers.ClearCache() + com, err := helpers.BeaconCommitteeFromState(context.Background(), savedState, tt.msg.GetData().Slot, tt.msg.GetData().CommitteeIndex) + require.NoError(t, err) + domain, err := signing.Domain(savedState.Fork(), tt.msg.GetData().Target.Epoch, params.BeaconConfig().DomainBeaconAttester, savedState.GenesisValidatorsRoot()) + require.NoError(t, err) + attRoot, err := signing.ComputeSigningRoot(tt.msg.GetData(), domain) + require.NoError(t, err) + tt.msg.SetSignature(keys[com[0]].Sign(attRoot[:]).Marshal()) + buf := new(bytes.Buffer) + _, err = p.Encoding().EncodeGossip(buf, tt.msg) + require.NoError(t, err) + topic := fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest) + m := &pubsub.Message{ + Message: &pubsubpb.Message{ + Data: buf.Bytes(), + Topic: &topic, + }, + } + + res, err := s.validateCommitteeIndexBeaconAttestation(ctx, "", m) + received := res == pubsub.ValidationAccept + if received != tt.want { + t.Fatalf("Did not received wanted validation. Got %v, wanted %v", !tt.want, tt.want) + } + if tt.want && err != nil { + t.Errorf("Non nil error returned: %v", err) + } + if tt.want && m.ValidatorData == nil { + t.Error("Expected validator data to be set") + } + }) + } +} + func TestService_setSeenCommitteeIndicesSlot(t *testing.T) { s := NewService(context.Background(), WithP2P(p2ptest.NewTestP2P(t))) s.initCaches() diff --git a/beacon-chain/sync/validate_beacon_blocks.go b/beacon-chain/sync/validate_beacon_blocks.go index 37699e189456..0e8085be9391 100644 --- a/beacon-chain/sync/validate_beacon_blocks.go +++ b/beacon-chain/sync/validate_beacon_blocks.go @@ -16,18 +16,17 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/config/features" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/runtime/version" prysmTime "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) var ( @@ -201,7 +200,7 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms } // Record attribute of valid block. - span.AddAttributes(trace.Int64Attribute("slotInEpoch", int64(blk.Block().Slot()%params.BeaconConfig().SlotsPerEpoch))) + span.SetAttributes(trace.Int64Attribute("slotInEpoch", int64(blk.Block().Slot()%params.BeaconConfig().SlotsPerEpoch))) blkPb, err := blk.Proto() if err != nil { log.WithError(err).WithFields(getBlockFields(blk)).Debug("Could not convert beacon block to protobuf type") @@ -303,8 +302,10 @@ func validateDenebBeaconBlock(blk interfaces.ReadOnlyBeaconBlock) error { } // [REJECT] The length of KZG commitments is less than or equal to the limitation defined in Consensus Layer // -- i.e. validate that len(body.signed_beacon_block.message.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK - if len(commits) > fieldparams.MaxBlobsPerBlock { - return errors.Wrapf(errRejectCommitmentLen, "%d > %d", len(commits), fieldparams.MaxBlobsPerBlock) + + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(blk.Slot()) + if len(commits) > maxBlobsPerBlock { + return errors.Wrapf(errRejectCommitmentLen, "%d > %d", len(commits), maxBlobsPerBlock) } return nil } @@ -345,7 +346,7 @@ func (s *Service) validateBellatrixBeaconBlock(ctx context.Context, parentState if err != nil { return err } - if payload.IsNil() { + if payload == nil || payload.IsNil() { return errors.New("execution payload is nil") } if payload.Timestamp() != uint64(t.Unix()) { @@ -369,7 +370,7 @@ func (s *Service) verifyPendingBlockSignature(ctx context.Context, blk interface return pubsub.ValidationIgnore, err } // Ignore block in the event of non-existent proposer. - _, err = roState.ValidatorAtIndex(blk.Block().ProposerIndex()) + _, err = roState.ValidatorAtIndexReadOnly(blk.Block().ProposerIndex()) if err != nil { return pubsub.ValidationIgnore, err } diff --git a/beacon-chain/sync/validate_blob.go b/beacon-chain/sync/validate_blob.go index 275015d6543d..1f06929b708e 100644 --- a/beacon-chain/sync/validate_blob.go +++ b/beacon-chain/sync/validate_blob.go @@ -51,14 +51,14 @@ func (s *Service) validateBlob(ctx context.Context, pid peer.ID, msg *pubsub.Mes if err != nil { return pubsub.ValidationReject, errors.Wrap(err, "roblob conversion failure") } - vf := s.newBlobVerifier(blob, verification.GossipSidecarRequirements) + vf := s.newBlobVerifier(blob, verification.GossipBlobSidecarRequirements) if err := vf.BlobIndexInBounds(); err != nil { return pubsub.ValidationReject, err } // [REJECT] The sidecar is for the correct subnet -- i.e. compute_subnet_for_blob_sidecar(sidecar.index) == subnet_id. - want := fmt.Sprintf("blob_sidecar_%d", computeSubnetForBlobSidecar(blob.Index)) + want := fmt.Sprintf("blob_sidecar_%d", computeSubnetForBlobSidecar(blob.Index, blob.Slot())) if !strings.Contains(*msg.Topic, want) { log.WithFields(blobFields(blob)).Debug("Sidecar index does not match topic") return pubsub.ValidationReject, fmt.Errorf("wrong topic name: %s", *msg.Topic) @@ -169,8 +169,12 @@ func blobFields(b blocks.ROBlob) logrus.Fields { } } -func computeSubnetForBlobSidecar(index uint64) uint64 { - return index % params.BeaconConfig().BlobsidecarSubnetCount +func computeSubnetForBlobSidecar(index uint64, slot primitives.Slot) uint64 { + subnetCount := params.BeaconConfig().BlobsidecarSubnetCount + if slots.ToEpoch(slot) >= params.BeaconConfig().ElectraForkEpoch { + subnetCount = params.BeaconConfig().BlobsidecarSubnetCountElectra + } + return index % subnetCount } // saveInvalidBlobToTemp as a block ssz. Writes to temp directory. diff --git a/beacon-chain/sync/validate_bls_to_execution_change.go b/beacon-chain/sync/validate_bls_to_execution_change.go index 009b2916b1db..76df5e466afb 100644 --- a/beacon-chain/sync/validate_bls_to_execution_change.go +++ b/beacon-chain/sync/validate_bls_to_execution_change.go @@ -7,8 +7,8 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) func (s *Service) validateBlsToExecutionChange(ctx context.Context, pid peer.ID, msg *pubsub.Message) (pubsub.ValidationResult, error) { diff --git a/beacon-chain/sync/validate_bls_to_execution_change_test.go b/beacon-chain/sync/validate_bls_to_execution_change_test.go index c6fb8d43c98d..255279048054 100644 --- a/beacon-chain/sync/validate_bls_to_execution_change_test.go +++ b/beacon-chain/sync/validate_bls_to_execution_change_test.go @@ -19,6 +19,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/encoder" mockp2p "github.com/prysmaticlabs/prysm/v5/beacon-chain/p2p/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stategen" mockSync "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/initial-sync/testing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" @@ -293,12 +294,13 @@ func TestService_ValidateBlsToExecutionChange(t *testing.T) { s.cfg.clock = startup.NewClock(time.Now(), [32]byte{'A'}) s.initCaches() st, keys := util.DeterministicGenesisStateCapella(t, 128) - assert.NoError(t, st.ApplyToEveryValidator(func(idx int, val *ethpb.Validator) (bool, *ethpb.Validator, error) { + assert.NoError(t, st.ApplyToEveryValidator(func(idx int, val state.ReadOnlyValidator) (*ethpb.Validator, error) { newCreds := make([]byte, 32) newCreds[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte copy(newCreds[12:], wantedExecAddress) - val.WithdrawalCredentials = newCreds - return true, val, nil + newVal := val.Copy() + newVal.WithdrawalCredentials = newCreds + return newVal, nil })) s.cfg.chain = &mockChain.ChainService{ State: st, diff --git a/beacon-chain/sync/validate_proposer_slashing.go b/beacon-chain/sync/validate_proposer_slashing.go index 88b231822cb1..729484ecb6e3 100644 --- a/beacon-chain/sync/validate_proposer_slashing.go +++ b/beacon-chain/sync/validate_proposer_slashing.go @@ -11,8 +11,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // Clients who receive a proposer slashing on this topic MUST validate the conditions within VerifyProposerSlashing before diff --git a/beacon-chain/sync/validate_sync_committee_message.go b/beacon-chain/sync/validate_sync_committee_message.go index e60bfc9806a3..f52a3591534c 100644 --- a/beacon-chain/sync/validate_sync_committee_message.go +++ b/beacon-chain/sync/validate_sync_committee_message.go @@ -18,8 +18,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // Sync committee subnets are used to propagate unaggregated sync committee messages to subsections of the network. diff --git a/beacon-chain/sync/validate_sync_contribution_proof.go b/beacon-chain/sync/validate_sync_contribution_proof.go index 12829db2d257..acb5b20fb660 100644 --- a/beacon-chain/sync/validate_sync_contribution_proof.go +++ b/beacon-chain/sync/validate_sync_contribution_proof.go @@ -16,8 +16,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // validateSyncContributionAndProof verifies the aggregated signature and the selection proof is valid before forwarding to the diff --git a/beacon-chain/sync/validate_voluntary_exit.go b/beacon-chain/sync/validate_voluntary_exit.go index 0426ba276378..7f46cdbcc1b3 100644 --- a/beacon-chain/sync/validate_voluntary_exit.go +++ b/beacon-chain/sync/validate_voluntary_exit.go @@ -11,8 +11,8 @@ import ( opfeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/operation" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" ) // Clients who receive a voluntary exit on this topic MUST validate the conditions within process_voluntary_exit before diff --git a/beacon-chain/sync/verify/BUILD.bazel b/beacon-chain/sync/verify/BUILD.bazel index 11d8848bb93b..82c66472f588 100644 --- a/beacon-chain/sync/verify/BUILD.bazel +++ b/beacon-chain/sync/verify/BUILD.bazel @@ -6,7 +6,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/verify", visibility = ["//visibility:public"], deps = [ - "//config/fieldparams:go_default_library", + "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//encoding/bytesutil:go_default_library", "//runtime/version:go_default_library", diff --git a/beacon-chain/sync/verify/blob.go b/beacon-chain/sync/verify/blob.go index 6171c0abed47..cb411ed482a8 100644 --- a/beacon-chain/sync/verify/blob.go +++ b/beacon-chain/sync/verify/blob.go @@ -2,7 +2,7 @@ package verify import ( "github.com/pkg/errors" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/runtime/version" @@ -20,8 +20,9 @@ func BlobAlignsWithBlock(blob blocks.ROBlob, block blocks.ROBlock) error { if block.Version() < version.Deneb { return nil } - if blob.Index >= fieldparams.MaxBlobsPerBlock { - return errors.Wrapf(ErrIncorrectBlobIndex, "index %d exceeds MAX_BLOBS_PER_BLOCK %d", blob.Index, fieldparams.MaxBlobsPerBlock) + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(blob.Slot()) + if blob.Index >= uint64(maxBlobsPerBlock) { + return errors.Wrapf(ErrIncorrectBlobIndex, "index %d exceeds MAX_BLOBS_PER_BLOCK %d", blob.Index, maxBlobsPerBlock) } if blob.BlockRoot() != block.Root() { diff --git a/beacon-chain/verification/BUILD.bazel b/beacon-chain/verification/BUILD.bazel index fa95e5451e65..2a129fe114fd 100644 --- a/beacon-chain/verification/BUILD.bazel +++ b/beacon-chain/verification/BUILD.bazel @@ -8,8 +8,10 @@ go_library( "cache.go", "error.go", "fake.go", + "filesystem.go", "initializer.go", "interface.go", + "log.go", "metrics.go", "mock.go", "result.go", @@ -25,7 +27,6 @@ go_library( "//beacon-chain/startup:go_default_library", "//beacon-chain/state:go_default_library", "//cache/lru:go_default_library", - "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", @@ -40,6 +41,7 @@ go_library( "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_spf13_afero//:go_default_library", ], ) @@ -59,7 +61,6 @@ go_test( "//beacon-chain/forkchoice/types:go_default_library", "//beacon-chain/startup:go_default_library", "//beacon-chain/state:go_default_library", - "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/primitives:go_default_library", diff --git a/beacon-chain/verification/batch_test.go b/beacon-chain/verification/batch_test.go index f0e987d79739..3d12b21efc05 100644 --- a/beacon-chain/verification/batch_test.go +++ b/beacon-chain/verification/batch_test.go @@ -41,7 +41,7 @@ func TestBatchVerifier(t *testing.T) { }, nv: func() NewBlobVerifier { return func(bl blocks.ROBlob, reqs []Requirement) BlobVerifier { - return &MockBlobVerifier{cbVerifiedROBlob: vbcb(bl, nil)} + return &MockBlobVerifier{CbVerifiedROBlob: vbcb(bl, nil)} } }, nblobs: 0, @@ -50,7 +50,7 @@ func TestBatchVerifier(t *testing.T) { name: "happy path", nv: func() NewBlobVerifier { return func(bl blocks.ROBlob, reqs []Requirement) BlobVerifier { - return &MockBlobVerifier{cbVerifiedROBlob: vbcb(bl, nil)} + return &MockBlobVerifier{CbVerifiedROBlob: vbcb(bl, nil)} } }, bandb: func(t *testing.T, nb int) (blocks.ROBlock, []blocks.ROBlob) { @@ -62,7 +62,7 @@ func TestBatchVerifier(t *testing.T) { name: "partial batch", nv: func() NewBlobVerifier { return func(bl blocks.ROBlob, reqs []Requirement) BlobVerifier { - return &MockBlobVerifier{cbVerifiedROBlob: vbcb(bl, nil)} + return &MockBlobVerifier{CbVerifiedROBlob: vbcb(bl, nil)} } }, bandb: func(t *testing.T, nb int) (blocks.ROBlock, []blocks.ROBlob) { @@ -76,7 +76,7 @@ func TestBatchVerifier(t *testing.T) { name: "invalid commitment", nv: func() NewBlobVerifier { return func(bl blocks.ROBlob, reqs []Requirement) BlobVerifier { - return &MockBlobVerifier{cbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { + return &MockBlobVerifier{CbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { t.Fatal("Batch verifier should stop before this point") return blocks.VerifiedROBlob{}, nil }} @@ -93,7 +93,7 @@ func TestBatchVerifier(t *testing.T) { name: "signature mismatch", nv: func() NewBlobVerifier { return func(bl blocks.ROBlob, reqs []Requirement) BlobVerifier { - return &MockBlobVerifier{cbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { + return &MockBlobVerifier{CbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { t.Fatal("Batch verifier should stop before this point") return blocks.VerifiedROBlob{}, nil }} @@ -111,7 +111,7 @@ func TestBatchVerifier(t *testing.T) { name: "root mismatch", nv: func() NewBlobVerifier { return func(bl blocks.ROBlob, reqs []Requirement) BlobVerifier { - return &MockBlobVerifier{cbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { + return &MockBlobVerifier{CbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { t.Fatal("Batch verifier should stop before this point") return blocks.VerifiedROBlob{}, nil }} @@ -133,7 +133,7 @@ func TestBatchVerifier(t *testing.T) { return func(bl blocks.ROBlob, reqs []Requirement) BlobVerifier { return &MockBlobVerifier{ ErrBlobIndexInBounds: ErrBlobIndexInvalid, - cbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { + CbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { t.Fatal("Batch verifier should stop before this point") return blocks.VerifiedROBlob{}, nil }} @@ -151,7 +151,7 @@ func TestBatchVerifier(t *testing.T) { return func(bl blocks.ROBlob, reqs []Requirement) BlobVerifier { return &MockBlobVerifier{ ErrSidecarInclusionProven: ErrSidecarInclusionProofInvalid, - cbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { + CbVerifiedROBlob: func() (blocks.VerifiedROBlob, error) { t.Fatal("Batch verifier should stop before this point") return blocks.VerifiedROBlob{}, nil }} @@ -169,7 +169,7 @@ func TestBatchVerifier(t *testing.T) { blk, blbs := c.bandb(t, c.nblobs) reqs := c.reqs if reqs == nil { - reqs = InitsyncSidecarRequirements + reqs = InitsyncBlobSidecarRequirements } bbv := NewBlobBatchVerifier(c.nv(), reqs) if c.cv == nil { diff --git a/beacon-chain/verification/blob.go b/beacon-chain/verification/blob.go index 916ddff3bc31..3e245ac6822d 100644 --- a/beacon-chain/verification/blob.go +++ b/beacon-chain/verification/blob.go @@ -2,17 +2,16 @@ package verification import ( "context" + goError "errors" "github.com/pkg/errors" forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/runtime/logging" "github.com/prysmaticlabs/prysm/v5/time/slots" - log "github.com/sirupsen/logrus" ) const ( @@ -29,7 +28,7 @@ const ( RequireSidecarProposerExpected ) -var allSidecarRequirements = []Requirement{ +var allBlobSidecarRequirements = []Requirement{ RequireBlobIndexInBounds, RequireNotFromFutureSlot, RequireSlotAboveFinalized, @@ -43,21 +42,21 @@ var allSidecarRequirements = []Requirement{ RequireSidecarProposerExpected, } -// GossipSidecarRequirements defines the set of requirements that BlobSidecars received on gossip +// GossipBlobSidecarRequirements defines the set of requirements that BlobSidecars received on gossip // must satisfy in order to upgrade an ROBlob to a VerifiedROBlob. -var GossipSidecarRequirements = requirementList(allSidecarRequirements).excluding() +var GossipBlobSidecarRequirements = requirementList(allBlobSidecarRequirements).excluding() -// SpectestSidecarRequirements is used by the forkchoice spectests when verifying blobs used in the on_block tests. +// SpectestBlobSidecarRequirements is used by the forkchoice spectests when verifying blobs used in the on_block tests. // The only requirements we exclude for these tests are the parent validity and seen tests, as these are specific to // gossip processing and require the bad block cache that we only use there. -var SpectestSidecarRequirements = requirementList(GossipSidecarRequirements).excluding( +var SpectestBlobSidecarRequirements = requirementList(GossipBlobSidecarRequirements).excluding( RequireSidecarParentSeen, RequireSidecarParentValid) -// InitsyncSidecarRequirements is the list of verification requirements to be used by the init-sync service +// InitsyncBlobSidecarRequirements is the list of verification requirements to be used by the init-sync service // for batch-mode syncing. Because we only perform batch verification as part of the IsDataAvailable method // for blobs after the block has been verified, and the blobs to be verified are keyed in the cache by the // block root, the list of required verifications is much shorter than gossip. -var InitsyncSidecarRequirements = requirementList(GossipSidecarRequirements).excluding( +var InitsyncBlobSidecarRequirements = requirementList(GossipBlobSidecarRequirements).excluding( RequireNotFromFutureSlot, RequireSlotAboveFinalized, RequireSidecarParentSeen, @@ -67,36 +66,22 @@ var InitsyncSidecarRequirements = requirementList(GossipSidecarRequirements).exc RequireSidecarProposerExpected, ) -// BackfillSidecarRequirements is the same as InitsyncSidecarRequirements. -var BackfillSidecarRequirements = requirementList(InitsyncSidecarRequirements).excluding() +// ELMemPoolRequirements defines the verification requirements for importing blobs and proofs +// from the execution layer's mempool. Currently, no requirements are enforced because it is +// assumed that blobs and proofs from the execution layer are correctly formatted, +// given the trusted relationship between the consensus layer and execution layer. +var ELMemPoolRequirements []Requirement -// PendingQueueSidecarRequirements is the same as InitsyncSidecarRequirements, used by the pending blocks queue. -var PendingQueueSidecarRequirements = requirementList(InitsyncSidecarRequirements).excluding() +// BackfillBlobSidecarRequirements is the same as InitsyncBlobSidecarRequirements. +var BackfillBlobSidecarRequirements = requirementList(InitsyncBlobSidecarRequirements).excluding() + +// PendingQueueBlobSidecarRequirements is the same as InitsyncBlobSidecarRequirements, used by the pending blocks queue. +var PendingQueueBlobSidecarRequirements = requirementList(InitsyncBlobSidecarRequirements).excluding() var ( ErrBlobInvalid = errors.New("blob failed verification") // ErrBlobIndexInvalid means RequireBlobIndexInBounds failed. - ErrBlobIndexInvalid = errors.Wrap(ErrBlobInvalid, "incorrect blob sidecar index") - // ErrFromFutureSlot means RequireSlotNotTooEarly failed. - ErrFromFutureSlot = errors.Wrap(ErrBlobInvalid, "slot is too far in the future") - // ErrSlotNotAfterFinalized means RequireSlotAboveFinalized failed. - ErrSlotNotAfterFinalized = errors.Wrap(ErrBlobInvalid, "slot <= finalized checkpoint") - // ErrInvalidProposerSignature means RequireValidProposerSignature failed. - ErrInvalidProposerSignature = errors.Wrap(ErrBlobInvalid, "proposer signature could not be verified") - // ErrSidecarParentNotSeen means RequireSidecarParentSeen failed. - ErrSidecarParentNotSeen = errors.Wrap(ErrBlobInvalid, "parent root has not been seen") - // ErrSidecarParentInvalid means RequireSidecarParentValid failed. - ErrSidecarParentInvalid = errors.Wrap(ErrBlobInvalid, "parent block is not valid") - // ErrSlotNotAfterParent means RequireSidecarParentSlotLower failed. - ErrSlotNotAfterParent = errors.Wrap(ErrBlobInvalid, "slot <= slot") - // ErrSidecarNotFinalizedDescendent means RequireSidecarDescendsFromFinalized failed. - ErrSidecarNotFinalizedDescendent = errors.Wrap(ErrBlobInvalid, "blob parent is not descended from the finalized block") - // ErrSidecarInclusionProofInvalid means RequireSidecarInclusionProven failed. - ErrSidecarInclusionProofInvalid = errors.Wrap(ErrBlobInvalid, "sidecar inclusion proof verification failed") - // ErrSidecarKzgProofInvalid means RequireSidecarKzgProofVerified failed. - ErrSidecarKzgProofInvalid = errors.Wrap(ErrBlobInvalid, "sidecar kzg commitment proof verification failed") - // ErrSidecarUnexpectedProposer means RequireSidecarProposerExpected failed. - ErrSidecarUnexpectedProposer = errors.Wrap(ErrBlobInvalid, "sidecar was not proposed by the expected proposer_index") + ErrBlobIndexInvalid = errors.New("incorrect blob sidecar index") ) type ROBlobVerifier struct { @@ -143,9 +128,10 @@ func (bv *ROBlobVerifier) recordResult(req Requirement, err *error) { // [REJECT] The sidecar's index is consistent with MAX_BLOBS_PER_BLOCK -- i.e. blob_sidecar.index < MAX_BLOBS_PER_BLOCK. func (bv *ROBlobVerifier) BlobIndexInBounds() (err error) { defer bv.recordResult(RequireBlobIndexInBounds, &err) - if bv.blob.Index >= fieldparams.MaxBlobsPerBlock { + maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(bv.blob.Slot()) + if bv.blob.Index >= uint64(maxBlobsPerBlock) { log.WithFields(logging.BlobFields(bv.blob)).Debug("Sidecar index >= MAX_BLOBS_PER_BLOCK") - return ErrBlobIndexInvalid + return blobErrBuilder(ErrBlobIndexInvalid) } return nil } @@ -164,7 +150,7 @@ func (bv *ROBlobVerifier) NotFromFutureSlot() (err error) { // If the system time is still before earliestStart, we consider the blob from a future slot and return an error. if bv.clock.Now().Before(earliestStart) { log.WithFields(logging.BlobFields(bv.blob)).Debug("sidecar slot is too far in the future") - return ErrFromFutureSlot + return blobErrBuilder(ErrFromFutureSlot) } return nil } @@ -177,11 +163,11 @@ func (bv *ROBlobVerifier) SlotAboveFinalized() (err error) { fcp := bv.fc.FinalizedCheckpoint() fSlot, err := slots.EpochStart(fcp.Epoch) if err != nil { - return errors.Wrapf(ErrSlotNotAfterFinalized, "error computing epoch start slot for finalized checkpoint (%d) %s", fcp.Epoch, err.Error()) + return errors.Wrapf(blobErrBuilder(ErrSlotNotAfterFinalized), "error computing epoch start slot for finalized checkpoint (%d) %s", fcp.Epoch, err.Error()) } if bv.blob.Slot() <= fSlot { log.WithFields(logging.BlobFields(bv.blob)).Debug("sidecar slot is not after finalized checkpoint") - return ErrSlotNotAfterFinalized + return blobErrBuilder(ErrSlotNotAfterFinalized) } return nil } @@ -199,7 +185,7 @@ func (bv *ROBlobVerifier) ValidProposerSignature(ctx context.Context) (err error if err != nil { log.WithFields(logging.BlobFields(bv.blob)).WithError(err).Debug("reusing failed proposer signature validation from cache") blobVerificationProposerSignatureCache.WithLabelValues("hit-invalid").Inc() - return ErrInvalidProposerSignature + return blobErrBuilder(ErrInvalidProposerSignature) } return nil } @@ -209,12 +195,12 @@ func (bv *ROBlobVerifier) ValidProposerSignature(ctx context.Context) (err error parent, err := bv.parentState(ctx) if err != nil { log.WithFields(logging.BlobFields(bv.blob)).WithError(err).Debug("could not replay parent state for blob signature verification") - return ErrInvalidProposerSignature + return blobErrBuilder(ErrInvalidProposerSignature) } // Full verification, which will subsequently be cached for anything sharing the signature cache. if err = bv.sc.VerifySignature(sd, parent); err != nil { log.WithFields(logging.BlobFields(bv.blob)).WithError(err).Debug("signature verification failed") - return ErrInvalidProposerSignature + return blobErrBuilder(ErrInvalidProposerSignature) } return nil } @@ -231,7 +217,7 @@ func (bv *ROBlobVerifier) SidecarParentSeen(parentSeen func([32]byte) bool) (err return nil } log.WithFields(logging.BlobFields(bv.blob)).Debug("parent root has not been seen") - return ErrSidecarParentNotSeen + return blobErrBuilder(ErrSidecarParentNotSeen) } // SidecarParentValid represents the spec verification: @@ -240,7 +226,7 @@ func (bv *ROBlobVerifier) SidecarParentValid(badParent func([32]byte) bool) (err defer bv.recordResult(RequireSidecarParentValid, &err) if badParent != nil && badParent(bv.blob.ParentRoot()) { log.WithFields(logging.BlobFields(bv.blob)).Debug("parent root is invalid") - return ErrSidecarParentInvalid + return blobErrBuilder(ErrSidecarParentInvalid) } return nil } @@ -251,10 +237,10 @@ func (bv *ROBlobVerifier) SidecarParentSlotLower() (err error) { defer bv.recordResult(RequireSidecarParentSlotLower, &err) parentSlot, err := bv.fc.Slot(bv.blob.ParentRoot()) if err != nil { - return errors.Wrap(ErrSlotNotAfterParent, "parent root not in forkchoice") + return errors.Wrap(blobErrBuilder(ErrSlotNotAfterParent), "parent root not in forkchoice") } if parentSlot >= bv.blob.Slot() { - return ErrSlotNotAfterParent + return blobErrBuilder(ErrSlotNotAfterParent) } return nil } @@ -266,7 +252,7 @@ func (bv *ROBlobVerifier) SidecarDescendsFromFinalized() (err error) { defer bv.recordResult(RequireSidecarDescendsFromFinalized, &err) if !bv.fc.HasNode(bv.blob.ParentRoot()) { log.WithFields(logging.BlobFields(bv.blob)).Debug("parent root not in forkchoice") - return ErrSidecarNotFinalizedDescendent + return blobErrBuilder(ErrSidecarNotFinalizedDescendent) } return nil } @@ -277,7 +263,7 @@ func (bv *ROBlobVerifier) SidecarInclusionProven() (err error) { defer bv.recordResult(RequireSidecarInclusionProven, &err) if err = blocks.VerifyKZGInclusionProof(bv.blob); err != nil { log.WithError(err).WithFields(logging.BlobFields(bv.blob)).Debug("sidecar inclusion proof verification failed") - return ErrSidecarInclusionProofInvalid + return blobErrBuilder(ErrSidecarInclusionProofInvalid) } return nil } @@ -289,7 +275,7 @@ func (bv *ROBlobVerifier) SidecarKzgProofVerified() (err error) { defer bv.recordResult(RequireSidecarKzgProofVerified, &err) if err = bv.verifyBlobCommitment(bv.blob); err != nil { log.WithError(err).WithFields(logging.BlobFields(bv.blob)).Debug("kzg commitment proof verification failed") - return ErrSidecarKzgProofInvalid + return blobErrBuilder(ErrSidecarKzgProofInvalid) } return nil } @@ -307,7 +293,7 @@ func (bv *ROBlobVerifier) SidecarProposerExpected(ctx context.Context) (err erro } r, err := bv.fc.TargetRootForEpoch(bv.blob.ParentRoot(), e) if err != nil { - return ErrSidecarUnexpectedProposer + return blobErrBuilder(ErrSidecarUnexpectedProposer) } c := &forkchoicetypes.Checkpoint{Root: r, Epoch: e} idx, cached := bv.pc.Proposer(c, bv.blob.Slot()) @@ -315,19 +301,19 @@ func (bv *ROBlobVerifier) SidecarProposerExpected(ctx context.Context) (err erro pst, err := bv.parentState(ctx) if err != nil { log.WithError(err).WithFields(logging.BlobFields(bv.blob)).Debug("state replay to parent_root failed") - return ErrSidecarUnexpectedProposer + return blobErrBuilder(ErrSidecarUnexpectedProposer) } idx, err = bv.pc.ComputeProposer(ctx, bv.blob.ParentRoot(), bv.blob.Slot(), pst) if err != nil { log.WithError(err).WithFields(logging.BlobFields(bv.blob)).Debug("error computing proposer index from parent state") - return ErrSidecarUnexpectedProposer + return blobErrBuilder(ErrSidecarUnexpectedProposer) } } if idx != bv.blob.ProposerIndex() { - log.WithError(ErrSidecarUnexpectedProposer). + log.WithError(blobErrBuilder(ErrSidecarUnexpectedProposer)). WithFields(logging.BlobFields(bv.blob)).WithField("expectedProposer", idx). Debug("unexpected blob proposer") - return ErrSidecarUnexpectedProposer + return blobErrBuilder(ErrSidecarUnexpectedProposer) } return nil } @@ -353,3 +339,7 @@ func blobToSignatureData(b blocks.ROBlob) SignatureData { Slot: b.Slot(), } } + +func blobErrBuilder(baseErr error) error { + return goError.Join(ErrBlobInvalid, baseErr) +} diff --git a/beacon-chain/verification/blob_test.go b/beacon-chain/verification/blob_test.go index e08707de464f..86ed8bf13ae0 100644 --- a/beacon-chain/verification/blob_test.go +++ b/beacon-chain/verification/blob_test.go @@ -12,7 +12,6 @@ import ( forkchoicetypes "github.com/prysmaticlabs/prysm/v5/beacon-chain/forkchoice/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/startup" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" @@ -27,13 +26,13 @@ func TestBlobIndexInBounds(t *testing.T) { _, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 1) b := blobs[0] // set Index to a value that is out of bounds - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.BlobIndexInBounds()) require.Equal(t, true, v.results.executed(RequireBlobIndexInBounds)) require.NoError(t, v.results.result(RequireBlobIndexInBounds)) - b.Index = fieldparams.MaxBlobsPerBlock - v = ini.NewBlobVerifier(b, GossipSidecarRequirements) + b.Index = uint64(params.BeaconConfig().MaxBlobsPerBlock(0)) + v = ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.BlobIndexInBounds(), ErrBlobIndexInvalid) require.Equal(t, true, v.results.executed(RequireBlobIndexInBounds)) require.NotNil(t, v.results.result(RequireBlobIndexInBounds)) @@ -52,7 +51,7 @@ func TestSlotNotTooEarly(t *testing.T) { // This clock will give a current slot of 1 on the nose happyClock := startup.NewClock(genesis, [32]byte{}, startup.WithNower(func() time.Time { return now })) ini := Initializer{shared: &sharedResources{clock: happyClock}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.NotFromFutureSlot()) require.Equal(t, true, v.results.executed(RequireNotFromFutureSlot)) require.NoError(t, v.results.result(RequireNotFromFutureSlot)) @@ -61,7 +60,7 @@ func TestSlotNotTooEarly(t *testing.T) { // but still in the previous slot. closeClock := startup.NewClock(genesis, [32]byte{}, startup.WithNower(func() time.Time { return now.Add(-1 * params.BeaconConfig().MaximumGossipClockDisparityDuration() / 2) })) ini = Initializer{shared: &sharedResources{clock: closeClock}} - v = ini.NewBlobVerifier(b, GossipSidecarRequirements) + v = ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.NotFromFutureSlot()) // This clock will give a current slot of 0, with now coming more than max clock disparity before slot 1 @@ -69,7 +68,7 @@ func TestSlotNotTooEarly(t *testing.T) { dispClock := startup.NewClock(genesis, [32]byte{}, startup.WithNower(func() time.Time { return disparate })) // Set up initializer to use the clock that will set now to a little to far before slot 1 ini = Initializer{shared: &sharedResources{clock: dispClock}} - v = ini.NewBlobVerifier(b, GossipSidecarRequirements) + v = ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.NotFromFutureSlot(), ErrFromFutureSlot) require.Equal(t, true, v.results.executed(RequireNotFromFutureSlot)) require.NotNil(t, v.results.result(RequireNotFromFutureSlot)) @@ -114,7 +113,7 @@ func TestSlotAboveFinalized(t *testing.T) { _, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 1) b := blobs[0] b.SignedBlockHeader.Header.Slot = c.slot - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) err := v.SlotAboveFinalized() require.Equal(t, true, v.results.executed(RequireSlotAboveFinalized)) if c.err == nil { @@ -146,7 +145,7 @@ func TestValidProposerSignature_Cached(t *testing.T) { }, } ini := Initializer{shared: &sharedResources{sc: sc, sr: &mockStateByRooter{sbr: sbrErrorIfCalled(t)}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.ValidProposerSignature(ctx)) require.Equal(t, true, v.results.executed(RequireValidProposerSignature)) require.NoError(t, v.results.result(RequireValidProposerSignature)) @@ -159,7 +158,7 @@ func TestValidProposerSignature_Cached(t *testing.T) { return true, errors.New("derp") } ini = Initializer{shared: &sharedResources{sc: sc, sr: &mockStateByRooter{sbr: sbrErrorIfCalled(t)}}} - v = ini.NewBlobVerifier(b, GossipSidecarRequirements) + v = ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.ValidProposerSignature(ctx), ErrInvalidProposerSignature) require.Equal(t, true, v.results.executed(RequireValidProposerSignature)) require.NotNil(t, v.results.result(RequireValidProposerSignature)) @@ -182,14 +181,14 @@ func TestValidProposerSignature_CacheMiss(t *testing.T) { }, } ini := Initializer{shared: &sharedResources{sc: sc, sr: sbrForValOverride(b.ProposerIndex(), ðpb.Validator{})}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.ValidProposerSignature(ctx)) require.Equal(t, true, v.results.executed(RequireValidProposerSignature)) require.NoError(t, v.results.result(RequireValidProposerSignature)) // simulate state not found ini = Initializer{shared: &sharedResources{sc: sc, sr: sbrNotFound(t, expectedSd.Parent)}} - v = ini.NewBlobVerifier(b, GossipSidecarRequirements) + v = ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.ValidProposerSignature(ctx), ErrInvalidProposerSignature) require.Equal(t, true, v.results.executed(RequireValidProposerSignature)) require.NotNil(t, v.results.result(RequireValidProposerSignature)) @@ -206,7 +205,7 @@ func TestValidProposerSignature_CacheMiss(t *testing.T) { }, } ini = Initializer{shared: &sharedResources{sc: sc, sr: sbr}} - v = ini.NewBlobVerifier(b, GossipSidecarRequirements) + v = ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) // make sure all the histories are clean before calling the method // so we don't get polluted by previous usages @@ -255,14 +254,14 @@ func TestSidecarParentSeen(t *testing.T) { t.Run("happy path", func(t *testing.T) { ini := Initializer{shared: &sharedResources{fc: fcHas}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.SidecarParentSeen(nil)) require.Equal(t, true, v.results.executed(RequireSidecarParentSeen)) require.NoError(t, v.results.result(RequireSidecarParentSeen)) }) t.Run("HasNode false, no badParent cb, expected error", func(t *testing.T) { ini := Initializer{shared: &sharedResources{fc: fcLacks}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarParentSeen(nil), ErrSidecarParentNotSeen) require.Equal(t, true, v.results.executed(RequireSidecarParentSeen)) require.NotNil(t, v.results.result(RequireSidecarParentSeen)) @@ -270,14 +269,14 @@ func TestSidecarParentSeen(t *testing.T) { t.Run("HasNode false, badParent true", func(t *testing.T) { ini := Initializer{shared: &sharedResources{fc: fcLacks}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.SidecarParentSeen(badParentCb(t, b.ParentRoot(), true))) require.Equal(t, true, v.results.executed(RequireSidecarParentSeen)) require.NoError(t, v.results.result(RequireSidecarParentSeen)) }) t.Run("HasNode false, badParent false", func(t *testing.T) { ini := Initializer{shared: &sharedResources{fc: fcLacks}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarParentSeen(badParentCb(t, b.ParentRoot(), false)), ErrSidecarParentNotSeen) require.Equal(t, true, v.results.executed(RequireSidecarParentSeen)) require.NotNil(t, v.results.result(RequireSidecarParentSeen)) @@ -289,14 +288,14 @@ func TestSidecarParentValid(t *testing.T) { b := blobs[0] t.Run("parent valid", func(t *testing.T) { ini := Initializer{shared: &sharedResources{}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.SidecarParentValid(badParentCb(t, b.ParentRoot(), false))) require.Equal(t, true, v.results.executed(RequireSidecarParentValid)) require.NoError(t, v.results.result(RequireSidecarParentValid)) }) t.Run("parent not valid", func(t *testing.T) { ini := Initializer{shared: &sharedResources{}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarParentValid(badParentCb(t, b.ParentRoot(), true)), ErrSidecarParentInvalid) require.Equal(t, true, v.results.executed(RequireSidecarParentValid)) require.NotNil(t, v.results.result(RequireSidecarParentValid)) @@ -340,7 +339,7 @@ func TestSidecarParentSlotLower(t *testing.T) { } return c.fcSlot, c.fcErr }}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) err := v.SidecarParentSlotLower() require.Equal(t, true, v.results.executed(RequireSidecarParentSlotLower)) if c.err == nil { @@ -364,7 +363,7 @@ func TestSidecarDescendsFromFinalized(t *testing.T) { } return false }}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarDescendsFromFinalized(), ErrSidecarNotFinalizedDescendent) require.Equal(t, true, v.results.executed(RequireSidecarDescendsFromFinalized)) require.NotNil(t, v.results.result(RequireSidecarDescendsFromFinalized)) @@ -376,7 +375,7 @@ func TestSidecarDescendsFromFinalized(t *testing.T) { } return true }}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.SidecarDescendsFromFinalized()) require.Equal(t, true, v.results.executed(RequireSidecarDescendsFromFinalized)) require.NoError(t, v.results.result(RequireSidecarDescendsFromFinalized)) @@ -389,7 +388,7 @@ func TestSidecarInclusionProven(t *testing.T) { b := blobs[0] ini := Initializer{} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.SidecarInclusionProven()) require.Equal(t, true, v.results.executed(RequireSidecarInclusionProven)) require.NoError(t, v.results.result(RequireSidecarInclusionProven)) @@ -397,7 +396,7 @@ func TestSidecarInclusionProven(t *testing.T) { // Invert bits of the first byte of the body root to mess up the proof byte0 := b.SignedBlockHeader.Header.BodyRoot[0] b.SignedBlockHeader.Header.BodyRoot[0] = byte0 ^ 255 - v = ini.NewBlobVerifier(b, GossipSidecarRequirements) + v = ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarInclusionProven(), ErrSidecarInclusionProofInvalid) require.Equal(t, true, v.results.executed(RequireSidecarInclusionProven)) require.NotNil(t, v.results.result(RequireSidecarInclusionProven)) @@ -409,7 +408,7 @@ func TestSidecarInclusionProvenElectra(t *testing.T) { b := blobs[0] ini := Initializer{} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.SidecarInclusionProven()) require.Equal(t, true, v.results.executed(RequireSidecarInclusionProven)) require.NoError(t, v.results.result(RequireSidecarInclusionProven)) @@ -417,7 +416,7 @@ func TestSidecarInclusionProvenElectra(t *testing.T) { // Invert bits of the first byte of the body root to mess up the proof byte0 := b.SignedBlockHeader.Header.BodyRoot[0] b.SignedBlockHeader.Header.BodyRoot[0] = byte0 ^ 255 - v = ini.NewBlobVerifier(b, GossipSidecarRequirements) + v = ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarInclusionProven(), ErrSidecarInclusionProofInvalid) require.Equal(t, true, v.results.executed(RequireSidecarInclusionProven)) require.NotNil(t, v.results.result(RequireSidecarInclusionProven)) @@ -452,21 +451,21 @@ func TestSidecarProposerExpected(t *testing.T) { b := blobs[0] t.Run("cached, matches", func(t *testing.T) { ini := Initializer{shared: &sharedResources{pc: &mockProposerCache{ProposerCB: pcReturnsIdx(b.ProposerIndex())}, fc: &mockForkchoicer{TargetRootForEpochCB: fcReturnsTargetRoot([32]byte{})}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.SidecarProposerExpected(ctx)) require.Equal(t, true, v.results.executed(RequireSidecarProposerExpected)) require.NoError(t, v.results.result(RequireSidecarProposerExpected)) }) t.Run("cached, does not match", func(t *testing.T) { ini := Initializer{shared: &sharedResources{pc: &mockProposerCache{ProposerCB: pcReturnsIdx(b.ProposerIndex() + 1)}, fc: &mockForkchoicer{TargetRootForEpochCB: fcReturnsTargetRoot([32]byte{})}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarProposerExpected(ctx), ErrSidecarUnexpectedProposer) require.Equal(t, true, v.results.executed(RequireSidecarProposerExpected)) require.NotNil(t, v.results.result(RequireSidecarProposerExpected)) }) t.Run("not cached, state lookup failure", func(t *testing.T) { ini := Initializer{shared: &sharedResources{sr: sbrNotFound(t, b.ParentRoot()), pc: &mockProposerCache{ProposerCB: pcReturnsNotFound()}, fc: &mockForkchoicer{TargetRootForEpochCB: fcReturnsTargetRoot([32]byte{})}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarProposerExpected(ctx), ErrSidecarUnexpectedProposer) require.Equal(t, true, v.results.executed(RequireSidecarProposerExpected)) require.NotNil(t, v.results.result(RequireSidecarProposerExpected)) @@ -475,14 +474,14 @@ func TestSidecarProposerExpected(t *testing.T) { t.Run("not cached, proposer matches", func(t *testing.T) { pc := &mockProposerCache{ ProposerCB: pcReturnsNotFound(), - ComputeProposerCB: func(ctx context.Context, root [32]byte, slot primitives.Slot, pst state.BeaconState) (primitives.ValidatorIndex, error) { + ComputeProposerCB: func(_ context.Context, root [32]byte, slot primitives.Slot, _ state.BeaconState) (primitives.ValidatorIndex, error) { require.Equal(t, b.ParentRoot(), root) require.Equal(t, b.Slot(), slot) return b.ProposerIndex(), nil }, } ini := Initializer{shared: &sharedResources{sr: sbrForValOverride(b.ProposerIndex(), ðpb.Validator{}), pc: pc, fc: &mockForkchoicer{TargetRootForEpochCB: fcReturnsTargetRoot([32]byte{})}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.NoError(t, v.SidecarProposerExpected(ctx)) require.Equal(t, true, v.results.executed(RequireSidecarProposerExpected)) require.NoError(t, v.results.result(RequireSidecarProposerExpected)) @@ -490,14 +489,14 @@ func TestSidecarProposerExpected(t *testing.T) { t.Run("not cached, proposer does not match", func(t *testing.T) { pc := &mockProposerCache{ ProposerCB: pcReturnsNotFound(), - ComputeProposerCB: func(ctx context.Context, root [32]byte, slot primitives.Slot, pst state.BeaconState) (primitives.ValidatorIndex, error) { + ComputeProposerCB: func(_ context.Context, root [32]byte, slot primitives.Slot, _ state.BeaconState) (primitives.ValidatorIndex, error) { require.Equal(t, b.ParentRoot(), root) require.Equal(t, b.Slot(), slot) return b.ProposerIndex() + 1, nil }, } ini := Initializer{shared: &sharedResources{sr: sbrForValOverride(b.ProposerIndex(), ðpb.Validator{}), pc: pc, fc: &mockForkchoicer{TargetRootForEpochCB: fcReturnsTargetRoot([32]byte{})}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarProposerExpected(ctx), ErrSidecarUnexpectedProposer) require.Equal(t, true, v.results.executed(RequireSidecarProposerExpected)) require.NotNil(t, v.results.result(RequireSidecarProposerExpected)) @@ -505,14 +504,14 @@ func TestSidecarProposerExpected(t *testing.T) { t.Run("not cached, ComputeProposer fails", func(t *testing.T) { pc := &mockProposerCache{ ProposerCB: pcReturnsNotFound(), - ComputeProposerCB: func(ctx context.Context, root [32]byte, slot primitives.Slot, pst state.BeaconState) (primitives.ValidatorIndex, error) { + ComputeProposerCB: func(_ context.Context, root [32]byte, slot primitives.Slot, _ state.BeaconState) (primitives.ValidatorIndex, error) { require.Equal(t, b.ParentRoot(), root) require.Equal(t, b.Slot(), slot) return 0, errors.New("ComputeProposer failed") }, } ini := Initializer{shared: &sharedResources{sr: sbrForValOverride(b.ProposerIndex(), ðpb.Validator{}), pc: pc, fc: &mockForkchoicer{TargetRootForEpochCB: fcReturnsTargetRoot([32]byte{})}}} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) require.ErrorIs(t, v.SidecarProposerExpected(ctx), ErrSidecarUnexpectedProposer) require.Equal(t, true, v.results.executed(RequireSidecarProposerExpected)) require.NotNil(t, v.results.result(RequireSidecarProposerExpected)) @@ -523,7 +522,7 @@ func TestRequirementSatisfaction(t *testing.T) { _, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 1, 1) b := blobs[0] ini := Initializer{} - v := ini.NewBlobVerifier(b, GossipSidecarRequirements) + v := ini.NewBlobVerifier(b, GossipBlobSidecarRequirements) _, err := v.VerifiedROBlob() require.ErrorIs(t, err, ErrBlobInvalid) @@ -537,7 +536,7 @@ func TestRequirementSatisfaction(t *testing.T) { } // satisfy everything through the backdoor and ensure we get the verified ro blob at the end - for _, r := range GossipSidecarRequirements { + for _, r := range GossipBlobSidecarRequirements { v.results.record(r, nil) } require.Equal(t, true, v.results.allSatisfied()) diff --git a/beacon-chain/verification/cache.go b/beacon-chain/verification/cache.go index ebfb09bd53fa..ff377744bae3 100644 --- a/beacon-chain/verification/cache.go +++ b/beacon-chain/verification/cache.go @@ -17,7 +17,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/network/forks" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" - log "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus" ) const ( @@ -50,8 +50,8 @@ type SignatureData struct { Slot primitives.Slot } -func (d SignatureData) logFields() log.Fields { - return log.Fields{ +func (d SignatureData) logFields() logrus.Fields { + return logrus.Fields{ "root": fmt.Sprintf("%#x", d.Root), "parentRoot": fmt.Sprintf("%#x", d.Parent), "signature": fmt.Sprintf("%#x", d.Signature), diff --git a/beacon-chain/verification/error.go b/beacon-chain/verification/error.go index 9260184e54f0..0ff9782e7573 100644 --- a/beacon-chain/verification/error.go +++ b/beacon-chain/verification/error.go @@ -1,9 +1,48 @@ package verification -import "github.com/pkg/errors" +import ( + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" +) -// ErrMissingVerification indicates that the given verification function was never performed on the value. -var ErrMissingVerification = errors.New("verification was not performed for requirement") +var ( + // ErrFromFutureSlot means RequireSlotNotTooEarly failed. + ErrFromFutureSlot = errors.New("slot is too far in the future") + + // ErrSlotNotAfterFinalized means RequireSlotAboveFinalized failed. + ErrSlotNotAfterFinalized = errors.New("slot <= finalized checkpoint") + + // ErrInvalidProposerSignature means RequireValidProposerSignature failed. + ErrInvalidProposerSignature = errors.New("proposer signature could not be verified") + + // ErrSidecarParentNotSeen means RequireSidecarParentSeen failed. + ErrSidecarParentNotSeen = errors.New("parent root has not been seen") + + // ErrSidecarParentInvalid means RequireSidecarParentValid failed. + ErrSidecarParentInvalid = errors.New("parent block is not valid") + + // ErrSlotNotAfterParent means RequireSidecarParentSlotLower failed. + ErrSlotNotAfterParent = errors.New("slot <= slot") + + // ErrSidecarNotFinalizedDescendent means RequireSidecarDescendsFromFinalized failed. + ErrSidecarNotFinalizedDescendent = errors.New("parent is not descended from the finalized block") + + // ErrSidecarInclusionProofInvalid means RequireSidecarInclusionProven failed. + ErrSidecarInclusionProofInvalid = errors.New("sidecar inclusion proof verification failed") + + // ErrSidecarKzgProofInvalid means RequireSidecarKzgProofVerified failed. + ErrSidecarKzgProofInvalid = errors.New("sidecar kzg commitment proof verification failed") + + // ErrSidecarUnexpectedProposer means RequireSidecarProposerExpected failed. + ErrSidecarUnexpectedProposer = errors.New("sidecar was not proposed by the expected proposer_index") + + // ErrMissingVerification indicates that the given verification function was never performed on the value. + ErrMissingVerification = errors.New("verification was not performed for requirement") + + // errVerificationImplementationFault indicates that a code path yielding VerifiedROBlobs has an implementation + // error, leading it to call VerifiedROBlobError with a nil error. + errVerificationImplementationFault = errors.New("could not verify blob data or create a valid VerifiedROBlob.") +) // VerificationMultiError is a custom error that can be used to access individual verification failures. type VerificationMultiError struct { @@ -36,3 +75,12 @@ func (ve VerificationMultiError) Failures() map[Requirement]error { func newVerificationMultiError(r *results, err error) VerificationMultiError { return VerificationMultiError{r: r, err: err} } + +// VerifiedROBlobError can be used by methods that have a VerifiedROBlob return type but do not have permission to +// create a value of that type in order to generate an error return value. +func VerifiedROBlobError(err error) (blocks.VerifiedROBlob, error) { + if err == nil { + return blocks.VerifiedROBlob{}, errVerificationImplementationFault + } + return blocks.VerifiedROBlob{}, err +} diff --git a/beacon-chain/verification/fake.go b/beacon-chain/verification/fake.go index ea348c2fcfe0..05ef842f3f2a 100644 --- a/beacon-chain/verification/fake.go +++ b/beacon-chain/verification/fake.go @@ -6,22 +6,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" ) -// BlobSidecarNoop is a FAKE verification function that simply launders a ROBlob->VerifiedROBlob. -// TODO: find all code that uses this method and replace it with full verification. -func BlobSidecarNoop(b blocks.ROBlob) (blocks.VerifiedROBlob, error) { - return blocks.NewVerifiedROBlob(b), nil -} - -// BlobSidecarSliceNoop is a FAKE verification function that simply launders a ROBlob->VerifiedROBlob. -// TODO: find all code that uses this method and replace it with full verification. -func BlobSidecarSliceNoop(b []blocks.ROBlob) ([]blocks.VerifiedROBlob, error) { - vbs := make([]blocks.VerifiedROBlob, len(b)) - for i := range b { - vbs[i] = blocks.NewVerifiedROBlob(b[i]) - } - return vbs, nil -} - // FakeVerifyForTest can be used by tests that need a VerifiedROBlob but don't want to do all the // expensive set up to perform full validation. func FakeVerifyForTest(t *testing.T, b blocks.ROBlob) blocks.VerifiedROBlob { @@ -35,7 +19,6 @@ func FakeVerifyForTest(t *testing.T, b blocks.ROBlob) blocks.VerifiedROBlob { func FakeVerifySliceForTest(t *testing.T, b []blocks.ROBlob) []blocks.VerifiedROBlob { // log so that t is truly required t.Log("producing fake []VerifiedROBlob for a test") - // tautological assertion that ensures this function can only be used in tests. vbs := make([]blocks.VerifiedROBlob, len(b)) for i := range b { vbs[i] = blocks.NewVerifiedROBlob(b[i]) diff --git a/beacon-chain/verification/filesystem.go b/beacon-chain/verification/filesystem.go new file mode 100644 index 000000000000..f880c93d7c64 --- /dev/null +++ b/beacon-chain/verification/filesystem.go @@ -0,0 +1,23 @@ +package verification + +import ( + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/spf13/afero" +) + +func VerifiedROBlobFromDisk(fs afero.Fs, root [32]byte, path string) (blocks.VerifiedROBlob, error) { + encoded, err := afero.ReadFile(fs, path) + if err != nil { + return VerifiedROBlobError(err) + } + s := ðpb.BlobSidecar{} + if err := s.UnmarshalSSZ(encoded); err != nil { + return VerifiedROBlobError(err) + } + ro, err := blocks.NewROBlobWithRoot(s, root) + if err != nil { + return VerifiedROBlobError(err) + } + return blocks.NewVerifiedROBlob(ro), nil +} diff --git a/beacon-chain/verification/log.go b/beacon-chain/verification/log.go new file mode 100644 index 000000000000..d49834803f7c --- /dev/null +++ b/beacon-chain/verification/log.go @@ -0,0 +1,5 @@ +package verification + +import "github.com/sirupsen/logrus" + +var log = logrus.WithField("prefix", "verification") diff --git a/beacon-chain/verification/mock.go b/beacon-chain/verification/mock.go index 8f956911de67..66c6e49071ff 100644 --- a/beacon-chain/verification/mock.go +++ b/beacon-chain/verification/mock.go @@ -18,11 +18,11 @@ type MockBlobVerifier struct { ErrSidecarInclusionProven error ErrSidecarKzgProofVerified error ErrSidecarProposerExpected error - cbVerifiedROBlob func() (blocks.VerifiedROBlob, error) + CbVerifiedROBlob func() (blocks.VerifiedROBlob, error) } func (m *MockBlobVerifier) VerifiedROBlob() (blocks.VerifiedROBlob, error) { - return m.cbVerifiedROBlob() + return m.CbVerifiedROBlob() } func (m *MockBlobVerifier) BlobIndexInBounds() (err error) { diff --git a/beacon-chain/verification/result_test.go b/beacon-chain/verification/result_test.go index 5f4f7f9664f9..036177ecbbeb 100644 --- a/beacon-chain/verification/result_test.go +++ b/beacon-chain/verification/result_test.go @@ -39,7 +39,7 @@ func TestResultList(t *testing.T) { func TestExportedBlobSanityCheck(t *testing.T) { // make sure all requirement lists contain the bare minimum checks sanity := []Requirement{RequireValidProposerSignature, RequireSidecarKzgProofVerified, RequireBlobIndexInBounds, RequireSidecarInclusionProven} - reqs := [][]Requirement{GossipSidecarRequirements, SpectestSidecarRequirements, InitsyncSidecarRequirements, BackfillSidecarRequirements, PendingQueueSidecarRequirements} + reqs := [][]Requirement{GossipBlobSidecarRequirements, SpectestBlobSidecarRequirements, InitsyncBlobSidecarRequirements, BackfillBlobSidecarRequirements, PendingQueueBlobSidecarRequirements} for i := range reqs { r := reqs[i] reqMap := make(map[Requirement]struct{}) @@ -51,13 +51,13 @@ func TestExportedBlobSanityCheck(t *testing.T) { require.Equal(t, true, ok) } } - require.DeepEqual(t, allSidecarRequirements, GossipSidecarRequirements) + require.DeepEqual(t, allBlobSidecarRequirements, GossipBlobSidecarRequirements) } func TestAllBlobRequirementsHaveStrings(t *testing.T) { var derp Requirement = math.MaxInt require.Equal(t, unknownRequirementName, derp.String()) - for i := range allSidecarRequirements { - require.NotEqual(t, unknownRequirementName, allSidecarRequirements[i].String()) + for i := range allBlobSidecarRequirements { + require.NotEqual(t, unknownRequirementName, allBlobSidecarRequirements[i].String()) } } diff --git a/changelog/james-prysm_blockv2-cognit.md b/changelog/james-prysm_blockv2-cognit.md new file mode 100644 index 000000000000..7f57635c20e3 --- /dev/null +++ b/changelog/james-prysm_blockv2-cognit.md @@ -0,0 +1,4 @@ +### Fixed + +- refactored publish block and block ssz functions to fix gocognit +- refactored publish blinded block and blinded block ssz to correctly deal with version headers and sent blocks \ No newline at end of file diff --git a/changelog/james-prysm_cleanup-payload-conversions.md b/changelog/james-prysm_cleanup-payload-conversions.md new file mode 100644 index 000000000000..c932564e31c0 --- /dev/null +++ b/changelog/james-prysm_cleanup-payload-conversions.md @@ -0,0 +1,7 @@ +### Ignored + +- code cleanup on payload types and payload conversions + +### Fixed + +- fixed gocognit in block conversions between json and proto types \ No newline at end of file diff --git a/changelog/james-prysm_deprecate-apis-for-electra.md b/changelog/james-prysm_deprecate-apis-for-electra.md new file mode 100644 index 000000000000..13cf7bc17f32 --- /dev/null +++ b/changelog/james-prysm_deprecate-apis-for-electra.md @@ -0,0 +1,3 @@ +### Changed + +- deprecate beacon api endpoints based on [3.0.0 release](https://github.com/ethereum/beacon-APIs/pull/506) for electra \ No newline at end of file diff --git a/changelog/james-prysm_dynamic-max-blobs.md b/changelog/james-prysm_dynamic-max-blobs.md new file mode 100644 index 000000000000..3298f684d070 --- /dev/null +++ b/changelog/james-prysm_dynamic-max-blobs.md @@ -0,0 +1,3 @@ +### Fixed + +- fixed max and target blob per block from static to dynamic values \ No newline at end of file diff --git a/changelog/james-prysm_electra-e2e.md b/changelog/james-prysm_electra-e2e.md new file mode 100644 index 000000000000..ec6de568cfda --- /dev/null +++ b/changelog/james-prysm_electra-e2e.md @@ -0,0 +1,7 @@ +### Added + +- enable E2E for minimal and mainnet tests + +### Changed + +- updates geth to 1.15.0 diff --git a/changelog/james-prysm_fix-builder-post-header.md b/changelog/james-prysm_fix-builder-post-header.md new file mode 100644 index 000000000000..c4a2cba10ccc --- /dev/null +++ b/changelog/james-prysm_fix-builder-post-header.md @@ -0,0 +1,3 @@ +### Fixed + +- adding in content type and accept headers for builder API call on registration \ No newline at end of file diff --git a/changelog/james-prysm_improve-execution-request-errors.md b/changelog/james-prysm_improve-execution-request-errors.md new file mode 100644 index 000000000000..ab35eeb9b6ba --- /dev/null +++ b/changelog/james-prysm_improve-execution-request-errors.md @@ -0,0 +1,3 @@ +### Changed + +- execution requests errors on ssz length have been improved \ No newline at end of file diff --git a/changelog/james-prysm_web3signer-electra-e2e.md b/changelog/james-prysm_web3signer-electra-e2e.md new file mode 100644 index 000000000000..59d1e3a64fdd --- /dev/null +++ b/changelog/james-prysm_web3signer-electra-e2e.md @@ -0,0 +1,3 @@ +### Added + +- enable web3signer E2E for electra \ No newline at end of file diff --git a/changelog/kasey_windows-layout-fix.md b/changelog/kasey_windows-layout-fix.md new file mode 100644 index 000000000000..8a13b53ce0fe --- /dev/null +++ b/changelog/kasey_windows-layout-fix.md @@ -0,0 +1,2 @@ +### Fixed +- Fixed bug that breaks new blob storage layout code on Windows, caused by accidental use of platform-dependent path parsing package. diff --git a/changelog/manu_fix_dependencies_doc.md b/changelog/manu_fix_dependencies_doc.md new file mode 100644 index 000000000000..0618b9fc2d57 --- /dev/null +++ b/changelog/manu_fix_dependencies_doc.md @@ -0,0 +1,2 @@ +### Fixed +- Fixed the `bazel run //:gazelle` command in `DEPENDENCIES.md`. \ No newline at end of file diff --git a/changelog/manu_remove_fulu_state_block.md b/changelog/manu_remove_fulu_state_block.md new file mode 100644 index 000000000000..ee8b572d8c1b --- /dev/null +++ b/changelog/manu_remove_fulu_state_block.md @@ -0,0 +1,3 @@ +### Removed + +- Remove Fulu state and block \ No newline at end of file diff --git a/changelog/manu_services_start_log_removal.md b/changelog/manu_services_start_log_removal.md new file mode 100644 index 000000000000..6036ed8b29bc --- /dev/null +++ b/changelog/manu_services_start_log_removal.md @@ -0,0 +1,2 @@ +### Removed +- Removed the log summarizing all started services. \ No newline at end of file diff --git a/changelog/manu_tracked_validators_ttl.md b/changelog/manu_tracked_validators_ttl.md new file mode 100644 index 000000000000..4664f840d98d --- /dev/null +++ b/changelog/manu_tracked_validators_ttl.md @@ -0,0 +1,8 @@ +### Added + +- Tracked validators cache: Added the `ItemCount` method. +- Tracked validators cache: Added the `Indices` method. + +### Changed + +- Tracked validators cache: Remove validators from the cache if not seen after 1 hour. \ No newline at end of file diff --git a/changelog/nisdas_add_deposit_request_testing.md b/changelog/nisdas_add_deposit_request_testing.md new file mode 100644 index 000000000000..94ed12844511 --- /dev/null +++ b/changelog/nisdas_add_deposit_request_testing.md @@ -0,0 +1,3 @@ +### Added + +- Added deposit request testing for electra. \ No newline at end of file diff --git a/changelog/nisdas_enable_multiclient_e2e_electra.md b/changelog/nisdas_enable_multiclient_e2e_electra.md new file mode 100644 index 000000000000..11ae5f6d1e40 --- /dev/null +++ b/changelog/nisdas_enable_multiclient_e2e_electra.md @@ -0,0 +1,4 @@ +### Added + +- Enable multiclient E2E for electra +- Enable Scenario E2E tests with electra \ No newline at end of file diff --git a/changelog/nisdas_fix_capabilites.md b/changelog/nisdas_fix_capabilites.md new file mode 100644 index 000000000000..ddebdc780024 --- /dev/null +++ b/changelog/nisdas_fix_capabilites.md @@ -0,0 +1,3 @@ +### Fixed + +- Only check for electra related engine methods if electra is active. \ No newline at end of file diff --git a/changelog/nisdas_fix_deposit_active_evaluator.md b/changelog/nisdas_fix_deposit_active_evaluator.md new file mode 100644 index 000000000000..704706f7d5de --- /dev/null +++ b/changelog/nisdas_fix_deposit_active_evaluator.md @@ -0,0 +1,3 @@ +### Fixed + +- Fix E2E Deposit Activation Evaluator for Electra. \ No newline at end of file diff --git a/changelog/nisdas_fix_process_deposit_evaluator.md b/changelog/nisdas_fix_process_deposit_evaluator.md new file mode 100644 index 000000000000..a02fc9721d68 --- /dev/null +++ b/changelog/nisdas_fix_process_deposit_evaluator.md @@ -0,0 +1,3 @@ +### Fixed + +- Fix E2E Process Deposit Evaluator for Electra. \ No newline at end of file diff --git a/changelog/nisdas_log_execution_requests.md b/changelog/nisdas_log_execution_requests.md new file mode 100644 index 000000000000..55198b988d7a --- /dev/null +++ b/changelog/nisdas_log_execution_requests.md @@ -0,0 +1,3 @@ +### Added + +- Log execution requests in each block. \ No newline at end of file diff --git a/changelog/nisdas_update_blst.md b/changelog/nisdas_update_blst.md new file mode 100644 index 000000000000..6afda289a6b7 --- /dev/null +++ b/changelog/nisdas_update_blst.md @@ -0,0 +1,3 @@ +### Changed + +- Updates blst to v3.14.0 and fixes the references in our deps.bzl file. \ No newline at end of file diff --git a/changelog/potuz_rpc_handler_log.md b/changelog/potuz_rpc_handler_log.md new file mode 100644 index 000000000000..1d5e89f0ca14 --- /dev/null +++ b/changelog/potuz_rpc_handler_log.md @@ -0,0 +1,3 @@ +### Ignored + +- Add logs for RPC handlers added/removed at forks. \ No newline at end of file diff --git a/changelog/pvl_S1009-fix.md b/changelog/pvl_S1009-fix.md new file mode 100644 index 000000000000..722c3b07faeb --- /dev/null +++ b/changelog/pvl_S1009-fix.md @@ -0,0 +1,3 @@ +### Fixed + +- Lint: Fix violations of S1009: should omit nil check; len() for nil slices is defined as zero diff --git a/changelog/pvl_fmt-fix.md b/changelog/pvl_fmt-fix.md new file mode 100644 index 000000000000..5f0d71ad9874 --- /dev/null +++ b/changelog/pvl_fmt-fix.md @@ -0,0 +1,3 @@ +### Fixed + +- Lint: Fix violations of non-constant format string in call diff --git a/changelog/pvl_go-cmp.md b/changelog/pvl_go-cmp.md new file mode 100644 index 000000000000..324fd8021b9f --- /dev/null +++ b/changelog/pvl_go-cmp.md @@ -0,0 +1,3 @@ +### Changed + +- Use go-cmp for printing better diffs for assertions.DeepEqual diff --git a/changelog/pvl_otel.md b/changelog/pvl_otel.md new file mode 100644 index 000000000000..a374d8b202ef --- /dev/null +++ b/changelog/pvl_otel.md @@ -0,0 +1,3 @@ +### Changed + +- Updated tracing exporter from jaeger to otelhttp. This should not be a breaking change. Jaeger supports otel format, however you may need to update your URL as the default otel-collector port is 4318. See the [OpenTelemtry Protocol Exporter docs](https://opentelemetry.io/docs/specs/otel/protocol/exporter/) for more details. diff --git a/changelog/pvl_otel_http.md b/changelog/pvl_otel_http.md new file mode 100644 index 000000000000..ae97bd96b51a --- /dev/null +++ b/changelog/pvl_otel_http.md @@ -0,0 +1,3 @@ +### Added + +- Added support for otel tracing transport in HTTP clients in Prysm. This allows for tracing headers to be sent with http requests such that spans between the validator and beacon chain can be connected in the tracing graph. This change does nothing without `--enable-tracing`. diff --git a/changelog/pvl_v5.3.0.md b/changelog/pvl_v5.3.0.md new file mode 100644 index 000000000000..a4d92136642c --- /dev/null +++ b/changelog/pvl_v5.3.0.md @@ -0,0 +1,3 @@ +### Ignored + +- Update changelog for v5.3.0 release. diff --git a/changelog/radek_monitor-single-atts.md b/changelog/radek_monitor-single-atts.md new file mode 100644 index 000000000000..48b135739401 --- /dev/null +++ b/changelog/radek_monitor-single-atts.md @@ -0,0 +1,3 @@ +### Fixed + +- Dedicated processing of `SingleAttestation` in the monitor service. \ No newline at end of file diff --git a/changelog/radek_no-maxcover-for-electra.md b/changelog/radek_no-maxcover-for-electra.md new file mode 100644 index 000000000000..ace4e446b04b --- /dev/null +++ b/changelog/radek_no-maxcover-for-electra.md @@ -0,0 +1,3 @@ +### Changed + +- Don't use MaxCover for Electra on-chain attestations. \ No newline at end of file diff --git a/changelog/radek_rename-slashing-files.md b/changelog/radek_rename-slashing-files.md new file mode 100644 index 000000000000..23fc1e76e4d0 --- /dev/null +++ b/changelog/radek_rename-slashing-files.md @@ -0,0 +1,3 @@ +### Ignored + +- Rename files in `beacon-chain/operations/slashings`. \ No newline at end of file diff --git a/changelog/saolyn_add-GetPendingDeposits.md b/changelog/saolyn_add-GetPendingDeposits.md new file mode 100644 index 000000000000..c85338de390b --- /dev/null +++ b/changelog/saolyn_add-GetPendingDeposits.md @@ -0,0 +1,3 @@ +### Added + +- Add endpoint for getting pending deposits. \ No newline at end of file diff --git a/changelog/saolyn_add-GetPendingPartialWithdrawals.md b/changelog/saolyn_add-GetPendingPartialWithdrawals.md new file mode 100644 index 000000000000..719049658f86 --- /dev/null +++ b/changelog/saolyn_add-GetPendingPartialWithdrawals.md @@ -0,0 +1,3 @@ +### Added + +- Add endpoint for getting pending partial withdrawals. diff --git a/changelog/tt_add_block_hash.md b/changelog/tt_add_block_hash.md new file mode 100644 index 000000000000..1992ee58d331 --- /dev/null +++ b/changelog/tt_add_block_hash.md @@ -0,0 +1,3 @@ +### Added + +- Add request hash to header for builder: executable data to block \ No newline at end of file diff --git a/changelog/tt_blob_by_range_electra_test.md b/changelog/tt_blob_by_range_electra_test.md new file mode 100644 index 000000000000..b6f5f94abadd --- /dev/null +++ b/changelog/tt_blob_by_range_electra_test.md @@ -0,0 +1,3 @@ +### Ignored + +- Add blobs by range electra test \ No newline at end of file diff --git a/changelog/tt_fork_digest.md b/changelog/tt_fork_digest.md new file mode 100644 index 000000000000..2d0cea6a6cba --- /dev/null +++ b/changelog/tt_fork_digest.md @@ -0,0 +1,3 @@ +### Ignored + +- Add more debugging information to mismatch fork digest error message \ No newline at end of file diff --git a/changelog/tt_validate_range.md b/changelog/tt_validate_range.md new file mode 100644 index 000000000000..8708bdfcd149 --- /dev/null +++ b/changelog/tt_validate_range.md @@ -0,0 +1,3 @@ +### Ignored + +- Add more debugging information to validate range debug message \ No newline at end of file diff --git a/cmd/beacon-chain/flags/BUILD.bazel b/cmd/beacon-chain/flags/BUILD.bazel index 0dfdcd088e4c..2385a70931c2 100644 --- a/cmd/beacon-chain/flags/BUILD.bazel +++ b/cmd/beacon-chain/flags/BUILD.bazel @@ -11,7 +11,7 @@ go_library( ], importpath = "github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags", visibility = [ - "//api/gateway:__pkg__", + "//api:__subpackages__", "//beacon-chain:__subpackages__", "//cmd/beacon-chain:__subpackages__", "//testing/endtoend:__subpackages__", diff --git a/cmd/beacon-chain/flags/base.go b/cmd/beacon-chain/flags/base.go index 731aac2e5c20..e4f0881cebfa 100644 --- a/cmd/beacon-chain/flags/base.go +++ b/cmd/beacon-chain/flags/base.go @@ -3,11 +3,24 @@ package flags import ( + "strings" + "github.com/prysmaticlabs/prysm/v5/cmd" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/urfave/cli/v2" ) +var ( + DefaultWebDomains = []string{"http://localhost:4200", "http://127.0.0.1:4200", "http://0.0.0.0:4200"} + DefaultHTTPServerDomains = []string{"http://localhost:7500", "http://127.0.0.1:7500", "http://0.0.0.0:7500"} + DefaultHTTPCorsDomains = func() []string { + s := []string{"http://localhost:3000", "http://0.0.0.0:3000", "http://127.0.0.1:3000"} + s = append(s, DefaultWebDomains...) + s = append(s, DefaultHTTPServerDomains...) + return s + }() +) + var ( // MevRelayEndpoint provides an HTTP access endpoint to a MEV builder network. MevRelayEndpoint = &cli.StringFlag{ @@ -21,8 +34,9 @@ var ( Value: 3, } MaxBuilderEpochMissedSlots = &cli.IntFlag{ - Name: "max-builder-epoch-missed-slots", - Usage: "Number of total skip slot to fallback from using relay/builder to local execution engine for block construction in last epoch rolling window", + Name: "max-builder-epoch-missed-slots", + Usage: "Number of total skip slot to fallback from using relay/builder to local execution engine for block construction in last epoch rolling window. " + + "The values are on the basis of the networks and the default value for mainnet is 5.", } // LocalBlockValueBoost sets a percentage boost for local block construction while using a custom builder. LocalBlockValueBoost = &cli.Uint64Flag{ @@ -117,30 +131,29 @@ var ( Usage: "Comma-separated list of API module names. Possible values: `" + PrysmAPIModule + `,` + EthAPIModule + "`.", Value: PrysmAPIModule + `,` + EthAPIModule, } - // DisableGRPCGateway for JSON-HTTP requests to the beacon node. - DisableGRPCGateway = &cli.BoolFlag{ - Name: "disable-grpc-gateway", - Usage: "Disable the gRPC gateway for JSON-HTTP requests", - } - // GRPCGatewayHost specifies a gRPC gateway host for Prysm. - GRPCGatewayHost = &cli.StringFlag{ - Name: "grpc-gateway-host", - Usage: "The host on which the gateway server runs on", - Value: "127.0.0.1", - } - // GRPCGatewayPort specifies a gRPC gateway port for Prysm. - GRPCGatewayPort = &cli.IntFlag{ - Name: "grpc-gateway-port", - Usage: "The port on which the gateway server runs on", - Value: 3500, - } - // GPRCGatewayCorsDomain serves preflight requests when serving gRPC JSON gateway. - GPRCGatewayCorsDomain = &cli.StringFlag{ - Name: "grpc-gateway-corsdomain", - Usage: "Comma separated list of domains from which to accept cross origin requests " + - "(browser enforced). This flag has no effect if not used with --grpc-gateway-port.", - Value: "http://localhost:4200,http://localhost:7500,http://127.0.0.1:4200,http://127.0.0.1:7500,http://0.0.0.0:4200,http://0.0.0.0:7500,http://localhost:3000,http://0.0.0.0:3000,http://127.0.0.1:3000", + + // HTTPServerHost specifies a HTTP server host for the validator client. + HTTPServerHost = &cli.StringFlag{ + Name: "http-host", + Usage: "Host on which the HTTP server runs on.", + Value: "127.0.0.1", + Aliases: []string{"grpc-gateway-host"}, + } + // HTTPServerPort enables a REST server port to be exposed for the validator client. + HTTPServerPort = &cli.IntFlag{ + Name: "http-port", + Usage: "Port on which the HTTP server runs on.", + Value: 3500, + Aliases: []string{"grpc-gateway-port"}, + } + // HTTPServerCorsDomain serves preflight requests when serving HTTP. + HTTPServerCorsDomain = &cli.StringFlag{ + Name: "http-cors-domain", + Usage: "Comma separated list of domains from which to accept cross origin requests.", + Value: strings.Join(DefaultHTTPCorsDomains, ", "), + Aliases: []string{"grpc-gateway-corsdomain"}, } + // MinSyncPeers specifies the required number of successful peer handshakes in order // to start syncing with external peers. MinSyncPeers = &cli.IntFlag{ @@ -183,13 +196,13 @@ var ( BlobBatchLimit = &cli.IntFlag{ Name: "blob-batch-limit", Usage: "The amount of blobs the local peer is bounded to request and respond to in a batch.", - Value: 64, + Value: 192, } // BlobBatchLimitBurstFactor specifies the factor by which blob batch size may increase. BlobBatchLimitBurstFactor = &cli.IntFlag{ Name: "blob-batch-limit-burst-factor", Usage: "The factor by which blob batch limit may increase on burst.", - Value: 2, + Value: 3, } // DisableDebugRPCEndpoints disables the debug Beacon API namespace. DisableDebugRPCEndpoints = &cli.BoolFlag{ @@ -283,4 +296,16 @@ var ( Usage: "Directory for the slasher database", Value: cmd.DefaultDataDir(), } + // BeaconDBPruning enables the pruning of beacon db. + BeaconDBPruning = &cli.BoolFlag{ + Name: "beacon-db-pruning", + Usage: "Enables pruning of beacon db beyond MIN_EPOCHS_FOR_BLOCK_REQUESTS duration. This is an opt-in feature," + + " and should only be enabled if operators doesn't require historical data.", + } + // PrunerRetentionEpochs defines the retention period for the pruner service in terms of epochs. + PrunerRetentionEpochs = &cli.Uint64Flag{ + Name: "pruner-retention-epochs", + Usage: "Specifies the retention period for the pruner service in terms of epochs. " + + "If this value is less than MIN_EPOCHS_FOR_BLOCK_REQUESTS, it will be ignored.", + } ) diff --git a/cmd/beacon-chain/flags/interop.go b/cmd/beacon-chain/flags/interop.go index 6aac9e666480..2552d9d0960e 100644 --- a/cmd/beacon-chain/flags/interop.go +++ b/cmd/beacon-chain/flags/interop.go @@ -10,16 +10,4 @@ var ( Name: "interop-eth1data-votes", Usage: "Enable mocking of eth1 data votes for proposers to package into blocks", } - - // InteropGenesisTimeFlag specifies genesis time for state generation. - InteropGenesisTimeFlag = &cli.Uint64Flag{ - Name: "interop-genesis-time", - Usage: "Specify the genesis time for interop genesis state generation. Must be used with " + - "--interop-num-validators", - } - // InteropNumValidatorsFlag specifies number of genesis validators for state generation. - InteropNumValidatorsFlag = &cli.Uint64Flag{ - Name: "interop-num-validators", - Usage: "Specify number of genesis validators to generate for interop. Must be used with --interop-genesis-time", - } ) diff --git a/cmd/beacon-chain/main.go b/cmd/beacon-chain/main.go index 0f3a42547615..70184dac2eac 100644 --- a/cmd/beacon-chain/main.go +++ b/cmd/beacon-chain/main.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" runtimeDebug "runtime/debug" + "time" gethlog "github.com/ethereum/go-ethereum/log" golog "github.com/ipfs/go-log/v2" @@ -49,10 +50,9 @@ var appFlags = []cli.Flag{ flags.CertFlag, flags.KeyFlag, flags.HTTPModules, - flags.DisableGRPCGateway, - flags.GRPCGatewayHost, - flags.GRPCGatewayPort, - flags.GPRCGatewayCorsDomain, + flags.HTTPServerHost, + flags.HTTPServerPort, + flags.HTTPServerCorsDomain, flags.MinSyncPeers, flags.ContractDeploymentBlock, flags.SetGCPercent, @@ -61,8 +61,6 @@ var appFlags = []cli.Flag{ flags.BlobBatchLimit, flags.BlobBatchLimitBurstFactor, flags.InteropMockEth1DataVotesFlag, - flags.InteropNumValidatorsFlag, - flags.InteropGenesisTimeFlag, flags.SlotsPerArchivedPoint, flags.DisableDebugRPCEndpoints, flags.SubscribeToAllSubnets, @@ -84,6 +82,8 @@ var appFlags = []cli.Flag{ flags.LocalBlockValueBoost, flags.MinBuilderBid, flags.MinBuilderDiff, + flags.BeaconDBPruning, + flags.PrunerRetentionEpochs, cmd.BackupWebhookOutputDir, cmd.MinimalConfigFlag, cmd.E2EConfigFlag, @@ -145,6 +145,7 @@ var appFlags = []cli.Flag{ flags.JwtId, storage.BlobStoragePathFlag, storage.BlobRetentionEpochFlag, + storage.BlobStorageLayout, bflags.EnableExperimentalBackfill, bflags.BackfillBatchSize, bflags.BackfillWorkerCount, @@ -166,7 +167,7 @@ func before(ctx *cli.Context) error { switch format { case "text": formatter := new(prefixed.TextFormatter) - formatter.TimestampFormat = "2006-01-02 15:04:05" + formatter.TimestampFormat = time.DateTime formatter.FullTimestamp = true // If persistent log files are written - we disable the log messages coloring because @@ -286,9 +287,7 @@ func startNode(ctx *cli.Context, cancel context.CancelFunc) error { // libp2p specific logging. golog.SetAllLoggers(golog.LevelDebug) // Geth specific logging. - glogger := gethlog.NewGlogHandler(gethlog.StreamHandler(os.Stderr, gethlog.TerminalFormat(true))) - glogger.Verbosity(gethlog.LvlTrace) - gethlog.Root().SetHandler(glogger) + gethlog.SetDefault(gethlog.NewLogger(gethlog.NewTerminalHandlerWithLevel(os.Stderr, gethlog.LvlTrace, true))) } blockchainFlagOpts, err := blockchaincmd.FlagOptions(ctx) diff --git a/cmd/beacon-chain/pprof.beacon-chain.samples.cpu.pb.gz b/cmd/beacon-chain/pprof.beacon-chain.samples.cpu.pb.gz index 553015b136cb..b969c435d73b 100644 Binary files a/cmd/beacon-chain/pprof.beacon-chain.samples.cpu.pb.gz and b/cmd/beacon-chain/pprof.beacon-chain.samples.cpu.pb.gz differ diff --git a/cmd/beacon-chain/storage/options.go b/cmd/beacon-chain/storage/options.go index 3ecd943ef0d3..5bef1f758ef3 100644 --- a/cmd/beacon-chain/storage/options.go +++ b/cmd/beacon-chain/storage/options.go @@ -2,6 +2,7 @@ package storage import ( "path" + "strings" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/db/filesystem" @@ -24,8 +25,30 @@ var ( Value: uint64(params.BeaconConfig().MinEpochsForBlobsSidecarsRequest), Aliases: []string{"extend-blob-retention-epoch"}, } + BlobStorageLayout = &cli.StringFlag{ + Name: "blob-storage-layout", + Usage: layoutFlagUsage(), + Value: filesystem.LayoutNameFlat, + } ) +func layoutOptions() string { + return "available options are: " + strings.Join(filesystem.LayoutNames, ", ") + "." +} + +func layoutFlagUsage() string { + return "Dictates how to organize the blob directory structure on disk, " + layoutOptions() +} + +func validateLayoutFlag(_ *cli.Context, v string) error { + for _, l := range filesystem.LayoutNames { + if v == l { + return nil + } + } + return errors.Errorf("invalid value '%s' for flag --%s, %s", v, BlobStorageLayout.Name, layoutOptions()) +} + // BeaconNodeOptions sets configuration values on the node.BeaconNode value at node startup. // Note: we can't get the right context from cli.Context, because the beacon node setup code uses this context to // create a cancellable context. If we switch to using App.RunContext, we can set up this cancellation in the cmd @@ -36,7 +59,9 @@ func BeaconNodeOptions(c *cli.Context) ([]node.Option, error) { return nil, err } opts := []node.Option{node.WithBlobStorageOptions( - filesystem.WithBlobRetentionEpochs(e), filesystem.WithBasePath(blobStoragePath(c)), + filesystem.WithBlobRetentionEpochs(e), + filesystem.WithBasePath(blobStoragePath(c)), + filesystem.WithLayout(c.String(BlobStorageLayout.Name)), // This is validated in the Action func for BlobStorageLayout. )} return opts, nil } @@ -69,3 +94,7 @@ func blobRetentionEpoch(cliCtx *cli.Context) (primitives.Epoch, error) { return re, nil } + +func init() { + BlobStorageLayout.Action = validateLayoutFlag +} diff --git a/cmd/beacon-chain/sync/backfill/options.go b/cmd/beacon-chain/sync/backfill/options.go index 4d2cb61d6c72..12cbcee5d922 100644 --- a/cmd/beacon-chain/sync/backfill/options.go +++ b/cmd/beacon-chain/sync/backfill/options.go @@ -19,7 +19,7 @@ func BeaconNodeOptions(c *cli.Context) ([]node.Option, error) { } // The zero value of this uint flag would be genesis, so we use IsSet to differentiate nil from zero case. if c.IsSet(flags.BackfillOldestSlot.Name) { - uv := c.Uint64(flags.BackfillBatchSize.Name) + uv := c.Uint64(flags.BackfillOldestSlot.Name) bno = append(bno, backfill.WithMinimumSlot(primitives.Slot(uv))) } node.BackfillOpts = bno diff --git a/cmd/beacon-chain/usage.go b/cmd/beacon-chain/usage.go index 66f7c1013f2f..6c5fda7d5aa6 100644 --- a/cmd/beacon-chain/usage.go +++ b/cmd/beacon-chain/usage.go @@ -103,10 +103,9 @@ var appHelpFlagGroups = []flagGroup{ flags.CertFlag, flags.KeyFlag, flags.HTTPModules, - flags.DisableGRPCGateway, - flags.GRPCGatewayHost, - flags.GRPCGatewayPort, - flags.GPRCGatewayCorsDomain, + flags.HTTPServerHost, + flags.HTTPServerPort, + flags.HTTPServerCorsDomain, flags.ExecutionEngineEndpoint, flags.ExecutionEngineHeaders, flags.ExecutionJWTSecretFlag, @@ -134,6 +133,8 @@ var appHelpFlagGroups = []flagGroup{ flags.MinBuilderBid, flags.MinBuilderDiff, flags.JwtId, + flags.BeaconDBPruning, + flags.PrunerRetentionEpochs, checkpoint.BlockPath, checkpoint.StatePath, checkpoint.RemoteURL, @@ -141,6 +142,7 @@ var appHelpFlagGroups = []flagGroup{ genesis.BeaconAPIURL, storage.BlobStoragePathFlag, storage.BlobRetentionEpochFlag, + storage.BlobStorageLayout, backfill.EnableExperimentalBackfill, backfill.BackfillWorkerCount, backfill.BackfillBatchSize, @@ -185,14 +187,6 @@ var appHelpFlagGroups = []flagGroup{ Name: "features", Flags: features.ActiveFlags(features.BeaconChainFlags), }, - { - Name: "interop", - Flags: []cli.Flag{ - genesis.StatePath, - flags.InteropGenesisTimeFlag, - flags.InteropNumValidatorsFlag, - }, - }, { Name: "deprecated", Flags: []cli.Flag{ diff --git a/cmd/client-stats/flags/flags.go b/cmd/client-stats/flags/flags.go index 605c9494b466..95ef697e4200 100644 --- a/cmd/client-stats/flags/flags.go +++ b/cmd/client-stats/flags/flags.go @@ -28,6 +28,6 @@ var ( ScrapeIntervalFlag = &cli.DurationFlag{ Name: "scrape-interval", Usage: "Frequency of scraping expressed as a duration, eg 2m or 1m5s.", - Value: 60 * time.Second, + Value: 120 * time.Second, } ) diff --git a/cmd/client-stats/main.go b/cmd/client-stats/main.go index 9962947b66e3..fd56b7e5f237 100644 --- a/cmd/client-stats/main.go +++ b/cmd/client-stats/main.go @@ -60,7 +60,7 @@ func main() { switch format { case "text": formatter := new(prefixed.TextFormatter) - formatter.TimestampFormat = "2006-01-02 15:04:05" + formatter.TimestampFormat = time.DateTime formatter.FullTimestamp = true // If persistent log files are written - we disable the log messages coloring because // the colors are ANSI codes and seen as gibberish in the log files. diff --git a/cmd/flags.go b/cmd/flags.go index bd7d135f6a0f..6c1c44e8d947 100644 --- a/cmd/flags.go +++ b/cmd/flags.go @@ -6,6 +6,7 @@ import ( "math" "slices" "strings" + "time" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/urfave/cli/v2" @@ -267,10 +268,10 @@ var ( Value: DefaultDataDir(), } // ApiTimeoutFlag specifies the timeout value for API requests in seconds. A timeout of zero means no timeout. - ApiTimeoutFlag = &cli.IntFlag{ + ApiTimeoutFlag = &cli.DurationFlag{ Name: "api-timeout", Usage: "Specifies the timeout value for API requests in seconds.", - Value: 120, + Value: 10 * time.Second, } // JwtOutputFileFlag specifies the JWT file path that gets generated into when invoked by generate-jwt-secret. JwtOutputFileFlag = &cli.StringFlag{ diff --git a/cmd/prysmctl/BUILD.bazel b/cmd/prysmctl/BUILD.bazel index fdcb9f00809d..44e339e856e2 100644 --- a/cmd/prysmctl/BUILD.bazel +++ b/cmd/prysmctl/BUILD.bazel @@ -22,7 +22,6 @@ go_library( go_binary( name = "prysmctl", embed = [":go_default_library"], - gotags = ["noMainnetGenesis"], visibility = ["//visibility:public"], ) diff --git a/cmd/prysmctl/checkpointsync/BUILD.bazel b/cmd/prysmctl/checkpointsync/BUILD.bazel index eafecf7c461d..c220ba325068 100644 --- a/cmd/prysmctl/checkpointsync/BUILD.bazel +++ b/cmd/prysmctl/checkpointsync/BUILD.bazel @@ -11,6 +11,7 @@ go_library( deps = [ "//api/client:go_default_library", "//api/client/beacon:go_default_library", + "//beacon-chain/sync/checkpoint:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library", ], diff --git a/cmd/prysmctl/checkpointsync/download.go b/cmd/prysmctl/checkpointsync/download.go index 77214ce0fecd..116743de8eea 100644 --- a/cmd/prysmctl/checkpointsync/download.go +++ b/cmd/prysmctl/checkpointsync/download.go @@ -7,6 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/api/client" "github.com/prysmaticlabs/prysm/v5/api/client/beacon" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/checkpoint" log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -46,7 +47,7 @@ func cliActionDownload(_ *cli.Context) error { ctx := context.Background() f := downloadFlags - opts := []client.ClientOpt{client.WithTimeout(f.Timeout)} + opts := []client.ClientOpt{client.WithTimeout(f.Timeout), client.WithMaxBodySize(client.MaxBodySizeState)} client, err := beacon.NewClient(downloadFlags.BeaconNodeHost, opts...) if err != nil { return err @@ -57,7 +58,7 @@ func cliActionDownload(_ *cli.Context) error { return err } - od, err := beacon.DownloadFinalizedData(ctx, client) + od, err := checkpoint.DownloadFinalizedData(ctx, client) if err != nil { return err } diff --git a/cmd/prysmctl/p2p/BUILD.bazel b/cmd/prysmctl/p2p/BUILD.bazel index bb04938b454f..712f4756a89e 100644 --- a/cmd/prysmctl/p2p/BUILD.bazel +++ b/cmd/prysmctl/p2p/BUILD.bazel @@ -29,6 +29,7 @@ go_library( "//crypto/ecdsa:go_default_library", "//encoding/bytesutil:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network:go_default_library", "//network/forks:go_default_library", "//proto/prysm/v1alpha1:go_default_library", @@ -50,7 +51,6 @@ go_library( "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_protobuf//types/known/emptypb:go_default_library", ], diff --git a/cmd/prysmctl/p2p/client.go b/cmd/prysmctl/p2p/client.go index 146e7f0ef365..c6fe6e39b849 100644 --- a/cmd/prysmctl/p2p/client.go +++ b/cmd/prysmctl/p2p/client.go @@ -25,13 +25,13 @@ import ( ecdsaprysm "github.com/prysmaticlabs/prysm/v5/crypto/ecdsa" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network" "github.com/prysmaticlabs/prysm/v5/network/forks" pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/metadata" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/emptypb" ) @@ -114,7 +114,7 @@ func (c *client) Send( ctx, span := trace.StartSpan(ctx, "p2p.Send") defer span.End() topic := baseTopic + c.Encoding().ProtocolSuffix() - span.AddAttributes(trace.StringAttribute("topic", topic)) + span.SetAttributes(trace.StringAttribute("topic", topic)) // Apply max dial timeout when opening a new stream. ctx, cancel := context.WithTimeout(ctx, 10*time.Minute) diff --git a/cmd/prysmctl/testnet/generate_genesis.go b/cmd/prysmctl/testnet/generate_genesis.go index 00357e075e6e..814deac8fa5d 100644 --- a/cmd/prysmctl/testnet/generate_genesis.go +++ b/cmd/prysmctl/testnet/generate_genesis.go @@ -31,7 +31,6 @@ var ( generateGenesisStateFlags = struct { DepositJsonFile string ChainConfigFile string - ConfigName string NumValidators uint64 GenesisTime uint64 GenesisTimeDelay uint64 @@ -83,12 +82,6 @@ var ( Destination: &generateGenesisStateFlags.DepositJsonFile, Usage: "Path to deposit_data.json file generated by the staking-deposit-cli tool for optionally specifying validators in genesis state", }, - &cli.StringFlag{ - Name: "config-name", - Usage: "Config kind to be used for generating the genesis state. Default: mainnet. Options include mainnet, interop, minimal, sepolia, holesky. --chain-config-file will override this flag.", - Destination: &generateGenesisStateFlags.ConfigName, - Value: params.MainnetName, - }, &cli.Uint64Flag{ Name: "num-validators", Usage: "Number of validators to deterministically generate in the genesis state", @@ -216,11 +209,7 @@ func setGlobalParams() error { log.Infof("Specified a chain config file: %s", chainConfigFile) return params.LoadChainConfigFile(chainConfigFile, nil) } - cfg, err := params.ByName(generateGenesisStateFlags.ConfigName) - if err != nil { - return fmt.Errorf("unable to find config using name %s: %w", generateGenesisStateFlags.ConfigName, err) - } - return params.SetActive(cfg.Copy()) + return errors.New("No chain config file was provided. Use `--chain-config-file` to provide a chain config.") } func generateGenesis(ctx context.Context) (state.BeaconState, error) { @@ -289,7 +278,6 @@ func generateGenesis(ctx context.Context) (state.BeaconState, error) { if v > version.Altair { // set ttd to zero so EL goes post-merge immediately gen.Config.TerminalTotalDifficulty = big.NewInt(0) - gen.Config.TerminalTotalDifficultyPassed = true } } else { gen = interop.GethTestnetGenesis(f.GenesisTime, params.BeaconConfig()) diff --git a/cmd/prysmctl/validator/BUILD.bazel b/cmd/prysmctl/validator/BUILD.bazel index 0d1174c503b6..7acc73159979 100644 --- a/cmd/prysmctl/validator/BUILD.bazel +++ b/cmd/prysmctl/validator/BUILD.bazel @@ -26,6 +26,7 @@ go_library( "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", "//io/prompt:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", "//runtime/tos:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", @@ -33,7 +34,6 @@ go_library( "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/cmd/prysmctl/validator/proposer_settings.go b/cmd/prysmctl/validator/proposer_settings.go index 5c9d84341b16..26de12a58dc0 100644 --- a/cmd/prysmctl/validator/proposer_settings.go +++ b/cmd/prysmctl/validator/proposer_settings.go @@ -14,10 +14,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/io/file" "github.com/prysmaticlabs/prysm/v5/io/prompt" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" - "go.opencensus.io/trace" ) func getProposerSettings(c *cli.Context, r io.Reader) error { diff --git a/cmd/prysmctl/validator/withdraw.go b/cmd/prysmctl/validator/withdraw.go index 6db3e1c99c23..e142e0ca548f 100644 --- a/cmd/prysmctl/validator/withdraw.go +++ b/cmd/prysmctl/validator/withdraw.go @@ -17,9 +17,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/api/server/structs" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" - "go.opencensus.io/trace" ) func setWithdrawalAddresses(c *cli.Context) error { diff --git a/cmd/prysmctl/weaksubjectivity/BUILD.bazel b/cmd/prysmctl/weaksubjectivity/BUILD.bazel index d0f9c0be50c9..f56ae220ff65 100644 --- a/cmd/prysmctl/weaksubjectivity/BUILD.bazel +++ b/cmd/prysmctl/weaksubjectivity/BUILD.bazel @@ -11,6 +11,7 @@ go_library( deps = [ "//api/client:go_default_library", "//api/client/beacon:go_default_library", + "//beacon-chain/sync/checkpoint:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library", ], diff --git a/cmd/prysmctl/weaksubjectivity/checkpoint.go b/cmd/prysmctl/weaksubjectivity/checkpoint.go index dc35c4432390..094a006f384d 100644 --- a/cmd/prysmctl/weaksubjectivity/checkpoint.go +++ b/cmd/prysmctl/weaksubjectivity/checkpoint.go @@ -7,6 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/api/client" "github.com/prysmaticlabs/prysm/v5/api/client/beacon" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/checkpoint" log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -52,7 +53,7 @@ func cliActionCheckpoint(_ *cli.Context) error { return err } - ws, err := beacon.ComputeWeakSubjectivityCheckpoint(ctx, client) + ws, err := checkpoint.ComputeWeakSubjectivityCheckpoint(ctx, client) if err != nil { return err } diff --git a/cmd/validator/flags/flags.go b/cmd/validator/flags/flags.go index 4a13aad669e4..e873d16c3f20 100644 --- a/cmd/validator/flags/flags.go +++ b/cmd/validator/flags/flags.go @@ -17,8 +17,8 @@ import ( const ( // WalletDefaultDirName for accounts. WalletDefaultDirName = "prysm-wallet-v2" - // DefaultGatewayHost for the validator client. - DefaultGatewayHost = "127.0.0.1" + // DefaultHTTPServerHost for the validator client. + DefaultHTTPServerHost = "127.0.0.1" ) var ( @@ -35,12 +35,7 @@ var ( Usage: "Beacon node RPC provider endpoint.", Value: "127.0.0.1:4000", } - // BeaconRPCGatewayProviderFlag defines a beacon node JSON-RPC endpoint. - BeaconRPCGatewayProviderFlag = &cli.StringFlag{ - Name: "beacon-rpc-gateway-provider", - Usage: "Beacon node RPC gateway provider endpoint.", - Value: "127.0.0.1:3500", - } + // BeaconRESTApiProviderFlag defines a beacon node REST API endpoint. BeaconRESTApiProviderFlag = &cli.StringFlag{ Name: "beacon-rest-api-provider", @@ -109,25 +104,27 @@ var ( Usage: `Comma separated list of key value pairs to pass as gRPC headers for all gRPC calls. Example: --grpc-headers=key=value`, } - // GRPCGatewayHost specifies a gRPC gateway host for the validator client. - GRPCGatewayHost = &cli.StringFlag{ - Name: "grpc-gateway-host", - Usage: "Host on which the gateway server runs on.", - Value: DefaultGatewayHost, - } - // GRPCGatewayPort enables a gRPC gateway to be exposed for the validator client. - GRPCGatewayPort = &cli.IntFlag{ - Name: "grpc-gateway-port", - Usage: "Enables gRPC gateway for JSON requests.", - Value: 7500, - } - // GRPCGatewayCorsDomain serves preflight requests when serving gRPC JSON gateway. - GRPCGatewayCorsDomain = &cli.StringFlag{ - Name: "grpc-gateway-corsdomain", - Usage: `Comma separated list of domains from which to accept cross origin requests (browser enforced). - This flag has no effect if not used with --grpc-gateway-port. -`, - Value: "http://localhost:7500,http://127.0.0.1:7500,http://0.0.0.0:7500,http://localhost:4242,http://127.0.0.1:4242,http://localhost:4200,http://0.0.0.0:4242,http://127.0.0.1:4200,http://0.0.0.0:4200,http://localhost:3000,http://0.0.0.0:3000,http://127.0.0.1:3000"} + // HTTPServerHost specifies a HTTP server host for the validator client. + HTTPServerHost = &cli.StringFlag{ + Name: "http-host", + Usage: "Host on which the HTTP server runs on.", + Value: DefaultHTTPServerHost, + Aliases: []string{"grpc-gateway-host"}, + } + // HTTPServerPort enables a HTTP server port to be exposed for the validator client. + HTTPServerPort = &cli.IntFlag{ + Name: "http-port", + Usage: "Port on which the HTTP server runs on.", + Value: 7500, + Aliases: []string{"grpc-gateway-port"}, + } + // HTTPServerCorsDomain adds accepted cross origin request addresses. + HTTPServerCorsDomain = &cli.StringFlag{ + Name: "http-cors-domain", + Usage: `Comma separated list of domains from which to accept cross origin requests (browser enforced).`, + Value: "http://localhost:7500,http://127.0.0.1:7500,http://0.0.0.0:7500,http://localhost:4242,http://127.0.0.1:4242,http://localhost:4200,http://0.0.0.0:4242,http://127.0.0.1:4200,http://0.0.0.0:4200,http://localhost:3000,http://0.0.0.0:3000,http://127.0.0.1:3000", + Aliases: []string{"grpc-gateway-corsdomain"}, + } // MonitoringPortFlag defines the http port used to serve prometheus metrics. MonitoringPortFlag = &cli.IntFlag{ Name: "monitoring-port", diff --git a/cmd/validator/main.go b/cmd/validator/main.go index cb0287a60c7f..a8c46975148b 100644 --- a/cmd/validator/main.go +++ b/cmd/validator/main.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" runtimeDebug "runtime/debug" + "time" joonix "github.com/joonix/log" "github.com/pkg/errors" @@ -50,7 +51,6 @@ func startNode(ctx *cli.Context) error { var appFlags = []cli.Flag{ flags.BeaconRPCProviderFlag, - flags.BeaconRPCGatewayProviderFlag, flags.BeaconRESTApiProviderFlag, flags.CertFlag, flags.GraffitiFlag, @@ -60,12 +60,12 @@ var appFlags = []cli.Flag{ flags.EnableRPCFlag, flags.RPCHost, flags.RPCPort, - flags.GRPCGatewayPort, - flags.GRPCGatewayHost, + flags.HTTPServerPort, + flags.HTTPServerHost, flags.GRPCRetriesFlag, flags.GRPCRetryDelayFlag, flags.GRPCHeadersFlag, - flags.GRPCGatewayCorsDomain, + flags.HTTPServerCorsDomain, flags.DisableAccountMetricsFlag, flags.MonitoringPortFlag, flags.SlasherRPCProviderFlag, @@ -154,7 +154,7 @@ func main() { switch format { case "text": formatter := new(prefixed.TextFormatter) - formatter.TimestampFormat = "2006-01-02 15:04:05" + formatter.TimestampFormat = time.DateTime formatter.FullTimestamp = true // If persistent log files are written - we disable the log messages coloring because // the colors are ANSI codes and seen as gibberish in the log files. diff --git a/cmd/validator/slashing-protection/import.go b/cmd/validator/slashing-protection/import.go index 3aa91085c78b..5f62bd991683 100644 --- a/cmd/validator/slashing-protection/import.go +++ b/cmd/validator/slashing-protection/import.go @@ -33,7 +33,7 @@ func importSlashingProtectionJSON(cliCtx *cli.Context) error { ) // Check if a minimal database is requested - isDatabaseMimimal := cliCtx.Bool(features.EnableMinimalSlashingProtection.Name) + isDatabaseMinimal := cliCtx.Bool(features.EnableMinimalSlashingProtection.Name) // Get the data directory from the CLI context. dataDir := cliCtx.String(cmd.DataDirFlag.Name) @@ -45,7 +45,7 @@ func importSlashingProtectionJSON(cliCtx *cli.Context) error { } // Ensure that the database is found under the specified directory or its subdirectories - if isDatabaseMimimal { + if isDatabaseMinimal { found, _, err = file.RecursiveDirFind(filesystem.DatabaseDirName, dataDir) } else { found, _, err = file.RecursiveFileFind(kv.ProtectionDbFileName, dataDir) @@ -63,7 +63,7 @@ func importSlashingProtectionJSON(cliCtx *cli.Context) error { log.Infof(message, dataDir) // Open the validator database. - if isDatabaseMimimal { + if isDatabaseMinimal { valDB, err = filesystem.NewStore(dataDir, nil) } else { valDB, err = kv.NewKVStore(cliCtx.Context, dataDir, nil) diff --git a/cmd/validator/usage.go b/cmd/validator/usage.go index 59f720b2f152..1341f797c037 100644 --- a/cmd/validator/usage.go +++ b/cmd/validator/usage.go @@ -96,15 +96,14 @@ var appHelpFlagGroups = []flagGroup{ Flags: []cli.Flag{ flags.CertFlag, flags.BeaconRPCProviderFlag, - flags.BeaconRPCGatewayProviderFlag, flags.EnableRPCFlag, flags.RPCHost, flags.RPCPort, - flags.GRPCGatewayPort, - flags.GRPCGatewayHost, + flags.HTTPServerPort, + flags.HTTPServerHost, flags.GRPCRetriesFlag, flags.GRPCRetryDelayFlag, - flags.GRPCGatewayCorsDomain, + flags.HTTPServerCorsDomain, flags.GRPCHeadersFlag, flags.BeaconRESTApiProviderFlag, }, diff --git a/cmd/validator/web/web.go b/cmd/validator/web/web.go index 34a4edb22ace..91c2c08c5724 100644 --- a/cmd/validator/web/web.go +++ b/cmd/validator/web/web.go @@ -24,8 +24,8 @@ var Commands = &cli.Command{ Description: `Generate an authentication token for the Prysm web interface`, Flags: cmd.WrapFlags([]cli.Flag{ flags.WalletDirFlag, - flags.GRPCGatewayHost, - flags.GRPCGatewayPort, + flags.HTTPServerHost, + flags.HTTPServerPort, flags.AuthTokenPathFlag, cmd.AcceptTosFlag, }), @@ -43,9 +43,9 @@ var Commands = &cli.Command{ if walletDirPath == "" { log.Fatal("--wallet-dir not specified") } - gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name) - gatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name) - validatorWebAddr := fmt.Sprintf("%s:%d", gatewayHost, gatewayPort) + host := cliCtx.String(flags.HTTPServerHost.Name) + port := cliCtx.Int(flags.HTTPServerPort.Name) + validatorWebAddr := fmt.Sprintf("%s:%d", host, port) authTokenPath := filepath.Join(walletDirPath, api.AuthTokenFileName) tempAuthTokenPath := cliCtx.String(flags.AuthTokenPathFlag.Name) if tempAuthTokenPath != "" { diff --git a/config/features/config.go b/config/features/config.go index e570274a352c..1ceb28edf7fc 100644 --- a/config/features/config.go +++ b/config/features/config.go @@ -48,7 +48,8 @@ type Flags struct { EnableDoppelGanger bool // EnableDoppelGanger enables doppelganger protection on startup for the validator. EnableHistoricalSpaceRepresentation bool // EnableHistoricalSpaceRepresentation enables the saving of registry validators in separate buckets to save space EnableBeaconRESTApi bool // EnableBeaconRESTApi enables experimental usage of the beacon REST API by the validator when querying a beacon node - EnableCommitteeAwarePacking bool // EnableCommitteeAwarePacking TODO + DisableCommitteeAwarePacking bool // DisableCommitteeAwarePacking changes the attestation packing algorithm to one that is not aware of attesting committees. + EnableExperimentalAttestationPool bool // EnableExperimentalAttestationPool enables an experimental attestation pool design. // Logging related toggles. DisableGRPCConnectionLogs bool // Disables logging when a new grpc client has connected. EnableFullSSZDataLogging bool // Enables logging for full ssz data on rejected gossip messages @@ -78,6 +79,8 @@ type Flags struct { SaveInvalidBlock bool // SaveInvalidBlock saves invalid block to temp. SaveInvalidBlob bool // SaveInvalidBlob saves invalid blob to temp. + EnableDiscoveryReboot bool // EnableDiscoveryReboot allows the node to have its local listener to be rebooted in the event of discovery issues. + // KeystoreImportDebounceInterval specifies the time duration the validator waits to reload new keys if they have // changed on disk. This feature is for advanced use cases only. KeystoreImportDebounceInterval time.Duration @@ -163,6 +166,7 @@ func applyHoleskyFeatureFlags(ctx *cli.Context) { // ConfigureBeaconChain sets the global config based // on what flags are enabled for the beacon-chain client. func ConfigureBeaconChain(ctx *cli.Context) error { + warnDeprecationUpcoming(ctx) complainOnDeprecatedFlags(ctx) cfg := &Flags{} if ctx.Bool(devModeFlag.Name) { @@ -172,9 +176,10 @@ func ConfigureBeaconChain(ctx *cli.Context) error { return err } - if ctx.Bool(enableExperimentalState.Name) { - logEnabled(enableExperimentalState) - cfg.EnableExperimentalState = true + cfg.EnableExperimentalState = true + if ctx.Bool(disableExperimentalState.Name) { + logEnabled(disableExperimentalState) + cfg.EnableExperimentalState = false } if ctx.Bool(writeSSZStateTransitionsFlag.Name) { @@ -251,13 +256,22 @@ func ConfigureBeaconChain(ctx *cli.Context) error { logEnabled(BlobSaveFsync) cfg.BlobSaveFsync = true } - if ctx.IsSet(EnableQUIC.Name) { - logEnabled(EnableQUIC) - cfg.EnableQUIC = true + cfg.EnableQUIC = true + if ctx.IsSet(DisableQUIC.Name) { + logDisabled(DisableQUIC) + cfg.EnableQUIC = false + } + if ctx.IsSet(DisableCommitteeAwarePacking.Name) { + logEnabled(DisableCommitteeAwarePacking) + cfg.DisableCommitteeAwarePacking = true + } + if ctx.IsSet(EnableDiscoveryReboot.Name) { + logEnabled(EnableDiscoveryReboot) + cfg.EnableDiscoveryReboot = true } - if ctx.IsSet(EnableCommitteeAwarePacking.Name) { - logEnabled(EnableCommitteeAwarePacking) - cfg.EnableCommitteeAwarePacking = true + if ctx.IsSet(enableExperimentalAttestationPool.Name) { + logEnabled(enableExperimentalAttestationPool) + cfg.EnableExperimentalAttestationPool = true } cfg.AggregateIntervals = [3]time.Duration{aggregateFirstInterval.Value, aggregateSecondInterval.Value, aggregateThirdInterval.Value} @@ -323,6 +337,22 @@ func complainOnDeprecatedFlags(ctx *cli.Context) { } } +var upcomingDeprecationExtra = map[string]string{ + enableHistoricalSpaceRepresentation.Name: "The node needs to be resynced after flag removal.", +} + +func warnDeprecationUpcoming(ctx *cli.Context) { + for _, f := range upcomingDeprecation { + if ctx.IsSet(f.Names()[0]) { + extra := "Please remove this flag from your configuration." + if special, ok := upcomingDeprecationExtra[f.Names()[0]]; ok { + extra += " " + special + } + log.Warnf("--%s is pending deprecation and will be removed in the next release. %s", f.Names()[0], extra) + } + } +} + func logEnabled(flag cli.DocGenerationFlag) { var name string if names := flag.Names(); len(names) > 0 { diff --git a/config/features/deprecated_flags.go b/config/features/deprecated_flags.go index ce04f877cff3..cecbadebef91 100644 --- a/config/features/deprecated_flags.go +++ b/config/features/deprecated_flags.go @@ -1,6 +1,8 @@ package features -import "github.com/urfave/cli/v2" +import ( + "github.com/urfave/cli/v2" +) // Deprecated flags list. const deprecatedUsage = "DEPRECATED. DO NOT USE." @@ -57,6 +59,45 @@ var ( Usage: deprecatedUsage, Hidden: true, } + + deprecatedBeaconRPCGatewayProviderFlag = &cli.StringFlag{ + Name: "beacon-rpc-gateway-provider", + Usage: deprecatedUsage, + Hidden: true, + } + + deprecatedDisableGRPCGateway = &cli.BoolFlag{ + Name: "disable-grpc-gateway", + Usage: deprecatedUsage, + Hidden: true, + } + + deprecatedEnableExperimentalState = &cli.BoolFlag{ + Name: "enable-experimental-state", + Usage: deprecatedUsage, + Hidden: true, + } + + deprecatedEnableCommitteeAwarePacking = &cli.BoolFlag{ + Name: "enable-committee-aware-packing", + Usage: deprecatedUsage, + Hidden: true, + } + deprecatedInteropGenesisTimeFlag = &cli.Uint64Flag{ + Name: "interop-genesis-time", + Usage: deprecatedUsage, + Hidden: true, + } + deprecatedInteropNumValidatorsFlag = &cli.Uint64Flag{ + Name: "interop-num-validators", + Usage: deprecatedUsage, + Hidden: true, + } + deprecatedEnableQuic = &cli.BoolFlag{ + Name: "enable-quic", + Usage: deprecatedUsage, + Hidden: true, + } ) // Deprecated flags for both the beacon node and validator client. @@ -71,8 +112,20 @@ var deprecatedFlags = []cli.Flag{ deprecatedDisableEIP4881, deprecatedVerboseSigVerification, deprecatedEnableDebugRPCEndpoints, + deprecatedBeaconRPCGatewayProviderFlag, + deprecatedDisableGRPCGateway, + deprecatedEnableExperimentalState, + deprecatedEnableCommitteeAwarePacking, + deprecatedInteropGenesisTimeFlag, + deprecatedEnableQuic, +} + +var upcomingDeprecation = []cli.Flag{ + enableHistoricalSpaceRepresentation, } // deprecatedBeaconFlags contains flags that are still used by other components // and therefore cannot be added to deprecatedFlags -var deprecatedBeaconFlags []cli.Flag +var deprecatedBeaconFlags = []cli.Flag{ + deprecatedInteropNumValidatorsFlag, +} diff --git a/config/features/flags.go b/config/features/flags.go index b53f08522923..d7a60a923f05 100644 --- a/config/features/flags.go +++ b/config/features/flags.go @@ -28,9 +28,9 @@ var ( Name: "dev", Usage: "Enables experimental features still in development. These features may not be stable.", } - enableExperimentalState = &cli.BoolFlag{ - Name: "enable-experimental-state", - Usage: "Turns on the latest and greatest (but potentially unstable) changes to the beacon state.", + disableExperimentalState = &cli.BoolFlag{ + Name: "disable-experimental-state", + Usage: "Turns off the latest and greatest changes to the beacon state. Disabling this is safe to do after the feature has been enabled.", } writeSSZStateTransitionsFlag = &cli.BoolFlag{ Name: "interop-write-ssz-state-transitions", @@ -144,7 +144,7 @@ var ( Usage: "Informs the engine to prepare all local payloads. Useful for relayers and builders.", } EnableLightClient = &cli.BoolFlag{ - Name: "enable-lightclient", + Name: "enable-light-client", Usage: "Enables the light client support in the beacon node", } disableResourceManager = &cli.BoolFlag{ @@ -161,22 +161,28 @@ var ( Name: "blob-save-fsync", Usage: "Forces new blob files to be fysnc'd before continuing, ensuring durable blob writes.", } - // EnableQUIC enables connection using the QUIC protocol for peers which support it. - EnableQUIC = &cli.BoolFlag{ - Name: "enable-quic", - Usage: "Enables connection using the QUIC protocol for peers which support it.", + // DisableQUIC disables connecting to peers using the QUIC protocol. + DisableQUIC = &cli.BoolFlag{ + Name: "disable-quic", + Usage: "Disables connecting using the QUIC protocol with peers.", } - EnableCommitteeAwarePacking = &cli.BoolFlag{ - Name: "enable-committee-aware-packing", - Usage: "Changes the attestation packing algorithm to one that is aware of attesting committees.", + DisableCommitteeAwarePacking = &cli.BoolFlag{ + Name: "disable-committee-aware-packing", + Usage: "Changes the attestation packing algorithm to one that is not aware of attesting committees.", + } + EnableDiscoveryReboot = &cli.BoolFlag{ + Name: "enable-discovery-reboot", + Usage: "Experimental: Enables the discovery listener to rebooted in the event of connectivity issues.", + } + enableExperimentalAttestationPool = &cli.BoolFlag{ + Name: "enable-experimental-attestation-pool", + Usage: "Enables an experimental attestation pool design.", } ) // devModeFlags holds list of flags that are set when development mode is on. var devModeFlags = []cli.Flag{ - enableExperimentalState, backfill.EnableExperimentalBackfill, - EnableQUIC, } // ValidatorFlags contains a list of all the feature flags that apply to the validator client. @@ -199,9 +205,9 @@ var E2EValidatorFlags = []string{ } // BeaconChainFlags contains a list of all the feature flags that apply to the beacon-chain client. -var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []cli.Flag{ +var BeaconChainFlags = combinedFlags([]cli.Flag{ devModeFlag, - enableExperimentalState, + disableExperimentalState, writeSSZStateTransitionsFlag, saveInvalidBlockTempFlag, saveInvalidBlobTempFlag, @@ -212,7 +218,6 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c disablePeerScorer, disableBroadcastSlashingFlag, enableSlasherFlag, - enableHistoricalSpaceRepresentation, disableStakinContractCheck, SaveFullExecutionPayloads, enableStartupOptimistic, @@ -226,9 +231,22 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c DisableRegistrationCache, EnableLightClient, BlobSaveFsync, - EnableQUIC, - EnableCommitteeAwarePacking, -}...)...) + DisableQUIC, + DisableCommitteeAwarePacking, + EnableDiscoveryReboot, + enableExperimentalAttestationPool, +}, deprecatedBeaconFlags, deprecatedFlags, upcomingDeprecation) + +func combinedFlags(flags ...[]cli.Flag) []cli.Flag { + if len(flags) == 0 { + return []cli.Flag{} + } + collected := flags[0] + for _, f := range flags[1:] { + collected = append(collected, f...) + } + return collected +} // E2EBeaconChainFlags contains a list of the beacon chain feature flags to be tested in E2E. var E2EBeaconChainFlags = []string{ diff --git a/config/fieldparams/mainnet.go b/config/fieldparams/mainnet.go index 6160fb2b1d51..5b04c4bac279 100644 --- a/config/fieldparams/mainnet.go +++ b/config/fieldparams/mainnet.go @@ -4,39 +4,53 @@ package field_params const ( Preset = "mainnet" - BlockRootsLength = 8192 // SLOTS_PER_HISTORICAL_ROOT - StateRootsLength = 8192 // SLOTS_PER_HISTORICAL_ROOT - RandaoMixesLength = 65536 // EPOCHS_PER_HISTORICAL_VECTOR - HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT - ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT - Eth1DataVotesLength = 2048 // SLOTS_PER_ETH1_VOTING_PERIOD - PreviousEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH - CurrentEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH - SlashingsLength = 8192 // EPOCHS_PER_SLASHINGS_VECTOR - SyncCommitteeLength = 512 // SYNC_COMMITTEE_SIZE - RootLength = 32 // RootLength defines the byte length of a Merkle root. - BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature. - BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature. - MaxTxsPerPayloadLength = 1048576 // MaxTxsPerPayloadLength defines the maximum number of transactions that can be included in a payload. - MaxBytesPerTxLength = 1073741824 // MaxBytesPerTxLength defines the maximum number of bytes that can be included in a transaction. - FeeRecipientLength = 20 // FeeRecipientLength defines the byte length of a fee recipient. - LogsBloomLength = 256 // LogsBloomLength defines the byte length of a logs bloom. - VersionLength = 4 // VersionLength defines the byte length of a fork version number. - SlotsPerEpoch = 32 // SlotsPerEpoch defines the number of slots per epoch. - SyncCommitteeAggregationBytesLength = 16 // SyncCommitteeAggregationBytesLength defines the length of sync committee aggregate bytes. - SyncAggregateSyncCommitteeBytesLength = 64 // SyncAggregateSyncCommitteeBytesLength defines the length of sync committee bytes in a sync aggregate. - MaxWithdrawalsPerPayload = 16 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload. - MaxBlobsPerBlock = 6 // MaxBlobsPerBlock defines the maximum number of blobs with respect to consensus rule can be included in a block. - MaxBlobCommitmentsPerBlock = 4096 // MaxBlobCommitmentsPerBlock defines the theoretical limit of blobs can be included in a block. - LogMaxBlobCommitments = 12 // Log_2 of MaxBlobCommitmentsPerBlock - BlobLength = 131072 // BlobLength defines the byte length of a blob. - BlobSize = 131072 // defined to match blob.size in bazel ssz codegen - KzgCommitmentInclusionProofDepth = 17 // Merkle proof depth for blob_kzg_commitments list item - NextSyncCommitteeBranchDepth = 5 // NextSyncCommitteeBranchDepth defines the depth of the next sync committee branch. - PendingBalanceDepositsLimit = 134217728 // Maximum number of pending balance deposits in the beacon state. - PendingPartialWithdrawalsLimit = 134217728 // Maximum number of pending partial withdrawals in the beacon state. - PendingConsolidationsLimit = 262144 // Maximum number of pending consolidations in the beacon state. - MaxDepositRequestsPerPayload = 8192 // Maximum number of deposit requests in an execution payload. - MaxWithdrawalRequestsPerPayload = 16 // Maximum number of execution layer withdrawal requests in an execution payload. - MaxConsolidationRequestsPerPayload = 1 // Maximum number of consolidation requests in an execution payload. + BlockRootsLength = 8192 // SLOTS_PER_HISTORICAL_ROOT + StateRootsLength = 8192 // SLOTS_PER_HISTORICAL_ROOT + RandaoMixesLength = 65536 // EPOCHS_PER_HISTORICAL_VECTOR + HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT + ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT + Eth1DataVotesLength = 2048 // SLOTS_PER_ETH1_VOTING_PERIOD + PreviousEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH + CurrentEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH + SlashingsLength = 8192 // EPOCHS_PER_SLASHINGS_VECTOR + SyncCommitteeLength = 512 // SYNC_COMMITTEE_SIZE + RootLength = 32 // RootLength defines the byte length of a Merkle root. + BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature. + BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature. + MaxTxsPerPayloadLength = 1048576 // MaxTxsPerPayloadLength defines the maximum number of transactions that can be included in a payload. + MaxBytesPerTxLength = 1073741824 // MaxBytesPerTxLength defines the maximum number of bytes that can be included in a transaction. + FeeRecipientLength = 20 // FeeRecipientLength defines the byte length of a fee recipient. + LogsBloomLength = 256 // LogsBloomLength defines the byte length of a logs bloom. + VersionLength = 4 // VersionLength defines the byte length of a fork version number. + SlotsPerEpoch = 32 // SlotsPerEpoch defines the number of slots per epoch. + SyncCommitteeAggregationBytesLength = 16 // SyncCommitteeAggregationBytesLength defines the length of sync committee aggregate bytes. + SyncAggregateSyncCommitteeBytesLength = 64 // SyncAggregateSyncCommitteeBytesLength defines the length of sync committee bytes in a sync aggregate. + MaxWithdrawalsPerPayload = 16 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload. + MaxBlobCommitmentsPerBlock = 4096 // MaxBlobCommitmentsPerBlock defines the theoretical limit of blobs can be included in a block. + LogMaxBlobCommitments = 12 // Log_2 of MaxBlobCommitmentsPerBlock + BlobLength = 131072 // BlobLength defines the byte length of a blob. + BlobSize = 131072 // defined to match blob.size in bazel ssz codegen + BlobSidecarSize = 131928 // defined to match blob sidecar size in bazel ssz codegen + KzgCommitmentInclusionProofDepth = 17 // Merkle proof depth for blob_kzg_commitments list item + ExecutionBranchDepth = 4 // ExecutionBranchDepth defines the number of leaves in a merkle proof of the execution payload header. + SyncCommitteeBranchDepth = 5 // SyncCommitteeBranchDepth defines the number of leaves in a merkle proof of a sync committee. + SyncCommitteeBranchDepthElectra = 6 // SyncCommitteeBranchDepthElectra defines the number of leaves in a merkle proof of a sync committee. + FinalityBranchDepth = 6 // FinalityBranchDepth defines the number of leaves in a merkle proof of the finalized checkpoint root. + FinalityBranchDepthElectra = 7 // FinalityBranchDepthElectra defines the number of leaves in a merkle proof of the finalized checkpoint root. + PendingDepositsLimit = 134217728 // Maximum number of pending balance deposits in the beacon state. + PendingPartialWithdrawalsLimit = 134217728 // Maximum number of pending partial withdrawals in the beacon state. + PendingConsolidationsLimit = 262144 // Maximum number of pending consolidations in the beacon state. + MaxDepositRequestsPerPayload = 8192 // Maximum number of deposit requests in an execution payload. + MaxWithdrawalRequestsPerPayload = 16 // Maximum number of execution layer withdrawal requests in an execution payload. + MaxConsolidationRequestsPerPayload = 1 // Maximum number of consolidation requests in an execution payload. + MaxProposerSlashings = 16 // Maximum number of proposer slashings in a block. + MaxAttesterSlashings = 2 // Maximum number of attester slashings in a block. + MaxAttesterSlashingsElectra = 1 // Maximum number of attester slashings in a block. + MaxAttestations = 128 // Maximum number of attestations in a block. + MaxAttestationsElectra = 8 // Maximum number of attestations in a block. + MaxDeposits = 16 // Maximum number of deposits in a block. + MaxVoluntaryExits = 16 // Maximum number of voluntary exits in a block. + MaxBlsToExecutionChanges = 16 // Maximum number of bls to execution changes in a block. + MaxRandomByte = uint64(1<<8 - 1) // MaxRandomByte defines max for a random byte using for proposer and sync committee sampling. + MaxRandomValueElectra = uint64(1<<16 - 1) // MaxRandomValueElectra defines max for a random value using for proposer and sync committee sampling. ) diff --git a/config/fieldparams/minimal.go b/config/fieldparams/minimal.go index d9bc80191532..c5e9eb4f0339 100644 --- a/config/fieldparams/minimal.go +++ b/config/fieldparams/minimal.go @@ -4,39 +4,53 @@ package field_params const ( Preset = "minimal" - BlockRootsLength = 64 // SLOTS_PER_HISTORICAL_ROOT - StateRootsLength = 64 // SLOTS_PER_HISTORICAL_ROOT - RandaoMixesLength = 64 // EPOCHS_PER_HISTORICAL_VECTOR - HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT - ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT - Eth1DataVotesLength = 32 // SLOTS_PER_ETH1_VOTING_PERIOD - PreviousEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH - CurrentEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH - SlashingsLength = 64 // EPOCHS_PER_SLASHINGS_VECTOR - SyncCommitteeLength = 32 // SYNC_COMMITTEE_SIZE - RootLength = 32 // RootLength defines the byte length of a Merkle root. - BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature. - BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature. - MaxTxsPerPayloadLength = 1048576 // MaxTxsPerPayloadLength defines the maximum number of transactions that can be included in a payload. - MaxBytesPerTxLength = 1073741824 // MaxBytesPerTxLength defines the maximum number of bytes that can be included in a transaction. - FeeRecipientLength = 20 // FeeRecipientLength defines the byte length of a fee recipient. - LogsBloomLength = 256 // LogsBloomLength defines the byte length of a logs bloom. - VersionLength = 4 // VersionLength defines the byte length of a fork version number. - SlotsPerEpoch = 8 // SlotsPerEpoch defines the number of slots per epoch. - SyncCommitteeAggregationBytesLength = 1 // SyncCommitteeAggregationBytesLength defines the sync committee aggregate bytes. - SyncAggregateSyncCommitteeBytesLength = 4 // SyncAggregateSyncCommitteeBytesLength defines the length of sync committee bytes in a sync aggregate. - MaxWithdrawalsPerPayload = 4 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload. - MaxBlobsPerBlock = 6 // MaxBlobsPerBlock defines the maximum number of blobs with respect to consensus rule can be included in a block. - MaxBlobCommitmentsPerBlock = 16 // MaxBlobCommitmentsPerBlock defines the theoretical limit of blobs can be included in a block. - LogMaxBlobCommitments = 4 // Log_2 of MaxBlobCommitmentsPerBlock - BlobLength = 131072 // BlobLength defines the byte length of a blob. - BlobSize = 131072 // defined to match blob.size in bazel ssz codegen - KzgCommitmentInclusionProofDepth = 17 // Merkle proof depth for blob_kzg_commitments list item - NextSyncCommitteeBranchDepth = 5 // NextSyncCommitteeBranchDepth defines the depth of the next sync committee branch. - PendingBalanceDepositsLimit = 134217728 // Maximum number of pending balance deposits in the beacon state. - PendingPartialWithdrawalsLimit = 64 // Maximum number of pending partial withdrawals in the beacon state. - PendingConsolidationsLimit = 64 // Maximum number of pending consolidations in the beacon state. - MaxDepositRequestsPerPayload = 4 // Maximum number of deposit requests in an execution payload. - MaxWithdrawalRequestsPerPayload = 2 // Maximum number of execution layer withdrawal requests in an execution payload. - MaxConsolidationRequestsPerPayload = 1 // Maximum number of consolidation requests in an execution payload. + BlockRootsLength = 64 // SLOTS_PER_HISTORICAL_ROOT + StateRootsLength = 64 // SLOTS_PER_HISTORICAL_ROOT + RandaoMixesLength = 64 // EPOCHS_PER_HISTORICAL_VECTOR + HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT + ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT + Eth1DataVotesLength = 32 // SLOTS_PER_ETH1_VOTING_PERIOD + PreviousEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH + CurrentEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH + SlashingsLength = 64 // EPOCHS_PER_SLASHINGS_VECTOR + SyncCommitteeLength = 32 // SYNC_COMMITTEE_SIZE + RootLength = 32 // RootLength defines the byte length of a Merkle root. + BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature. + BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature. + MaxTxsPerPayloadLength = 1048576 // MaxTxsPerPayloadLength defines the maximum number of transactions that can be included in a payload. + MaxBytesPerTxLength = 1073741824 // MaxBytesPerTxLength defines the maximum number of bytes that can be included in a transaction. + FeeRecipientLength = 20 // FeeRecipientLength defines the byte length of a fee recipient. + LogsBloomLength = 256 // LogsBloomLength defines the byte length of a logs bloom. + VersionLength = 4 // VersionLength defines the byte length of a fork version number. + SlotsPerEpoch = 8 // SlotsPerEpoch defines the number of slots per epoch. + SyncCommitteeAggregationBytesLength = 1 // SyncCommitteeAggregationBytesLength defines the sync committee aggregate bytes. + SyncAggregateSyncCommitteeBytesLength = 4 // SyncAggregateSyncCommitteeBytesLength defines the length of sync committee bytes in a sync aggregate. + MaxWithdrawalsPerPayload = 4 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload. + MaxBlobCommitmentsPerBlock = 32 // MaxBlobCommitmentsPerBlock defines the theoretical limit of blobs can be included in a block. + LogMaxBlobCommitments = 5 // Log_2 of MaxBlobCommitmentsPerBlock + BlobLength = 131072 // BlobLength defines the byte length of a blob. + BlobSize = 131072 // defined to match blob.size in bazel ssz codegen + BlobSidecarSize = 131928 // defined to match blob sidecar size in bazel ssz codegen + KzgCommitmentInclusionProofDepth = 10 // Merkle proof depth for blob_kzg_commitments list item + ExecutionBranchDepth = 4 // ExecutionBranchDepth defines the number of leaves in a merkle proof of the execution payload header. + SyncCommitteeBranchDepth = 5 // SyncCommitteeBranchDepth defines the number of leaves in a merkle proof of a sync committee. + SyncCommitteeBranchDepthElectra = 6 // SyncCommitteeBranchDepthElectra defines the number of leaves in a merkle proof of a sync committee. + FinalityBranchDepth = 6 // FinalityBranchDepth defines the number of leaves in a merkle proof of the finalized checkpoint root. + FinalityBranchDepthElectra = 7 // FinalityBranchDepthElectra defines the number of leaves in a merkle proof of the finalized checkpoint root. + PendingDepositsLimit = 134217728 // Maximum number of pending balance deposits in the beacon state. + PendingPartialWithdrawalsLimit = 64 // Maximum number of pending partial withdrawals in the beacon state. + PendingConsolidationsLimit = 64 // Maximum number of pending consolidations in the beacon state. + MaxDepositRequestsPerPayload = 4 // Maximum number of deposit requests in an execution payload. + MaxWithdrawalRequestsPerPayload = 2 // Maximum number of execution layer withdrawal requests in an execution payload. + MaxConsolidationRequestsPerPayload = 1 // Maximum number of consolidation requests in an execution payload. + MaxProposerSlashings = 16 // Maximum number of proposer slashings in a block. + MaxAttesterSlashings = 2 // Maximum number of attester slashings in a block. + MaxAttesterSlashingsElectra = 1 // Maximum number of attester slashings in a block. + MaxAttestations = 128 // Maximum number of attestations in a block. + MaxAttestationsElectra = 8 // Maximum number of attestations in a block. + MaxDeposits = 16 // Maximum number of deposits in a block. + MaxVoluntaryExits = 16 // Maximum number of voluntary exits in a block. + MaxBlsToExecutionChanges = 16 // Maximum number of bls to execution changes in a block. + MaxRandomByte = uint64(1<<8 - 1) // Maximum value for a random value using for proposer and sync committee sampling. + MaxRandomValueElectra = uint64(1<<16 - 1) // Maximum value for a random value using for proposer and sync committee sampling. ) diff --git a/config/params/BUILD.bazel b/config/params/BUILD.bazel index e97f4d1f9f18..b6cf387580da 100644 --- a/config/params/BUILD.bazel +++ b/config/params/BUILD.bazel @@ -49,6 +49,7 @@ go_test( "mainnet_config_test.go", "testnet_config_test.go", "testnet_holesky_config_test.go", + "testnet_sepolia_config_test.go", ], data = glob(["*.yaml"]) + [ "testdata/e2e_config.yaml", @@ -57,14 +58,17 @@ go_test( "@consensus_spec_tests_minimal//:test_data", "@eth2_networks//:configs", "@holesky_testnet//:configs", + "@sepolia_testnet//:configs", ], embed = [":go_default_library"], gotags = ["develop"], tags = ["CI_race_detection"], deps = [ + "//beacon-chain/state/genesis:go_default_library", "//consensus-types/primitives:go_default_library", "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", diff --git a/config/params/config.go b/config/params/config.go index 69f7193df13a..3681a3204cb1 100644 --- a/config/params/config.go +++ b/config/params/config.go @@ -70,7 +70,7 @@ type BeaconChainConfig struct { // Fork choice algorithm constants. ProposerScoreBoost uint64 `yaml:"PROPOSER_SCORE_BOOST" spec:"true"` // ProposerScoreBoost defines a value that is a % of the committee weight for fork-choice boosting. - ReorgWeightThreshold uint64 `yaml:"REORG_WEIGHT_THRESHOLD" spec:"true"` // ReorgWeightThreshold defines a value that is a % of the committee weight to consider a block weak and subject to being orphaned. + ReorgHeadWeightThreshold uint64 `yaml:"REORG_HEAD_WEIGHT_THRESHOLD" spec:"true"` // ReorgHeadWeightThreshold defines a value that is a % of the committee weight to consider a block weak and subject to being orphaned. ReorgParentWeightThreshold uint64 `yaml:"REORG_PARENT_WEIGHT_THRESHOLD" spec:"true"` // ReorgParentWeightThreshold defines a value that is a % of the committee weight to consider a parent block strong and subject its child to being orphaned. ReorgMaxEpochsSinceFinalization primitives.Epoch `yaml:"REORG_MAX_EPOCHS_SINCE_FINALIZATION" spec:"true"` // This defines a limit to consider safe to orphan a block if the network is finalizing IntervalsPerSlot uint64 `yaml:"INTERVALS_PER_SLOT" spec:"true"` // IntervalsPerSlot defines the number of fork choice intervals in a slot defined in the fork choice spec. @@ -125,9 +125,9 @@ type BeaconChainConfig struct { DomainApplicationMask [4]byte `yaml:"DOMAIN_APPLICATION_MASK" spec:"true"` // DomainApplicationMask defines the BLS signature domain for application mask. DomainApplicationBuilder [4]byte `yaml:"DOMAIN_APPLICATION_BUILDER" spec:"true"` // DomainApplicationBuilder defines the BLS signature domain for application builder. DomainBLSToExecutionChange [4]byte `yaml:"DOMAIN_BLS_TO_EXECUTION_CHANGE" spec:"true"` // DomainBLSToExecutionChange defines the BLS signature domain to change withdrawal addresses to ETH1 prefix - DomainConsolidation [4]byte `yaml:"DOMAIN_CONSOLIDATION" spec:"true"` // Prysm constants. + GenesisValidatorsRoot [32]byte // GenesisValidatorsRoot is the root hash of the genesis validators. GweiPerEth uint64 // GweiPerEth is the amount of gwei corresponding to 1 eth. BLSSecretKeyLength int // BLSSecretKeyLength defines the expected length of BLS secret keys in bytes. BLSPubkeyLength int // BLSPubkeyLength defines the expected length of BLS public keys in bytes. @@ -146,6 +146,7 @@ type BeaconChainConfig struct { BeaconStateCapellaFieldCount int // BeaconStateCapellaFieldCount defines how many fields are in beacon state post upgrade to Capella. BeaconStateDenebFieldCount int // BeaconStateDenebFieldCount defines how many fields are in beacon state post upgrade to Deneb. BeaconStateElectraFieldCount int // BeaconStateElectraFieldCount defines how many fields are in beacon state post upgrade to Electra. + BeaconStateFuluFieldCount int // BeaconStateFuluFieldCount defines how many fields are in beacon state post upgrade to Fulu. // Slasher constants. WeakSubjectivityPeriod primitives.Epoch // WeakSubjectivityPeriod defines the time period expressed in number of epochs were proof of stake network should validate block headers and attestations for slashable events. @@ -164,8 +165,10 @@ type BeaconChainConfig struct { CapellaForkEpoch primitives.Epoch `yaml:"CAPELLA_FORK_EPOCH" spec:"true"` // CapellaForkEpoch is used to represent the assigned fork epoch for capella. DenebForkVersion []byte `yaml:"DENEB_FORK_VERSION" spec:"true"` // DenebForkVersion is used to represent the fork version for deneb. DenebForkEpoch primitives.Epoch `yaml:"DENEB_FORK_EPOCH" spec:"true"` // DenebForkEpoch is used to represent the assigned fork epoch for deneb. - ElectraForkVersion []byte `yaml:"ELECTRA_FORK_VERSION" spec:"true"` // ElectraForkVersion is used to represent the fork version for deneb. - ElectraForkEpoch primitives.Epoch `yaml:"ELECTRA_FORK_EPOCH" spec:"true"` // ElectraForkEpoch is used to represent the assigned fork epoch for deneb. + ElectraForkVersion []byte `yaml:"ELECTRA_FORK_VERSION" spec:"true"` // ElectraForkVersion is used to represent the fork version for electra. + ElectraForkEpoch primitives.Epoch `yaml:"ELECTRA_FORK_EPOCH" spec:"true"` // ElectraForkEpoch is used to represent the assigned fork epoch for electra. + FuluForkVersion []byte `yaml:"FULU_FORK_VERSION" spec:"true"` // FuluForkVersion is used to represent the fork version for fulu. + FuluForkEpoch primitives.Epoch `yaml:"FULU_FORK_EPOCH" spec:"true"` // FuluForkEpoch is used to represent the assigned fork epoch for fulu. ForkVersionSchedule map[[fieldparams.VersionLength]byte]primitives.Epoch // Schedule of fork epochs by version. ForkVersionNames map[[fieldparams.VersionLength]byte]string // Human-readable names of fork versions. @@ -214,6 +217,10 @@ type BeaconChainConfig struct { TerminalBlockHash common.Hash `yaml:"TERMINAL_BLOCK_HASH" spec:"true"` // TerminalBlockHash of beacon chain. TerminalBlockHashActivationEpoch primitives.Epoch `yaml:"TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH" spec:"true"` // TerminalBlockHashActivationEpoch of beacon chain. TerminalTotalDifficulty string `yaml:"TERMINAL_TOTAL_DIFFICULTY" spec:"true"` // TerminalTotalDifficulty is part of the experimental Bellatrix spec. This value is type is currently TBD. + MaxBytesPerTransaction uint64 `yaml:"MAX_BYTES_PER_TRANSACTION" spec:"true"` // MaxBytesPerTransaction is the maximum number of bytes a single transaction can have. + MaxTransactionsPerPayload uint64 `yaml:"MAX_TRANSACTIONS_PER_PAYLOAD" spec:"true"` // MaxTransactionsPerPayload is the maximum number of transactions a single execution payload can include. + BytesPerLogsBloom uint64 `yaml:"BYTES_PER_LOGS_BLOOM" spec:"true"` // BytesPerLogsBloom is the number of bytes that constitute a log bloom filter. + MaxExtraDataBytes uint64 `yaml:"MAX_EXTRA_DATA_BYTES" spec:"true"` // MaxExtraDataBytes is the maximum number of bytes for the execution payload's extra data field. DefaultFeeRecipient common.Address // DefaultFeeRecipient where the transaction fee goes to. EthBurnAddressHex string // EthBurnAddressHex is the constant eth address written in hex format to burn fees in that network. the default is 0x0 DefaultBuilderGasLimit uint64 // DefaultBuilderGasLimit is the default used to set the gaslimit for the Builder APIs, typically at around 30M wei. @@ -228,32 +235,45 @@ type BeaconChainConfig struct { ExecutionEngineTimeoutValue uint64 // ExecutionEngineTimeoutValue defines the seconds to wait before timing out engine endpoints with execution payload execution semantics (newPayload, forkchoiceUpdated). // Subnet value - BlobsidecarSubnetCount uint64 `yaml:"BLOB_SIDECAR_SUBNET_COUNT"` // BlobsidecarSubnetCount is the number of blobsidecar subnets used in the gossipsub protocol. + BlobsidecarSubnetCount uint64 `yaml:"BLOB_SIDECAR_SUBNET_COUNT"` // BlobsidecarSubnetCount is the number of blobsidecar subnets used in the gossipsub protocol. + BlobsidecarSubnetCountElectra uint64 `yaml:"BLOB_SIDECAR_SUBNET_COUNT_ELECTRA"` // BlobsidecarSubnetCountElectra is the number of blobsidecar subnets used in the gossipsub protocol post Electra hard fork. // Values introduced in Deneb hard fork MaxPerEpochActivationChurnLimit uint64 `yaml:"MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT" spec:"true"` // MaxPerEpochActivationChurnLimit is the maximum amount of churn allotted for validator activation. MinEpochsForBlobsSidecarsRequest primitives.Epoch `yaml:"MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS" spec:"true"` // MinEpochsForBlobsSidecarsRequest is the minimum number of epochs the node will keep the blobs for. MaxRequestBlobSidecars uint64 `yaml:"MAX_REQUEST_BLOB_SIDECARS" spec:"true"` // MaxRequestBlobSidecars is the maximum number of blobs to request in a single request. + MaxRequestBlobSidecarsElectra uint64 `yaml:"MAX_REQUEST_BLOB_SIDECARS_ELECTRA" spec:"true"` // MaxRequestBlobSidecarsElectra is the maximum number of blobs to request in a single request. MaxRequestBlocksDeneb uint64 `yaml:"MAX_REQUEST_BLOCKS_DENEB" spec:"true"` // MaxRequestBlocksDeneb is the maximum number of blocks in a single request after the deneb epoch. + FieldElementsPerBlob uint64 `yaml:"FIELD_ELEMENTS_PER_BLOB" spec:"true"` // FieldElementsPerBlob is the number of field elements that constitute a single blob. + MaxBlobCommitmentsPerBlock uint64 `yaml:"MAX_BLOB_COMMITMENTS_PER_BLOCK" spec:"true"` // MaxBlobCommitmentsPerBlock is the maximum number of KZG commitments that a block can have. + KzgCommitmentInclusionProofDepth uint64 `yaml:"KZG_COMMITMENT_INCLUSION_PROOF_DEPTH" spec:"true"` // KzgCommitmentInclusionProofDepth is the depth of the merkle proof of a KZG commitment. - // Values introduce in Electra upgrade - DataColumnSidecarSubnetCount uint64 `yaml:"DATA_COLUMN_SIDECAR_SUBNET_COUNT" spec:"true"` // DataColumnSidecarSubnetCount is the number of data column sidecar subnets used in the gossipsub protocol + // Values introduced in Electra upgrade MaxPerEpochActivationExitChurnLimit uint64 `yaml:"MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT" spec:"true"` // MaxPerEpochActivationExitChurnLimit represents the maximum combined activation and exit churn. MinPerEpochChurnLimitElectra uint64 `yaml:"MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA" spec:"true"` // MinPerEpochChurnLimitElectra is the minimum amount of churn allotted for validator rotations for electra. - MaxRequestDataColumnSidecars uint64 `yaml:"MAX_REQUEST_DATA_COLUMN_SIDECARS" spec:"true"` // MaxRequestDataColumnSidecars is the maximum number of data column sidecars in a single request MaxEffectiveBalanceElectra uint64 `yaml:"MAX_EFFECTIVE_BALANCE_ELECTRA" spec:"true"` // MaxEffectiveBalanceElectra is the maximal amount of Gwei that is effective for staking, increased in electra. MinSlashingPenaltyQuotientElectra uint64 `yaml:"MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA" spec:"true"` // MinSlashingPenaltyQuotientElectra is used to calculate the minimum penalty to prevent DoS attacks, modified for electra. WhistleBlowerRewardQuotientElectra uint64 `yaml:"WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA" spec:"true"` // WhistleBlowerRewardQuotientElectra is used to calculate whistle blower reward, modified in electra. - PendingBalanceDepositLimit uint64 `yaml:"PENDING_BALANCE_DEPOSITS_LIMIT" spec:"true"` // PendingBalanceDepositLimit is the maximum number of pending balance deposits allowed in the beacon state. + PendingDepositsLimit uint64 `yaml:"PENDING_DEPOSITS_LIMIT" spec:"true"` // PendingDepositsLimit is the maximum number of pending balance deposits allowed in the beacon state. PendingPartialWithdrawalsLimit uint64 `yaml:"PENDING_PARTIAL_WITHDRAWALS_LIMIT" spec:"true"` // PendingPartialWithdrawalsLimit is the maximum number of pending partial withdrawals allowed in the beacon state. PendingConsolidationsLimit uint64 `yaml:"PENDING_CONSOLIDATIONS_LIMIT" spec:"true"` // PendingConsolidationsLimit is the maximum number of pending validator consolidations allowed in the beacon state. MaxConsolidationsRequestsPerPayload uint64 `yaml:"MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD" spec:"true"` // MaxConsolidationsRequestsPerPayload is the maximum number of consolidations in a block. MaxPendingPartialsPerWithdrawalsSweep uint64 `yaml:"MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP" spec:"true"` // MaxPendingPartialsPerWithdrawalsSweep is the maximum number of pending partial withdrawals to process per payload. + MaxPendingDepositsPerEpoch uint64 `yaml:"MAX_PENDING_DEPOSITS_PER_EPOCH" spec:"true"` // MaxPendingDepositsPerEpoch is the maximum number of pending deposits per epoch processing. FullExitRequestAmount uint64 `yaml:"FULL_EXIT_REQUEST_AMOUNT" spec:"true"` // FullExitRequestAmount is the amount of Gwei required to request a full exit. MaxWithdrawalRequestsPerPayload uint64 `yaml:"MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD" spec:"true"` // MaxWithdrawalRequestsPerPayload is the maximum number of execution layer withdrawal requests in each payload. MaxDepositRequestsPerPayload uint64 `yaml:"MAX_DEPOSIT_REQUESTS_PER_PAYLOAD" spec:"true"` // MaxDepositRequestsPerPayload is the maximum number of execution layer deposits in each payload UnsetDepositRequestsStartIndex uint64 `yaml:"UNSET_DEPOSIT_REQUESTS_START_INDEX" spec:"true"` // UnsetDepositRequestsStartIndex is used to check the start index for eip6110 + // PeerDAS Values + SamplesPerSlot uint64 `yaml:"SAMPLES_PER_SLOT"` // SamplesPerSlot refers to the number of random samples a node queries per slot. + CustodyRequirement uint64 `yaml:"CUSTODY_REQUIREMENT"` // CustodyRequirement refers to the minimum amount of subnets a peer must custody and serve samples from. + MinEpochsForDataColumnSidecarsRequest primitives.Epoch `yaml:"MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS"` // MinEpochsForDataColumnSidecarsRequest is the minimum number of epochs the node will keep the data columns for. + MaxRequestDataColumnSidecars uint64 `yaml:"MAX_REQUEST_DATA_COLUMN_SIDECARS" spec:"true"` // MaxRequestDataColumnSidecars is the maximum number of data column sidecars in a single request + MaxCellsInExtendedMatrix uint64 `yaml:"MAX_CELLS_IN_EXTENDED_MATRIX" spec:"true"` // MaxCellsInExtendedMatrix is the full data of one-dimensional erasure coding extended blobs (in row major format). + NumberOfColumns uint64 `yaml:"NUMBER_OF_COLUMNS" spec:"true"` // NumberOfColumns in the extended data matrix. + DataColumnSidecarSubnetCount uint64 `yaml:"DATA_COLUMN_SIDECAR_SUBNET_COUNT" spec:"true"` // DataColumnSidecarSubnetCount is the number of data column sidecar subnets used in the gossipsub protocol + // Networking Specific Parameters GossipMaxSize uint64 `yaml:"GOSSIP_MAX_SIZE" spec:"true"` // GossipMaxSize is the maximum allowed size of uncompressed gossip messages. MaxChunkSize uint64 `yaml:"MAX_CHUNK_SIZE" spec:"true"` // MaxChunkSize is the maximum allowed size of uncompressed req/resp chunked responses. @@ -272,9 +292,19 @@ type BeaconChainConfig struct { SubnetsPerNode uint64 `yaml:"SUBNETS_PER_NODE" spec:"true"` // SubnetsPerNode is the number of long-lived subnets a beacon node should be subscribed to. NodeIdBits uint64 `yaml:"NODE_ID_BITS" spec:"true"` // NodeIdBits defines the bit length of a node id. - // PeerDAS - NumberOfColumns uint64 `yaml:"NUMBER_OF_COLUMNS" spec:"true"` // NumberOfColumns in the extended data matrix. - MaxCellsInExtendedMatrix uint64 `yaml:"MAX_CELLS_IN_EXTENDED_MATRIX" spec:"true"` // MaxCellsInExtendedMatrix is the full data of one-dimensional erasure coding extended blobs (in row major format). + // Blobs Values + + // Deprecated_MaxBlobsPerBlock defines the max blobs that could exist in a block. + // Deprecated: This field is no longer supported. Avoid using it. + DeprecatedMaxBlobsPerBlock int `yaml:"MAX_BLOBS_PER_BLOCK" spec:"true"` + + // DeprecatedMaxBlobsPerBlockElectra defines the max blobs that could exist in a block post Electra hard fork. + // Deprecated: This field is no longer supported. Avoid using it. + DeprecatedMaxBlobsPerBlockElectra int `yaml:"MAX_BLOBS_PER_BLOCK_ELECTRA" spec:"true"` + + // DeprecatedTargetBlobsPerBlockElectra defines the target number of blobs per block post Electra hard fork. + // Deprecated: This field is no longer supported. Avoid using it. + DeprecatedTargetBlobsPerBlockElectra int `yaml:"TARGET_BLOBS_PER_BLOCK_ELECTRA" spec:"true"` } // InitializeForkSchedule initializes the schedules forks baked into the config. @@ -292,6 +322,7 @@ func configForkSchedule(b *BeaconChainConfig) map[[fieldparams.VersionLength]byt fvs[bytesutil.ToBytes4(b.CapellaForkVersion)] = b.CapellaForkEpoch fvs[bytesutil.ToBytes4(b.DenebForkVersion)] = b.DenebForkEpoch fvs[bytesutil.ToBytes4(b.ElectraForkVersion)] = b.ElectraForkEpoch + fvs[bytesutil.ToBytes4(b.FuluForkVersion)] = b.FuluForkEpoch return fvs } @@ -314,6 +345,7 @@ func ConfigForkVersions(b *BeaconChainConfig) map[[fieldparams.VersionLength]byt bytesutil.ToBytes4(b.CapellaForkVersion): version.Capella, bytesutil.ToBytes4(b.DenebForkVersion): version.Deneb, bytesutil.ToBytes4(b.ElectraForkVersion): version.Electra, + bytesutil.ToBytes4(b.FuluForkVersion): version.Fulu, } } @@ -352,6 +384,41 @@ func (b *BeaconChainConfig) MaximumGossipClockDisparityDuration() time.Duration return time.Duration(b.MaximumGossipClockDisparity) * time.Millisecond } +// TargetBlobsPerBlock returns the target number of blobs per block for the given slot, +// accounting for changes introduced by the Electra fork. +func (b *BeaconChainConfig) TargetBlobsPerBlock(slot primitives.Slot) int { + if primitives.Epoch(slot.DivSlot(b.SlotsPerEpoch)) >= b.ElectraForkEpoch { + return b.DeprecatedTargetBlobsPerBlockElectra + } + return b.DeprecatedMaxBlobsPerBlock / 2 +} + +// MaxBlobsPerBlock returns the maximum number of blobs per block for the given slot, +// adjusting for the Electra fork. +func (b *BeaconChainConfig) MaxBlobsPerBlock(slot primitives.Slot) int { + if primitives.Epoch(slot.DivSlot(b.SlotsPerEpoch)) >= b.ElectraForkEpoch { + return b.DeprecatedMaxBlobsPerBlockElectra + } + return b.DeprecatedMaxBlobsPerBlock +} + +// MaxBlobsPerBlockByVersion returns the maximum number of blobs per block for the given fork version +func (b *BeaconChainConfig) MaxBlobsPerBlockByVersion(v int) int { + if v >= version.Electra { + return b.DeprecatedMaxBlobsPerBlockElectra + } + return b.DeprecatedMaxBlobsPerBlock +} + +// MaxBlobsPerBlockByEpoch returns the maximum number of blobs per block for the given epoch, +// adjusting for the Electra fork. +func (b *BeaconChainConfig) MaxBlobsPerBlockAtEpoch(epoch primitives.Epoch) int { + if epoch >= b.ElectraForkEpoch { + return b.DeprecatedMaxBlobsPerBlockElectra + } + return b.DeprecatedMaxBlobsPerBlock +} + // DenebEnabled centralizes the check to determine if code paths // that are specific to deneb should be allowed to execute. This will make it easier to find call sites that do this // kind of check and remove them post-deneb. @@ -359,6 +426,19 @@ func DenebEnabled() bool { return BeaconConfig().DenebForkEpoch < math.MaxUint64 } +// ElectraEnabled centralizes the check to determine if code paths +// that are specific to electra should be allowed to execute. This will make it easier to find call sites that do this +// kind of check and remove them post-electra. +func ElectraEnabled() bool { + return BeaconConfig().ElectraForkEpoch < math.MaxUint64 +} + +// PeerDASEnabled centralizes the check to determine if code paths +// that are specific to peerdas should be allowed to execute. +func PeerDASEnabled() bool { + return BeaconConfig().FuluForkEpoch < math.MaxUint64 +} + // WithinDAPeriod checks if the block epoch is within MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS of the given current epoch. func WithinDAPeriod(block, current primitives.Epoch) bool { return block+BeaconConfig().MinEpochsForBlobsSidecarsRequest >= current diff --git a/config/params/config_test.go b/config/params/config_test.go index 52cb4b23e549..43c8b1c95d20 100644 --- a/config/params/config_test.go +++ b/config/params/config_test.go @@ -1,11 +1,15 @@ package params_test import ( + "bytes" + "math" "sync" "testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/genesis" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -92,3 +96,63 @@ func TestConfig_WithinDAPeriod(t *testing.T) { }) } } + +func TestConfigGenesisValidatorRoot(t *testing.T) { + g, err := genesis.State(params.MainnetName) + require.NoError(t, err) + + gvr := g.GenesisValidatorsRoot() + + if !bytes.Equal(gvr, params.BeaconConfig().GenesisValidatorsRoot[:]) { + t.Fatal("mainnet params genesis validator root does not match the mainnet genesis state value") + } +} + +func Test_MaxBlobCount(t *testing.T) { + cfg := params.MainnetConfig() + cfg.ElectraForkEpoch = 10 + require.Equal(t, cfg.MaxBlobsPerBlock(primitives.Slot(cfg.ElectraForkEpoch)*cfg.SlotsPerEpoch-1), 6) + require.Equal(t, cfg.MaxBlobsPerBlock(primitives.Slot(cfg.ElectraForkEpoch)*cfg.SlotsPerEpoch), 9) + cfg.ElectraForkEpoch = math.MaxUint64 +} + +func Test_TargetBlobCount(t *testing.T) { + cfg := params.MainnetConfig() + cfg.ElectraForkEpoch = 10 + require.Equal(t, cfg.TargetBlobsPerBlock(primitives.Slot(cfg.ElectraForkEpoch)*cfg.SlotsPerEpoch-1), 3) + require.Equal(t, cfg.TargetBlobsPerBlock(primitives.Slot(cfg.ElectraForkEpoch)*cfg.SlotsPerEpoch), 6) + cfg.ElectraForkEpoch = math.MaxUint64 +} + +func TestMaxBlobsPerBlockByVersion(t *testing.T) { + tests := []struct { + name string + v int + want int + }{ + { + name: "Version below Electra", + v: version.Electra - 1, + want: params.BeaconConfig().DeprecatedMaxBlobsPerBlock, + }, + { + name: "Version equal to Electra", + v: version.Electra, + want: params.BeaconConfig().DeprecatedMaxBlobsPerBlockElectra, + }, + { + name: "Version above Electra", + v: version.Electra + 1, + want: params.BeaconConfig().DeprecatedMaxBlobsPerBlockElectra, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := params.BeaconConfig().MaxBlobsPerBlockByVersion(tt.v) + if got != tt.want { + t.Errorf("MaxBlobsPerBlockByVersion(%d) = %d, want %d", tt.v, got, tt.want) + } + }) + } +} diff --git a/config/params/configset_test.go b/config/params/configset_test.go index ea15a994db2f..bfe4f72c0eb6 100644 --- a/config/params/configset_test.go +++ b/config/params/configset_test.go @@ -132,6 +132,7 @@ func compareConfigs(t *testing.T, expected, actual *BeaconChainConfig) { require.DeepEqual(t, expected.ProportionalSlashingMultiplier, actual.ProportionalSlashingMultiplier) require.DeepEqual(t, expected.MaxProposerSlashings, actual.MaxProposerSlashings) require.DeepEqual(t, expected.MaxAttesterSlashings, actual.MaxAttesterSlashings) + require.DeepEqual(t, expected.MaxAttesterSlashingsElectra, actual.MaxAttesterSlashingsElectra) require.DeepEqual(t, expected.MaxAttestations, actual.MaxAttestations) require.DeepEqual(t, expected.MaxDeposits, actual.MaxDeposits) require.DeepEqual(t, expected.MaxVoluntaryExits, actual.MaxVoluntaryExits) diff --git a/config/params/interop.go b/config/params/interop.go index 44c2c048aa50..c997646ae98f 100644 --- a/config/params/interop.go +++ b/config/params/interop.go @@ -12,6 +12,7 @@ func InteropConfig() *BeaconChainConfig { c.CapellaForkVersion = []byte{3, 0, 0, 235} c.DenebForkVersion = []byte{4, 0, 0, 235} c.ElectraForkVersion = []byte{5, 0, 0, 235} + c.FuluForkVersion = []byte{6, 0, 0, 235} c.InitializeForkSchedule() return c diff --git a/config/params/loader.go b/config/params/loader.go index e8e2aba491ab..658d1206c687 100644 --- a/config/params/loader.go +++ b/config/params/loader.go @@ -65,6 +65,8 @@ func UnmarshalConfig(yamlFile []byte, conf *BeaconChainConfig) (*BeaconChainConf } // recompute SqrRootSlotsPerEpoch constant to handle non-standard values of SlotsPerEpoch conf.SqrRootSlotsPerEpoch = primitives.Slot(math.IntegerSquareRoot(uint64(conf.SlotsPerEpoch))) + // Recompute the fork schedule + conf.InitializeForkSchedule() log.Debugf("Config file values: %+v", conf) return conf, nil } @@ -212,11 +214,15 @@ func ConfigToYaml(cfg *BeaconChainConfig) []byte { fmt.Sprintf("MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: %d", cfg.MinEpochsForBlobsSidecarsRequest), fmt.Sprintf("MAX_REQUEST_BLOCKS_DENEB: %d", cfg.MaxRequestBlocksDeneb), fmt.Sprintf("MAX_REQUEST_BLOB_SIDECARS: %d", cfg.MaxRequestBlobSidecars), + fmt.Sprintf("MAX_REQUEST_BLOB_SIDECARS_ELECTRA: %d", cfg.MaxRequestBlobSidecarsElectra), fmt.Sprintf("BLOB_SIDECAR_SUBNET_COUNT: %d", cfg.BlobsidecarSubnetCount), + fmt.Sprintf("BLOB_SIDECAR_SUBNET_COUNT_ELECTRA: %d", cfg.BlobsidecarSubnetCountElectra), fmt.Sprintf("DENEB_FORK_EPOCH: %d", cfg.DenebForkEpoch), fmt.Sprintf("DENEB_FORK_VERSION: %#x", cfg.DenebForkVersion), fmt.Sprintf("ELECTRA_FORK_EPOCH: %d", cfg.ElectraForkEpoch), fmt.Sprintf("ELECTRA_FORK_VERSION: %#x", cfg.ElectraForkVersion), + fmt.Sprintf("FULU_FORK_EPOCH: %d", cfg.FuluForkEpoch), + fmt.Sprintf("FULU_FORK_VERSION: %#x", cfg.FuluForkVersion), fmt.Sprintf("EPOCHS_PER_SUBNET_SUBSCRIPTION: %d", cfg.EpochsPerSubnetSubscription), fmt.Sprintf("ATTESTATION_SUBNET_EXTRA_BITS: %d", cfg.AttestationSubnetExtraBits), fmt.Sprintf("ATTESTATION_SUBNET_PREFIX_BITS: %d", cfg.AttestationSubnetPrefixBits), @@ -233,8 +239,9 @@ func ConfigToYaml(cfg *BeaconChainConfig) []byte { fmt.Sprintf("MESSAGE_DOMAIN_INVALID_SNAPPY: %#x", cfg.MessageDomainInvalidSnappy), fmt.Sprintf("MESSAGE_DOMAIN_VALID_SNAPPY: %#x", cfg.MessageDomainValidSnappy), fmt.Sprintf("MIN_EPOCHS_FOR_BLOCK_REQUESTS: %d", int(cfg.MinEpochsForBlockRequests)), - fmt.Sprintf("ELECTRA_FORK_EPOCH: %d", cfg.ElectraForkEpoch), - fmt.Sprintf("ELECTRA_FORK_VERSION: %#x", cfg.ElectraForkVersion), + fmt.Sprintf("MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: %d", cfg.MinPerEpochChurnLimitElectra), + fmt.Sprintf("MAX_BLOBS_PER_BLOCK: %d", cfg.DeprecatedMaxBlobsPerBlock), + fmt.Sprintf("MAX_BLOBS_PER_BLOCK_ELECTRA: %d", cfg.DeprecatedMaxBlobsPerBlockElectra), } yamlFile := []byte(strings.Join(lines, "\n")) diff --git a/config/params/loader_test.go b/config/params/loader_test.go index 4f8872b29235..c23900be42d2 100644 --- a/config/params/loader_test.go +++ b/config/params/loader_test.go @@ -24,25 +24,22 @@ import ( // These are variables that we don't use in Prysm. (i.e. future hardfork, light client... etc) // IMPORTANT: Use one field per line and sort these alphabetically to reduce conflicts. var placeholderFields = []string{ - "BYTES_PER_LOGS_BLOOM", // Compile time constant on ExecutionPayload.logs_bloom. - "CUSTODY_REQUIREMENT", + "BALANCE_PER_ADDITIONAL_CUSTODY_GROUP", + "BLOB_SIDECAR_SUBNET_COUNT_FULU", "EIP6110_FORK_EPOCH", "EIP6110_FORK_VERSION", "EIP7002_FORK_EPOCH", "EIP7002_FORK_VERSION", - "EIP7594_FORK_EPOCH", - "EIP7594_FORK_VERSION", - "FIELD_ELEMENTS_PER_BLOB", // Compile time constant. - "KZG_COMMITMENT_INCLUSION_PROOF_DEPTH", // Compile time constant on BlobSidecar.commitment_inclusion_proof. - "MAX_BLOBS_PER_BLOCK", - "MAX_BLOB_COMMITMENTS_PER_BLOCK", // Compile time constant on BeaconBlockBodyDeneb.blob_kzg_commitments. - "MAX_BYTES_PER_TRANSACTION", // Used for ssz of EL transactions. Unused in Prysm. - "MAX_EXTRA_DATA_BYTES", // Compile time constant on ExecutionPayload.extra_data. - "MAX_TRANSACTIONS_PER_PAYLOAD", // Compile time constant on ExecutionPayload.transactions. - "REORG_HEAD_WEIGHT_THRESHOLD", - "SAMPLES_PER_SLOT", + "EIP7732_FORK_EPOCH", + "EIP7732_FORK_VERSION", + "MAX_BLOBS_PER_BLOCK_FULU", + "MAX_PAYLOAD_SIZE", + "MAX_REQUEST_BLOB_SIDECARS_FULU", + "MAX_REQUEST_PAYLOADS", // Compile time constant on BeaconBlockBody.ExecutionRequests + "NUMBER_OF_CUSTODY_GROUPS", "TARGET_NUMBER_OF_PEERS", "UPDATE_TIMEOUT", + "VALIDATOR_CUSTODY_REQUIREMENT", "WHISK_EPOCHS_PER_SHUFFLING_PHASE", "WHISK_FORK_EPOCH", "WHISK_FORK_VERSION", @@ -132,6 +129,7 @@ func assertEqualConfigs(t *testing.T, name string, fields []string, expected, ac // Max operations per block. assert.Equal(t, expected.MaxProposerSlashings, actual.MaxProposerSlashings, "%s: MaxProposerSlashings", name) assert.Equal(t, expected.MaxAttesterSlashings, actual.MaxAttesterSlashings, "%s: MaxAttesterSlashings", name) + assert.Equal(t, expected.MaxAttesterSlashingsElectra, actual.MaxAttesterSlashingsElectra, "%s: MaxAttesterSlashingsElectra", name) assert.Equal(t, expected.MaxAttestations, actual.MaxAttestations, "%s: MaxAttestations", name) assert.Equal(t, expected.MaxDeposits, actual.MaxDeposits, "%s: MaxDeposits", name) assert.Equal(t, expected.MaxVoluntaryExits, actual.MaxVoluntaryExits, "%s: MaxVoluntaryExits", name) @@ -150,6 +148,7 @@ func assertEqualConfigs(t *testing.T, name string, fields []string, expected, ac assert.Equal(t, expected.CapellaForkEpoch, actual.CapellaForkEpoch, "%s: CapellaForkEpoch", name) assert.Equal(t, expected.DenebForkEpoch, actual.DenebForkEpoch, "%s: DenebForkEpoch", name) assert.Equal(t, expected.ElectraForkEpoch, actual.ElectraForkEpoch, "%s: ElectraForkEpoch", name) + assert.Equal(t, expected.FuluForkEpoch, actual.FuluForkEpoch, "%s: FuluForkEpoch", name) assert.Equal(t, expected.SqrRootSlotsPerEpoch, actual.SqrRootSlotsPerEpoch, "%s: SqrRootSlotsPerEpoch", name) assert.DeepEqual(t, expected.GenesisForkVersion, actual.GenesisForkVersion, "%s: GenesisForkVersion", name) assert.DeepEqual(t, expected.AltairForkVersion, actual.AltairForkVersion, "%s: AltairForkVersion", name) @@ -157,6 +156,7 @@ func assertEqualConfigs(t *testing.T, name string, fields []string, expected, ac assert.DeepEqual(t, expected.CapellaForkVersion, actual.CapellaForkVersion, "%s: CapellaForkVersion", name) assert.DeepEqual(t, expected.DenebForkVersion, actual.DenebForkVersion, "%s: DenebForkVersion", name) assert.DeepEqual(t, expected.ElectraForkVersion, actual.ElectraForkVersion, "%s: ElectraForkVersion", name) + assert.DeepEqual(t, expected.FuluForkVersion, actual.FuluForkVersion, "%s: FuluForkVersion", name) assertYamlFieldsMatch(t, name, fields, expected, actual) } diff --git a/config/params/mainnet_config.go b/config/params/mainnet_config.go index 3cd9fc47a8d0..28d0ae808a9a 100644 --- a/config/params/mainnet_config.go +++ b/config/params/mainnet_config.go @@ -29,6 +29,8 @@ const ( mainnetDenebForkEpoch = 269568 // March 13, 2024, 13:55:35 UTC // Electra Fork Epoch for mainnet config mainnetElectraForkEpoch = math.MaxUint64 // Far future / to be defined + // Fulu Fork Epoch for mainnet config + mainnetFuluForkEpoch = math.MaxUint64 // Far future / to be defined ) var mainnetNetworkConfig = &NetworkConfig{ @@ -109,7 +111,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{ // Fork choice algorithm constants. ProposerScoreBoost: 40, - ReorgWeightThreshold: 20, + ReorgHeadWeightThreshold: 20, ReorgParentWeightThreshold: 160, ReorgMaxEpochsSinceFinalization: 2, IntervalsPerSlot: 3, @@ -171,9 +173,9 @@ var mainnetBeaconConfig = &BeaconChainConfig{ DomainApplicationMask: bytesutil.Uint32ToBytes4(0x00000001), DomainApplicationBuilder: bytesutil.Uint32ToBytes4(0x00000001), DomainBLSToExecutionChange: bytesutil.Uint32ToBytes4(0x0A000000), - DomainConsolidation: bytesutil.Uint32ToBytes4(0x0B000000), // Prysm constants. + GenesisValidatorsRoot: [32]byte{75, 54, 61, 185, 78, 40, 97, 32, 215, 110, 185, 5, 52, 15, 221, 78, 84, 191, 233, 240, 107, 243, 63, 246, 207, 90, 210, 127, 81, 27, 254, 149}, GweiPerEth: 1000000000, BLSSecretKeyLength: 32, BLSPubkeyLength: 48, @@ -194,6 +196,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{ BeaconStateCapellaFieldCount: 28, BeaconStateDenebFieldCount: 28, BeaconStateElectraFieldCount: 37, + BeaconStateFuluFieldCount: 37, // Slasher related values. WeakSubjectivityPeriod: 54000, @@ -216,6 +219,8 @@ var mainnetBeaconConfig = &BeaconChainConfig{ DenebForkEpoch: mainnetDenebForkEpoch, ElectraForkVersion: []byte{5, 0, 0, 0}, ElectraForkEpoch: mainnetElectraForkEpoch, + FuluForkVersion: []byte{6, 0, 0, 0}, + FuluForkEpoch: mainnetFuluForkEpoch, // New values introduced in Altair hard fork 1. // Participation flag indices. @@ -242,7 +247,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{ EpochsPerSyncCommitteePeriod: 256, // Updated penalty values. - InactivityPenaltyQuotientAltair: 3 * 1 << 24, //50331648 + InactivityPenaltyQuotientAltair: 3 * 1 << 24, // 50331648 MinSlashingPenaltyQuotientAltair: 64, ProportionalSlashingMultiplierAltair: 2, MinSlashingPenaltyQuotientBellatrix: 32, @@ -257,6 +262,10 @@ var mainnetBeaconConfig = &BeaconChainConfig{ TerminalBlockHashActivationEpoch: 18446744073709551615, TerminalBlockHash: [32]byte{}, TerminalTotalDifficulty: "58750000000000000000000", // Estimated: Sept 15, 2022 + MaxBytesPerTransaction: 1073741824, + MaxTransactionsPerPayload: 1048576, + BytesPerLogsBloom: 256, + MaxExtraDataBytes: 32, EthBurnAddressHex: "0x0000000000000000000000000000000000000000", DefaultBuilderGasLimit: uint64(30000000), @@ -267,32 +276,44 @@ var mainnetBeaconConfig = &BeaconChainConfig{ ExecutionEngineTimeoutValue: 8, // 8 seconds default based on: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#core // Subnet value - BlobsidecarSubnetCount: 6, + BlobsidecarSubnetCount: 6, + BlobsidecarSubnetCountElectra: 9, MaxPerEpochActivationChurnLimit: 8, MinEpochsForBlobsSidecarsRequest: 4096, MaxRequestBlobSidecars: 768, MaxRequestBlocksDeneb: 128, + FieldElementsPerBlob: 4096, + MaxBlobCommitmentsPerBlock: 4096, + KzgCommitmentInclusionProofDepth: 17, // Values related to electra MaxRequestDataColumnSidecars: 16384, - DataColumnSidecarSubnetCount: 32, + DataColumnSidecarSubnetCount: 128, MinPerEpochChurnLimitElectra: 128_000_000_000, MaxPerEpochActivationExitChurnLimit: 256_000_000_000, MaxEffectiveBalanceElectra: 2048_000_000_000, MinSlashingPenaltyQuotientElectra: 4096, WhistleBlowerRewardQuotientElectra: 4096, - PendingBalanceDepositLimit: 134_217_728, + PendingDepositsLimit: 134_217_728, PendingPartialWithdrawalsLimit: 134_217_728, PendingConsolidationsLimit: 262_144, MinActivationBalance: 32_000_000_000, - MaxConsolidationsRequestsPerPayload: 1, + MaxConsolidationsRequestsPerPayload: 2, MaxPendingPartialsPerWithdrawalsSweep: 8, + MaxPendingDepositsPerEpoch: 16, FullExitRequestAmount: 0, MaxWithdrawalRequestsPerPayload: 16, MaxDepositRequestsPerPayload: 8192, // 2**13 (= 8192) UnsetDepositRequestsStartIndex: math.MaxUint64, + // PeerDAS + NumberOfColumns: 128, + MaxCellsInExtendedMatrix: 768, + SamplesPerSlot: 8, + CustodyRequirement: 4, + MinEpochsForDataColumnSidecarsRequest: 4096, + // Values related to networking parameters. GossipMaxSize: 10 * 1 << 20, // 10 MiB MaxChunkSize: 10 * 1 << 20, // 10 MiB @@ -311,9 +332,10 @@ var mainnetBeaconConfig = &BeaconChainConfig{ SubnetsPerNode: 2, NodeIdBits: 256, - // PeerDAS - NumberOfColumns: 128, - MaxCellsInExtendedMatrix: 768, + DeprecatedMaxBlobsPerBlock: 6, + DeprecatedMaxBlobsPerBlockElectra: 9, + DeprecatedTargetBlobsPerBlockElectra: 6, + MaxRequestBlobSidecarsElectra: 1152, } // MainnetTestConfig provides a version of the mainnet config that has a different name @@ -335,6 +357,7 @@ func FillTestVersions(c *BeaconChainConfig, b byte) { c.CapellaForkVersion = make([]byte, fieldparams.VersionLength) c.DenebForkVersion = make([]byte, fieldparams.VersionLength) c.ElectraForkVersion = make([]byte, fieldparams.VersionLength) + c.FuluForkVersion = make([]byte, fieldparams.VersionLength) c.GenesisForkVersion[fieldparams.VersionLength-1] = b c.AltairForkVersion[fieldparams.VersionLength-1] = b @@ -342,6 +365,7 @@ func FillTestVersions(c *BeaconChainConfig, b byte) { c.CapellaForkVersion[fieldparams.VersionLength-1] = b c.DenebForkVersion[fieldparams.VersionLength-1] = b c.ElectraForkVersion[fieldparams.VersionLength-1] = b + c.FuluForkVersion[fieldparams.VersionLength-1] = b c.GenesisForkVersion[0] = 0 c.AltairForkVersion[0] = 1 @@ -349,4 +373,5 @@ func FillTestVersions(c *BeaconChainConfig, b byte) { c.CapellaForkVersion[0] = 3 c.DenebForkVersion[0] = 4 c.ElectraForkVersion[0] = 5 + c.FuluForkVersion[0] = 6 } diff --git a/config/params/minimal_config.go b/config/params/minimal_config.go index 0fd7d0fb378e..41abf3ba64d5 100644 --- a/config/params/minimal_config.go +++ b/config/params/minimal_config.go @@ -70,6 +70,7 @@ func MinimalSpecConfig() *BeaconChainConfig { minimalConfig.MaxDeposits = 16 minimalConfig.MaxVoluntaryExits = 16 minimalConfig.MaxWithdrawalsPerPayload = 4 + minimalConfig.MaxBlsToExecutionChanges = 16 minimalConfig.MaxValidatorsPerWithdrawalsSweep = 16 // Signature domains @@ -84,7 +85,6 @@ func MinimalSpecConfig() *BeaconChainConfig { minimalConfig.FarFutureEpoch = math.MaxUint64 minimalConfig.FarFutureSlot = math.MaxUint64 - // New Altair params minimalConfig.AltairForkVersion = []byte{1, 0, 0, 1} // Highest byte set to 0x01 to avoid collisions with mainnet versioning minimalConfig.AltairForkEpoch = math.MaxUint64 minimalConfig.BellatrixForkVersion = []byte{2, 0, 0, 1} @@ -95,12 +95,18 @@ func MinimalSpecConfig() *BeaconChainConfig { minimalConfig.DenebForkEpoch = math.MaxUint64 minimalConfig.ElectraForkVersion = []byte{5, 0, 0, 1} minimalConfig.ElectraForkEpoch = math.MaxUint64 + minimalConfig.FuluForkVersion = []byte{6, 0, 0, 1} + minimalConfig.FuluForkEpoch = math.MaxUint64 minimalConfig.SyncCommitteeSize = 32 minimalConfig.InactivityScoreBias = 4 minimalConfig.EpochsPerSyncCommitteePeriod = 8 minimalConfig.MinEpochsForBlockRequests = 272 + // New Deneb params + minimalConfig.MaxBlobCommitmentsPerBlock = 32 + minimalConfig.KzgCommitmentInclusionProofDepth = 10 + // New Electra params minimalConfig.MinPerEpochChurnLimitElectra = 64000000000 minimalConfig.MaxPerEpochActivationExitChurnLimit = 128000000000 @@ -109,7 +115,9 @@ func MinimalSpecConfig() *BeaconChainConfig { minimalConfig.MaxWithdrawalRequestsPerPayload = 2 minimalConfig.MaxDepositRequestsPerPayload = 4 minimalConfig.PendingPartialWithdrawalsLimit = 64 - minimalConfig.MaxPendingPartialsPerWithdrawalsSweep = 1 + minimalConfig.MaxPendingPartialsPerWithdrawalsSweep = 2 + minimalConfig.PendingDepositsLimit = 134217728 + minimalConfig.MaxPendingDepositsPerEpoch = 16 // Ethereum PoW parameters. minimalConfig.DepositChainID = 5 // Chain ID of eth1 goerli. diff --git a/config/params/testdata/e2e_config.yaml b/config/params/testdata/e2e_config.yaml index d264fbb6188c..e67d85556507 100644 --- a/config/params/testdata/e2e_config.yaml +++ b/config/params/testdata/e2e_config.yaml @@ -46,7 +46,10 @@ DENEB_FORK_VERSION: 0x040000fd DENEB_FORK_EPOCH: 12 # Electra ELECTRA_FORK_VERSION: 0x050000fd -ELECTRA_FORK_EPOCH: 18446744073709551615 +ELECTRA_FORK_EPOCH: 14 +# Fulu +FULU_FORK_VERSION: 0x060000fd +FULU_FORK_EPOCH: 18446744073709551615 # Time parameters diff --git a/config/params/testnet_config_test.go b/config/params/testnet_config_test.go index 617e77a2abfc..e84d8b387f4f 100644 --- a/config/params/testnet_config_test.go +++ b/config/params/testnet_config_test.go @@ -88,6 +88,7 @@ func compareConfigs(t *testing.T, expected, actual *params.BeaconChainConfig) { require.DeepEqual(t, expected.ProportionalSlashingMultiplier, actual.ProportionalSlashingMultiplier) require.DeepEqual(t, expected.MaxProposerSlashings, actual.MaxProposerSlashings) require.DeepEqual(t, expected.MaxAttesterSlashings, actual.MaxAttesterSlashings) + require.DeepEqual(t, expected.MaxAttesterSlashingsElectra, actual.MaxAttesterSlashingsElectra) require.DeepEqual(t, expected.MaxAttestations, actual.MaxAttestations) require.DeepEqual(t, expected.MaxDeposits, actual.MaxDeposits) require.DeepEqual(t, expected.MaxVoluntaryExits, actual.MaxVoluntaryExits) diff --git a/config/params/testnet_e2e_config.go b/config/params/testnet_e2e_config.go index a82c02ec16b7..a3e829fd52b0 100644 --- a/config/params/testnet_e2e_config.go +++ b/config/params/testnet_e2e_config.go @@ -7,7 +7,8 @@ const ( BellatrixE2EForkEpoch = 8 CapellaE2EForkEpoch = 10 DenebE2EForkEpoch = 12 - ElectraE2EForkEpoch = math.MaxUint64 + ElectraE2EForkEpoch = 14 + FuluE2EForkEpoch = math.MaxUint64 ) // E2ETestConfig retrieves the configurations made specifically for E2E testing. @@ -44,6 +45,7 @@ func E2ETestConfig() *BeaconChainConfig { e2eConfig.CapellaForkEpoch = CapellaE2EForkEpoch e2eConfig.DenebForkEpoch = DenebE2EForkEpoch e2eConfig.ElectraForkEpoch = ElectraE2EForkEpoch + e2eConfig.FuluForkEpoch = FuluE2EForkEpoch // Terminal Total Difficulty. e2eConfig.TerminalTotalDifficulty = "480" @@ -56,6 +58,7 @@ func E2ETestConfig() *BeaconChainConfig { e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 253} e2eConfig.DenebForkVersion = []byte{4, 0, 0, 253} e2eConfig.ElectraForkVersion = []byte{5, 0, 0, 253} + e2eConfig.FuluForkVersion = []byte{6, 0, 0, 253} e2eConfig.InitializeForkSchedule() return e2eConfig @@ -88,6 +91,7 @@ func E2EMainnetTestConfig() *BeaconChainConfig { e2eConfig.CapellaForkEpoch = CapellaE2EForkEpoch e2eConfig.DenebForkEpoch = DenebE2EForkEpoch e2eConfig.ElectraForkEpoch = ElectraE2EForkEpoch + e2eConfig.FuluForkEpoch = FuluE2EForkEpoch // Terminal Total Difficulty. e2eConfig.TerminalTotalDifficulty = "480" @@ -100,6 +104,7 @@ func E2EMainnetTestConfig() *BeaconChainConfig { e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 254} e2eConfig.DenebForkVersion = []byte{4, 0, 0, 254} e2eConfig.ElectraForkVersion = []byte{5, 0, 0, 254} + e2eConfig.FuluForkVersion = []byte{6, 0, 0, 254} // Deneb changes. e2eConfig.MinPerEpochChurnLimit = 2 diff --git a/config/params/testnet_holesky_config.go b/config/params/testnet_holesky_config.go index 66bf9bd23fcb..46140d19cc8f 100644 --- a/config/params/testnet_holesky_config.go +++ b/config/params/testnet_holesky_config.go @@ -26,6 +26,7 @@ func HoleskyConfig() *BeaconChainConfig { cfg.MinGenesisTime = 1695902100 cfg.GenesisDelay = 300 cfg.ConfigName = HoleskyName + cfg.GenesisValidatorsRoot = [32]byte{145, 67, 170, 124, 97, 90, 127, 113, 21, 226, 182, 170, 195, 25, 192, 53, 41, 223, 130, 66, 174, 112, 95, 186, 157, 243, 155, 121, 197, 159, 168, 177} cfg.GenesisForkVersion = []byte{0x01, 0x01, 0x70, 0x00} cfg.SecondsPerETH1Block = 14 cfg.DepositChainID = 17000 @@ -38,8 +39,10 @@ func HoleskyConfig() *BeaconChainConfig { cfg.CapellaForkVersion = []byte{0x4, 0x1, 0x70, 0x0} cfg.DenebForkEpoch = 29696 cfg.DenebForkVersion = []byte{0x05, 0x1, 0x70, 0x0} - cfg.ElectraForkEpoch = math.MaxUint64 - cfg.ElectraForkVersion = []byte{0x06, 0x1, 0x70, 0x0} // TODO: Define holesky fork version for electra. This is a placeholder value. + cfg.ElectraForkEpoch = 115968 // Mon, Feb 24 at 21:55:12 UTC + cfg.ElectraForkVersion = []byte{0x06, 0x1, 0x70, 0x0} + cfg.FuluForkEpoch = math.MaxUint64 + cfg.FuluForkVersion = []byte{0x07, 0x1, 0x70, 0x0} // TODO: Define holesky fork version for fulu. This is a placeholder value. cfg.TerminalTotalDifficulty = "0" cfg.DepositContractAddress = "0x4242424242424242424242424242424242424242" cfg.EjectionBalance = 28000000000 diff --git a/config/params/testnet_sepolia_config.go b/config/params/testnet_sepolia_config.go index 0df3e1e51d00..26e13ac8d995 100644 --- a/config/params/testnet_sepolia_config.go +++ b/config/params/testnet_sepolia_config.go @@ -11,11 +11,15 @@ func UseSepoliaNetworkConfig() { cfg := BeaconNetworkConfig().Copy() cfg.ContractDeploymentBlock = 1273020 cfg.BootstrapNodes = []string{ - // EF boot nodes + "enr:-Ku4QDZ_rCowZFsozeWr60WwLgOfHzv1Fz2cuMvJqN5iJzLxKtVjoIURY42X_YTokMi3IGstW5v32uSYZyGUXj9Q_IECh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhIpEe5iJc2VjcDI1NmsxoQNHTpFdaNSCEWiN_QqT396nb0PzcUpLe3OVtLph-AciBYN1ZHCCIy0", + "enr:-Ku4QHRyRwEPT7s0XLYzJ_EeeWvZTXBQb4UCGy1F_3m-YtCNTtDlGsCMr4UTgo4uR89pv11uM-xq4w6GKfKhqU31hTgCh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhIrFM7WJc2VjcDI1NmsxoQI4diTwChN3zAAkarf7smOHCdFb1q3DSwdiQ_Lc_FdzFIN1ZHCCIy0", + "enr:-Ku4QOkvvf0u5Hg4-HhY-SJmEyft77G5h3rUM8VF_e-Hag5cAma3jtmFoX4WElLAqdILCA-UWFRN1ZCDJJVuEHrFeLkDh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhJK-AWeJc2VjcDI1NmsxoQLFcT5VE_NMiIC8Ll7GypWDnQ4UEmuzD7hF_Hf4veDJwIN1ZHCCIy0", + "enr:-Ku4QH6tYsHKITYeHUu5kdfXgEZWI18EWk_2RtGOn1jBPlx2UlS_uF3Pm5Dx7tnjOvla_zs-wwlPgjnEOcQDWXey51QCh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhIs7Mc6Jc2VjcDI1NmsxoQIET4Mlv9YzhrYhX_H9D7aWMemUrvki6W4J2Qo0YmFMp4N1ZHCCIy0", + "enr:-Ku4QDmz-4c1InchGitsgNk4qzorWMiFUoaPJT4G0IiF8r2UaevrekND1o7fdoftNucirj7sFFTTn2-JdC2Ej0p1Mn8Ch2F0dG5ldHOIAAAAAAAAAACEZXRoMpCo_ujukAAAaf__________gmlkgnY0gmlwhKpA-liJc2VjcDI1NmsxoQMpHP5U1DK8O_JQU6FadmWbE42qEdcGlllR8HcSkkfWq4N1ZHCCIy0", + "enr:-KO4QP7MmB3juk8rUjJHcUoxZDU9Np4FlW0HyDEGIjSO7GD9PbSsabu7713cWSUWKDkxIypIXg1A-6lG7ySRGOMZHeGCAmuEZXRoMpDTH2GRkAAAc___________gmlkgnY0gmlwhBSoyGOJc2VjcDI1NmsxoQNta5b_bexSSwwrGW2Re24MjfMntzFd0f2SAxQtMj3ueYN0Y3CCIyiDdWRwgiMo", + "enr:-KG4QJejf8KVtMeAPWFhN_P0c4efuwu1pZHELTveiXUeim6nKYcYcMIQpGxxdgT2Xp9h-M5pr9gn2NbbwEAtxzu50Y8BgmlkgnY0gmlwhEEVkQCDaXA2kCoBBPnAEJg4AAAAAAAAAAGJc2VjcDI1NmsxoQLEh_eVvk07AQABvLkTGBQTrrIOQkzouMgSBtNHIRUxOIN1ZHCCIyiEdWRwNoIjKA", "enr:-Iq4QMCTfIMXnow27baRUb35Q8iiFHSIDBJh6hQM5Axohhf4b6Kr_cOCu0htQ5WvVqKvFgY28893DHAg8gnBAXsAVqmGAX53x8JggmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk", - "enr:-KG4QE5OIg5ThTjkzrlVF32WT_-XT14WeJtIz2zoTqLLjQhYAmJlnk4ItSoH41_2x0RX0wTFIe5GgjRzU2u7Q1fN4vADhGV0aDKQqP7o7pAAAHAyAAAAAAAAAIJpZIJ2NIJpcISlFsStiXNlY3AyNTZrMaEC-Rrd_bBZwhKpXzFCrStKp1q_HmGOewxY3KwM8ofAj_ODdGNwgiMog3VkcIIjKA", - // Teku boot node - "enr:-Ly4QFoZTWR8ulxGVsWydTNGdwEESueIdj-wB6UmmjUcm-AOPxnQi7wprzwcdo7-1jBW_JxELlUKJdJES8TDsbl1EdNlh2F0dG5ldHOI__78_v2bsV-EZXRoMpA2-lATkAAAcf__________gmlkgnY0gmlwhBLYJjGJc2VjcDI1NmsxoQI0gujXac9rMAb48NtMqtSTyHIeNYlpjkbYpWJw46PmYYhzeW5jbmV0cw-DdGNwgiMog3VkcIIjKA", + "enr:-L64QC9Hhov4DhQ7mRukTOz4_jHm4DHlGL726NWH4ojH1wFgEwSin_6H95Gs6nW2fktTWbPachHJ6rUFu0iJNgA0SB2CARqHYXR0bmV0c4j__________4RldGgykDb6UBOQAABx__________-CaWSCdjSCaXCEA-2vzolzZWNwMjU2azGhA17lsUg60R776rauYMdrAz383UUgESoaHEzMkvm4K6k6iHN5bmNuZXRzD4N0Y3CCIyiDdWRwgiMo", } OverrideBeaconNetworkConfig(cfg) } @@ -26,6 +30,7 @@ func SepoliaConfig() *BeaconChainConfig { cfg.MinGenesisTime = 1655647200 cfg.GenesisDelay = 86400 cfg.MinGenesisActiveValidatorCount = 1300 + cfg.GenesisValidatorsRoot = [32]byte{216, 234, 23, 31, 60, 148, 174, 162, 30, 188, 66, 161, 237, 97, 5, 42, 207, 63, 146, 9, 192, 14, 78, 251, 170, 221, 172, 9, 237, 155, 128, 120} cfg.ConfigName = SepoliaName cfg.GenesisForkVersion = []byte{0x90, 0x00, 0x00, 0x69} cfg.SecondsPerETH1Block = 14 @@ -39,8 +44,10 @@ func SepoliaConfig() *BeaconChainConfig { cfg.CapellaForkVersion = []byte{0x90, 0x00, 0x00, 0x72} cfg.DenebForkEpoch = 132608 cfg.DenebForkVersion = []byte{0x90, 0x00, 0x00, 0x73} - cfg.ElectraForkEpoch = math.MaxUint64 - cfg.ElectraForkVersion = []byte{0x90, 0x00, 0x00, 0x74} // TODO: Define sepolia fork version for electra. This is a placeholder value. + cfg.ElectraForkEpoch = 222464 // Wed, Mar 5 at 07:29:36 UTC + cfg.ElectraForkVersion = []byte{0x90, 0x00, 0x00, 0x74} + cfg.FuluForkEpoch = math.MaxUint64 + cfg.FuluForkVersion = []byte{0x90, 0x00, 0x00, 0x75} // TODO: Define sepolia fork version for fulu. This is a placeholder value. cfg.TerminalTotalDifficulty = "17000000000000000" cfg.DepositContractAddress = "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D" cfg.InitializeForkSchedule() diff --git a/config/params/testnet_sepolia_config_test.go b/config/params/testnet_sepolia_config_test.go new file mode 100644 index 000000000000..6b87f3385cc3 --- /dev/null +++ b/config/params/testnet_sepolia_config_test.go @@ -0,0 +1,28 @@ +package params_test + +import ( + "path" + "testing" + + "github.com/bazelbuild/rules_go/go/tools/bazel" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +func TestSepoliaConfigMatchesUpstreamYaml(t *testing.T) { + presetFPs := presetsFilePath(t, "mainnet") + mn, err := params.ByName(params.MainnetName) + require.NoError(t, err) + cfg := mn.Copy() + for _, fp := range presetFPs { + cfg, err = params.UnmarshalConfigFile(fp, cfg) + require.NoError(t, err) + } + fPath, err := bazel.Runfile("external/sepolia_testnet") + require.NoError(t, err) + configFP := path.Join(fPath, "metadata", "config.yaml") + pcfg, err := params.UnmarshalConfigFile(configFP, nil) + require.NoError(t, err) + fields := fieldsFromYamls(t, append(presetFPs, configFP)) + assertYamlFieldsMatch(t, "sepolia", fields, pcfg, params.SepoliaConfig()) +} diff --git a/config/proposer/loader/loader.go b/config/proposer/loader/loader.go index 2a5fce40955e..5ba4c3e4b51c 100644 --- a/config/proposer/loader/loader.go +++ b/config/proposer/loader/loader.go @@ -28,7 +28,7 @@ const ( onlyDB ) -type settingsLoader struct { +type SettingsLoader struct { loadMethods []settingsType existsInDB bool db iface.ValidatorDB @@ -41,11 +41,11 @@ type flagOptions struct { } // SettingsLoaderOption sets additional options that affect the proposer settings -type SettingsLoaderOption func(cliCtx *cli.Context, psl *settingsLoader) error +type SettingsLoaderOption func(cliCtx *cli.Context, psl *SettingsLoader) error // WithBuilderConfig applies the --enable-builder flag to proposer settings func WithBuilderConfig() SettingsLoaderOption { - return func(cliCtx *cli.Context, psl *settingsLoader) error { + return func(cliCtx *cli.Context, psl *SettingsLoader) error { if cliCtx.Bool(flags.EnableBuilderFlag.Name) { psl.options.builderConfig = &proposer.BuilderConfig{ Enabled: true, @@ -58,7 +58,7 @@ func WithBuilderConfig() SettingsLoaderOption { // WithGasLimit applies the --suggested-gas-limit flag to proposer settings func WithGasLimit() SettingsLoaderOption { - return func(cliCtx *cli.Context, psl *settingsLoader) error { + return func(cliCtx *cli.Context, psl *SettingsLoader) error { sgl := cliCtx.String(flags.BuilderGasLimitFlag.Name) if sgl != "" { gl, err := strconv.ParseUint(sgl, 10, 64) @@ -76,7 +76,7 @@ func WithGasLimit() SettingsLoaderOption { } // NewProposerSettingsLoader returns a new proposer settings loader that can process the proposer settings based on flag options -func NewProposerSettingsLoader(cliCtx *cli.Context, db iface.ValidatorDB, opts ...SettingsLoaderOption) (*settingsLoader, error) { +func NewProposerSettingsLoader(cliCtx *cli.Context, db iface.ValidatorDB, opts ...SettingsLoaderOption) (*SettingsLoader, error) { if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) && cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) { return nil, fmt.Errorf("cannot specify both --%s and --%s flags; choose one method for specifying proposer settings", flags.ProposerSettingsFlag.Name, flags.ProposerSettingsURLFlag.Name) } @@ -84,43 +84,47 @@ func NewProposerSettingsLoader(cliCtx *cli.Context, db iface.ValidatorDB, opts . if err != nil { return nil, err } - psl := &settingsLoader{db: db, existsInDB: psExists, options: &flagOptions{}} + psl := &SettingsLoader{db: db, existsInDB: psExists, options: &flagOptions{}} + + psl.loadMethods = determineLoadMethods(cliCtx, psl.existsInDB) + + for _, o := range opts { + if err := o(cliCtx, psl); err != nil { + return nil, err + } + } + + return psl, nil +} + +func determineLoadMethods(cliCtx *cli.Context, loadedFromDB bool) []settingsType { + var methods []settingsType if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) { - psl.loadMethods = append(psl.loadMethods, defaultFlag) + methods = append(methods, defaultFlag) } if cliCtx.IsSet(flags.ProposerSettingsFlag.Name) { - psl.loadMethods = append(psl.loadMethods, fileFlag) + methods = append(methods, fileFlag) } if cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) { - psl.loadMethods = append(psl.loadMethods, urlFlag) + methods = append(methods, urlFlag) } - if len(psl.loadMethods) == 0 { - method := none - if psExists { - // override with db - method = onlyDB - } - psl.loadMethods = append(psl.loadMethods, method) + if len(methods) == 0 && loadedFromDB { + methods = append(methods, onlyDB) } - - for _, o := range opts { - if err := o(cliCtx, psl); err != nil { - return nil, err - } + if len(methods) == 0 { + methods = append(methods, none) } - return psl, nil + return methods } // Load saves the proposer settings to the database -func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error) { - loadConfig := &validatorpb.ProposerSettingsPayload{} +func (psl *SettingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error) { + var loadedSettings, dbSettings *validatorpb.ProposerSettingsPayload // override settings based on other options - if psl.options.builderConfig != nil && psl.options.gasLimit != nil { - psl.options.builderConfig.GasLimit = *psl.options.gasLimit - } + psl.applyOverrides() // check if database has settings already if psl.existsInDB { @@ -128,9 +132,9 @@ func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error) if err != nil { return nil, err } - loadConfig = dbps.ToConsensus() + dbSettings = dbps.ToConsensus() log.Debugf("DB loaded proposer settings: %s", func() string { - b, err := json.Marshal(loadConfig) + b, err := json.Marshal(dbSettings) if err != nil { return err.Error() } @@ -140,72 +144,39 @@ func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error) // start to process based on load method for _, method := range psl.loadMethods { + var err error switch method { case defaultFlag: - if psl.existsInDB && len(psl.loadMethods) == 1 { - // only log the below if default flag is the only load method - log.Warn("Previously saved proposer settings were loaded from the DB, only default settings will be updated. Please provide new proposer settings or clear DB to reset proposer settings.") - } - suggestedFeeRecipient := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name) - if !common.IsHexAddress(suggestedFeeRecipient) { - return nil, errors.Errorf("--%s is not a valid Ethereum address", flags.SuggestedFeeRecipientFlag.Name) - } - if err := config.WarnNonChecksummedAddress(suggestedFeeRecipient); err != nil { + loadedSettings, err = psl.loadFromDefault(cliCtx, dbSettings) + if err != nil { return nil, err } - defaultConfig := &validatorpb.ProposerOptionPayload{ - FeeRecipient: suggestedFeeRecipient, - } - if psl.options.builderConfig != nil { - defaultConfig.Builder = psl.options.builderConfig.ToConsensus() - } - loadConfig.DefaultConfig = defaultConfig case fileFlag: - var settingFromFile *validatorpb.ProposerSettingsPayload - if err := config.UnmarshalFromFile(cliCtx.String(flags.ProposerSettingsFlag.Name), &settingFromFile); err != nil { + loadedSettings, err = psl.loadFromFile(cliCtx, dbSettings) + if err != nil { return nil, err } - if settingFromFile == nil { - return nil, errors.Errorf("proposer settings is empty after unmarshalling from file specified by %s flag", flags.ProposerSettingsFlag.Name) - } - loadConfig = psl.processProposerSettings(settingFromFile, loadConfig) - log.WithField(flags.ProposerSettingsFlag.Name, cliCtx.String(flags.ProposerSettingsFlag.Name)).Info("Proposer settings loaded from file") case urlFlag: - var settingFromURL *validatorpb.ProposerSettingsPayload - if err := config.UnmarshalFromURL(cliCtx.Context, cliCtx.String(flags.ProposerSettingsURLFlag.Name), &settingFromURL); err != nil { + loadedSettings, err = psl.loadFromURL(cliCtx, dbSettings) + if err != nil { return nil, err } - if settingFromURL == nil { - return nil, errors.New("proposer settings is empty after unmarshalling from url") - } - loadConfig = psl.processProposerSettings(settingFromURL, loadConfig) - log.WithField(flags.ProposerSettingsURLFlag.Name, cliCtx.String(flags.ProposerSettingsURLFlag.Name)).Infof("Proposer settings loaded from URL") - case onlyDB: - loadConfig = psl.processProposerSettings(nil, loadConfig) - log.Info("Proposer settings loaded from the DB") - case none: + case onlyDB, none: + loadedSettings = psl.processProposerSettings(&validatorpb.ProposerSettingsPayload{}, dbSettings) if psl.existsInDB { log.Info("Proposer settings loaded from the DB") } - if psl.options.builderConfig != nil { - // if there are no proposer settings provided, create a default where fee recipient is not populated, this will be skipped for validator registration on validators that don't have a fee recipient set. - // skip saving to DB if only builder settings are provided until a trigger like keymanager API updates with fee recipient values - option := &proposer.Option{ - BuilderConfig: psl.options.builderConfig.Clone(), - } - loadConfig.DefaultConfig = option.ToConsensus() - } default: return nil, errors.New("load method for proposer settings does not exist") } } // exit early if nothing is provided - if loadConfig == nil || (loadConfig.ProposerConfig == nil && loadConfig.DefaultConfig == nil) { + if loadedSettings == nil || (loadedSettings.ProposerConfig == nil && loadedSettings.DefaultConfig == nil) { log.Warn("No proposer settings were provided") return nil, nil } - ps, err := proposer.SettingFromConsensus(loadConfig) + ps, err := proposer.SettingFromConsensus(loadedSettings) if err != nil { return nil, err } @@ -215,66 +186,128 @@ func (psl *settingsLoader) Load(cliCtx *cli.Context) (*proposer.Settings, error) return ps, nil } -func (psl *settingsLoader) processProposerSettings(loadedSettings, dbSettings *validatorpb.ProposerSettingsPayload) *validatorpb.ProposerSettingsPayload { +func (psl *SettingsLoader) applyOverrides() { + if psl.options.builderConfig != nil && psl.options.gasLimit != nil { + psl.options.builderConfig.GasLimit = *psl.options.gasLimit + } +} + +func (psl *SettingsLoader) loadFromDefault(cliCtx *cli.Context, dbSettings *validatorpb.ProposerSettingsPayload) (*validatorpb.ProposerSettingsPayload, error) { + suggestedFeeRecipient := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name) + if !common.IsHexAddress(suggestedFeeRecipient) { + return nil, errors.Errorf("--%s is not a valid Ethereum address", flags.SuggestedFeeRecipientFlag.Name) + } + if err := config.WarnNonChecksummedAddress(suggestedFeeRecipient); err != nil { + return nil, err + } + + if psl.existsInDB && len(psl.loadMethods) == 1 { + // only log the below if default flag is the only load method + log.Debug("Overriding previously saved proposer default settings.") + } + log.WithField(flags.SuggestedFeeRecipientFlag.Name, cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)).Info("Proposer settings loaded from default") + return psl.processProposerSettings(&validatorpb.ProposerSettingsPayload{DefaultConfig: &validatorpb.ProposerOptionPayload{ + FeeRecipient: suggestedFeeRecipient, + }}, dbSettings), nil +} + +func (psl *SettingsLoader) loadFromFile(cliCtx *cli.Context, dbSettings *validatorpb.ProposerSettingsPayload) (*validatorpb.ProposerSettingsPayload, error) { + var settingFromFile *validatorpb.ProposerSettingsPayload + if err := config.UnmarshalFromFile(cliCtx.String(flags.ProposerSettingsFlag.Name), &settingFromFile); err != nil { + return nil, err + } + if settingFromFile == nil { + return nil, errors.Errorf("proposer settings is empty after unmarshalling from file specified by %s flag", flags.ProposerSettingsFlag.Name) + } + log.WithField(flags.ProposerSettingsFlag.Name, cliCtx.String(flags.ProposerSettingsFlag.Name)).Info("Proposer settings loaded from file") + return psl.processProposerSettings(settingFromFile, dbSettings), nil +} + +func (psl *SettingsLoader) loadFromURL(cliCtx *cli.Context, dbSettings *validatorpb.ProposerSettingsPayload) (*validatorpb.ProposerSettingsPayload, error) { + var settingFromURL *validatorpb.ProposerSettingsPayload + if err := config.UnmarshalFromURL(cliCtx.Context, cliCtx.String(flags.ProposerSettingsURLFlag.Name), &settingFromURL); err != nil { + return nil, err + } + if settingFromURL == nil { + return nil, errors.Errorf("proposer settings is empty after unmarshalling from url specified by %s flag", flags.ProposerSettingsURLFlag.Name) + } + log.WithField(flags.ProposerSettingsURLFlag.Name, cliCtx.String(flags.ProposerSettingsURLFlag.Name)).Infof("Proposer settings loaded from URL") + return psl.processProposerSettings(settingFromURL, dbSettings), nil +} + +func (psl *SettingsLoader) processProposerSettings(loadedSettings, dbSettings *validatorpb.ProposerSettingsPayload) *validatorpb.ProposerSettingsPayload { if loadedSettings == nil && dbSettings == nil { return nil } - // loaded settings have higher priority than db settings - newSettings := &validatorpb.ProposerSettingsPayload{} + // Merge settings with priority: loadedSettings > dbSettings + newSettings := mergeProposerSettings(loadedSettings, dbSettings, psl.options) + + // Return nil if settings remain empty + if newSettings.DefaultConfig == nil && len(newSettings.ProposerConfig) == 0 { + return nil + } + + return newSettings +} +// mergeProposerSettings merges database settings with loaded settings, giving precedence to loadedSettings +func mergeProposerSettings(loaded, db *validatorpb.ProposerSettingsPayload, options *flagOptions) *validatorpb.ProposerSettingsPayload { + merged := &validatorpb.ProposerSettingsPayload{} + + // Apply builder config overrides var builderConfig *validatorpb.BuilderConfig var gasLimitOnly *validator.Uint64 - if psl.options != nil { - if psl.options.builderConfig != nil { - builderConfig = psl.options.builderConfig.ToConsensus() + if options != nil { + if options.builderConfig != nil { + builderConfig = options.builderConfig.ToConsensus() } - if psl.options.gasLimit != nil { - gasLimitOnly = psl.options.gasLimit + if options.gasLimit != nil { + gasLimitOnly = options.gasLimit } } - if dbSettings != nil && dbSettings.DefaultConfig != nil { + // Merge DefaultConfig + if db != nil && db.DefaultConfig != nil { + merged.DefaultConfig = db.DefaultConfig + // db always falls back to local building if no builder settings are provided if builderConfig == nil { - dbSettings.DefaultConfig.Builder = nil + db.DefaultConfig.Builder = nil } - newSettings.DefaultConfig = dbSettings.DefaultConfig - } - if loadedSettings != nil && loadedSettings.DefaultConfig != nil { - newSettings.DefaultConfig = loadedSettings.DefaultConfig } - - // process any builder overrides on defaults - if newSettings.DefaultConfig != nil { - newSettings.DefaultConfig.Builder = processBuilderConfig(newSettings.DefaultConfig.Builder, builderConfig, gasLimitOnly) + if loaded != nil && loaded.DefaultConfig != nil { + merged.DefaultConfig = loaded.DefaultConfig } - if dbSettings != nil && len(dbSettings.ProposerConfig) != 0 { - for _, option := range dbSettings.ProposerConfig { + // Merge ProposerConfig + if db != nil && len(db.ProposerConfig) > 0 { + merged.ProposerConfig = db.ProposerConfig + for _, option := range db.ProposerConfig { + // db always falls back to local building if no builder settings are provided if builderConfig == nil { option.Builder = nil } } - newSettings.ProposerConfig = dbSettings.ProposerConfig } - if loadedSettings != nil && len(loadedSettings.ProposerConfig) != 0 { - newSettings.ProposerConfig = loadedSettings.ProposerConfig + if loaded != nil && len(loaded.ProposerConfig) > 0 { + merged.ProposerConfig = loaded.ProposerConfig } - // process any overrides for proposer config - for _, option := range newSettings.ProposerConfig { + if merged.DefaultConfig != nil { + merged.DefaultConfig.Builder = processBuilderConfig(merged.DefaultConfig.Builder, builderConfig, gasLimitOnly) + } + for _, option := range merged.ProposerConfig { if option != nil { option.Builder = processBuilderConfig(option.Builder, builderConfig, gasLimitOnly) } } - // if default and proposer configs are both missing even after db setting - if newSettings.DefaultConfig == nil && newSettings.ProposerConfig == nil { - return nil + if merged.DefaultConfig == nil && builderConfig != nil { + merged.DefaultConfig = &validatorpb.ProposerOptionPayload{Builder: builderConfig} } - return newSettings + return merged } func processBuilderConfig(current *validatorpb.BuilderConfig, override *validatorpb.BuilderConfig, gasLimitOnly *validator.Uint64) *validatorpb.BuilderConfig { diff --git a/config/proposer/settings.go b/config/proposer/settings.go index 88338eca7dbe..e9d38ac2a8dd 100644 --- a/config/proposer/settings.go +++ b/config/proposer/settings.go @@ -16,7 +16,7 @@ import ( // SettingFromConsensus converts struct to Settings while verifying the fields func SettingFromConsensus(ps *validatorpb.ProposerSettingsPayload) (*Settings, error) { settings := &Settings{} - if ps.ProposerConfig != nil && len(ps.ProposerConfig) != 0 { + if len(ps.ProposerConfig) != 0 { settings.ProposeConfig = make(map[[fieldparams.BLSPubkeyLength]byte]*Option) for key, optionPayload := range ps.ProposerConfig { decodedKey, err := hexutil.Decode(key) diff --git a/consensus-types/blocks/BUILD.bazel b/consensus-types/blocks/BUILD.bazel index c39b47ed342a..f60964a5f740 100644 --- a/consensus-types/blocks/BUILD.bazel +++ b/consensus-types/blocks/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "get_payload.go", "getters.go", "kzg.go", + "proofs.go", "proto.go", "roblob.go", "roblock.go", @@ -17,14 +18,17 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks", visibility = ["//visibility:public"], deps = [ + "//beacon-chain/state/stateutil:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//container/trie:go_default_library", + "//crypto/hash/htr:go_default_library", "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", @@ -43,6 +47,7 @@ go_test( "factory_test.go", "getters_test.go", "kzg_test.go", + "proofs_test.go", "proto_test.go", "roblob_test.go", "roblock_test.go", @@ -50,6 +55,7 @@ go_test( embed = [":go_default_library"], deps = [ "//config/fieldparams:go_default_library", + "//config/params:go_default_library", "//consensus-types:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", diff --git a/consensus-types/blocks/execution.go b/consensus-types/blocks/execution.go index 6d47aa3c5a8f..e01901a7d782 100644 --- a/consensus-types/blocks/execution.go +++ b/consensus-types/blocks/execution.go @@ -14,8 +14,6 @@ import ( "google.golang.org/protobuf/proto" ) -var _ interfaces.ExecutionDataElectra = (*executionPayloadElectra)(nil) - // executionPayload is a convenience wrapper around a beacon block body's execution payload data structure // This wrapper allows us to conform to a common interface so that beacon // blocks for future forks can also be applied across Prysm without issues. @@ -39,10 +37,9 @@ func NewWrappedExecutionData(v proto.Message) (interfaces.ExecutionData, error) return WrappedExecutionPayloadDeneb(pbStruct) case *enginev1.ExecutionPayloadDenebWithValueAndBlobsBundle: return WrappedExecutionPayloadDeneb(pbStruct.Payload) - case *enginev1.ExecutionPayloadElectra: - return WrappedExecutionPayloadElectra(pbStruct) - case *enginev1.ExecutionPayloadElectraWithValueAndBlobsBundle: - return WrappedExecutionPayloadElectra(pbStruct.Payload) + case *enginev1.ExecutionBundleElectra: + // note: no payload changes in electra so using deneb + return WrappedExecutionPayloadDeneb(pbStruct.Payload) default: return nil, ErrUnsupportedVersion } @@ -787,74 +784,10 @@ func PayloadToHeaderDeneb(payload interfaces.ExecutionData) (*enginev1.Execution }, nil } -// PayloadToHeaderElectra converts `payload` into execution payload header format. -func PayloadToHeaderElectra(payload interfaces.ExecutionDataElectra) (*enginev1.ExecutionPayloadHeaderElectra, error) { - txs, err := payload.Transactions() - if err != nil { - return nil, err - } - txRoot, err := ssz.TransactionsRoot(txs) - if err != nil { - return nil, err - } - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, err - } - withdrawalsRoot, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) - if err != nil { - return nil, err - } - blobGasUsed, err := payload.BlobGasUsed() - if err != nil { - return nil, err - } - excessBlobGas, err := payload.ExcessBlobGas() - if err != nil { - return nil, err - } - - depositRequests := payload.DepositRequests() - depositRequestsRoot, err := ssz.DepositRequestsSliceRoot(depositRequests, fieldparams.MaxDepositRequestsPerPayload) - if err != nil { - return nil, err - } - - withdrawalRequests := payload.WithdrawalRequests() - withdrawalRequestsRoot, err := ssz.WithdrawalRequestsSliceRoot(withdrawalRequests, fieldparams.MaxWithdrawalRequestsPerPayload) - if err != nil { - return nil, err - } - - consolidationRequests := payload.ConsolidationRequests() - consolidationRequestsRoot, err := ssz.ConsolidationRequestsSliceRoot(consolidationRequests, fieldparams.MaxConsolidationRequestsPerPayload) - if err != nil { - return nil, err - } - - return &enginev1.ExecutionPayloadHeaderElectra{ - ParentHash: bytesutil.SafeCopyBytes(payload.ParentHash()), - FeeRecipient: bytesutil.SafeCopyBytes(payload.FeeRecipient()), - StateRoot: bytesutil.SafeCopyBytes(payload.StateRoot()), - ReceiptsRoot: bytesutil.SafeCopyBytes(payload.ReceiptsRoot()), - LogsBloom: bytesutil.SafeCopyBytes(payload.LogsBloom()), - PrevRandao: bytesutil.SafeCopyBytes(payload.PrevRandao()), - BlockNumber: payload.BlockNumber(), - GasLimit: payload.GasLimit(), - GasUsed: payload.GasUsed(), - Timestamp: payload.Timestamp(), - ExtraData: bytesutil.SafeCopyBytes(payload.ExtraData()), - BaseFeePerGas: bytesutil.SafeCopyBytes(payload.BaseFeePerGas()), - BlockHash: bytesutil.SafeCopyBytes(payload.BlockHash()), - TransactionsRoot: txRoot[:], - WithdrawalsRoot: withdrawalsRoot[:], - BlobGasUsed: blobGasUsed, - ExcessBlobGas: excessBlobGas, - DepositRequestsRoot: depositRequestsRoot[:], - WithdrawalRequestsRoot: withdrawalRequestsRoot[:], - ConsolidationRequestsRoot: consolidationRequestsRoot[:], - }, nil -} +var ( + PayloadToHeaderElectra = PayloadToHeaderDeneb + PayloadToHeaderFulu = PayloadToHeaderDeneb +) // IsEmptyExecutionData checks if an execution data is empty underneath. If a single field has // a non-zero value, this function will return false. @@ -913,20 +846,6 @@ func IsEmptyExecutionData(data interfaces.ExecutionData) (bool, error) { if data.Timestamp() != 0 { return false, nil } - - epe, postElectra := data.(interfaces.ExecutionDataElectra) - if postElectra { - drs := epe.DepositRequests() - if len(drs) != 0 { - return false, nil - } - - wrs := epe.WithdrawalRequests() - if len(wrs) != 0 { - return false, nil - } - } - return true, nil } @@ -1243,342 +1162,3 @@ func (e executionPayloadDeneb) ExcessBlobGas() (uint64, error) { func (e executionPayloadDeneb) IsBlinded() bool { return false } - -// executionPayloadHeaderElectra is a convenience wrapper around a blinded beacon block body's execution header data structure. -// This wrapper allows us to conform to a common interface so that beacon -// blocks for future forks can also be applied across Prysm without issues. -type executionPayloadHeaderElectra struct { - p *enginev1.ExecutionPayloadHeaderElectra -} - -var _ interfaces.ExecutionData = &executionPayloadElectra{} - -// WrappedExecutionPayloadHeaderElectra is a constructor which wraps a protobuf execution header into an interface. -func WrappedExecutionPayloadHeaderElectra(p *enginev1.ExecutionPayloadHeaderElectra) (interfaces.ExecutionData, error) { - w := executionPayloadHeaderElectra{p: p} - if w.IsNil() { - return nil, consensus_types.ErrNilObjectWrapped - } - return w, nil -} - -// IsNil checks if the underlying data is nil. -func (e executionPayloadHeaderElectra) IsNil() bool { - return e.p == nil -} - -// MarshalSSZ -- -func (e executionPayloadHeaderElectra) MarshalSSZ() ([]byte, error) { - return e.p.MarshalSSZ() -} - -// MarshalSSZTo -- -func (e executionPayloadHeaderElectra) MarshalSSZTo(dst []byte) ([]byte, error) { - return e.p.MarshalSSZTo(dst) -} - -// SizeSSZ -- -func (e executionPayloadHeaderElectra) SizeSSZ() int { - return e.p.SizeSSZ() -} - -// UnmarshalSSZ -- -func (e executionPayloadHeaderElectra) UnmarshalSSZ(buf []byte) error { - return e.p.UnmarshalSSZ(buf) -} - -// HashTreeRoot -- -func (e executionPayloadHeaderElectra) HashTreeRoot() ([32]byte, error) { - return e.p.HashTreeRoot() -} - -// HashTreeRootWith -- -func (e executionPayloadHeaderElectra) HashTreeRootWith(hh *fastssz.Hasher) error { - return e.p.HashTreeRootWith(hh) -} - -// Proto -- -func (e executionPayloadHeaderElectra) Proto() proto.Message { - return e.p -} - -// ParentHash -- -func (e executionPayloadHeaderElectra) ParentHash() []byte { - return e.p.ParentHash -} - -// FeeRecipient -- -func (e executionPayloadHeaderElectra) FeeRecipient() []byte { - return e.p.FeeRecipient -} - -// StateRoot -- -func (e executionPayloadHeaderElectra) StateRoot() []byte { - return e.p.StateRoot -} - -// ReceiptsRoot -- -func (e executionPayloadHeaderElectra) ReceiptsRoot() []byte { - return e.p.ReceiptsRoot -} - -// LogsBloom -- -func (e executionPayloadHeaderElectra) LogsBloom() []byte { - return e.p.LogsBloom -} - -// PrevRandao -- -func (e executionPayloadHeaderElectra) PrevRandao() []byte { - return e.p.PrevRandao -} - -// BlockNumber -- -func (e executionPayloadHeaderElectra) BlockNumber() uint64 { - return e.p.BlockNumber -} - -// GasLimit -- -func (e executionPayloadHeaderElectra) GasLimit() uint64 { - return e.p.GasLimit -} - -// GasUsed -- -func (e executionPayloadHeaderElectra) GasUsed() uint64 { - return e.p.GasUsed -} - -// Timestamp -- -func (e executionPayloadHeaderElectra) Timestamp() uint64 { - return e.p.Timestamp -} - -// ExtraData -- -func (e executionPayloadHeaderElectra) ExtraData() []byte { - return e.p.ExtraData -} - -// BaseFeePerGas -- -func (e executionPayloadHeaderElectra) BaseFeePerGas() []byte { - return e.p.BaseFeePerGas -} - -// BlockHash -- -func (e executionPayloadHeaderElectra) BlockHash() []byte { - return e.p.BlockHash -} - -// Transactions -- -func (executionPayloadHeaderElectra) Transactions() ([][]byte, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// TransactionsRoot -- -func (e executionPayloadHeaderElectra) TransactionsRoot() ([]byte, error) { - return e.p.TransactionsRoot, nil -} - -// Withdrawals -- -func (e executionPayloadHeaderElectra) Withdrawals() ([]*enginev1.Withdrawal, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// WithdrawalsRoot -- -func (e executionPayloadHeaderElectra) WithdrawalsRoot() ([]byte, error) { - return e.p.WithdrawalsRoot, nil -} - -// BlobGasUsed -- -func (e executionPayloadHeaderElectra) BlobGasUsed() (uint64, error) { - return e.p.BlobGasUsed, nil -} - -// ExcessBlobGas -- -func (e executionPayloadHeaderElectra) ExcessBlobGas() (uint64, error) { - return e.p.ExcessBlobGas, nil -} - -// DepositRequests -- -func (e executionPayloadHeaderElectra) DepositRequests() ([]*enginev1.DepositRequest, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// WithdrawalRequests -- -func (e executionPayloadHeaderElectra) WithdrawalRequests() ([]*enginev1.WithdrawalRequest, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// IsBlinded returns true if the underlying data is blinded. -func (e executionPayloadHeaderElectra) IsBlinded() bool { - return true -} - -// executionPayloadElectra is a convenience wrapper around a beacon block body's execution payload data structure -// This wrapper allows us to conform to a common interface so that beacon -// blocks for future forks can also be applied across Prysm without issues. -type executionPayloadElectra struct { - p *enginev1.ExecutionPayloadElectra -} - -// WrappedExecutionPayloadElectra is a constructor which wraps a protobuf execution payload into an interface. -func WrappedExecutionPayloadElectra(p *enginev1.ExecutionPayloadElectra) (interfaces.ExecutionData, error) { - w := executionPayloadElectra{p: p} - if w.IsNil() { - return nil, consensus_types.ErrNilObjectWrapped - } - return w, nil -} - -var _ interfaces.ExecutionData = &executionPayloadElectra{} - -// IsNil checks if the underlying data is nil. -func (e executionPayloadElectra) IsNil() bool { - return e.p == nil -} - -// MarshalSSZ -- -func (e executionPayloadElectra) MarshalSSZ() ([]byte, error) { - return e.p.MarshalSSZ() -} - -// MarshalSSZTo -- -func (e executionPayloadElectra) MarshalSSZTo(dst []byte) ([]byte, error) { - return e.p.MarshalSSZTo(dst) -} - -// SizeSSZ -- -func (e executionPayloadElectra) SizeSSZ() int { - return e.p.SizeSSZ() -} - -// UnmarshalSSZ -- -func (e executionPayloadElectra) UnmarshalSSZ(buf []byte) error { - return e.p.UnmarshalSSZ(buf) -} - -// HashTreeRoot -- -func (e executionPayloadElectra) HashTreeRoot() ([32]byte, error) { - return e.p.HashTreeRoot() -} - -// HashTreeRootWith -- -func (e executionPayloadElectra) HashTreeRootWith(hh *fastssz.Hasher) error { - return e.p.HashTreeRootWith(hh) -} - -// Proto -- -func (e executionPayloadElectra) Proto() proto.Message { - return e.p -} - -// ParentHash -- -func (e executionPayloadElectra) ParentHash() []byte { - return e.p.ParentHash -} - -// FeeRecipient -- -func (e executionPayloadElectra) FeeRecipient() []byte { - return e.p.FeeRecipient -} - -// StateRoot -- -func (e executionPayloadElectra) StateRoot() []byte { - return e.p.StateRoot -} - -// ReceiptsRoot -- -func (e executionPayloadElectra) ReceiptsRoot() []byte { - return e.p.ReceiptsRoot -} - -// LogsBloom -- -func (e executionPayloadElectra) LogsBloom() []byte { - return e.p.LogsBloom -} - -// PrevRandao -- -func (e executionPayloadElectra) PrevRandao() []byte { - return e.p.PrevRandao -} - -// BlockNumber -- -func (e executionPayloadElectra) BlockNumber() uint64 { - return e.p.BlockNumber -} - -// GasLimit -- -func (e executionPayloadElectra) GasLimit() uint64 { - return e.p.GasLimit -} - -// GasUsed -- -func (e executionPayloadElectra) GasUsed() uint64 { - return e.p.GasUsed -} - -// Timestamp -- -func (e executionPayloadElectra) Timestamp() uint64 { - return e.p.Timestamp -} - -// ExtraData -- -func (e executionPayloadElectra) ExtraData() []byte { - return e.p.ExtraData -} - -// BaseFeePerGas -- -func (e executionPayloadElectra) BaseFeePerGas() []byte { - return e.p.BaseFeePerGas -} - -// BlockHash -- -func (e executionPayloadElectra) BlockHash() []byte { - return e.p.BlockHash -} - -// Transactions -- -func (e executionPayloadElectra) Transactions() ([][]byte, error) { - return e.p.Transactions, nil -} - -// TransactionsRoot -- -func (e executionPayloadElectra) TransactionsRoot() ([]byte, error) { - return nil, consensus_types.ErrUnsupportedField -} - -// Withdrawals -- -func (e executionPayloadElectra) Withdrawals() ([]*enginev1.Withdrawal, error) { - return e.p.Withdrawals, nil -} - -// WithdrawalsRoot -- -func (e executionPayloadElectra) WithdrawalsRoot() ([]byte, error) { - return nil, consensus_types.ErrUnsupportedField -} - -func (e executionPayloadElectra) BlobGasUsed() (uint64, error) { - return e.p.BlobGasUsed, nil -} - -func (e executionPayloadElectra) ExcessBlobGas() (uint64, error) { - return e.p.ExcessBlobGas, nil -} - -// DepositRequests -- -func (e executionPayloadElectra) DepositRequests() []*enginev1.DepositRequest { - return e.p.DepositRequests -} - -// WithdrawalRequests -- -func (e executionPayloadElectra) WithdrawalRequests() []*enginev1.WithdrawalRequest { - return e.p.WithdrawalRequests -} - -// ConsolidationRequests -- -func (e executionPayloadElectra) ConsolidationRequests() []*enginev1.ConsolidationRequest { - return e.p.ConsolidationRequests -} - -// IsBlinded returns true if the underlying data is blinded. -func (e executionPayloadElectra) IsBlinded() bool { - return false -} diff --git a/consensus-types/blocks/factory.go b/consensus-types/blocks/factory.go index 2de69c0c03be..4ebed3245b35 100644 --- a/consensus-types/blocks/factory.go +++ b/consensus-types/blocks/factory.go @@ -74,6 +74,14 @@ func NewSignedBeaconBlock(i interface{}) (interfaces.SignedBeaconBlock, error) { return initBlindedSignedBlockFromProtoElectra(b) case *eth.GenericSignedBeaconBlock_BlindedElectra: return initBlindedSignedBlockFromProtoElectra(b.BlindedElectra) + case *eth.GenericSignedBeaconBlock_Fulu: + return initSignedBlockFromProtoFulu(b.Fulu.Block) + case *eth.SignedBeaconBlockFulu: + return initSignedBlockFromProtoFulu(b) + case *eth.SignedBlindedBeaconBlockFulu: + return initBlindedSignedBlockFromProtoFulu(b) + case *eth.GenericSignedBeaconBlock_BlindedFulu: + return initBlindedSignedBlockFromProtoFulu(b.BlindedFulu) default: return nil, errors.Wrapf(ErrUnsupportedSignedBeaconBlock, "unable to create block from type %T", i) } @@ -124,6 +132,12 @@ func NewBeaconBlock(i interface{}) (interfaces.ReadOnlyBeaconBlock, error) { return initBlindedBlockFromProtoElectra(b) case *eth.GenericBeaconBlock_BlindedElectra: return initBlindedBlockFromProtoElectra(b.BlindedElectra) + case *eth.GenericBeaconBlock_Fulu: + return initBlockFromProtoFulu(b.Fulu.Block) + case *eth.BlindedBeaconBlockFulu: + return initBlindedBlockFromProtoFulu(b) + case *eth.GenericBeaconBlock_BlindedFulu: + return initBlindedBlockFromProtoFulu(b.BlindedFulu) default: return nil, errors.Wrapf(errUnsupportedBeaconBlock, "unable to create block from type %T", i) } @@ -233,14 +247,68 @@ func BuildSignedBeaconBlock(blk interfaces.ReadOnlyBeaconBlock, signature []byte return nil, errIncorrectBlockVersion } return NewSignedBeaconBlock(ð.SignedBeaconBlockElectra{Block: pb, Signature: signature}) + case version.Fulu: + if blk.IsBlinded() { + pb, ok := pb.(*eth.BlindedBeaconBlockFulu) + if !ok { + return nil, errIncorrectBlockVersion + } + return NewSignedBeaconBlock(ð.SignedBlindedBeaconBlockFulu{Message: pb, Signature: signature}) + } + pb, ok := pb.(*eth.BeaconBlockElectra) + if !ok { + return nil, errIncorrectBlockVersion + } + return NewSignedBeaconBlock(ð.SignedBeaconBlockFulu{Block: pb, Signature: signature}) default: return nil, errUnsupportedBeaconBlock } } +func getWrappedPayload(payload interface{}) (wrappedPayload interfaces.ExecutionData, wrapErr error) { + switch p := payload.(type) { + case *enginev1.ExecutionPayload: + wrappedPayload, wrapErr = WrappedExecutionPayload(p) + case *enginev1.ExecutionPayloadCapella: + wrappedPayload, wrapErr = WrappedExecutionPayloadCapella(p) + case *enginev1.ExecutionPayloadDeneb: + wrappedPayload, wrapErr = WrappedExecutionPayloadDeneb(p) + default: + wrappedPayload, wrapErr = nil, fmt.Errorf("%T is not a type of execution payload", p) + } + return wrappedPayload, wrapErr +} + +func checkPayloadAgainstHeader(wrappedPayload, payloadHeader interfaces.ExecutionData) error { + empty, err := IsEmptyExecutionData(wrappedPayload) + if err != nil { + return err + } + if empty { + return nil + } + payloadRoot, err := wrappedPayload.HashTreeRoot() + if err != nil { + return errors.Wrap(err, "could not hash tree root execution payload") + } + payloadHeaderRoot, err := payloadHeader.HashTreeRoot() + if err != nil { + return errors.Wrap(err, "could not hash tree root payload header") + } + if payloadRoot != payloadHeaderRoot { + return fmt.Errorf( + "payload %#x and header %#x roots do not match", + payloadRoot, + payloadHeaderRoot, + ) + } + return nil +} + // BuildSignedBeaconBlockFromExecutionPayload takes a signed, blinded beacon block and converts into // a full, signed beacon block by specifying an execution payload. -func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBeaconBlock, payload interface{}) (interfaces.SignedBeaconBlock, error) { // nolint:gocognit +// nolint:gocognit +func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBeaconBlock, payload interface{}) (interfaces.SignedBeaconBlock, error) { if err := BeaconBlockIsNil(blk); err != nil { return nil, err } @@ -253,43 +321,12 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea return nil, errors.Wrap(err, "could not get execution payload header") } - var wrappedPayload interfaces.ExecutionData - var wrapErr error - switch p := payload.(type) { - case *enginev1.ExecutionPayload: - wrappedPayload, wrapErr = WrappedExecutionPayload(p) - case *enginev1.ExecutionPayloadCapella: - wrappedPayload, wrapErr = WrappedExecutionPayloadCapella(p) - case *enginev1.ExecutionPayloadDeneb: - wrappedPayload, wrapErr = WrappedExecutionPayloadDeneb(p) - case *enginev1.ExecutionPayloadElectra: - wrappedPayload, wrapErr = WrappedExecutionPayloadElectra(p) - default: - return nil, fmt.Errorf("%T is not a type of execution payload", p) - } - if wrapErr != nil { - return nil, wrapErr - } - empty, err := IsEmptyExecutionData(wrappedPayload) + wrappedPayload, err := getWrappedPayload(payload) if err != nil { return nil, err } - if !empty { - payloadRoot, err := wrappedPayload.HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "could not hash tree root execution payload") - } - payloadHeaderRoot, err := payloadHeader.HashTreeRoot() - if err != nil { - return nil, errors.Wrap(err, "could not hash tree root payload header") - } - if payloadRoot != payloadHeaderRoot { - return nil, fmt.Errorf( - "payload %#x and header %#x roots do not match", - payloadRoot, - payloadHeaderRoot, - ) - } + if err := checkPayloadAgainstHeader(wrappedPayload, payloadHeader); err != nil { + return nil, err } syncAgg, err := b.Body().SyncAggregate() if err != nil { @@ -302,8 +339,12 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea sig := blk.Signature() var fullBlock interface{} - switch p := payload.(type) { - case *enginev1.ExecutionPayload: + switch blk.Version() { + case version.Bellatrix: + p, ok := payload.(*enginev1.ExecutionPayload) + if !ok { + return nil, fmt.Errorf("payload has wrong type (expected %T, got %T)", &enginev1.ExecutionPayload{}, payload) + } var atts []*eth.Attestation if b.Body().Attestations() != nil { atts = make([]*eth.Attestation, len(b.Body().Attestations())) @@ -347,7 +388,11 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea }, Signature: sig[:], } - case *enginev1.ExecutionPayloadCapella: + case version.Capella: + p, ok := payload.(*enginev1.ExecutionPayloadCapella) + if !ok { + return nil, fmt.Errorf("payload has wrong type (expected %T, got %T)", &enginev1.ExecutionPayloadCapella{}, payload) + } blsToExecutionChanges, err := b.Body().BLSToExecutionChanges() if err != nil { return nil, err @@ -396,7 +441,11 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea }, Signature: sig[:], } - case *enginev1.ExecutionPayloadDeneb: + case version.Deneb: + p, ok := payload.(*enginev1.ExecutionPayloadDeneb) + if !ok { + return nil, fmt.Errorf("payload has wrong type (expected %T, got %T)", &enginev1.ExecutionPayloadDeneb{}, payload) + } blsToExecutionChanges, err := b.Body().BLSToExecutionChanges() if err != nil { return nil, err @@ -450,7 +499,76 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea }, Signature: sig[:], } - case *enginev1.ExecutionPayloadElectra: + case version.Electra: + p, ok := payload.(*enginev1.ExecutionPayloadDeneb) + if !ok { + return nil, fmt.Errorf("payload has wrong type (expected %T, got %T)", &enginev1.ExecutionPayloadDeneb{}, payload) + } + blsToExecutionChanges, err := b.Body().BLSToExecutionChanges() + if err != nil { + return nil, err + } + commitments, err := b.Body().BlobKzgCommitments() + if err != nil { + return nil, err + } + var atts []*eth.AttestationElectra + if b.Body().Attestations() != nil { + atts = make([]*eth.AttestationElectra, len(b.Body().Attestations())) + for i, att := range b.Body().Attestations() { + a, ok := att.(*eth.AttestationElectra) + if !ok { + return nil, fmt.Errorf("attestation has wrong type (expected %T, got %T)", ð.AttestationElectra{}, att) + } + atts[i] = a + } + } + var attSlashings []*eth.AttesterSlashingElectra + if b.Body().AttesterSlashings() != nil { + attSlashings = make([]*eth.AttesterSlashingElectra, len(b.Body().AttesterSlashings())) + for i, slashing := range b.Body().AttesterSlashings() { + s, ok := slashing.(*eth.AttesterSlashingElectra) + if !ok { + return nil, fmt.Errorf("attester slashing has wrong type (expected %T, got %T)", ð.AttesterSlashingElectra{}, slashing) + } + attSlashings[i] = s + } + } + + er, err := b.Body().ExecutionRequests() + if err != nil { + return nil, err + } + + fullBlock = ð.SignedBeaconBlockElectra{ + Block: ð.BeaconBlockElectra{ + Slot: b.Slot(), + ProposerIndex: b.ProposerIndex(), + ParentRoot: parentRoot[:], + StateRoot: stateRoot[:], + Body: ð.BeaconBlockBodyElectra{ + RandaoReveal: randaoReveal[:], + Eth1Data: b.Body().Eth1Data(), + Graffiti: graffiti[:], + ProposerSlashings: b.Body().ProposerSlashings(), + AttesterSlashings: attSlashings, + Attestations: atts, + Deposits: b.Body().Deposits(), + VoluntaryExits: b.Body().VoluntaryExits(), + SyncAggregate: syncAgg, + ExecutionPayload: p, + BlsToExecutionChanges: blsToExecutionChanges, + BlobKzgCommitments: commitments, + ExecutionRequests: er, + }, + }, + Signature: sig[:], + } + case version.Fulu: + p, ok := payload.(*enginev1.ExecutionPayloadDeneb) + if !ok { + return nil, fmt.Errorf("payload has wrong type (expected %T, got %T)", &enginev1.ExecutionPayloadDeneb{}, payload) + } blsToExecutionChanges, err := b.Body().BLSToExecutionChanges() if err != nil { return nil, err @@ -481,7 +599,13 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea attSlashings[i] = s } } - fullBlock = ð.SignedBeaconBlockElectra{ + + er, err := b.Body().ExecutionRequests() + if err != nil { + return nil, err + } + + fullBlock = ð.SignedBeaconBlockFulu{ Block: ð.BeaconBlockElectra{ Slot: b.Slot(), ProposerIndex: b.ProposerIndex(), @@ -500,12 +624,13 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea ExecutionPayload: p, BlsToExecutionChanges: blsToExecutionChanges, BlobKzgCommitments: commitments, + ExecutionRequests: er, }, }, Signature: sig[:], } default: - return nil, fmt.Errorf("%T is not a type of execution payload", p) + return nil, errors.New("Block not of known type") } return NewSignedBeaconBlock(fullBlock) @@ -515,6 +640,10 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea // This is particularly useful for using the values from API calls. func BeaconBlockContainerToSignedBeaconBlock(obj *eth.BeaconBlockContainer) (interfaces.ReadOnlySignedBeaconBlock, error) { switch obj.Block.(type) { + case *eth.BeaconBlockContainer_BlindedElectraBlock: + return NewSignedBeaconBlock(obj.GetBlindedElectraBlock()) + case *eth.BeaconBlockContainer_ElectraBlock: + return NewSignedBeaconBlock(obj.GetElectraBlock()) case *eth.BeaconBlockContainer_BlindedDenebBlock: return NewSignedBeaconBlock(obj.GetBlindedDenebBlock()) case *eth.BeaconBlockContainer_DenebBlock: diff --git a/consensus-types/blocks/get_payload.go b/consensus-types/blocks/get_payload.go index c12e84a3acd0..9ee52ccfc7e9 100644 --- a/consensus-types/blocks/get_payload.go +++ b/consensus-types/blocks/get_payload.go @@ -14,7 +14,8 @@ type GetPayloadResponse struct { BlobsBundle *pb.BlobsBundle OverrideBuilder bool // todo: should we convert this to Gwei up front? - Bid primitives.Wei + Bid primitives.Wei + ExecutionRequests *pb.ExecutionRequests } // bundleGetter is an interface satisfied by get payload responses that have a blobs bundle. @@ -31,6 +32,10 @@ type shouldOverrideBuilderGetter interface { GetShouldOverrideBuilder() bool } +type executionRequestsGetter interface { + GetDecodedExecutionRequests() (*pb.ExecutionRequests, error) +} + func NewGetPayloadResponse(msg proto.Message) (*GetPayloadResponse, error) { r := &GetPayloadResponse{} bundleGetter, hasBundle := msg.(bundleGetter) @@ -38,6 +43,7 @@ func NewGetPayloadResponse(msg proto.Message) (*GetPayloadResponse, error) { r.BlobsBundle = bundleGetter.GetBlobsBundle() } bidValueGetter, hasBid := msg.(bidValueGetter) + executionRequestsGetter, hasExecutionRequests := msg.(executionRequestsGetter) wei := primitives.ZeroWei() if hasBid { // The protobuf types that engine api responses unmarshal into store their values in little endian form. @@ -56,5 +62,12 @@ func NewGetPayloadResponse(msg proto.Message) (*GetPayloadResponse, error) { return nil, err } r.ExecutionData = ed + if hasExecutionRequests { + requests, err := executionRequestsGetter.GetDecodedExecutionRequests() + if err != nil { + return nil, err + } + r.ExecutionRequests = requests + } return r, nil } diff --git a/consensus-types/blocks/getters.go b/consensus-types/blocks/getters.go index 410e53317d6b..6d4a728c0913 100644 --- a/consensus-types/blocks/getters.go +++ b/consensus-types/blocks/getters.go @@ -75,6 +75,11 @@ func (b *SignedBeaconBlock) Copy() (interfaces.SignedBeaconBlock, error) { return initBlindedSignedBlockFromProtoElectra(pb.(*eth.SignedBlindedBeaconBlockElectra).Copy()) } return initSignedBlockFromProtoElectra(pb.(*eth.SignedBeaconBlockElectra).Copy()) + case version.Fulu: + if b.IsBlinded() { + return initBlindedSignedBlockFromProtoFulu(pb.(*eth.SignedBlindedBeaconBlockFulu).Copy()) + } + return initSignedBlockFromProtoFulu(pb.(*eth.SignedBeaconBlockFulu).Copy()) default: return nil, errIncorrectBlockVersion } @@ -119,8 +124,12 @@ func (b *SignedBeaconBlock) PbGenericBlock() (*eth.GenericSignedBeaconBlock, err Block: ð.GenericSignedBeaconBlock_BlindedDeneb{BlindedDeneb: pb.(*eth.SignedBlindedBeaconBlockDeneb)}, }, nil } + bc, ok := pb.(*eth.SignedBeaconBlockContentsDeneb) + if !ok { + return nil, fmt.Errorf("PbGenericBlock() only supports block content type but got %T", pb) + } return ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Deneb{Deneb: pb.(*eth.SignedBeaconBlockContentsDeneb)}, + Block: ð.GenericSignedBeaconBlock_Deneb{Deneb: bc}, }, nil case version.Electra: if b.IsBlinded() { @@ -128,8 +137,25 @@ func (b *SignedBeaconBlock) PbGenericBlock() (*eth.GenericSignedBeaconBlock, err Block: ð.GenericSignedBeaconBlock_BlindedElectra{BlindedElectra: pb.(*eth.SignedBlindedBeaconBlockElectra)}, }, nil } + bc, ok := pb.(*eth.SignedBeaconBlockContentsElectra) + if !ok { + return nil, fmt.Errorf("PbGenericBlock() only supports block content type but got %T", pb) + } + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_Electra{Electra: bc}, + }, nil + case version.Fulu: + if b.IsBlinded() { + return ð.GenericSignedBeaconBlock{ + Block: ð.GenericSignedBeaconBlock_BlindedFulu{BlindedFulu: pb.(*eth.SignedBlindedBeaconBlockFulu)}, + }, nil + } + bc, ok := pb.(*eth.SignedBeaconBlockContentsFulu) + if !ok { + return nil, fmt.Errorf("PbGenericBlock() only supports block content type but got %T", pb) + } return ð.GenericSignedBeaconBlock{ - Block: ð.GenericSignedBeaconBlock_Electra{Electra: pb.(*eth.SignedBeaconBlockContentsElectra)}, + Block: ð.GenericSignedBeaconBlock_Fulu{Fulu: bc}, }, nil default: return nil, errIncorrectBlockVersion @@ -152,11 +178,84 @@ func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, e return nil, err } + if b.version >= version.Fulu { + p, ok := payload.Proto().(*enginev1.ExecutionPayloadDeneb) + if !ok { + return nil, fmt.Errorf("%T is not an execution payload header of Deneb version", p) + } + header, err := PayloadToHeaderFulu(payload) + if err != nil { + return nil, errors.Wrap(err, "payload to header fulu") + } + + return initBlindedSignedBlockFromProtoFulu( + ð.SignedBlindedBeaconBlockFulu{ + Message: ð.BlindedBeaconBlockFulu{ + Slot: b.block.slot, + ProposerIndex: b.block.proposerIndex, + ParentRoot: b.block.parentRoot[:], + StateRoot: b.block.stateRoot[:], + Body: ð.BlindedBeaconBlockBodyElectra{ + RandaoReveal: b.block.body.randaoReveal[:], + Eth1Data: b.block.body.eth1Data, + Graffiti: b.block.body.graffiti[:], + ProposerSlashings: b.block.body.proposerSlashings, + AttesterSlashings: b.block.body.attesterSlashingsElectra, + Attestations: b.block.body.attestationsElectra, + Deposits: b.block.body.deposits, + VoluntaryExits: b.block.body.voluntaryExits, + SyncAggregate: b.block.body.syncAggregate, + ExecutionPayloadHeader: header, + BlsToExecutionChanges: b.block.body.blsToExecutionChanges, + BlobKzgCommitments: b.block.body.blobKzgCommitments, + ExecutionRequests: b.block.body.executionRequests, + }, + }, + Signature: b.signature[:], + }) + } + + if b.version >= version.Electra { + p, ok := payload.Proto().(*enginev1.ExecutionPayloadDeneb) + if !ok { + return nil, fmt.Errorf("%T is not an execution payload header of Deneb version", p) + } + header, err := PayloadToHeaderElectra(payload) + if err != nil { + return nil, errors.Wrap(err, "payload to header electra") + } + return initBlindedSignedBlockFromProtoElectra( + ð.SignedBlindedBeaconBlockElectra{ + Message: ð.BlindedBeaconBlockElectra{ + Slot: b.block.slot, + ProposerIndex: b.block.proposerIndex, + ParentRoot: b.block.parentRoot[:], + StateRoot: b.block.stateRoot[:], + Body: ð.BlindedBeaconBlockBodyElectra{ + RandaoReveal: b.block.body.randaoReveal[:], + Eth1Data: b.block.body.eth1Data, + Graffiti: b.block.body.graffiti[:], + ProposerSlashings: b.block.body.proposerSlashings, + AttesterSlashings: b.block.body.attesterSlashingsElectra, + Attestations: b.block.body.attestationsElectra, + Deposits: b.block.body.deposits, + VoluntaryExits: b.block.body.voluntaryExits, + SyncAggregate: b.block.body.syncAggregate, + ExecutionPayloadHeader: header, + BlsToExecutionChanges: b.block.body.blsToExecutionChanges, + BlobKzgCommitments: b.block.body.blobKzgCommitments, + ExecutionRequests: b.block.body.executionRequests, + }, + }, + Signature: b.signature[:], + }) + } + switch p := payload.Proto().(type) { case *enginev1.ExecutionPayload: header, err := PayloadToHeader(payload) if err != nil { - return nil, err + return nil, errors.Wrap(err, "payload to header") } return initBlindedSignedBlockFromProtoBellatrix( ð.SignedBlindedBeaconBlockBellatrix{ @@ -211,7 +310,7 @@ func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, e case *enginev1.ExecutionPayloadDeneb: header, err := PayloadToHeaderDeneb(payload) if err != nil { - return nil, err + return nil, errors.Wrap(err, "payload to header deneb") } return initBlindedSignedBlockFromProtoDeneb( ð.SignedBlindedBeaconBlockDeneb{ @@ -237,46 +336,13 @@ func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, e }, Signature: b.signature[:], }) - case *enginev1.ExecutionPayloadElectra: - pe, ok := payload.(interfaces.ExecutionDataElectra) - if !ok { - return nil, interfaces.ErrIncompatibleFork - } - header, err := PayloadToHeaderElectra(pe) - if err != nil { - return nil, err - } - return initBlindedSignedBlockFromProtoElectra( - ð.SignedBlindedBeaconBlockElectra{ - Message: ð.BlindedBeaconBlockElectra{ - Slot: b.block.slot, - ProposerIndex: b.block.proposerIndex, - ParentRoot: b.block.parentRoot[:], - StateRoot: b.block.stateRoot[:], - Body: ð.BlindedBeaconBlockBodyElectra{ - RandaoReveal: b.block.body.randaoReveal[:], - Eth1Data: b.block.body.eth1Data, - Graffiti: b.block.body.graffiti[:], - ProposerSlashings: b.block.body.proposerSlashings, - AttesterSlashings: b.block.body.attesterSlashingsElectra, - Attestations: b.block.body.attestationsElectra, - Deposits: b.block.body.deposits, - VoluntaryExits: b.block.body.voluntaryExits, - SyncAggregate: b.block.body.syncAggregate, - ExecutionPayloadHeader: header, - BlsToExecutionChanges: b.block.body.blsToExecutionChanges, - BlobKzgCommitments: b.block.body.blobKzgCommitments, - }, - }, - Signature: b.signature[:], - }) default: return nil, fmt.Errorf("%T is not an execution payload header", p) } } func (b *SignedBeaconBlock) Unblind(e interfaces.ExecutionData) error { - if e.IsNil() { + if e == nil || e.IsNil() { return errors.New("cannot unblind with nil execution data") } if !b.IsBlinded() { @@ -366,6 +432,11 @@ func (b *SignedBeaconBlock) MarshalSSZ() ([]byte, error) { return pb.(*eth.SignedBlindedBeaconBlockElectra).MarshalSSZ() } return pb.(*eth.SignedBeaconBlockElectra).MarshalSSZ() + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.SignedBlindedBeaconBlockFulu).MarshalSSZ() + } + return pb.(*eth.SignedBeaconBlockFulu).MarshalSSZ() default: return []byte{}, errIncorrectBlockVersion } @@ -403,6 +474,11 @@ func (b *SignedBeaconBlock) MarshalSSZTo(dst []byte) ([]byte, error) { return pb.(*eth.SignedBlindedBeaconBlockElectra).MarshalSSZTo(dst) } return pb.(*eth.SignedBeaconBlockElectra).MarshalSSZTo(dst) + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.SignedBlindedBeaconBlockFulu).MarshalSSZTo(dst) + } + return pb.(*eth.SignedBeaconBlockFulu).MarshalSSZTo(dst) default: return []byte{}, errIncorrectBlockVersion } @@ -444,12 +520,18 @@ func (b *SignedBeaconBlock) SizeSSZ() int { return pb.(*eth.SignedBlindedBeaconBlockElectra).SizeSSZ() } return pb.(*eth.SignedBeaconBlockElectra).SizeSSZ() + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.SignedBlindedBeaconBlockFulu).SizeSSZ() + } + return pb.(*eth.SignedBeaconBlockFulu).SizeSSZ() default: panic(incorrectBlockVersion) } } // UnmarshalSSZ unmarshals the signed beacon block from its relevant ssz form. +// nolint:gocognit func (b *SignedBeaconBlock) UnmarshalSSZ(buf []byte) error { var newBlock *SignedBeaconBlock switch b.version { @@ -561,6 +643,28 @@ func (b *SignedBeaconBlock) UnmarshalSSZ(buf []byte) error { return err } } + case version.Fulu: + if b.IsBlinded() { + pb := ð.SignedBlindedBeaconBlockFulu{} + if err := pb.UnmarshalSSZ(buf); err != nil { + return err + } + var err error + newBlock, err = initBlindedSignedBlockFromProtoFulu(pb) + if err != nil { + return err + } + } else { + pb := ð.SignedBeaconBlockFulu{} + if err := pb.UnmarshalSSZ(buf); err != nil { + return err + } + var err error + newBlock, err = initSignedBlockFromProtoFulu(pb) + if err != nil { + return err + } + } default: return errIncorrectBlockVersion } @@ -639,6 +743,11 @@ func (b *BeaconBlock) HashTreeRoot() ([field_params.RootLength]byte, error) { return pb.(*eth.BlindedBeaconBlockElectra).HashTreeRoot() } return pb.(*eth.BeaconBlockElectra).HashTreeRoot() + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.BlindedBeaconBlockFulu).HashTreeRoot() + } + return pb.(*eth.BeaconBlockElectra).HashTreeRoot() default: return [field_params.RootLength]byte{}, errIncorrectBlockVersion } @@ -675,6 +784,11 @@ func (b *BeaconBlock) HashTreeRootWith(h *ssz.Hasher) error { return pb.(*eth.BlindedBeaconBlockElectra).HashTreeRootWith(h) } return pb.(*eth.BeaconBlockElectra).HashTreeRootWith(h) + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.BlindedBeaconBlockFulu).HashTreeRootWith(h) + } + return pb.(*eth.BeaconBlockElectra).HashTreeRootWith(h) default: return errIncorrectBlockVersion } @@ -712,6 +826,11 @@ func (b *BeaconBlock) MarshalSSZ() ([]byte, error) { return pb.(*eth.BlindedBeaconBlockElectra).MarshalSSZ() } return pb.(*eth.BeaconBlockElectra).MarshalSSZ() + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.BlindedBeaconBlockFulu).MarshalSSZ() + } + return pb.(*eth.BeaconBlockElectra).MarshalSSZ() default: return []byte{}, errIncorrectBlockVersion } @@ -749,6 +868,11 @@ func (b *BeaconBlock) MarshalSSZTo(dst []byte) ([]byte, error) { return pb.(*eth.BlindedBeaconBlockElectra).MarshalSSZTo(dst) } return pb.(*eth.BeaconBlockElectra).MarshalSSZTo(dst) + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.BlindedBeaconBlockFulu).MarshalSSZTo(dst) + } + return pb.(*eth.BeaconBlockElectra).MarshalSSZTo(dst) default: return []byte{}, errIncorrectBlockVersion } @@ -790,12 +914,18 @@ func (b *BeaconBlock) SizeSSZ() int { return pb.(*eth.BlindedBeaconBlockElectra).SizeSSZ() } return pb.(*eth.BeaconBlockElectra).SizeSSZ() + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.BlindedBeaconBlockFulu).SizeSSZ() + } + return pb.(*eth.BeaconBlockElectra).SizeSSZ() default: panic(incorrectBodyVersion) } } // UnmarshalSSZ unmarshals the beacon block from its relevant ssz form. +// nolint:gocognit func (b *BeaconBlock) UnmarshalSSZ(buf []byte) error { var newBlock *BeaconBlock switch b.version { @@ -907,6 +1037,28 @@ func (b *BeaconBlock) UnmarshalSSZ(buf []byte) error { return err } } + case version.Fulu: + if b.IsBlinded() { + pb := ð.BlindedBeaconBlockFulu{} + if err := pb.UnmarshalSSZ(buf); err != nil { + return err + } + var err error + newBlock, err = initBlindedBlockFromProtoFulu(pb) + if err != nil { + return err + } + } else { + pb := ð.BeaconBlockElectra{} + if err := pb.UnmarshalSSZ(buf); err != nil { + return err + } + var err error + newBlock, err = initBlockFromProtoFulu(pb) + if err != nil { + return err + } + } default: return errIncorrectBlockVersion } @@ -945,45 +1097,11 @@ func (b *BeaconBlock) AsSignRequestObject() (validatorpb.SignRequestObject, erro return &validatorpb.SignRequest_BlindedBlockElectra{BlindedBlockElectra: pb.(*eth.BlindedBeaconBlockElectra)}, nil } return &validatorpb.SignRequest_BlockElectra{BlockElectra: pb.(*eth.BeaconBlockElectra)}, nil - default: - return nil, errIncorrectBlockVersion - } -} - -func (b *BeaconBlock) Copy() (interfaces.ReadOnlyBeaconBlock, error) { - if b == nil { - return nil, nil - } - - pb, err := b.Proto() - if err != nil { - return nil, err - } - switch b.version { - case version.Phase0: - return initBlockFromProtoPhase0(pb.(*eth.BeaconBlock).Copy()) - case version.Altair: - return initBlockFromProtoAltair(pb.(*eth.BeaconBlockAltair).Copy()) - case version.Bellatrix: + case version.Fulu: if b.IsBlinded() { - return initBlindedBlockFromProtoBellatrix(pb.(*eth.BlindedBeaconBlockBellatrix).Copy()) + return &validatorpb.SignRequest_BlindedBlockFulu{BlindedBlockFulu: pb.(*eth.BlindedBeaconBlockFulu)}, nil } - return initBlockFromProtoBellatrix(pb.(*eth.BeaconBlockBellatrix).Copy()) - case version.Capella: - if b.IsBlinded() { - return initBlindedBlockFromProtoCapella(pb.(*eth.BlindedBeaconBlockCapella).Copy()) - } - return initBlockFromProtoCapella(pb.(*eth.BeaconBlockCapella).Copy()) - case version.Deneb: - if b.IsBlinded() { - return initBlindedBlockFromProtoDeneb(pb.(*eth.BlindedBeaconBlockDeneb).Copy()) - } - return initBlockFromProtoDeneb(pb.(*eth.BeaconBlockDeneb).Copy()) - case version.Electra: - if b.IsBlinded() { - return initBlindedBlockFromProtoElectra(pb.(*eth.BlindedBeaconBlockElectra).Copy()) - } - return initBlockFromProtoElectra(pb.(*eth.BeaconBlockElectra).Copy()) + return &validatorpb.SignRequest_BlockFulu{BlockFulu: pb.(*eth.BeaconBlockElectra)}, nil default: return nil, errIncorrectBlockVersion } @@ -1100,14 +1218,23 @@ func (b *BeaconBlockBody) BLSToExecutionChanges() ([]*eth.SignedBLSToExecutionCh // BlobKzgCommitments returns the blob kzg commitments in the block. func (b *BeaconBlockBody) BlobKzgCommitments() ([][]byte, error) { - switch b.version { - case version.Phase0, version.Altair, version.Bellatrix, version.Capella: - return nil, consensus_types.ErrNotSupported("BlobKzgCommitments", b.version) - case version.Deneb, version.Electra: + if b.version >= version.Deneb { return b.blobKzgCommitments, nil - default: - return nil, errIncorrectBlockVersion } + + if b.version >= version.Phase0 { + return nil, consensus_types.ErrNotSupported("BlobKzgCommitments", b.version) + } + + return nil, errIncorrectBlockVersion +} + +// ExecutionRequests returns the execution requests +func (b *BeaconBlockBody) ExecutionRequests() (*enginev1.ExecutionRequests, error) { + if b.version < version.Electra { + return nil, consensus_types.ErrNotSupported("ExecutionRequests", b.version) + } + return b.executionRequests, nil } // Version returns the version of the beacon block body @@ -1146,6 +1273,11 @@ func (b *BeaconBlockBody) HashTreeRoot() ([field_params.RootLength]byte, error) return pb.(*eth.BlindedBeaconBlockBodyElectra).HashTreeRoot() } return pb.(*eth.BeaconBlockBodyElectra).HashTreeRoot() + case version.Fulu: + if b.IsBlinded() { + return pb.(*eth.BlindedBeaconBlockBodyElectra).HashTreeRoot() + } + return pb.(*eth.BeaconBlockBodyElectra).HashTreeRoot() default: return [field_params.RootLength]byte{}, errIncorrectBodyVersion } diff --git a/consensus-types/blocks/getters_test.go b/consensus-types/blocks/getters_test.go index 826db3bc13e6..147f09b50cb7 100644 --- a/consensus-types/blocks/getters_test.go +++ b/consensus-types/blocks/getters_test.go @@ -169,70 +169,6 @@ func Test_BeaconBlock_Body(t *testing.T) { assert.Equal(t, bb, b.Body()) } -func Test_BeaconBlock_Copy(t *testing.T) { - bb := &BeaconBlockBody{randaoReveal: bytesutil.ToBytes96([]byte{246}), graffiti: bytesutil.ToBytes32([]byte("graffiti"))} - b := &BeaconBlock{body: bb, slot: 123, proposerIndex: 456, parentRoot: bytesutil.ToBytes32([]byte("parentroot")), stateRoot: bytesutil.ToBytes32([]byte("stateroot"))} - cp, err := b.Copy() - require.NoError(t, err) - assert.NotEqual(t, cp, b) - assert.NotEqual(t, cp.Body(), bb) - - b.version = version.Altair - b.body.version = b.version - cp, err = b.Copy() - require.NoError(t, err) - assert.NotEqual(t, cp, b) - assert.NotEqual(t, cp.Body(), bb) - - b.version = version.Bellatrix - b.body.version = b.version - cp, err = b.Copy() - require.NoError(t, err) - assert.NotEqual(t, cp, b) - assert.NotEqual(t, cp.Body(), bb) - - b.version = version.Capella - b.body.version = b.version - cp, err = b.Copy() - require.NoError(t, err) - assert.NotEqual(t, cp, b) - assert.NotEqual(t, cp.Body(), bb) - - b.version = version.Bellatrix - b.body.version = b.version - cp, err = b.Copy() - require.NoError(t, err) - assert.NotEqual(t, cp, b) - assert.NotEqual(t, cp.Body(), bb) - - b.version = version.Capella - b.body.version = b.version - cp, err = b.Copy() - require.NoError(t, err) - assert.NotEqual(t, cp, b) - assert.NotEqual(t, cp.Body(), bb) - - payload := &pb.ExecutionPayloadDeneb{ExcessBlobGas: 123} - header := &pb.ExecutionPayloadHeaderDeneb{ExcessBlobGas: 223} - payloadInterface, err := WrappedExecutionPayloadDeneb(payload) - require.NoError(t, err) - headerInterface, err := WrappedExecutionPayloadHeaderDeneb(header) - require.NoError(t, err) - bb = &BeaconBlockBody{executionPayload: payloadInterface, executionPayloadHeader: headerInterface, randaoReveal: bytesutil.ToBytes96([]byte{246}), graffiti: bytesutil.ToBytes32([]byte("graffiti"))} - b = &BeaconBlock{body: bb, slot: 123, proposerIndex: 456, parentRoot: bytesutil.ToBytes32([]byte("parentroot")), stateRoot: bytesutil.ToBytes32([]byte("stateroot"))} - b.version = version.Deneb - b.body.version = b.version - cp, err = b.Copy() - require.NoError(t, err) - assert.NotEqual(t, cp, b) - assert.NotEqual(t, cp.Body(), bb) - e, err := cp.Body().Execution() - require.NoError(t, err) - gas, err := e.ExcessBlobGas() - require.NoError(t, err) - require.DeepEqual(t, gas, uint64(123)) -} - func Test_BeaconBlock_IsNil(t *testing.T) { t.Run("nil block", func(t *testing.T) { var b *BeaconBlock @@ -503,8 +439,133 @@ func hydrateBeaconBlockBody() *eth.BeaconBlockBody { } } -func TestPreElectraFailsInterfaceAssertion(t *testing.T) { - var epd interfaces.ExecutionData = &executionPayloadDeneb{} - _, ok := epd.(interfaces.ExecutionDataElectra) - require.Equal(t, false, ok) +func hydrateBeaconBlockBodyAltair() *eth.BeaconBlockBodyAltair { + return ð.BeaconBlockBodyAltair{ + RandaoReveal: make([]byte, fieldparams.BLSSignatureLength), + Graffiti: make([]byte, fieldparams.RootLength), + Eth1Data: ð.Eth1Data{ + DepositRoot: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, + SyncAggregate: ð.SyncAggregate{ + SyncCommitteeBits: make([]byte, 64), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + } +} + +func hydrateBeaconBlockBodyBellatrix() *eth.BeaconBlockBodyBellatrix { + return ð.BeaconBlockBodyBellatrix{ + RandaoReveal: make([]byte, fieldparams.BLSSignatureLength), + Graffiti: make([]byte, fieldparams.RootLength), + Eth1Data: ð.Eth1Data{ + DepositRoot: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, + SyncAggregate: ð.SyncAggregate{ + SyncCommitteeBits: make([]byte, 64), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + ExecutionPayload: &pb.ExecutionPayload{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + Transactions: make([][]byte, 0), + }, + } +} + +func hydrateBeaconBlockBodyCapella() *eth.BeaconBlockBodyCapella { + return ð.BeaconBlockBodyCapella{ + RandaoReveal: make([]byte, fieldparams.BLSSignatureLength), + Graffiti: make([]byte, fieldparams.RootLength), + Eth1Data: ð.Eth1Data{ + DepositRoot: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, + SyncAggregate: ð.SyncAggregate{ + SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + ExecutionPayload: &pb.ExecutionPayloadCapella{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + Transactions: make([][]byte, 0), + Withdrawals: make([]*pb.Withdrawal, 0), + }, + } +} + +func hydrateBeaconBlockBodyDeneb() *eth.BeaconBlockBodyDeneb { + return ð.BeaconBlockBodyDeneb{ + RandaoReveal: make([]byte, fieldparams.BLSSignatureLength), + Graffiti: make([]byte, fieldparams.RootLength), + Eth1Data: ð.Eth1Data{ + DepositRoot: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, + SyncAggregate: ð.SyncAggregate{ + SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + ExecutionPayload: &pb.ExecutionPayloadDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + Transactions: make([][]byte, 0), + Withdrawals: make([]*pb.Withdrawal, 0), + }, + } +} + +func hydrateBeaconBlockBodyElectra() *eth.BeaconBlockBodyElectra { + return ð.BeaconBlockBodyElectra{ + RandaoReveal: make([]byte, fieldparams.BLSSignatureLength), + Graffiti: make([]byte, fieldparams.RootLength), + Eth1Data: ð.Eth1Data{ + DepositRoot: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + }, + SyncAggregate: ð.SyncAggregate{ + SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + ExecutionPayload: &pb.ExecutionPayloadDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + Transactions: make([][]byte, 0), + Withdrawals: make([]*pb.Withdrawal, 0), + }, + ExecutionRequests: &pb.ExecutionRequests{ + Deposits: make([]*pb.DepositRequest, 0), + Withdrawals: make([]*pb.WithdrawalRequest, 0), + Consolidations: make([]*pb.ConsolidationRequest, 0), + }, + } } diff --git a/consensus-types/blocks/kzg.go b/consensus-types/blocks/kzg.go index b5e2800bf702..e33d4dd7e034 100644 --- a/consensus-types/blocks/kzg.go +++ b/consensus-types/blocks/kzg.go @@ -12,7 +12,7 @@ import ( ) const ( - bodyLength = 12 // The number of elements in the BeaconBlockBody Container + bodyLength = 13 // The number of elements in the BeaconBlockBody Container for Electra logBodyLength = 4 // The log 2 of bodyLength kzgPosition = 11 // The index of the KZG commitment list in the Body kzgRootIndex = 54 // The Merkle index of the KZG commitment list's root in the Body's Merkle tree @@ -229,5 +229,18 @@ func topLevelRoots(body interfaces.ReadOnlyBeaconBlockBody) ([][]byte, error) { copy(layer[10], root[:]) // KZG commitments is not needed + + // Execution requests + if body.Version() >= version.Electra { + er, err := body.ExecutionRequests() + if err != nil { + return nil, err + } + root, err = er.HashTreeRoot() + if err != nil { + return nil, err + } + copy(layer[12], root[:]) + } return layer, nil } diff --git a/consensus-types/blocks/proofs.go b/consensus-types/blocks/proofs.go new file mode 100644 index 000000000000..c5ffb2a7db52 --- /dev/null +++ b/consensus-types/blocks/proofs.go @@ -0,0 +1,254 @@ +package blocks + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/container/trie" + "github.com/prysmaticlabs/prysm/v5/crypto/hash/htr" + "github.com/prysmaticlabs/prysm/v5/encoding/ssz" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" + "github.com/prysmaticlabs/prysm/v5/runtime/version" +) + +const ( + payloadFieldIndex = 9 + bodyFieldIndex = 4 +) + +func ComputeBlockBodyFieldRoots(ctx context.Context, blockBody *BeaconBlockBody) ([][]byte, error) { + _, span := trace.StartSpan(ctx, "blocks.ComputeBlockBodyFieldRoots") + defer span.End() + + if blockBody == nil { + return nil, errNilBlockBody + } + + var fieldRoots [][]byte + switch blockBody.version { + case version.Phase0: + fieldRoots = make([][]byte, 8) + case version.Altair: + fieldRoots = make([][]byte, 9) + case version.Bellatrix: + fieldRoots = make([][]byte, 10) + case version.Capella: + fieldRoots = make([][]byte, 11) + case version.Deneb: + fieldRoots = make([][]byte, 12) + case version.Electra: + fieldRoots = make([][]byte, 13) + case version.Fulu: + fieldRoots = make([][]byte, 13) + default: + return nil, fmt.Errorf("unknown block body version %s", version.String(blockBody.version)) + } + + for i := range fieldRoots { + fieldRoots[i] = make([]byte, 32) + } + + // Randao Reveal + randao := blockBody.RandaoReveal() + root, err := ssz.MerkleizeByteSliceSSZ(randao[:]) + if err != nil { + return nil, err + } + copy(fieldRoots[0], root[:]) + + // eth1_data + eth1 := blockBody.Eth1Data() + root, err = eth1.HashTreeRoot() + if err != nil { + return nil, err + } + copy(fieldRoots[1], root[:]) + + // graffiti + root = blockBody.Graffiti() + copy(fieldRoots[2], root[:]) + + // Proposer slashings + ps := blockBody.ProposerSlashings() + root, err = ssz.MerkleizeListSSZ(ps, params.BeaconConfig().MaxProposerSlashings) + if err != nil { + return nil, err + } + copy(fieldRoots[3], root[:]) + + // Attester slashings + as := blockBody.AttesterSlashings() + bodyVersion := blockBody.Version() + if bodyVersion < version.Electra { + root, err = ssz.MerkleizeListSSZ(as, params.BeaconConfig().MaxAttesterSlashings) + } else { + root, err = ssz.MerkleizeListSSZ(as, params.BeaconConfig().MaxAttesterSlashingsElectra) + } + if err != nil { + return nil, err + } + copy(fieldRoots[4], root[:]) + + // Attestations + att := blockBody.Attestations() + if bodyVersion < version.Electra { + root, err = ssz.MerkleizeListSSZ(att, params.BeaconConfig().MaxAttestations) + } else { + root, err = ssz.MerkleizeListSSZ(att, params.BeaconConfig().MaxAttestationsElectra) + } + if err != nil { + return nil, err + } + copy(fieldRoots[5], root[:]) + + // Deposits + dep := blockBody.Deposits() + root, err = ssz.MerkleizeListSSZ(dep, params.BeaconConfig().MaxDeposits) + if err != nil { + return nil, err + } + copy(fieldRoots[6], root[:]) + + // Voluntary Exits + ve := blockBody.VoluntaryExits() + root, err = ssz.MerkleizeListSSZ(ve, params.BeaconConfig().MaxVoluntaryExits) + if err != nil { + return nil, err + } + copy(fieldRoots[7], root[:]) + + if blockBody.version >= version.Altair { + // Sync Aggregate + sa, err := blockBody.SyncAggregate() + if err != nil { + return nil, err + } + root, err = sa.HashTreeRoot() + if err != nil { + return nil, err + } + copy(fieldRoots[8], root[:]) + } + + if blockBody.version >= version.Bellatrix { + // Execution Payload + ep, err := blockBody.Execution() + if err != nil { + return nil, err + } + root, err = ep.HashTreeRoot() + if err != nil { + return nil, err + } + copy(fieldRoots[9], root[:]) + } + + if blockBody.version >= version.Capella { + // BLS Changes + bls, err := blockBody.BLSToExecutionChanges() + if err != nil { + return nil, err + } + root, err = ssz.MerkleizeListSSZ(bls, params.BeaconConfig().MaxBlsToExecutionChanges) + if err != nil { + return nil, err + } + copy(fieldRoots[10], root[:]) + } + + if blockBody.version >= version.Deneb { + // KZG commitments + roots := make([][32]byte, len(blockBody.blobKzgCommitments)) + for i, commitment := range blockBody.blobKzgCommitments { + chunks, err := ssz.PackByChunk([][]byte{commitment}) + if err != nil { + return nil, err + } + roots[i] = htr.VectorizedSha256(chunks)[0] + } + commitmentsRoot, err := ssz.BitwiseMerkleize(roots, uint64(len(roots)), 4096) + if err != nil { + return nil, err + } + length := make([]byte, 32) + binary.LittleEndian.PutUint64(length[:8], uint64(len(roots))) + root = ssz.MixInLength(commitmentsRoot, length) + copy(fieldRoots[11], root[:]) + } + + if blockBody.version >= version.Electra { + // Execution Requests + er, err := blockBody.ExecutionRequests() + if err != nil { + return nil, err + } + root, err := er.HashTreeRoot() + if err != nil { + return nil, err + } + copy(fieldRoots[12], root[:]) + } + return fieldRoots, nil +} + +func ComputeBlockFieldRoots(ctx context.Context, block interfaces.ReadOnlyBeaconBlock) ([][]byte, error) { + _, span := trace.StartSpan(ctx, "blocks.ComputeBlockFieldRoots") + defer span.End() + + if block == nil { + return nil, errNilBlock + } + + fieldRoots := make([][]byte, 5) + for i := range fieldRoots { + fieldRoots[i] = make([]byte, 32) + } + + // Slot + slotRoot := ssz.Uint64Root(uint64(block.Slot())) + copy(fieldRoots[0], slotRoot[:]) + + // Proposer Index + proposerRoot := ssz.Uint64Root(uint64(block.ProposerIndex())) + copy(fieldRoots[1], proposerRoot[:]) + + // Parent Root + parentRoot := block.ParentRoot() + copy(fieldRoots[2], parentRoot[:]) + + // State Root + stateRoot := block.StateRoot() + copy(fieldRoots[3], stateRoot[:]) + + // block body Root + blockBodyRoot, err := block.Body().HashTreeRoot() + if err != nil { + return nil, err + } + copy(fieldRoots[4], blockBodyRoot[:]) + + return fieldRoots, nil +} + +func PayloadProof(ctx context.Context, block interfaces.ReadOnlyBeaconBlock) ([][]byte, error) { + i := block.Body() + blockBody, ok := i.(*BeaconBlockBody) + if !ok { + return nil, errors.New("failed to cast block body") + } + + fieldRoots, err := ComputeBlockBodyFieldRoots(ctx, blockBody) + if err != nil { + return nil, err + } + + fieldRootsTrie := stateutil.Merkleize(fieldRoots) + proof := trie.ProofFromMerkleLayers(fieldRootsTrie, payloadFieldIndex) + + return proof, nil +} diff --git a/consensus-types/blocks/proofs_test.go b/consensus-types/blocks/proofs_test.go new file mode 100644 index 000000000000..ad3067024e42 --- /dev/null +++ b/consensus-types/blocks/proofs_test.go @@ -0,0 +1,147 @@ +package blocks + +import ( + "context" + "testing" + + "github.com/prysmaticlabs/prysm/v5/container/trie" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +func TestComputeBlockBodyFieldRoots_Phase0(t *testing.T) { + blockBodyPhase0 := hydrateBeaconBlockBody() + i, err := NewBeaconBlockBody(blockBodyPhase0) + require.NoError(t, err) + + b, ok := i.(*BeaconBlockBody) + require.Equal(t, true, ok) + + fieldRoots, err := ComputeBlockBodyFieldRoots(context.Background(), b) + require.NoError(t, err) + trie, err := trie.GenerateTrieFromItems(fieldRoots, 3) + require.NoError(t, err) + layers := trie.ToProto().GetLayers() + + hash := layers[len(layers)-1].Layer[0] + require.NoError(t, err) + + correctHash, err := b.HashTreeRoot() + require.NoError(t, err) + + require.DeepEqual(t, correctHash[:], hash) +} + +func TestComputeBlockBodyFieldRoots_Altair(t *testing.T) { + blockBodyAltair := hydrateBeaconBlockBodyAltair() + i, err := NewBeaconBlockBody(blockBodyAltair) + require.NoError(t, err) + + b, ok := i.(*BeaconBlockBody) + require.Equal(t, true, ok) + + fieldRoots, err := ComputeBlockBodyFieldRoots(context.Background(), b) + require.NoError(t, err) + trie, err := trie.GenerateTrieFromItems(fieldRoots, 4) + require.NoError(t, err) + layers := trie.ToProto().GetLayers() + + hash := layers[len(layers)-1].Layer[0] + require.NoError(t, err) + + correctHash, err := b.HashTreeRoot() + require.NoError(t, err) + + require.DeepEqual(t, correctHash[:], hash) +} + +func TestComputeBlockBodyFieldRoots_Bellatrix(t *testing.T) { + blockBodyBellatrix := hydrateBeaconBlockBodyBellatrix() + i, err := NewBeaconBlockBody(blockBodyBellatrix) + require.NoError(t, err) + + b, ok := i.(*BeaconBlockBody) + require.Equal(t, true, ok) + + fieldRoots, err := ComputeBlockBodyFieldRoots(context.Background(), b) + require.NoError(t, err) + trie, err := trie.GenerateTrieFromItems(fieldRoots, 4) + require.NoError(t, err) + layers := trie.ToProto().GetLayers() + + hash := layers[len(layers)-1].Layer[0] + require.NoError(t, err) + + correctHash, err := b.HashTreeRoot() + require.NoError(t, err) + + require.DeepEqual(t, correctHash[:], hash) +} + +func TestComputeBlockBodyFieldRoots_Capella(t *testing.T) { + blockBodyCapella := hydrateBeaconBlockBodyCapella() + i, err := NewBeaconBlockBody(blockBodyCapella) + require.NoError(t, err) + + b, ok := i.(*BeaconBlockBody) + require.Equal(t, true, ok) + + fieldRoots, err := ComputeBlockBodyFieldRoots(context.Background(), b) + require.NoError(t, err) + trie, err := trie.GenerateTrieFromItems(fieldRoots, 4) + require.NoError(t, err) + layers := trie.ToProto().GetLayers() + + hash := layers[len(layers)-1].Layer[0] + require.NoError(t, err) + + correctHash, err := b.HashTreeRoot() + require.NoError(t, err) + + require.DeepEqual(t, correctHash[:], hash) +} + +func TestComputeBlockBodyFieldRoots_Deneb(t *testing.T) { + blockBodyDeneb := hydrateBeaconBlockBodyDeneb() + i, err := NewBeaconBlockBody(blockBodyDeneb) + require.NoError(t, err) + + b, ok := i.(*BeaconBlockBody) + require.Equal(t, true, ok) + + fieldRoots, err := ComputeBlockBodyFieldRoots(context.Background(), b) + require.NoError(t, err) + trie, err := trie.GenerateTrieFromItems(fieldRoots, 4) + require.NoError(t, err) + layers := trie.ToProto().GetLayers() + + hash := layers[len(layers)-1].Layer[0] + require.NoError(t, err) + + correctHash, err := b.HashTreeRoot() + require.NoError(t, err) + + require.DeepEqual(t, correctHash[:], hash) +} + +func TestComputeBlockBodyFieldRoots_Electra(t *testing.T) { + blockBodyElectra := hydrateBeaconBlockBodyElectra() + i, err := NewBeaconBlockBody(blockBodyElectra) + require.NoError(t, err) + + b, ok := i.(*BeaconBlockBody) + require.Equal(t, true, ok) + + fieldRoots, err := ComputeBlockBodyFieldRoots(context.Background(), b) + require.NoError(t, err) + trie, err := trie.GenerateTrieFromItems(fieldRoots, 4) + require.NoError(t, err) + layers := trie.ToProto().GetLayers() + + hash := layers[len(layers)-1].Layer[0] + require.NoError(t, err) + + correctHash, err := b.HashTreeRoot() + require.NoError(t, err) + + require.DeepEqual(t, correctHash[:], hash) +} diff --git a/consensus-types/blocks/proto.go b/consensus-types/blocks/proto.go index 4704c08ed4e0..a12234a880df 100644 --- a/consensus-types/blocks/proto.go +++ b/consensus-types/blocks/proto.go @@ -156,6 +156,33 @@ func (b *SignedBeaconBlock) Proto() (proto.Message, error) { // nolint:gocognit Block: block, Signature: b.signature[:], }, nil + case version.Fulu: + if b.IsBlinded() { + var block *eth.BlindedBeaconBlockFulu + if blockMessage != nil { + var ok bool + block, ok = blockMessage.(*eth.BlindedBeaconBlockFulu) + if !ok { + return nil, errIncorrectBlockVersion + } + } + return ð.SignedBlindedBeaconBlockFulu{ + Message: block, + Signature: b.signature[:], + }, nil + } + var block *eth.BeaconBlockElectra + if blockMessage != nil { + var ok bool + block, ok = blockMessage.(*eth.BeaconBlockElectra) + if !ok { + return nil, errIncorrectBlockVersion + } + } + return ð.SignedBeaconBlockFulu{ + Block: block, + Signature: b.signature[:], + }, nil default: return nil, errors.New("unsupported signed beacon block version") } @@ -337,13 +364,46 @@ func (b *BeaconBlock) Proto() (proto.Message, error) { // nolint:gocognit StateRoot: b.stateRoot[:], Body: body, }, nil - + case version.Fulu: + if b.IsBlinded() { + var body *eth.BlindedBeaconBlockBodyElectra + if bodyMessage != nil { + var ok bool + body, ok = bodyMessage.(*eth.BlindedBeaconBlockBodyElectra) + if !ok { + return nil, errIncorrectBodyVersion + } + } + return ð.BlindedBeaconBlockFulu{ + Slot: b.slot, + ProposerIndex: b.proposerIndex, + ParentRoot: b.parentRoot[:], + StateRoot: b.stateRoot[:], + Body: body, + }, nil + } + var body *eth.BeaconBlockBodyElectra + if bodyMessage != nil { + var ok bool + body, ok = bodyMessage.(*eth.BeaconBlockBodyElectra) + if !ok { + return nil, errIncorrectBodyVersion + } + } + return ð.BeaconBlockElectra{ + Slot: b.slot, + ProposerIndex: b.proposerIndex, + ParentRoot: b.parentRoot[:], + StateRoot: b.stateRoot[:], + Body: body, + }, nil default: return nil, errors.New("unsupported beacon block version") } } // Proto converts the beacon block body to a protobuf object. +// nolint:gocognit func (b *BeaconBlockBody) Proto() (proto.Message, error) { if b == nil { return nil, nil @@ -510,10 +570,10 @@ func (b *BeaconBlockBody) Proto() (proto.Message, error) { }, nil case version.Electra: if b.IsBlinded() { - var ph *enginev1.ExecutionPayloadHeaderElectra + var ph *enginev1.ExecutionPayloadHeaderDeneb var ok bool if b.executionPayloadHeader != nil { - ph, ok = b.executionPayloadHeader.Proto().(*enginev1.ExecutionPayloadHeaderElectra) + ph, ok = b.executionPayloadHeader.Proto().(*enginev1.ExecutionPayloadHeaderDeneb) if !ok { return nil, errPayloadHeaderWrongType } @@ -531,12 +591,13 @@ func (b *BeaconBlockBody) Proto() (proto.Message, error) { ExecutionPayloadHeader: ph, BlsToExecutionChanges: b.blsToExecutionChanges, BlobKzgCommitments: b.blobKzgCommitments, + ExecutionRequests: b.executionRequests, }, nil } - var p *enginev1.ExecutionPayloadElectra + var p *enginev1.ExecutionPayloadDeneb var ok bool if b.executionPayload != nil { - p, ok = b.executionPayload.Proto().(*enginev1.ExecutionPayloadElectra) + p, ok = b.executionPayload.Proto().(*enginev1.ExecutionPayloadDeneb) if !ok { return nil, errPayloadWrongType } @@ -554,13 +615,66 @@ func (b *BeaconBlockBody) Proto() (proto.Message, error) { ExecutionPayload: p, BlsToExecutionChanges: b.blsToExecutionChanges, BlobKzgCommitments: b.blobKzgCommitments, + ExecutionRequests: b.executionRequests, + }, nil + case version.Fulu: + if b.IsBlinded() { + var ph *enginev1.ExecutionPayloadHeaderDeneb + var ok bool + if b.executionPayloadHeader != nil { + ph, ok = b.executionPayloadHeader.Proto().(*enginev1.ExecutionPayloadHeaderDeneb) + if !ok { + return nil, errPayloadHeaderWrongType + } + } + return ð.BlindedBeaconBlockBodyElectra{ + RandaoReveal: b.randaoReveal[:], + Eth1Data: b.eth1Data, + Graffiti: b.graffiti[:], + ProposerSlashings: b.proposerSlashings, + AttesterSlashings: b.attesterSlashingsElectra, + Attestations: b.attestationsElectra, + Deposits: b.deposits, + VoluntaryExits: b.voluntaryExits, + SyncAggregate: b.syncAggregate, + ExecutionPayloadHeader: ph, + BlsToExecutionChanges: b.blsToExecutionChanges, + BlobKzgCommitments: b.blobKzgCommitments, + ExecutionRequests: b.executionRequests, + }, nil + } + var p *enginev1.ExecutionPayloadDeneb + var ok bool + if b.executionPayload != nil { + p, ok = b.executionPayload.Proto().(*enginev1.ExecutionPayloadDeneb) + if !ok { + return nil, errPayloadWrongType + } + } + return ð.BeaconBlockBodyElectra{ + RandaoReveal: b.randaoReveal[:], + Eth1Data: b.eth1Data, + Graffiti: b.graffiti[:], + ProposerSlashings: b.proposerSlashings, + AttesterSlashings: b.attesterSlashingsElectra, + Attestations: b.attestationsElectra, + Deposits: b.deposits, + VoluntaryExits: b.voluntaryExits, + SyncAggregate: b.syncAggregate, + ExecutionPayload: p, + BlsToExecutionChanges: b.blsToExecutionChanges, + BlobKzgCommitments: b.blobKzgCommitments, + ExecutionRequests: b.executionRequests, }, nil - default: return nil, errors.New("unsupported beacon block body version") } } +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + func initSignedBlockFromProtoPhase0(pb *eth.SignedBeaconBlock) (*SignedBeaconBlock, error) { if pb == nil { return nil, errNilBlock @@ -578,170 +692,155 @@ func initSignedBlockFromProtoPhase0(pb *eth.SignedBeaconBlock) (*SignedBeaconBlo return b, nil } -func initSignedBlockFromProtoAltair(pb *eth.SignedBeaconBlockAltair) (*SignedBeaconBlock, error) { +func initBlockFromProtoPhase0(pb *eth.BeaconBlock) (*BeaconBlock, error) { if pb == nil { return nil, errNilBlock } - block, err := initBlockFromProtoAltair(pb.Block) + body, err := initBlockBodyFromProtoPhase0(pb.Body) if err != nil { return nil, err } - b := &SignedBeaconBlock{ - version: version.Altair, - block: block, - signature: bytesutil.ToBytes96(pb.Signature), + b := &BeaconBlock{ + version: version.Phase0, + slot: pb.Slot, + proposerIndex: pb.ProposerIndex, + parentRoot: bytesutil.ToBytes32(pb.ParentRoot), + stateRoot: bytesutil.ToBytes32(pb.StateRoot), + body: body, } return b, nil } -func initSignedBlockFromProtoBellatrix(pb *eth.SignedBeaconBlockBellatrix) (*SignedBeaconBlock, error) { +func initBlockBodyFromProtoPhase0(pb *eth.BeaconBlockBody) (*BeaconBlockBody, error) { if pb == nil { - return nil, errNilBlock + return nil, errNilBlockBody } - block, err := initBlockFromProtoBellatrix(pb.Block) - if err != nil { - return nil, err - } - b := &SignedBeaconBlock{ - version: version.Bellatrix, - block: block, - signature: bytesutil.ToBytes96(pb.Signature), + b := &BeaconBlockBody{ + version: version.Phase0, + randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), + eth1Data: pb.Eth1Data, + graffiti: bytesutil.ToBytes32(pb.Graffiti), + proposerSlashings: pb.ProposerSlashings, + attesterSlashings: pb.AttesterSlashings, + attestations: pb.Attestations, + deposits: pb.Deposits, + voluntaryExits: pb.VoluntaryExits, } return b, nil } -func initSignedBlockFromProtoCapella(pb *eth.SignedBeaconBlockCapella) (*SignedBeaconBlock, error) { - if pb == nil { - return nil, errNilBlock - } - - block, err := initBlockFromProtoCapella(pb.Block) - if err != nil { - return nil, err - } - b := &SignedBeaconBlock{ - version: version.Capella, - block: block, - signature: bytesutil.ToBytes96(pb.Signature), - } - return b, nil -} +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- -func initSignedBlockFromProtoDeneb(pb *eth.SignedBeaconBlockDeneb) (*SignedBeaconBlock, error) { +func initSignedBlockFromProtoAltair(pb *eth.SignedBeaconBlockAltair) (*SignedBeaconBlock, error) { if pb == nil { return nil, errNilBlock } - block, err := initBlockFromProtoDeneb(pb.Block) + block, err := initBlockFromProtoAltair(pb.Block) if err != nil { return nil, err } b := &SignedBeaconBlock{ - version: version.Deneb, + version: version.Altair, block: block, signature: bytesutil.ToBytes96(pb.Signature), } return b, nil } -func initSignedBlockFromProtoElectra(pb *eth.SignedBeaconBlockElectra) (*SignedBeaconBlock, error) { +func initBlockFromProtoAltair(pb *eth.BeaconBlockAltair) (*BeaconBlock, error) { if pb == nil { return nil, errNilBlock } - block, err := initBlockFromProtoElectra(pb.Block) + body, err := initBlockBodyFromProtoAltair(pb.Body) if err != nil { return nil, err } - b := &SignedBeaconBlock{ - version: version.Electra, - block: block, - signature: bytesutil.ToBytes96(pb.Signature), + b := &BeaconBlock{ + version: version.Altair, + slot: pb.Slot, + proposerIndex: pb.ProposerIndex, + parentRoot: bytesutil.ToBytes32(pb.ParentRoot), + stateRoot: bytesutil.ToBytes32(pb.StateRoot), + body: body, } return b, nil } -func initBlindedSignedBlockFromProtoBellatrix(pb *eth.SignedBlindedBeaconBlockBellatrix) (*SignedBeaconBlock, error) { +func initBlockBodyFromProtoAltair(pb *eth.BeaconBlockBodyAltair) (*BeaconBlockBody, error) { if pb == nil { - return nil, errNilBlock + return nil, errNilBlockBody } - block, err := initBlindedBlockFromProtoBellatrix(pb.Block) - if err != nil { - return nil, err - } - b := &SignedBeaconBlock{ - version: version.Bellatrix, - block: block, - signature: bytesutil.ToBytes96(pb.Signature), + b := &BeaconBlockBody{ + version: version.Altair, + randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), + eth1Data: pb.Eth1Data, + graffiti: bytesutil.ToBytes32(pb.Graffiti), + proposerSlashings: pb.ProposerSlashings, + attesterSlashings: pb.AttesterSlashings, + attestations: pb.Attestations, + deposits: pb.Deposits, + voluntaryExits: pb.VoluntaryExits, + syncAggregate: pb.SyncAggregate, } return b, nil } -func initBlindedSignedBlockFromProtoCapella(pb *eth.SignedBlindedBeaconBlockCapella) (*SignedBeaconBlock, error) { - if pb == nil { - return nil, errNilBlock - } - - block, err := initBlindedBlockFromProtoCapella(pb.Block) - if err != nil { - return nil, err - } - b := &SignedBeaconBlock{ - version: version.Capella, - block: block, - signature: bytesutil.ToBytes96(pb.Signature), - } - return b, nil -} +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- -func initBlindedSignedBlockFromProtoDeneb(pb *eth.SignedBlindedBeaconBlockDeneb) (*SignedBeaconBlock, error) { +func initSignedBlockFromProtoBellatrix(pb *eth.SignedBeaconBlockBellatrix) (*SignedBeaconBlock, error) { if pb == nil { return nil, errNilBlock } - block, err := initBlindedBlockFromProtoDeneb(pb.Message) + block, err := initBlockFromProtoBellatrix(pb.Block) if err != nil { return nil, err } b := &SignedBeaconBlock{ - version: version.Deneb, + version: version.Bellatrix, block: block, signature: bytesutil.ToBytes96(pb.Signature), } return b, nil } -func initBlindedSignedBlockFromProtoElectra(pb *eth.SignedBlindedBeaconBlockElectra) (*SignedBeaconBlock, error) { +func initBlindedSignedBlockFromProtoBellatrix(pb *eth.SignedBlindedBeaconBlockBellatrix) (*SignedBeaconBlock, error) { if pb == nil { return nil, errNilBlock } - block, err := initBlindedBlockFromProtoElectra(pb.Message) + block, err := initBlindedBlockFromProtoBellatrix(pb.Block) if err != nil { return nil, err } b := &SignedBeaconBlock{ - version: version.Electra, + version: version.Bellatrix, block: block, signature: bytesutil.ToBytes96(pb.Signature), } return b, nil } -func initBlockFromProtoPhase0(pb *eth.BeaconBlock) (*BeaconBlock, error) { +func initBlockFromProtoBellatrix(pb *eth.BeaconBlockBellatrix) (*BeaconBlock, error) { if pb == nil { return nil, errNilBlock } - body, err := initBlockBodyFromProtoPhase0(pb.Body) + body, err := initBlockBodyFromProtoBellatrix(pb.Body) if err != nil { return nil, err } b := &BeaconBlock{ - version: version.Phase0, + version: version.Bellatrix, slot: pb.Slot, proposerIndex: pb.ProposerIndex, parentRoot: bytesutil.ToBytes32(pb.ParentRoot), @@ -751,17 +850,17 @@ func initBlockFromProtoPhase0(pb *eth.BeaconBlock) (*BeaconBlock, error) { return b, nil } -func initBlockFromProtoAltair(pb *eth.BeaconBlockAltair) (*BeaconBlock, error) { +func initBlindedBlockFromProtoBellatrix(pb *eth.BlindedBeaconBlockBellatrix) (*BeaconBlock, error) { if pb == nil { return nil, errNilBlock } - body, err := initBlockBodyFromProtoAltair(pb.Body) + body, err := initBlindedBlockBodyFromProtoBellatrix(pb.Body) if err != nil { return nil, err } b := &BeaconBlock{ - version: version.Altair, + version: version.Bellatrix, slot: pb.Slot, proposerIndex: pb.ProposerIndex, parentRoot: bytesutil.ToBytes32(pb.ParentRoot), @@ -771,97 +870,107 @@ func initBlockFromProtoAltair(pb *eth.BeaconBlockAltair) (*BeaconBlock, error) { return b, nil } -func initBlockFromProtoBellatrix(pb *eth.BeaconBlockBellatrix) (*BeaconBlock, error) { +func initBlockBodyFromProtoBellatrix(pb *eth.BeaconBlockBodyBellatrix) (*BeaconBlockBody, error) { if pb == nil { - return nil, errNilBlock + return nil, errNilBlockBody } - body, err := initBlockBodyFromProtoBellatrix(pb.Body) - if err != nil { + p, err := WrappedExecutionPayload(pb.ExecutionPayload) + // We allow the payload to be nil + if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } - b := &BeaconBlock{ - version: version.Bellatrix, - slot: pb.Slot, - proposerIndex: pb.ProposerIndex, - parentRoot: bytesutil.ToBytes32(pb.ParentRoot), - stateRoot: bytesutil.ToBytes32(pb.StateRoot), - body: body, + b := &BeaconBlockBody{ + version: version.Bellatrix, + randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), + eth1Data: pb.Eth1Data, + graffiti: bytesutil.ToBytes32(pb.Graffiti), + proposerSlashings: pb.ProposerSlashings, + attesterSlashings: pb.AttesterSlashings, + attestations: pb.Attestations, + deposits: pb.Deposits, + voluntaryExits: pb.VoluntaryExits, + syncAggregate: pb.SyncAggregate, + executionPayload: p, } return b, nil } -func initBlindedBlockFromProtoBellatrix(pb *eth.BlindedBeaconBlockBellatrix) (*BeaconBlock, error) { +func initBlindedBlockBodyFromProtoBellatrix(pb *eth.BlindedBeaconBlockBodyBellatrix) (*BeaconBlockBody, error) { if pb == nil { - return nil, errNilBlock + return nil, errNilBlockBody } - body, err := initBlindedBlockBodyFromProtoBellatrix(pb.Body) - if err != nil { + ph, err := WrappedExecutionPayloadHeader(pb.ExecutionPayloadHeader) + // We allow the payload to be nil + if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } - b := &BeaconBlock{ - version: version.Bellatrix, - slot: pb.Slot, - proposerIndex: pb.ProposerIndex, - parentRoot: bytesutil.ToBytes32(pb.ParentRoot), - stateRoot: bytesutil.ToBytes32(pb.StateRoot), - body: body, + b := &BeaconBlockBody{ + version: version.Bellatrix, + randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), + eth1Data: pb.Eth1Data, + graffiti: bytesutil.ToBytes32(pb.Graffiti), + proposerSlashings: pb.ProposerSlashings, + attesterSlashings: pb.AttesterSlashings, + attestations: pb.Attestations, + deposits: pb.Deposits, + voluntaryExits: pb.VoluntaryExits, + syncAggregate: pb.SyncAggregate, + executionPayloadHeader: ph, } return b, nil } -func initBlockFromProtoCapella(pb *eth.BeaconBlockCapella) (*BeaconBlock, error) { +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + +func initSignedBlockFromProtoCapella(pb *eth.SignedBeaconBlockCapella) (*SignedBeaconBlock, error) { if pb == nil { return nil, errNilBlock } - body, err := initBlockBodyFromProtoCapella(pb.Body) + block, err := initBlockFromProtoCapella(pb.Block) if err != nil { return nil, err } - b := &BeaconBlock{ - version: version.Capella, - slot: pb.Slot, - proposerIndex: pb.ProposerIndex, - parentRoot: bytesutil.ToBytes32(pb.ParentRoot), - stateRoot: bytesutil.ToBytes32(pb.StateRoot), - body: body, + b := &SignedBeaconBlock{ + version: version.Capella, + block: block, + signature: bytesutil.ToBytes96(pb.Signature), } return b, nil } -func initBlockFromProtoDeneb(pb *eth.BeaconBlockDeneb) (*BeaconBlock, error) { +func initBlindedSignedBlockFromProtoCapella(pb *eth.SignedBlindedBeaconBlockCapella) (*SignedBeaconBlock, error) { if pb == nil { return nil, errNilBlock } - body, err := initBlockBodyFromProtoDeneb(pb.Body) + block, err := initBlindedBlockFromProtoCapella(pb.Block) if err != nil { return nil, err } - b := &BeaconBlock{ - version: version.Deneb, - slot: pb.Slot, - proposerIndex: pb.ProposerIndex, - parentRoot: bytesutil.ToBytes32(pb.ParentRoot), - stateRoot: bytesutil.ToBytes32(pb.StateRoot), - body: body, + b := &SignedBeaconBlock{ + version: version.Capella, + block: block, + signature: bytesutil.ToBytes96(pb.Signature), } return b, nil } -func initBlockFromProtoElectra(pb *eth.BeaconBlockElectra) (*BeaconBlock, error) { +func initBlockFromProtoCapella(pb *eth.BeaconBlockCapella) (*BeaconBlock, error) { if pb == nil { return nil, errNilBlock } - body, err := initBlockBodyFromProtoElectra(pb.Body) + body, err := initBlockBodyFromProtoCapella(pb.Body) if err != nil { return nil, err } b := &BeaconBlock{ - version: version.Electra, + version: version.Capella, slot: pb.Slot, proposerIndex: pb.ProposerIndex, parentRoot: bytesutil.ToBytes32(pb.ParentRoot), @@ -891,149 +1000,150 @@ func initBlindedBlockFromProtoCapella(pb *eth.BlindedBeaconBlockCapella) (*Beaco return b, nil } -func initBlindedBlockFromProtoDeneb(pb *eth.BlindedBeaconBlockDeneb) (*BeaconBlock, error) { +func initBlockBodyFromProtoCapella(pb *eth.BeaconBlockBodyCapella) (*BeaconBlockBody, error) { if pb == nil { - return nil, errNilBlock + return nil, errNilBlockBody } - body, err := initBlindedBlockBodyFromProtoDeneb(pb.Body) - if err != nil { + p, err := WrappedExecutionPayloadCapella(pb.ExecutionPayload) + // We allow the payload to be nil + if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } - b := &BeaconBlock{ - version: version.Deneb, - slot: pb.Slot, - proposerIndex: pb.ProposerIndex, - parentRoot: bytesutil.ToBytes32(pb.ParentRoot), - stateRoot: bytesutil.ToBytes32(pb.StateRoot), - body: body, + b := &BeaconBlockBody{ + version: version.Capella, + randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), + eth1Data: pb.Eth1Data, + graffiti: bytesutil.ToBytes32(pb.Graffiti), + proposerSlashings: pb.ProposerSlashings, + attesterSlashings: pb.AttesterSlashings, + attestations: pb.Attestations, + deposits: pb.Deposits, + voluntaryExits: pb.VoluntaryExits, + syncAggregate: pb.SyncAggregate, + executionPayload: p, + blsToExecutionChanges: pb.BlsToExecutionChanges, } return b, nil } -func initBlindedBlockFromProtoElectra(pb *eth.BlindedBeaconBlockElectra) (*BeaconBlock, error) { +func initBlindedBlockBodyFromProtoCapella(pb *eth.BlindedBeaconBlockBodyCapella) (*BeaconBlockBody, error) { if pb == nil { - return nil, errNilBlock + return nil, errNilBlockBody } - body, err := initBlindedBlockBodyFromProtoElectra(pb.Body) - if err != nil { + ph, err := WrappedExecutionPayloadHeaderCapella(pb.ExecutionPayloadHeader) + // We allow the payload to be nil + if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } - b := &BeaconBlock{ - version: version.Electra, - slot: pb.Slot, - proposerIndex: pb.ProposerIndex, - parentRoot: bytesutil.ToBytes32(pb.ParentRoot), - stateRoot: bytesutil.ToBytes32(pb.StateRoot), - body: body, + b := &BeaconBlockBody{ + version: version.Capella, + randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), + eth1Data: pb.Eth1Data, + graffiti: bytesutil.ToBytes32(pb.Graffiti), + proposerSlashings: pb.ProposerSlashings, + attesterSlashings: pb.AttesterSlashings, + attestations: pb.Attestations, + deposits: pb.Deposits, + voluntaryExits: pb.VoluntaryExits, + syncAggregate: pb.SyncAggregate, + executionPayloadHeader: ph, + blsToExecutionChanges: pb.BlsToExecutionChanges, } return b, nil } -func initBlockBodyFromProtoPhase0(pb *eth.BeaconBlockBody) (*BeaconBlockBody, error) { +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + +func initSignedBlockFromProtoDeneb(pb *eth.SignedBeaconBlockDeneb) (*SignedBeaconBlock, error) { if pb == nil { - return nil, errNilBlockBody + return nil, errNilBlock } - b := &BeaconBlockBody{ - version: version.Phase0, - randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), - eth1Data: pb.Eth1Data, - graffiti: bytesutil.ToBytes32(pb.Graffiti), - proposerSlashings: pb.ProposerSlashings, - attesterSlashings: pb.AttesterSlashings, - attestations: pb.Attestations, - deposits: pb.Deposits, - voluntaryExits: pb.VoluntaryExits, + block, err := initBlockFromProtoDeneb(pb.Block) + if err != nil { + return nil, err + } + b := &SignedBeaconBlock{ + version: version.Deneb, + block: block, + signature: bytesutil.ToBytes96(pb.Signature), } return b, nil } -func initBlockBodyFromProtoAltair(pb *eth.BeaconBlockBodyAltair) (*BeaconBlockBody, error) { +func initBlindedSignedBlockFromProtoDeneb(pb *eth.SignedBlindedBeaconBlockDeneb) (*SignedBeaconBlock, error) { if pb == nil { - return nil, errNilBlockBody + return nil, errNilBlock } - b := &BeaconBlockBody{ - version: version.Altair, - randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), - eth1Data: pb.Eth1Data, - graffiti: bytesutil.ToBytes32(pb.Graffiti), - proposerSlashings: pb.ProposerSlashings, - attesterSlashings: pb.AttesterSlashings, - attestations: pb.Attestations, - deposits: pb.Deposits, - voluntaryExits: pb.VoluntaryExits, - syncAggregate: pb.SyncAggregate, + block, err := initBlindedBlockFromProtoDeneb(pb.Message) + if err != nil { + return nil, err + } + b := &SignedBeaconBlock{ + version: version.Deneb, + block: block, + signature: bytesutil.ToBytes96(pb.Signature), } return b, nil } -func initBlockBodyFromProtoBellatrix(pb *eth.BeaconBlockBodyBellatrix) (*BeaconBlockBody, error) { +func initBlockFromProtoDeneb(pb *eth.BeaconBlockDeneb) (*BeaconBlock, error) { if pb == nil { - return nil, errNilBlockBody + return nil, errNilBlock } - p, err := WrappedExecutionPayload(pb.ExecutionPayload) - // We allow the payload to be nil - if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { + body, err := initBlockBodyFromProtoDeneb(pb.Body) + if err != nil { return nil, err } - b := &BeaconBlockBody{ - version: version.Bellatrix, - randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), - eth1Data: pb.Eth1Data, - graffiti: bytesutil.ToBytes32(pb.Graffiti), - proposerSlashings: pb.ProposerSlashings, - attesterSlashings: pb.AttesterSlashings, - attestations: pb.Attestations, - deposits: pb.Deposits, - voluntaryExits: pb.VoluntaryExits, - syncAggregate: pb.SyncAggregate, - executionPayload: p, + b := &BeaconBlock{ + version: version.Deneb, + slot: pb.Slot, + proposerIndex: pb.ProposerIndex, + parentRoot: bytesutil.ToBytes32(pb.ParentRoot), + stateRoot: bytesutil.ToBytes32(pb.StateRoot), + body: body, } return b, nil } -func initBlindedBlockBodyFromProtoBellatrix(pb *eth.BlindedBeaconBlockBodyBellatrix) (*BeaconBlockBody, error) { +func initBlindedBlockFromProtoDeneb(pb *eth.BlindedBeaconBlockDeneb) (*BeaconBlock, error) { if pb == nil { - return nil, errNilBlockBody + return nil, errNilBlock } - ph, err := WrappedExecutionPayloadHeader(pb.ExecutionPayloadHeader) - // We allow the payload to be nil - if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { + body, err := initBlindedBlockBodyFromProtoDeneb(pb.Body) + if err != nil { return nil, err } - b := &BeaconBlockBody{ - version: version.Bellatrix, - randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), - eth1Data: pb.Eth1Data, - graffiti: bytesutil.ToBytes32(pb.Graffiti), - proposerSlashings: pb.ProposerSlashings, - attesterSlashings: pb.AttesterSlashings, - attestations: pb.Attestations, - deposits: pb.Deposits, - voluntaryExits: pb.VoluntaryExits, - syncAggregate: pb.SyncAggregate, - executionPayloadHeader: ph, + b := &BeaconBlock{ + version: version.Deneb, + slot: pb.Slot, + proposerIndex: pb.ProposerIndex, + parentRoot: bytesutil.ToBytes32(pb.ParentRoot), + stateRoot: bytesutil.ToBytes32(pb.StateRoot), + body: body, } return b, nil } -func initBlockBodyFromProtoCapella(pb *eth.BeaconBlockBodyCapella) (*BeaconBlockBody, error) { +func initBlockBodyFromProtoDeneb(pb *eth.BeaconBlockBodyDeneb) (*BeaconBlockBody, error) { if pb == nil { return nil, errNilBlockBody } - p, err := WrappedExecutionPayloadCapella(pb.ExecutionPayload) + p, err := WrappedExecutionPayloadDeneb(pb.ExecutionPayload) // We allow the payload to be nil if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } b := &BeaconBlockBody{ - version: version.Capella, + version: version.Deneb, randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), eth1Data: pb.Eth1Data, graffiti: bytesutil.ToBytes32(pb.Graffiti), @@ -1045,22 +1155,23 @@ func initBlockBodyFromProtoCapella(pb *eth.BeaconBlockBodyCapella) (*BeaconBlock syncAggregate: pb.SyncAggregate, executionPayload: p, blsToExecutionChanges: pb.BlsToExecutionChanges, + blobKzgCommitments: pb.BlobKzgCommitments, } return b, nil } -func initBlindedBlockBodyFromProtoCapella(pb *eth.BlindedBeaconBlockBodyCapella) (*BeaconBlockBody, error) { +func initBlindedBlockBodyFromProtoDeneb(pb *eth.BlindedBeaconBlockBodyDeneb) (*BeaconBlockBody, error) { if pb == nil { return nil, errNilBlockBody } - ph, err := WrappedExecutionPayloadHeaderCapella(pb.ExecutionPayloadHeader) + ph, err := WrappedExecutionPayloadHeaderDeneb(pb.ExecutionPayloadHeader) // We allow the payload to be nil if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } b := &BeaconBlockBody{ - version: version.Capella, + version: version.Deneb, randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), eth1Data: pb.Eth1Data, graffiti: bytesutil.ToBytes32(pb.Graffiti), @@ -1072,11 +1183,90 @@ func initBlindedBlockBodyFromProtoCapella(pb *eth.BlindedBeaconBlockBodyCapella) syncAggregate: pb.SyncAggregate, executionPayloadHeader: ph, blsToExecutionChanges: pb.BlsToExecutionChanges, + blobKzgCommitments: pb.BlobKzgCommitments, } return b, nil } -func initBlockBodyFromProtoDeneb(pb *eth.BeaconBlockBodyDeneb) (*BeaconBlockBody, error) { +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +func initSignedBlockFromProtoElectra(pb *eth.SignedBeaconBlockElectra) (*SignedBeaconBlock, error) { + if pb == nil { + return nil, errNilBlock + } + + block, err := initBlockFromProtoElectra(pb.Block) + if err != nil { + return nil, err + } + b := &SignedBeaconBlock{ + version: version.Electra, + block: block, + signature: bytesutil.ToBytes96(pb.Signature), + } + return b, nil +} + +func initBlindedSignedBlockFromProtoElectra(pb *eth.SignedBlindedBeaconBlockElectra) (*SignedBeaconBlock, error) { + if pb == nil { + return nil, errNilBlock + } + + block, err := initBlindedBlockFromProtoElectra(pb.Message) + if err != nil { + return nil, err + } + b := &SignedBeaconBlock{ + version: version.Electra, + block: block, + signature: bytesutil.ToBytes96(pb.Signature), + } + return b, nil +} + +func initBlockFromProtoElectra(pb *eth.BeaconBlockElectra) (*BeaconBlock, error) { + if pb == nil { + return nil, errNilBlock + } + + body, err := initBlockBodyFromProtoElectra(pb.Body) + if err != nil { + return nil, err + } + b := &BeaconBlock{ + version: version.Electra, + slot: pb.Slot, + proposerIndex: pb.ProposerIndex, + parentRoot: bytesutil.ToBytes32(pb.ParentRoot), + stateRoot: bytesutil.ToBytes32(pb.StateRoot), + body: body, + } + return b, nil +} + +func initBlindedBlockFromProtoElectra(pb *eth.BlindedBeaconBlockElectra) (*BeaconBlock, error) { + if pb == nil { + return nil, errNilBlock + } + + body, err := initBlindedBlockBodyFromProtoElectra(pb.Body) + if err != nil { + return nil, err + } + b := &BeaconBlock{ + version: version.Electra, + slot: pb.Slot, + proposerIndex: pb.ProposerIndex, + parentRoot: bytesutil.ToBytes32(pb.ParentRoot), + stateRoot: bytesutil.ToBytes32(pb.StateRoot), + body: body, + } + return b, nil +} + +func initBlockBodyFromProtoElectra(pb *eth.BeaconBlockBodyElectra) (*BeaconBlockBody, error) { if pb == nil { return nil, errNilBlockBody } @@ -1086,25 +1276,30 @@ func initBlockBodyFromProtoDeneb(pb *eth.BeaconBlockBodyDeneb) (*BeaconBlockBody if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } + er := pb.ExecutionRequests + if er == nil { + er = &enginev1.ExecutionRequests{} + } b := &BeaconBlockBody{ - version: version.Deneb, - randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), - eth1Data: pb.Eth1Data, - graffiti: bytesutil.ToBytes32(pb.Graffiti), - proposerSlashings: pb.ProposerSlashings, - attesterSlashings: pb.AttesterSlashings, - attestations: pb.Attestations, - deposits: pb.Deposits, - voluntaryExits: pb.VoluntaryExits, - syncAggregate: pb.SyncAggregate, - executionPayload: p, - blsToExecutionChanges: pb.BlsToExecutionChanges, - blobKzgCommitments: pb.BlobKzgCommitments, + version: version.Electra, + randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), + eth1Data: pb.Eth1Data, + graffiti: bytesutil.ToBytes32(pb.Graffiti), + proposerSlashings: pb.ProposerSlashings, + attesterSlashingsElectra: pb.AttesterSlashings, + attestationsElectra: pb.Attestations, + deposits: pb.Deposits, + voluntaryExits: pb.VoluntaryExits, + syncAggregate: pb.SyncAggregate, + executionPayload: p, + blsToExecutionChanges: pb.BlsToExecutionChanges, + blobKzgCommitments: pb.BlobKzgCommitments, + executionRequests: er, } return b, nil } -func initBlindedBlockBodyFromProtoDeneb(pb *eth.BlindedBeaconBlockBodyDeneb) (*BeaconBlockBody, error) { +func initBlindedBlockBodyFromProtoElectra(pb *eth.BlindedBeaconBlockBodyElectra) (*BeaconBlockBody, error) { if pb == nil { return nil, errNilBlockBody } @@ -1114,36 +1309,123 @@ func initBlindedBlockBodyFromProtoDeneb(pb *eth.BlindedBeaconBlockBodyDeneb) (*B if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } + er := pb.ExecutionRequests + if er == nil { + er = &enginev1.ExecutionRequests{} + } b := &BeaconBlockBody{ - version: version.Deneb, - randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), - eth1Data: pb.Eth1Data, - graffiti: bytesutil.ToBytes32(pb.Graffiti), - proposerSlashings: pb.ProposerSlashings, - attesterSlashings: pb.AttesterSlashings, - attestations: pb.Attestations, - deposits: pb.Deposits, - voluntaryExits: pb.VoluntaryExits, - syncAggregate: pb.SyncAggregate, - executionPayloadHeader: ph, - blsToExecutionChanges: pb.BlsToExecutionChanges, - blobKzgCommitments: pb.BlobKzgCommitments, + version: version.Electra, + randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), + eth1Data: pb.Eth1Data, + graffiti: bytesutil.ToBytes32(pb.Graffiti), + proposerSlashings: pb.ProposerSlashings, + attesterSlashingsElectra: pb.AttesterSlashings, + attestationsElectra: pb.Attestations, + deposits: pb.Deposits, + voluntaryExits: pb.VoluntaryExits, + syncAggregate: pb.SyncAggregate, + executionPayloadHeader: ph, + blsToExecutionChanges: pb.BlsToExecutionChanges, + blobKzgCommitments: pb.BlobKzgCommitments, + executionRequests: er, } return b, nil } -func initBlockBodyFromProtoElectra(pb *eth.BeaconBlockBodyElectra) (*BeaconBlockBody, error) { +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +func initSignedBlockFromProtoFulu(pb *eth.SignedBeaconBlockFulu) (*SignedBeaconBlock, error) { + if pb == nil { + return nil, errNilBlock + } + + block, err := initBlockFromProtoFulu(pb.Block) + if err != nil { + return nil, err + } + b := &SignedBeaconBlock{ + version: version.Fulu, + block: block, + signature: bytesutil.ToBytes96(pb.Signature), + } + return b, nil +} + +func initBlindedSignedBlockFromProtoFulu(pb *eth.SignedBlindedBeaconBlockFulu) (*SignedBeaconBlock, error) { + if pb == nil { + return nil, errNilBlock + } + + block, err := initBlindedBlockFromProtoFulu(pb.Message) + if err != nil { + return nil, err + } + b := &SignedBeaconBlock{ + version: version.Fulu, + block: block, + signature: bytesutil.ToBytes96(pb.Signature), + } + return b, nil +} + +func initBlockFromProtoFulu(pb *eth.BeaconBlockElectra) (*BeaconBlock, error) { + if pb == nil { + return nil, errNilBlock + } + + body, err := initBlockBodyFromProtoFulu(pb.Body) + if err != nil { + return nil, err + } + b := &BeaconBlock{ + version: version.Fulu, + slot: pb.Slot, + proposerIndex: pb.ProposerIndex, + parentRoot: bytesutil.ToBytes32(pb.ParentRoot), + stateRoot: bytesutil.ToBytes32(pb.StateRoot), + body: body, + } + return b, nil +} + +func initBlindedBlockFromProtoFulu(pb *eth.BlindedBeaconBlockFulu) (*BeaconBlock, error) { + if pb == nil { + return nil, errNilBlock + } + + body, err := initBlindedBlockBodyFromProtoFulu(pb.Body) + if err != nil { + return nil, err + } + b := &BeaconBlock{ + version: version.Fulu, + slot: pb.Slot, + proposerIndex: pb.ProposerIndex, + parentRoot: bytesutil.ToBytes32(pb.ParentRoot), + stateRoot: bytesutil.ToBytes32(pb.StateRoot), + body: body, + } + return b, nil +} + +func initBlockBodyFromProtoFulu(pb *eth.BeaconBlockBodyElectra) (*BeaconBlockBody, error) { if pb == nil { return nil, errNilBlockBody } - p, err := WrappedExecutionPayloadElectra(pb.ExecutionPayload) + p, err := WrappedExecutionPayloadDeneb(pb.ExecutionPayload) // We allow the payload to be nil if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } + er := pb.ExecutionRequests + if er == nil { + er = &enginev1.ExecutionRequests{} + } b := &BeaconBlockBody{ - version: version.Electra, + version: version.Fulu, randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), eth1Data: pb.Eth1Data, graffiti: bytesutil.ToBytes32(pb.Graffiti), @@ -1156,22 +1438,27 @@ func initBlockBodyFromProtoElectra(pb *eth.BeaconBlockBodyElectra) (*BeaconBlock executionPayload: p, blsToExecutionChanges: pb.BlsToExecutionChanges, blobKzgCommitments: pb.BlobKzgCommitments, + executionRequests: er, } return b, nil } -func initBlindedBlockBodyFromProtoElectra(pb *eth.BlindedBeaconBlockBodyElectra) (*BeaconBlockBody, error) { +func initBlindedBlockBodyFromProtoFulu(pb *eth.BlindedBeaconBlockBodyElectra) (*BeaconBlockBody, error) { if pb == nil { return nil, errNilBlockBody } - ph, err := WrappedExecutionPayloadHeaderElectra(pb.ExecutionPayloadHeader) + ph, err := WrappedExecutionPayloadHeaderDeneb(pb.ExecutionPayloadHeader) // We allow the payload to be nil if err != nil && !errors.Is(err, consensus_types.ErrNilObjectWrapped) { return nil, err } + er := pb.ExecutionRequests + if er == nil { + er = &enginev1.ExecutionRequests{} + } b := &BeaconBlockBody{ - version: version.Electra, + version: version.Fulu, randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal), eth1Data: pb.Eth1Data, graffiti: bytesutil.ToBytes32(pb.Graffiti), @@ -1184,6 +1471,7 @@ func initBlindedBlockBodyFromProtoElectra(pb *eth.BlindedBeaconBlockBodyElectra) executionPayloadHeader: ph, blsToExecutionChanges: pb.BlsToExecutionChanges, blobKzgCommitments: pb.BlobKzgCommitments, + executionRequests: er, } return b, nil } diff --git a/consensus-types/blocks/proto_test.go b/consensus-types/blocks/proto_test.go index 880edb63db99..f606e07452a4 100644 --- a/consensus-types/blocks/proto_test.go +++ b/consensus-types/blocks/proto_test.go @@ -4,6 +4,8 @@ import ( "testing" "github.com/prysmaticlabs/go-bitfield" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -17,8 +19,10 @@ type fields struct { sig [96]byte deposits []*eth.Deposit atts []*eth.Attestation + attsElectra []*eth.AttestationElectra proposerSlashings []*eth.ProposerSlashing attesterSlashings []*eth.AttesterSlashing + attesterSlashingsElectra []*eth.AttesterSlashingElectra voluntaryExits []*eth.SignedVoluntaryExit syncAggregate *eth.SyncAggregate execPayload *enginev1.ExecutionPayload @@ -29,6 +33,7 @@ type fields struct { execPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb blsToExecutionChanges []*eth.SignedBLSToExecutionChange kzgCommitments [][]byte + execRequests *enginev1.ExecutionRequests } func Test_SignedBeaconBlock_Proto(t *testing.T) { @@ -306,6 +311,74 @@ func Test_SignedBeaconBlock_Proto(t *testing.T) { require.NoError(t, err) assert.DeepEqual(t, expectedHTR, resultHTR) }) + t.Run("Electra", func(t *testing.T) { + expectedBlock := ð.SignedBeaconBlockElectra{ + Block: ð.BeaconBlockElectra{ + Slot: 128, + ProposerIndex: 128, + ParentRoot: f.root[:], + StateRoot: f.root[:], + Body: bodyPbElectra(), + }, + Signature: f.sig[:], + } + block := &SignedBeaconBlock{ + version: version.Electra, + block: &BeaconBlock{ + version: version.Electra, + slot: 128, + proposerIndex: 128, + parentRoot: f.root, + stateRoot: f.root, + body: bodyElectra(t), + }, + signature: f.sig, + } + + result, err := block.Proto() + require.NoError(t, err) + resultBlock, ok := result.(*eth.SignedBeaconBlockElectra) + require.Equal(t, true, ok) + resultHTR, err := resultBlock.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBlock.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) + }) + t.Run("ElectraBlind", func(t *testing.T) { + expectedBlock := ð.SignedBlindedBeaconBlockElectra{ + Message: ð.BlindedBeaconBlockElectra{ + Slot: 128, + ProposerIndex: 128, + ParentRoot: f.root[:], + StateRoot: f.root[:], + Body: bodyPbBlindedElectra(), + }, + Signature: f.sig[:], + } + block := &SignedBeaconBlock{ + version: version.Electra, + block: &BeaconBlock{ + version: version.Electra, + slot: 128, + proposerIndex: 128, + parentRoot: f.root, + stateRoot: f.root, + body: bodyBlindedElectra(t), + }, + signature: f.sig, + } + + result, err := block.Proto() + require.NoError(t, err) + resultBlock, ok := result.(*eth.SignedBlindedBeaconBlockElectra) + require.Equal(t, true, ok) + resultHTR, err := resultBlock.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBlock.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) + }) } func Test_BeaconBlock_Proto(t *testing.T) { @@ -527,6 +600,60 @@ func Test_BeaconBlock_Proto(t *testing.T) { require.NoError(t, err) assert.DeepEqual(t, expectedHTR, resultHTR) }) + t.Run("Electra", func(t *testing.T) { + expectedBlock := ð.BeaconBlockElectra{ + Slot: 128, + ProposerIndex: 128, + ParentRoot: f.root[:], + StateRoot: f.root[:], + Body: bodyPbElectra(), + } + block := &BeaconBlock{ + version: version.Electra, + slot: 128, + proposerIndex: 128, + parentRoot: f.root, + stateRoot: f.root, + body: bodyElectra(t), + } + + result, err := block.Proto() + require.NoError(t, err) + resultBlock, ok := result.(*eth.BeaconBlockElectra) + require.Equal(t, true, ok) + resultHTR, err := resultBlock.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBlock.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) + }) + t.Run("ElectraBlind", func(t *testing.T) { + expectedBlock := ð.BlindedBeaconBlockElectra{ + Slot: 128, + ProposerIndex: 128, + ParentRoot: f.root[:], + StateRoot: f.root[:], + Body: bodyPbBlindedElectra(), + } + block := &BeaconBlock{ + version: version.Electra, + slot: 128, + proposerIndex: 128, + parentRoot: f.root, + stateRoot: f.root, + body: bodyBlindedElectra(t), + } + + result, err := block.Proto() + require.NoError(t, err) + resultBlock, ok := result.(*eth.BlindedBeaconBlockElectra) + require.Equal(t, true, ok) + resultHTR, err := resultBlock.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBlock.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) + }) } func Test_BeaconBlockBody_Proto(t *testing.T) { @@ -635,6 +762,32 @@ func Test_BeaconBlockBody_Proto(t *testing.T) { require.NoError(t, err) assert.DeepEqual(t, expectedHTR, resultHTR) }) + t.Run("Electra", func(t *testing.T) { + expectedBody := bodyPbElectra() + body := bodyElectra(t) + result, err := body.Proto() + require.NoError(t, err) + resultBlock, ok := result.(*eth.BeaconBlockBodyElectra) + require.Equal(t, true, ok) + resultHTR, err := resultBlock.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBody.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) + }) + t.Run("ElectraBlind", func(t *testing.T) { + expectedBody := bodyPbBlindedElectra() + body := bodyBlindedElectra(t) + result, err := body.Proto() + require.NoError(t, err) + resultBlock, ok := result.(*eth.BlindedBeaconBlockBodyElectra) + require.Equal(t, true, ok) + resultHTR, err := resultBlock.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBody.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) + }) t.Run("Bellatrix - wrong payload type", func(t *testing.T) { body := bodyBellatrix(t) body.executionPayload = &executionPayloadHeader{} @@ -671,6 +824,18 @@ func Test_BeaconBlockBody_Proto(t *testing.T) { _, err := body.Proto() require.ErrorIs(t, err, errPayloadHeaderWrongType) }) + t.Run("Electra - wrong payload type", func(t *testing.T) { + body := bodyElectra(t) + body.executionPayload = &executionPayloadHeaderDeneb{} + _, err := body.Proto() + require.ErrorIs(t, err, errPayloadWrongType) + }) + t.Run("ElectraBlind - wrong payload type", func(t *testing.T) { + body := bodyBlindedElectra(t) + body.executionPayloadHeader = &executionPayloadDeneb{} + _, err := body.Proto() + require.ErrorIs(t, err, errPayloadHeaderWrongType) + }) } func Test_initSignedBlockFromProtoPhase0(t *testing.T) { @@ -849,6 +1014,50 @@ func Test_initBlindedSignedBlockFromProtoDeneb(t *testing.T) { assert.DeepEqual(t, expectedBlock.Signature, resultBlock.signature[:]) } +func Test_initSignedBlockFromProtoElectra(t *testing.T) { + f := getFields() + expectedBlock := ð.SignedBeaconBlockElectra{ + Block: ð.BeaconBlockElectra{ + Slot: 128, + ProposerIndex: 128, + ParentRoot: f.root[:], + StateRoot: f.root[:], + Body: bodyPbElectra(), + }, + Signature: f.sig[:], + } + resultBlock, err := initSignedBlockFromProtoElectra(expectedBlock) + require.NoError(t, err) + resultHTR, err := resultBlock.block.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBlock.Block.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) + assert.DeepEqual(t, expectedBlock.Signature, resultBlock.signature[:]) +} + +func Test_initBlindedSignedBlockFromProtoElectra(t *testing.T) { + f := getFields() + expectedBlock := ð.SignedBlindedBeaconBlockElectra{ + Message: ð.BlindedBeaconBlockElectra{ + Slot: 128, + ProposerIndex: 128, + ParentRoot: f.root[:], + StateRoot: f.root[:], + Body: bodyPbBlindedElectra(), + }, + Signature: f.sig[:], + } + resultBlock, err := initBlindedSignedBlockFromProtoElectra(expectedBlock) + require.NoError(t, err) + resultHTR, err := resultBlock.block.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBlock.Message.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) + assert.DeepEqual(t, expectedBlock.Signature, resultBlock.signature[:]) +} + func Test_initBlockFromProtoPhase0(t *testing.T) { f := getFields() expectedBlock := ð.BeaconBlock{ @@ -993,6 +1202,42 @@ func Test_initBlockFromProtoBlindedDeneb(t *testing.T) { assert.DeepEqual(t, expectedHTR, resultHTR) } +func Test_initBlockFromProtoElectra(t *testing.T) { + f := getFields() + expectedBlock := ð.BeaconBlockElectra{ + Slot: 128, + ProposerIndex: 128, + ParentRoot: f.root[:], + StateRoot: f.root[:], + Body: bodyPbElectra(), + } + resultBlock, err := initBlockFromProtoElectra(expectedBlock) + require.NoError(t, err) + resultHTR, err := resultBlock.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBlock.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) +} + +func Test_initBlockFromProtoBlindedElectra(t *testing.T) { + f := getFields() + expectedBlock := ð.BlindedBeaconBlockElectra{ + Slot: 128, + ProposerIndex: 128, + ParentRoot: f.root[:], + StateRoot: f.root[:], + Body: bodyPbBlindedElectra(), + } + resultBlock, err := initBlindedBlockFromProtoElectra(expectedBlock) + require.NoError(t, err) + resultHTR, err := resultBlock.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBlock.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) +} + func Test_initBlockBodyFromProtoPhase0(t *testing.T) { expectedBody := bodyPbPhase0() resultBody, err := initBlockBodyFromProtoPhase0(expectedBody) @@ -1081,6 +1326,28 @@ func Test_initBlockBodyFromProtoBlindedDeneb(t *testing.T) { assert.DeepEqual(t, expectedHTR, resultHTR) } +func Test_initBlockBodyFromProtoElectra(t *testing.T) { + expectedBody := bodyPbElectra() + resultBody, err := initBlockBodyFromProtoElectra(expectedBody) + require.NoError(t, err) + resultHTR, err := resultBody.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBody.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) +} + +func Test_initBlockBodyFromProtoBlindedElectra(t *testing.T) { + expectedBody := bodyPbBlindedElectra() + resultBody, err := initBlindedBlockBodyFromProtoElectra(expectedBody) + require.NoError(t, err) + resultHTR, err := resultBody.HashTreeRoot() + require.NoError(t, err) + expectedHTR, err := expectedBody.HashTreeRoot() + require.NoError(t, err) + assert.DeepEqual(t, expectedHTR, resultHTR) +} + func bodyPbPhase0() *eth.BeaconBlockBody { f := getFields() return ð.BeaconBlockBody{ @@ -1244,6 +1511,52 @@ func bodyPbBlindedDeneb() *eth.BlindedBeaconBlockBodyDeneb { } } +func bodyPbElectra() *eth.BeaconBlockBodyElectra { + f := getFields() + return ð.BeaconBlockBodyElectra{ + RandaoReveal: f.sig[:], + Eth1Data: ð.Eth1Data{ + DepositRoot: f.root[:], + DepositCount: 128, + BlockHash: f.root[:], + }, + Graffiti: f.root[:], + ProposerSlashings: f.proposerSlashings, + AttesterSlashings: f.attesterSlashingsElectra, + Attestations: f.attsElectra, + Deposits: f.deposits, + VoluntaryExits: f.voluntaryExits, + SyncAggregate: f.syncAggregate, + ExecutionPayload: f.execPayloadDeneb, + BlsToExecutionChanges: f.blsToExecutionChanges, + BlobKzgCommitments: f.kzgCommitments, + ExecutionRequests: f.execRequests, + } +} + +func bodyPbBlindedElectra() *eth.BlindedBeaconBlockBodyElectra { + f := getFields() + return ð.BlindedBeaconBlockBodyElectra{ + RandaoReveal: f.sig[:], + Eth1Data: ð.Eth1Data{ + DepositRoot: f.root[:], + DepositCount: 128, + BlockHash: f.root[:], + }, + Graffiti: f.root[:], + ProposerSlashings: f.proposerSlashings, + AttesterSlashings: f.attesterSlashingsElectra, + Attestations: f.attsElectra, + Deposits: f.deposits, + VoluntaryExits: f.voluntaryExits, + SyncAggregate: f.syncAggregate, + ExecutionPayloadHeader: f.execPayloadHeaderDeneb, + BlsToExecutionChanges: f.blsToExecutionChanges, + BlobKzgCommitments: f.kzgCommitments, + ExecutionRequests: f.execRequests, + } +} + func bodyPhase0() *BeaconBlockBody { f := getFields() return &BeaconBlockBody{ @@ -1427,6 +1740,58 @@ func bodyBlindedDeneb(t *testing.T) *BeaconBlockBody { } } +func bodyElectra(t *testing.T) *BeaconBlockBody { + f := getFields() + p, err := WrappedExecutionPayloadDeneb(f.execPayloadDeneb) + require.NoError(t, err) + return &BeaconBlockBody{ + version: version.Electra, + randaoReveal: f.sig, + eth1Data: ð.Eth1Data{ + DepositRoot: f.root[:], + DepositCount: 128, + BlockHash: f.root[:], + }, + graffiti: f.root, + proposerSlashings: f.proposerSlashings, + attesterSlashingsElectra: f.attesterSlashingsElectra, + attestationsElectra: f.attsElectra, + deposits: f.deposits, + voluntaryExits: f.voluntaryExits, + syncAggregate: f.syncAggregate, + executionPayload: p, + blsToExecutionChanges: f.blsToExecutionChanges, + blobKzgCommitments: f.kzgCommitments, + executionRequests: f.execRequests, + } +} + +func bodyBlindedElectra(t *testing.T) *BeaconBlockBody { + f := getFields() + ph, err := WrappedExecutionPayloadHeaderDeneb(f.execPayloadHeaderDeneb) + require.NoError(t, err) + return &BeaconBlockBody{ + version: version.Electra, + randaoReveal: f.sig, + eth1Data: ð.Eth1Data{ + DepositRoot: f.root[:], + DepositCount: 128, + BlockHash: f.root[:], + }, + graffiti: f.root, + proposerSlashings: f.proposerSlashings, + attesterSlashingsElectra: f.attesterSlashingsElectra, + attestationsElectra: f.attsElectra, + deposits: f.deposits, + voluntaryExits: f.voluntaryExits, + syncAggregate: f.syncAggregate, + executionPayloadHeader: ph, + blsToExecutionChanges: f.blsToExecutionChanges, + blobKzgCommitments: f.kzgCommitments, + executionRequests: f.execRequests, + } +} + func getFields() fields { b20 := make([]byte, 20) b48 := make([]byte, 48) @@ -1452,11 +1817,14 @@ func getFields() fields { Signature: sig[:], } } - atts := make([]*eth.Attestation, 128) + + attBits := bitfield.NewBitlist(1) + committeeBits := primitives.NewAttestationCommitteeBits() + atts := make([]*eth.Attestation, params.BeaconConfig().MaxAttestations) for i := range atts { atts[i] = ð.Attestation{} atts[i].Signature = sig[:] - atts[i].AggregationBits = bitfield.NewBitlist(1) + atts[i].AggregationBits = attBits atts[i].Data = ð.AttestationData{ Slot: 128, CommitteeIndex: 128, @@ -1471,6 +1839,27 @@ func getFields() fields { }, } } + attsElectra := make([]*eth.AttestationElectra, params.BeaconConfig().MaxAttestationsElectra) + for i := range attsElectra { + attsElectra[i] = ð.AttestationElectra{} + attsElectra[i].Signature = sig[:] + attsElectra[i].AggregationBits = attBits + attsElectra[i].CommitteeBits = committeeBits + attsElectra[i].Data = ð.AttestationData{ + Slot: 128, + CommitteeIndex: 128, + BeaconBlockRoot: root[:], + Source: ð.Checkpoint{ + Epoch: 128, + Root: root[:], + }, + Target: ð.Checkpoint{ + Epoch: 128, + Root: root[:], + }, + } + } + proposerSlashing := ð.ProposerSlashing{ Header_1: ð.SignedBeaconBlockHeader{ Header: ð.BeaconBlockHeader{ @@ -1529,6 +1918,42 @@ func getFields() fields { Signature: sig[:], }, } + attesterSlashingElectra := ð.AttesterSlashingElectra{ + Attestation_1: ð.IndexedAttestationElectra{ + AttestingIndices: []uint64{1, 2, 8}, + Data: ð.AttestationData{ + Slot: 128, + CommitteeIndex: 128, + BeaconBlockRoot: root[:], + Source: ð.Checkpoint{ + Epoch: 128, + Root: root[:], + }, + Target: ð.Checkpoint{ + Epoch: 128, + Root: root[:], + }, + }, + Signature: sig[:], + }, + Attestation_2: ð.IndexedAttestationElectra{ + AttestingIndices: []uint64{1, 2, 8}, + Data: ð.AttestationData{ + Slot: 128, + CommitteeIndex: 128, + BeaconBlockRoot: root[:], + Source: ð.Checkpoint{ + Epoch: 128, + Root: root[:], + }, + Target: ð.Checkpoint{ + Epoch: 128, + Root: root[:], + }, + }, + Signature: sig[:], + }, + } voluntaryExit := ð.SignedVoluntaryExit{ Exit: ð.VoluntaryExit{ Epoch: 128, @@ -1689,13 +2114,35 @@ func getFields() fields { bytesutil.PadTo([]byte{143}, 48), } + execRequests := &enginev1.ExecutionRequests{ + Deposits: []*enginev1.DepositRequest{{ + Pubkey: b48, + WithdrawalCredentials: root[:], + Amount: 128, + Signature: sig[:], + Index: 128, + }}, + Withdrawals: []*enginev1.WithdrawalRequest{{ + SourceAddress: b20, + ValidatorPubkey: b48, + Amount: 128, + }}, + Consolidations: []*enginev1.ConsolidationRequest{{ + SourceAddress: b20, + SourcePubkey: b48, + TargetPubkey: b48, + }}, + } + return fields{ root: root, sig: sig, deposits: deposits, atts: atts, + attsElectra: attsElectra, proposerSlashings: []*eth.ProposerSlashing{proposerSlashing}, attesterSlashings: []*eth.AttesterSlashing{attesterSlashing}, + attesterSlashingsElectra: []*eth.AttesterSlashingElectra{attesterSlashingElectra}, voluntaryExits: []*eth.SignedVoluntaryExit{voluntaryExit}, syncAggregate: syncAggregate, execPayload: execPayload, @@ -1706,5 +2153,6 @@ func getFields() fields { execPayloadHeaderDeneb: execPayloadHeaderDeneb, blsToExecutionChanges: blsToExecutionChanges, kzgCommitments: kzgCommitments, + execRequests: execRequests, } } diff --git a/consensus-types/blocks/setters.go b/consensus-types/blocks/setters.go index 3650903404d0..a2f376c76c0f 100644 --- a/consensus-types/blocks/setters.go +++ b/consensus-types/blocks/setters.go @@ -6,6 +6,7 @@ import ( consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" ) @@ -172,3 +173,12 @@ func (b *SignedBeaconBlock) SetBlobKzgCommitments(c [][]byte) error { b.block.body.blobKzgCommitments = c return nil } + +// SetExecutionRequests sets the execution requests in the block. +func (b *SignedBeaconBlock) SetExecutionRequests(req *enginev1.ExecutionRequests) error { + if b.version < version.Electra { + return consensus_types.ErrNotSupported("SetExecutionRequests", b.version) + } + b.block.body.executionRequests = req + return nil +} diff --git a/consensus-types/blocks/testing/factory.go b/consensus-types/blocks/testing/factory.go index 79599b84134e..c8af23911be6 100644 --- a/consensus-types/blocks/testing/factory.go +++ b/consensus-types/blocks/testing/factory.go @@ -32,7 +32,10 @@ func NewSignedBeaconBlockFromGeneric(gb *eth.GenericSignedBeaconBlock) (interfac return blocks.NewSignedBeaconBlock(bb.BlindedDeneb) case *eth.GenericSignedBeaconBlock_Electra: return blocks.NewSignedBeaconBlock(bb.Electra.Block) - // Generic Signed Beacon Block Deneb can't be used here as it is not a block, but block content with blobs + // Generic Signed Beacon Block Deneb can't be used here as it is not a block, but block content with blobs + case *eth.GenericSignedBeaconBlock_Fulu: + return blocks.NewSignedBeaconBlock(bb.Fulu.Block) + // Generic Signed Beacon Block Deneb can't be used here as it is not a block, but block content with blobs default: return nil, errors.Wrapf(blocks.ErrUnsupportedSignedBeaconBlock, "unable to create block from type %T", gb) } diff --git a/consensus-types/blocks/types.go b/consensus-types/blocks/types.go index 093be45a2cd6..350fbe915437 100644 --- a/consensus-types/blocks/types.go +++ b/consensus-types/blocks/types.go @@ -5,6 +5,7 @@ import ( field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) @@ -54,6 +55,7 @@ type BeaconBlockBody struct { executionPayloadHeader interfaces.ExecutionData blsToExecutionChanges []*eth.SignedBLSToExecutionChange blobKzgCommitments [][]byte + executionRequests *enginev1.ExecutionRequests } var _ interfaces.ReadOnlyBeaconBlockBody = &BeaconBlockBody{} diff --git a/consensus-types/interfaces/BUILD.bazel b/consensus-types/interfaces/BUILD.bazel index 9e17fe3adf00..51b9c89816c0 100644 --- a/consensus-types/interfaces/BUILD.bazel +++ b/consensus-types/interfaces/BUILD.bazel @@ -5,6 +5,7 @@ go_library( srcs = [ "beacon_block.go", "error.go", + "light_client.go", "utils.go", "validator.go", ], diff --git a/consensus-types/interfaces/beacon_block.go b/consensus-types/interfaces/beacon_block.go index 42ad27d0a459..02c6bb513ce6 100644 --- a/consensus-types/interfaces/beacon_block.go +++ b/consensus-types/interfaces/beacon_block.go @@ -47,7 +47,6 @@ type ReadOnlyBeaconBlock interface { ssz.HashRoot Version() int AsSignRequestObject() (validatorpb.SignRequestObject, error) - Copy() (ReadOnlyBeaconBlock, error) } // ReadOnlyBeaconBlockBody describes the method set employed by an object @@ -69,6 +68,7 @@ type ReadOnlyBeaconBlockBody interface { Execution() (ExecutionData, error) BLSToExecutionChanges() ([]*ethpb.SignedBLSToExecutionChange, error) BlobKzgCommitments() ([][]byte, error) + ExecutionRequests() (*enginev1.ExecutionRequests, error) } type SignedBeaconBlock interface { @@ -90,6 +90,7 @@ type SignedBeaconBlock interface { SetProposerIndex(idx primitives.ValidatorIndex) SetSlot(slot primitives.Slot) SetSignature(sig []byte) + SetExecutionRequests(er *enginev1.ExecutionRequests) error Unblind(e ExecutionData) error } @@ -122,10 +123,3 @@ type ExecutionData interface { Withdrawals() ([]*enginev1.Withdrawal, error) WithdrawalsRoot() ([]byte, error) } - -type ExecutionDataElectra interface { - ExecutionData - DepositRequests() []*enginev1.DepositRequest - WithdrawalRequests() []*enginev1.WithdrawalRequest - ConsolidationRequests() []*enginev1.ConsolidationRequest -} diff --git a/consensus-types/interfaces/light_client.go b/consensus-types/interfaces/light_client.go new file mode 100644 index 000000000000..1a6576305535 --- /dev/null +++ b/consensus-types/interfaces/light_client.go @@ -0,0 +1,82 @@ +package interfaces + +import ( + ssz "github.com/prysmaticlabs/fastssz" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "google.golang.org/protobuf/proto" +) + +type LightClientExecutionBranch = [fieldparams.ExecutionBranchDepth][fieldparams.RootLength]byte +type LightClientSyncCommitteeBranch = [fieldparams.SyncCommitteeBranchDepth][fieldparams.RootLength]byte +type LightClientSyncCommitteeBranchElectra = [fieldparams.SyncCommitteeBranchDepthElectra][fieldparams.RootLength]byte +type LightClientFinalityBranch = [fieldparams.FinalityBranchDepth][fieldparams.RootLength]byte +type LightClientFinalityBranchElectra = [fieldparams.FinalityBranchDepthElectra][fieldparams.RootLength]byte + +type LightClientHeader interface { + ssz.Marshaler + Proto() proto.Message + Version() int + Beacon() *pb.BeaconBlockHeader + Execution() (ExecutionData, error) + ExecutionBranch() (LightClientExecutionBranch, error) +} + +type LightClientBootstrap interface { + ssz.Marshaler + Version() int + Proto() proto.Message + Header() LightClientHeader + SetHeader(header LightClientHeader) error + CurrentSyncCommittee() *pb.SyncCommittee + SetCurrentSyncCommittee(sc *pb.SyncCommittee) error + CurrentSyncCommitteeBranch() (LightClientSyncCommitteeBranch, error) + CurrentSyncCommitteeBranchElectra() (LightClientSyncCommitteeBranchElectra, error) + SetCurrentSyncCommitteeBranch(branch [][]byte) error +} + +type LightClientUpdate interface { + ssz.Marshaler + Proto() proto.Message + Version() int + AttestedHeader() LightClientHeader + SetAttestedHeader(header LightClientHeader) error + NextSyncCommittee() *pb.SyncCommittee + SetNextSyncCommittee(sc *pb.SyncCommittee) + NextSyncCommitteeBranch() (LightClientSyncCommitteeBranch, error) + SetNextSyncCommitteeBranch(branch [][]byte) error + NextSyncCommitteeBranchElectra() (LightClientSyncCommitteeBranchElectra, error) + FinalizedHeader() LightClientHeader + SetFinalizedHeader(header LightClientHeader) error + FinalityBranch() (LightClientFinalityBranch, error) + FinalityBranchElectra() (LightClientFinalityBranchElectra, error) + SetFinalityBranch(branch [][]byte) error + SyncAggregate() *pb.SyncAggregate + SetSyncAggregate(sa *pb.SyncAggregate) + SignatureSlot() primitives.Slot + SetSignatureSlot(slot primitives.Slot) +} + +type LightClientFinalityUpdate interface { + ssz.Marshaler + ssz.Unmarshaler + Proto() proto.Message + Version() int + AttestedHeader() LightClientHeader + FinalizedHeader() LightClientHeader + FinalityBranch() (LightClientFinalityBranch, error) + FinalityBranchElectra() (LightClientFinalityBranchElectra, error) + SyncAggregate() *pb.SyncAggregate + SignatureSlot() primitives.Slot +} + +type LightClientOptimisticUpdate interface { + ssz.Marshaler + ssz.Unmarshaler + Proto() proto.Message + Version() int + AttestedHeader() LightClientHeader + SyncAggregate() *pb.SyncAggregate + SignatureSlot() primitives.Slot +} diff --git a/consensus-types/light-client/BUILD.bazel b/consensus-types/light-client/BUILD.bazel new file mode 100644 index 000000000000..78432c8eecba --- /dev/null +++ b/consensus-types/light-client/BUILD.bazel @@ -0,0 +1,28 @@ +load("@prysm//tools/go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "bootstrap.go", + "finality_update.go", + "header.go", + "helpers.go", + "optimistic_update.go", + "update.go", + ], + importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client", + visibility = ["//visibility:public"], + deps = [ + "//config/fieldparams:go_default_library", + "//config/params:go_default_library", + "//consensus-types:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/interfaces:go_default_library", + "//consensus-types/primitives:go_default_library", + "//encoding/bytesutil:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", + "//time/slots:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + ], +) diff --git a/consensus-types/light-client/bootstrap.go b/consensus-types/light-client/bootstrap.go new file mode 100644 index 000000000000..e9e583a657c9 --- /dev/null +++ b/consensus-types/light-client/bootstrap.go @@ -0,0 +1,450 @@ +package light_client + +import ( + "fmt" + + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "google.golang.org/protobuf/proto" +) + +func NewWrappedBootstrap(m proto.Message) (interfaces.LightClientBootstrap, error) { + if m == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + switch t := m.(type) { + case *pb.LightClientBootstrapAltair: + return NewWrappedBootstrapAltair(t) + case *pb.LightClientBootstrapCapella: + return NewWrappedBootstrapCapella(t) + case *pb.LightClientBootstrapDeneb: + return NewWrappedBootstrapDeneb(t) + case *pb.LightClientBootstrapElectra: + return NewWrappedBootstrapElectra(t) + default: + return nil, fmt.Errorf("cannot construct light client bootstrap from type %T", t) + } +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type bootstrapAltair struct { + p *pb.LightClientBootstrapAltair + header interfaces.LightClientHeader + currentSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch +} + +var _ interfaces.LightClientBootstrap = &bootstrapAltair{} + +func NewWrappedBootstrapAltair(p *pb.LightClientBootstrapAltair) (interfaces.LightClientBootstrap, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + + var header interfaces.LightClientHeader + var err error + if p.Header != nil { + header, err = NewWrappedHeader(p.Header) + if err != nil { + return nil, err + } + } + + branch, err := createBranch[interfaces.LightClientSyncCommitteeBranch]( + "sync committee", + p.CurrentSyncCommitteeBranch, + fieldparams.SyncCommitteeBranchDepth, + ) + if err != nil { + return nil, err + } + + return &bootstrapAltair{ + p: p, + header: header, + currentSyncCommitteeBranch: branch, + }, nil +} + +func (h *bootstrapAltair) MarshalSSZTo(dst []byte) ([]byte, error) { + return h.p.MarshalSSZTo(dst) +} + +func (h *bootstrapAltair) MarshalSSZ() ([]byte, error) { + return h.p.MarshalSSZ() +} + +func (h *bootstrapAltair) SizeSSZ() int { + return h.p.SizeSSZ() +} + +func (h *bootstrapAltair) Version() int { + return version.Altair +} + +func (h *bootstrapAltair) Proto() proto.Message { + return h.p +} + +func (h *bootstrapAltair) Header() interfaces.LightClientHeader { + return h.header +} + +func (h *bootstrapAltair) SetHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderAltair) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderAltair{}) + } + h.p.Header = p + h.header = header + return nil +} + +func (h *bootstrapAltair) CurrentSyncCommittee() *pb.SyncCommittee { + return h.p.CurrentSyncCommittee +} + +func (h *bootstrapAltair) SetCurrentSyncCommittee(sc *pb.SyncCommittee) error { + h.p.CurrentSyncCommittee = sc + return nil +} + +func (h *bootstrapAltair) CurrentSyncCommitteeBranch() (interfaces.LightClientSyncCommitteeBranch, error) { + return h.currentSyncCommitteeBranch, nil +} + +func (h *bootstrapAltair) SetCurrentSyncCommitteeBranch(branch [][]byte) error { + if len(branch) != fieldparams.SyncCommitteeBranchDepth { + return fmt.Errorf("branch length %d is not %d", len(branch), fieldparams.SyncCommitteeBranchDepth) + } + newBranch := [fieldparams.SyncCommitteeBranchDepth][32]byte{} + for i, root := range branch { + copy(newBranch[i][:], root) + } + h.currentSyncCommitteeBranch = newBranch + h.p.CurrentSyncCommitteeBranch = branch + return nil +} + +func (h *bootstrapAltair) CurrentSyncCommitteeBranchElectra() (interfaces.LightClientSyncCommitteeBranchElectra, error) { + return [6][32]byte{}, consensustypes.ErrNotSupported("CurrentSyncCommitteeBranchElectra", version.Altair) +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type bootstrapCapella struct { + p *pb.LightClientBootstrapCapella + header interfaces.LightClientHeader + currentSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch +} + +var _ interfaces.LightClientBootstrap = &bootstrapCapella{} + +func NewWrappedBootstrapCapella(p *pb.LightClientBootstrapCapella) (interfaces.LightClientBootstrap, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + + var header interfaces.LightClientHeader + var err error + if p.Header != nil { + header, err = NewWrappedHeader(p.Header) + if err != nil { + return nil, err + } + } + + branch, err := createBranch[interfaces.LightClientSyncCommitteeBranch]( + "sync committee", + p.CurrentSyncCommitteeBranch, + fieldparams.SyncCommitteeBranchDepth, + ) + if err != nil { + return nil, err + } + + return &bootstrapCapella{ + p: p, + header: header, + currentSyncCommitteeBranch: branch, + }, nil +} + +func (h *bootstrapCapella) MarshalSSZTo(dst []byte) ([]byte, error) { + return h.p.MarshalSSZTo(dst) +} + +func (h *bootstrapCapella) MarshalSSZ() ([]byte, error) { + return h.p.MarshalSSZ() +} + +func (h *bootstrapCapella) SizeSSZ() int { + return h.p.SizeSSZ() +} + +func (h *bootstrapCapella) Version() int { + return version.Capella +} + +func (h *bootstrapCapella) Proto() proto.Message { + return h.p +} + +func (h *bootstrapCapella) Header() interfaces.LightClientHeader { + return h.header +} + +func (h *bootstrapCapella) SetHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderCapella) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderCapella{}) + } + h.p.Header = p + h.header = header + return nil +} + +func (h *bootstrapCapella) CurrentSyncCommittee() *pb.SyncCommittee { + return h.p.CurrentSyncCommittee +} + +func (h *bootstrapCapella) SetCurrentSyncCommittee(sc *pb.SyncCommittee) error { + h.p.CurrentSyncCommittee = sc + return nil +} + +func (h *bootstrapCapella) CurrentSyncCommitteeBranch() (interfaces.LightClientSyncCommitteeBranch, error) { + return h.currentSyncCommitteeBranch, nil +} + +func (h *bootstrapCapella) SetCurrentSyncCommitteeBranch(branch [][]byte) error { + if len(branch) != fieldparams.SyncCommitteeBranchDepth { + return fmt.Errorf("branch length %d is not %d", len(branch), fieldparams.SyncCommitteeBranchDepth) + } + newBranch := [fieldparams.SyncCommitteeBranchDepth][32]byte{} + for i, root := range branch { + copy(newBranch[i][:], root) + } + h.currentSyncCommitteeBranch = newBranch + h.p.CurrentSyncCommitteeBranch = branch + return nil +} + +func (h *bootstrapCapella) CurrentSyncCommitteeBranchElectra() (interfaces.LightClientSyncCommitteeBranchElectra, error) { + return [6][32]byte{}, consensustypes.ErrNotSupported("CurrentSyncCommitteeBranchElectra", version.Capella) +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type bootstrapDeneb struct { + p *pb.LightClientBootstrapDeneb + header interfaces.LightClientHeader + currentSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch +} + +var _ interfaces.LightClientBootstrap = &bootstrapDeneb{} + +func NewWrappedBootstrapDeneb(p *pb.LightClientBootstrapDeneb) (interfaces.LightClientBootstrap, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + + var header interfaces.LightClientHeader + var err error + if p.Header != nil { + header, err = NewWrappedHeader(p.Header) + if err != nil { + return nil, err + } + } + + branch, err := createBranch[interfaces.LightClientSyncCommitteeBranch]( + "sync committee", + p.CurrentSyncCommitteeBranch, + fieldparams.SyncCommitteeBranchDepth, + ) + if err != nil { + return nil, err + } + + return &bootstrapDeneb{ + p: p, + header: header, + currentSyncCommitteeBranch: branch, + }, nil +} + +func (h *bootstrapDeneb) MarshalSSZTo(dst []byte) ([]byte, error) { + return h.p.MarshalSSZTo(dst) +} + +func (h *bootstrapDeneb) MarshalSSZ() ([]byte, error) { + return h.p.MarshalSSZ() +} + +func (h *bootstrapDeneb) SizeSSZ() int { + return h.p.SizeSSZ() +} + +func (h *bootstrapDeneb) Version() int { + return version.Deneb +} + +func (h *bootstrapDeneb) Proto() proto.Message { + return h.p +} + +func (h *bootstrapDeneb) Header() interfaces.LightClientHeader { + return h.header +} + +func (h *bootstrapDeneb) SetHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderDeneb{}) + } + h.p.Header = p + h.header = header + return nil +} + +func (h *bootstrapDeneb) CurrentSyncCommittee() *pb.SyncCommittee { + return h.p.CurrentSyncCommittee +} + +func (h *bootstrapDeneb) SetCurrentSyncCommittee(sc *pb.SyncCommittee) error { + h.p.CurrentSyncCommittee = sc + return nil +} + +func (h *bootstrapDeneb) CurrentSyncCommitteeBranch() (interfaces.LightClientSyncCommitteeBranch, error) { + return h.currentSyncCommitteeBranch, nil +} + +func (h *bootstrapDeneb) SetCurrentSyncCommitteeBranch(branch [][]byte) error { + if len(branch) != fieldparams.SyncCommitteeBranchDepth { + return fmt.Errorf("branch length %d is not %d", len(branch), fieldparams.SyncCommitteeBranchDepth) + } + newBranch := [fieldparams.SyncCommitteeBranchDepth][32]byte{} + for i, root := range branch { + copy(newBranch[i][:], root) + } + h.currentSyncCommitteeBranch = newBranch + h.p.CurrentSyncCommitteeBranch = branch + return nil +} + +func (h *bootstrapDeneb) CurrentSyncCommitteeBranchElectra() (interfaces.LightClientSyncCommitteeBranchElectra, error) { + return [6][32]byte{}, consensustypes.ErrNotSupported("CurrentSyncCommitteeBranchElectra", version.Deneb) +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type bootstrapElectra struct { + p *pb.LightClientBootstrapElectra + header interfaces.LightClientHeader + currentSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranchElectra +} + +var _ interfaces.LightClientBootstrap = &bootstrapElectra{} + +func NewWrappedBootstrapElectra(p *pb.LightClientBootstrapElectra) (interfaces.LightClientBootstrap, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + + var header interfaces.LightClientHeader + var err error + if p.Header != nil { + header, err = NewWrappedHeader(p.Header) + if err != nil { + return nil, err + } + } + + branch, err := createBranch[interfaces.LightClientSyncCommitteeBranchElectra]( + "sync committee", + p.CurrentSyncCommitteeBranch, + fieldparams.SyncCommitteeBranchDepthElectra, + ) + if err != nil { + return nil, err + } + + return &bootstrapElectra{ + p: p, + header: header, + currentSyncCommitteeBranch: branch, + }, nil +} + +func (h *bootstrapElectra) MarshalSSZTo(dst []byte) ([]byte, error) { + return h.p.MarshalSSZTo(dst) +} + +func (h *bootstrapElectra) MarshalSSZ() ([]byte, error) { + return h.p.MarshalSSZ() +} + +func (h *bootstrapElectra) SizeSSZ() int { + return h.p.SizeSSZ() +} + +func (h *bootstrapElectra) Version() int { + return version.Electra +} + +func (h *bootstrapElectra) Proto() proto.Message { + return h.p +} + +func (h *bootstrapElectra) Header() interfaces.LightClientHeader { + return h.header +} + +func (h *bootstrapElectra) SetHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderDeneb{}) + } + h.p.Header = p + h.header = header + return nil +} + +func (h *bootstrapElectra) CurrentSyncCommittee() *pb.SyncCommittee { + return h.p.CurrentSyncCommittee +} + +func (h *bootstrapElectra) SetCurrentSyncCommittee(sc *pb.SyncCommittee) error { + h.p.CurrentSyncCommittee = sc + return nil +} + +func (h *bootstrapElectra) CurrentSyncCommitteeBranch() (interfaces.LightClientSyncCommitteeBranch, error) { + return [5][32]byte{}, consensustypes.ErrNotSupported("CurrentSyncCommitteeBranch", version.Electra) +} + +func (h *bootstrapElectra) SetCurrentSyncCommitteeBranch(branch [][]byte) error { + if len(branch) != fieldparams.SyncCommitteeBranchDepthElectra { + return fmt.Errorf("branch length %d is not %d", len(branch), fieldparams.SyncCommitteeBranchDepthElectra) + } + newBranch := [fieldparams.SyncCommitteeBranchDepthElectra][32]byte{} + for i, root := range branch { + copy(newBranch[i][:], root) + } + h.currentSyncCommitteeBranch = newBranch + h.p.CurrentSyncCommitteeBranch = branch + return nil +} + +func (h *bootstrapElectra) CurrentSyncCommitteeBranchElectra() (interfaces.LightClientSyncCommitteeBranchElectra, error) { + return h.currentSyncCommitteeBranch, nil +} diff --git a/consensus-types/light-client/finality_update.go b/consensus-types/light-client/finality_update.go new file mode 100644 index 000000000000..d728130ccd8e --- /dev/null +++ b/consensus-types/light-client/finality_update.go @@ -0,0 +1,499 @@ +package light_client + +import ( + "fmt" + + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "google.golang.org/protobuf/proto" +) + +func NewWrappedFinalityUpdate(m proto.Message) (interfaces.LightClientFinalityUpdate, error) { + if m == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + switch t := m.(type) { + case *pb.LightClientFinalityUpdateAltair: + return NewWrappedFinalityUpdateAltair(t) + case *pb.LightClientFinalityUpdateCapella: + return NewWrappedFinalityUpdateCapella(t) + case *pb.LightClientFinalityUpdateDeneb: + return NewWrappedFinalityUpdateDeneb(t) + case *pb.LightClientFinalityUpdateElectra: + return NewWrappedFinalityUpdateElectra(t) + default: + return nil, fmt.Errorf("cannot construct light client finality update from type %T", t) + } +} + +func NewFinalityUpdateFromUpdate(update interfaces.LightClientUpdate) (interfaces.LightClientFinalityUpdate, error) { + switch t := update.(type) { + case *updateAltair: + return &finalityUpdateAltair{ + p: &pb.LightClientFinalityUpdateAltair{ + AttestedHeader: t.p.AttestedHeader, + FinalizedHeader: t.p.FinalizedHeader, + FinalityBranch: t.p.FinalityBranch, + SyncAggregate: t.p.SyncAggregate, + SignatureSlot: t.p.SignatureSlot, + }, + attestedHeader: t.attestedHeader, + finalizedHeader: t.finalizedHeader, + finalityBranch: t.finalityBranch, + }, nil + case *updateCapella: + return &finalityUpdateCapella{ + p: &pb.LightClientFinalityUpdateCapella{ + AttestedHeader: t.p.AttestedHeader, + FinalizedHeader: t.p.FinalizedHeader, + FinalityBranch: t.p.FinalityBranch, + SyncAggregate: t.p.SyncAggregate, + SignatureSlot: t.p.SignatureSlot, + }, + attestedHeader: t.attestedHeader, + finalizedHeader: t.finalizedHeader, + finalityBranch: t.finalityBranch, + }, nil + case *updateDeneb: + return &finalityUpdateDeneb{ + p: &pb.LightClientFinalityUpdateDeneb{ + AttestedHeader: t.p.AttestedHeader, + FinalizedHeader: t.p.FinalizedHeader, + FinalityBranch: t.p.FinalityBranch, + SyncAggregate: t.p.SyncAggregate, + SignatureSlot: t.p.SignatureSlot, + }, + attestedHeader: t.attestedHeader, + finalizedHeader: t.finalizedHeader, + finalityBranch: t.finalityBranch, + }, nil + case *updateElectra: + return &finalityUpdateElectra{ + p: &pb.LightClientFinalityUpdateElectra{ + AttestedHeader: t.p.AttestedHeader, + FinalizedHeader: t.p.FinalizedHeader, + FinalityBranch: t.p.FinalityBranch, + SyncAggregate: t.p.SyncAggregate, + SignatureSlot: t.p.SignatureSlot, + }, + attestedHeader: t.attestedHeader, + finalizedHeader: t.finalizedHeader, + finalityBranch: t.finalityBranch, + }, nil + default: + return nil, fmt.Errorf("unsupported type %T", t) + } +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type finalityUpdateAltair struct { + p *pb.LightClientFinalityUpdateAltair + attestedHeader interfaces.LightClientHeader + finalizedHeader interfaces.LightClientHeader + finalityBranch interfaces.LightClientFinalityBranch +} + +var _ interfaces.LightClientFinalityUpdate = &finalityUpdateAltair{} + +func NewWrappedFinalityUpdateAltair(p *pb.LightClientFinalityUpdateAltair) (interfaces.LightClientFinalityUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + attestedHeader, err := NewWrappedHeader(p.AttestedHeader) + if err != nil { + return nil, err + } + finalizedHeader, err := NewWrappedHeader(p.FinalizedHeader) + if err != nil { + return nil, err + } + branch, err := createBranch[interfaces.LightClientFinalityBranch]( + "finality", + p.FinalityBranch, + fieldparams.FinalityBranchDepth, + ) + if err != nil { + return nil, err + } + + return &finalityUpdateAltair{ + p: p, + attestedHeader: attestedHeader, + finalizedHeader: finalizedHeader, + finalityBranch: branch, + }, nil +} + +func (u *finalityUpdateAltair) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *finalityUpdateAltair) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *finalityUpdateAltair) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *finalityUpdateAltair) UnmarshalSSZ(buf []byte) error { + p := &pb.LightClientFinalityUpdateAltair{} + if err := p.UnmarshalSSZ(buf); err != nil { + return err + } + updateInterface, err := NewWrappedFinalityUpdateAltair(p) + if err != nil { + return err + } + update, ok := updateInterface.(*finalityUpdateAltair) + if !ok { + return fmt.Errorf("unexpected update type %T", updateInterface) + } + *u = *update + return nil +} + +func (u *finalityUpdateAltair) Proto() proto.Message { + return u.p +} + +func (u *finalityUpdateAltair) Version() int { + return version.Altair +} + +func (u *finalityUpdateAltair) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *finalityUpdateAltair) FinalizedHeader() interfaces.LightClientHeader { + return u.finalizedHeader +} + +func (u *finalityUpdateAltair) FinalityBranch() (interfaces.LightClientFinalityBranch, error) { + return u.finalityBranch, nil +} + +func (u *finalityUpdateAltair) FinalityBranchElectra() (interfaces.LightClientFinalityBranchElectra, error) { + return interfaces.LightClientFinalityBranchElectra{}, consensustypes.ErrNotSupported("FinalityBranchElectra", u.Version()) +} + +func (u *finalityUpdateAltair) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *finalityUpdateAltair) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type finalityUpdateCapella struct { + p *pb.LightClientFinalityUpdateCapella + attestedHeader interfaces.LightClientHeader + finalizedHeader interfaces.LightClientHeader + finalityBranch interfaces.LightClientFinalityBranch +} + +var _ interfaces.LightClientFinalityUpdate = &finalityUpdateCapella{} + +func NewWrappedFinalityUpdateCapella(p *pb.LightClientFinalityUpdateCapella) (interfaces.LightClientFinalityUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + attestedHeader, err := NewWrappedHeader(p.AttestedHeader) + if err != nil { + return nil, err + } + finalizedHeader, err := NewWrappedHeader(p.FinalizedHeader) + if err != nil { + return nil, err + } + branch, err := createBranch[interfaces.LightClientFinalityBranch]( + "finality", + p.FinalityBranch, + fieldparams.FinalityBranchDepth, + ) + if err != nil { + return nil, err + } + + return &finalityUpdateCapella{ + p: p, + attestedHeader: attestedHeader, + finalizedHeader: finalizedHeader, + finalityBranch: branch, + }, nil +} + +func (u *finalityUpdateCapella) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *finalityUpdateCapella) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *finalityUpdateCapella) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *finalityUpdateCapella) UnmarshalSSZ(buf []byte) error { + p := &pb.LightClientFinalityUpdateCapella{} + if err := p.UnmarshalSSZ(buf); err != nil { + return err + } + updateInterface, err := NewWrappedFinalityUpdateCapella(p) + if err != nil { + return err + } + update, ok := updateInterface.(*finalityUpdateCapella) + if !ok { + return fmt.Errorf("unexpected update type %T", updateInterface) + } + *u = *update + return nil +} + +func (u *finalityUpdateCapella) Proto() proto.Message { + return u.p +} + +func (u *finalityUpdateCapella) Version() int { + return version.Capella +} + +func (u *finalityUpdateCapella) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *finalityUpdateCapella) FinalizedHeader() interfaces.LightClientHeader { + return u.finalizedHeader +} + +func (u *finalityUpdateCapella) FinalityBranch() (interfaces.LightClientFinalityBranch, error) { + return u.finalityBranch, nil +} + +func (u *finalityUpdateCapella) FinalityBranchElectra() (interfaces.LightClientFinalityBranchElectra, error) { + return interfaces.LightClientFinalityBranchElectra{}, consensustypes.ErrNotSupported("FinalityBranchElectra", u.Version()) +} + +func (u *finalityUpdateCapella) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *finalityUpdateCapella) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type finalityUpdateDeneb struct { + p *pb.LightClientFinalityUpdateDeneb + attestedHeader interfaces.LightClientHeader + finalizedHeader interfaces.LightClientHeader + finalityBranch interfaces.LightClientFinalityBranch +} + +var _ interfaces.LightClientFinalityUpdate = &finalityUpdateDeneb{} + +func NewWrappedFinalityUpdateDeneb(p *pb.LightClientFinalityUpdateDeneb) (interfaces.LightClientFinalityUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + attestedHeader, err := NewWrappedHeader(p.AttestedHeader) + if err != nil { + return nil, err + } + finalizedHeader, err := NewWrappedHeader(p.FinalizedHeader) + if err != nil { + return nil, err + } + branch, err := createBranch[interfaces.LightClientFinalityBranch]( + "finality", + p.FinalityBranch, + fieldparams.FinalityBranchDepth, + ) + if err != nil { + return nil, err + } + + return &finalityUpdateDeneb{ + p: p, + attestedHeader: attestedHeader, + finalizedHeader: finalizedHeader, + finalityBranch: branch, + }, nil +} + +func (u *finalityUpdateDeneb) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *finalityUpdateDeneb) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *finalityUpdateDeneb) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *finalityUpdateDeneb) UnmarshalSSZ(buf []byte) error { + p := &pb.LightClientFinalityUpdateDeneb{} + if err := p.UnmarshalSSZ(buf); err != nil { + return err + } + updateInterface, err := NewWrappedFinalityUpdateDeneb(p) + if err != nil { + return err + } + update, ok := updateInterface.(*finalityUpdateDeneb) + if !ok { + return fmt.Errorf("unexpected update type %T", updateInterface) + } + *u = *update + return nil +} + +func (u *finalityUpdateDeneb) Proto() proto.Message { + return u.p +} + +func (u *finalityUpdateDeneb) Version() int { + return version.Deneb +} + +func (u *finalityUpdateDeneb) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *finalityUpdateDeneb) FinalizedHeader() interfaces.LightClientHeader { + return u.finalizedHeader +} + +func (u *finalityUpdateDeneb) FinalityBranch() (interfaces.LightClientFinalityBranch, error) { + return u.finalityBranch, nil +} + +func (u *finalityUpdateDeneb) FinalityBranchElectra() (interfaces.LightClientFinalityBranchElectra, error) { + return interfaces.LightClientFinalityBranchElectra{}, consensustypes.ErrNotSupported("FinalityBranchElectra", u.Version()) +} + +func (u *finalityUpdateDeneb) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *finalityUpdateDeneb) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type finalityUpdateElectra struct { + p *pb.LightClientFinalityUpdateElectra + attestedHeader interfaces.LightClientHeader + finalizedHeader interfaces.LightClientHeader + finalityBranch interfaces.LightClientFinalityBranchElectra +} + +var _ interfaces.LightClientFinalityUpdate = &finalityUpdateElectra{} + +func NewWrappedFinalityUpdateElectra(p *pb.LightClientFinalityUpdateElectra) (interfaces.LightClientFinalityUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + attestedHeader, err := NewWrappedHeader(p.AttestedHeader) + if err != nil { + return nil, err + } + finalizedHeader, err := NewWrappedHeader(p.FinalizedHeader) + if err != nil { + return nil, err + } + + finalityBranch, err := createBranch[interfaces.LightClientFinalityBranchElectra]( + "finality", + p.FinalityBranch, + fieldparams.FinalityBranchDepthElectra, + ) + if err != nil { + return nil, err + } + + return &finalityUpdateElectra{ + p: p, + attestedHeader: attestedHeader, + finalizedHeader: finalizedHeader, + finalityBranch: finalityBranch, + }, nil +} + +func (u *finalityUpdateElectra) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *finalityUpdateElectra) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *finalityUpdateElectra) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *finalityUpdateElectra) UnmarshalSSZ(buf []byte) error { + p := &pb.LightClientFinalityUpdateElectra{} + if err := p.UnmarshalSSZ(buf); err != nil { + return err + } + updateInterface, err := NewWrappedFinalityUpdateElectra(p) + if err != nil { + return err + } + update, ok := updateInterface.(*finalityUpdateElectra) + if !ok { + return fmt.Errorf("unexpected update type %T", updateInterface) + } + *u = *update + return nil +} + +func (u *finalityUpdateElectra) Proto() proto.Message { + return u.p +} + +func (u *finalityUpdateElectra) Version() int { + return version.Electra +} + +func (u *finalityUpdateElectra) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *finalityUpdateElectra) FinalizedHeader() interfaces.LightClientHeader { + return u.finalizedHeader +} + +func (u *finalityUpdateElectra) FinalityBranch() (interfaces.LightClientFinalityBranch, error) { + return interfaces.LightClientFinalityBranch{}, consensustypes.ErrNotSupported("FinalityBranch", u.Version()) +} + +func (u *finalityUpdateElectra) FinalityBranchElectra() (interfaces.LightClientFinalityBranchElectra, error) { + return u.finalityBranch, nil +} + +func (u *finalityUpdateElectra) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *finalityUpdateElectra) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} diff --git a/consensus-types/light-client/header.go b/consensus-types/light-client/header.go new file mode 100644 index 000000000000..4ed8ce0de91d --- /dev/null +++ b/consensus-types/light-client/header.go @@ -0,0 +1,274 @@ +package light_client + +import ( + "fmt" + + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" + consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/time/slots" + "google.golang.org/protobuf/proto" +) + +func NewWrappedHeader(m proto.Message) (interfaces.LightClientHeader, error) { + if m == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + switch t := m.(type) { + case *pb.LightClientHeaderAltair: + return NewWrappedHeaderAltair(t) + case *pb.LightClientHeaderCapella: + return NewWrappedHeaderCapella(t) + case *pb.LightClientHeaderDeneb: + if slots.ToEpoch(t.Beacon.Slot) >= params.BeaconConfig().ElectraForkEpoch { + return NewWrappedHeaderElectra(t) + } + return NewWrappedHeaderDeneb(t) + default: + return nil, fmt.Errorf("cannot construct light client header from type %T", t) + } +} + +type headerAltair struct { + p *pb.LightClientHeaderAltair +} + +var _ interfaces.LightClientHeader = &headerAltair{} + +func NewWrappedHeaderAltair(p *pb.LightClientHeaderAltair) (interfaces.LightClientHeader, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + return &headerAltair{p: p}, nil +} + +func (h *headerAltair) MarshalSSZTo(dst []byte) ([]byte, error) { + return h.p.MarshalSSZTo(dst) +} + +func (h *headerAltair) MarshalSSZ() ([]byte, error) { + return h.p.MarshalSSZ() +} + +func (h *headerAltair) SizeSSZ() int { + return h.p.SizeSSZ() +} + +func (h *headerAltair) Proto() proto.Message { + return h.p +} + +func (h *headerAltair) Version() int { + return version.Altair +} + +func (h *headerAltair) Beacon() *pb.BeaconBlockHeader { + return h.p.Beacon +} + +func (h *headerAltair) Execution() (interfaces.ExecutionData, error) { + return nil, consensustypes.ErrNotSupported("Execution", h.Version()) +} + +func (h *headerAltair) ExecutionBranch() (interfaces.LightClientExecutionBranch, error) { + return interfaces.LightClientExecutionBranch{}, consensustypes.ErrNotSupported("ExecutionBranch", h.Version()) +} + +type headerCapella struct { + p *pb.LightClientHeaderCapella + execution interfaces.ExecutionData + executionBranch interfaces.LightClientExecutionBranch +} + +var _ interfaces.LightClientHeader = &headerCapella{} + +func NewWrappedHeaderCapella(p *pb.LightClientHeaderCapella) (interfaces.LightClientHeader, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + execution, err := blocks.WrappedExecutionPayloadHeaderCapella(p.Execution) + if err != nil { + return nil, err + } + + branch, err := createBranch[interfaces.LightClientExecutionBranch]( + "execution", + p.ExecutionBranch, + fieldparams.ExecutionBranchDepth, + ) + if err != nil { + return nil, err + } + + return &headerCapella{ + p: p, + execution: execution, + executionBranch: branch, + }, nil +} + +func (h *headerCapella) MarshalSSZTo(dst []byte) ([]byte, error) { + return h.p.MarshalSSZTo(dst) +} + +func (h *headerCapella) MarshalSSZ() ([]byte, error) { + return h.p.MarshalSSZ() +} + +func (h *headerCapella) SizeSSZ() int { + return h.p.SizeSSZ() +} + +func (h *headerCapella) Proto() proto.Message { + return h.p +} + +func (h *headerCapella) Version() int { + return version.Capella +} + +func (h *headerCapella) Beacon() *pb.BeaconBlockHeader { + return h.p.Beacon +} + +func (h *headerCapella) Execution() (interfaces.ExecutionData, error) { + return h.execution, nil +} + +func (h *headerCapella) ExecutionBranch() (interfaces.LightClientExecutionBranch, error) { + return h.executionBranch, nil +} + +type headerDeneb struct { + p *pb.LightClientHeaderDeneb + execution interfaces.ExecutionData + executionBranch interfaces.LightClientExecutionBranch +} + +var _ interfaces.LightClientHeader = &headerDeneb{} + +func NewWrappedHeaderDeneb(p *pb.LightClientHeaderDeneb) (interfaces.LightClientHeader, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + execution, err := blocks.WrappedExecutionPayloadHeaderDeneb(p.Execution) + if err != nil { + return nil, err + } + + branch, err := createBranch[interfaces.LightClientExecutionBranch]( + "execution", + p.ExecutionBranch, + fieldparams.ExecutionBranchDepth, + ) + if err != nil { + return nil, err + } + + return &headerDeneb{ + p: p, + execution: execution, + executionBranch: branch, + }, nil +} + +func (h *headerDeneb) MarshalSSZTo(dst []byte) ([]byte, error) { + return h.p.MarshalSSZTo(dst) +} + +func (h *headerDeneb) MarshalSSZ() ([]byte, error) { + return h.p.MarshalSSZ() +} + +func (h *headerDeneb) SizeSSZ() int { + return h.p.SizeSSZ() +} + +func (h *headerDeneb) Proto() proto.Message { + return h.p +} + +func (h *headerDeneb) Version() int { + return version.Deneb +} + +func (h *headerDeneb) Beacon() *pb.BeaconBlockHeader { + return h.p.Beacon +} + +func (h *headerDeneb) Execution() (interfaces.ExecutionData, error) { + return h.execution, nil +} + +func (h *headerDeneb) ExecutionBranch() (interfaces.LightClientExecutionBranch, error) { + return h.executionBranch, nil +} + +type headerElectra struct { + p *pb.LightClientHeaderDeneb + execution interfaces.ExecutionData + executionBranch interfaces.LightClientExecutionBranch +} + +var _ interfaces.LightClientHeader = &headerElectra{} + +func NewWrappedHeaderElectra(p *pb.LightClientHeaderDeneb) (interfaces.LightClientHeader, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + execution, err := blocks.WrappedExecutionPayloadHeaderDeneb(p.Execution) + if err != nil { + return nil, err + } + + branch, err := createBranch[interfaces.LightClientExecutionBranch]( + "execution", + p.ExecutionBranch, + fieldparams.ExecutionBranchDepth, + ) + if err != nil { + return nil, err + } + + return &headerElectra{ + p: p, + execution: execution, + executionBranch: branch, + }, nil +} + +func (h *headerElectra) MarshalSSZTo(dst []byte) ([]byte, error) { + return h.p.MarshalSSZTo(dst) +} + +func (h *headerElectra) MarshalSSZ() ([]byte, error) { + return h.p.MarshalSSZ() +} + +func (h *headerElectra) SizeSSZ() int { + return h.p.SizeSSZ() +} + +func (h *headerElectra) Proto() proto.Message { + return h.p +} + +func (h *headerElectra) Version() int { + return version.Electra +} + +func (h *headerElectra) Beacon() *pb.BeaconBlockHeader { + return h.p.Beacon +} + +func (h *headerElectra) Execution() (interfaces.ExecutionData, error) { + return h.execution, nil +} + +func (h *headerElectra) ExecutionBranch() (interfaces.LightClientExecutionBranch, error) { + return h.executionBranch, nil +} diff --git a/consensus-types/light-client/helpers.go b/consensus-types/light-client/helpers.go new file mode 100644 index 000000000000..8a6313b42943 --- /dev/null +++ b/consensus-types/light-client/helpers.go @@ -0,0 +1,29 @@ +package light_client + +import ( + "fmt" + + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" +) + +type branchConstraint interface { + [4][fieldparams.RootLength]byte | [5][fieldparams.RootLength]byte | [6][fieldparams.RootLength]byte | [7][fieldparams.RootLength]byte +} + +func createBranch[T branchConstraint](name string, input [][]byte, depth int) (T, error) { + var zero T + + if len(input) != depth { + return zero, fmt.Errorf("%s branch has %d leaves instead of expected %d", name, len(input), depth) + } + var branch T + for i, leaf := range input { + if len(leaf) != fieldparams.RootLength { + return zero, fmt.Errorf("%s branch leaf at index %d has length %d instead of expected %d", name, i, len(leaf), fieldparams.RootLength) + } + branch[i] = bytesutil.ToBytes32(leaf) + } + + return branch, nil +} diff --git a/consensus-types/light-client/optimistic_update.go b/consensus-types/light-client/optimistic_update.go new file mode 100644 index 000000000000..15fa12eb62b1 --- /dev/null +++ b/consensus-types/light-client/optimistic_update.go @@ -0,0 +1,293 @@ +package light_client + +import ( + "fmt" + + consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "google.golang.org/protobuf/proto" +) + +func NewWrappedOptimisticUpdate(m proto.Message) (interfaces.LightClientOptimisticUpdate, error) { + if m == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + switch t := m.(type) { + case *pb.LightClientOptimisticUpdateAltair: + return NewWrappedOptimisticUpdateAltair(t) + case *pb.LightClientOptimisticUpdateCapella: + return NewWrappedOptimisticUpdateCapella(t) + case *pb.LightClientOptimisticUpdateDeneb: + return NewWrappedOptimisticUpdateDeneb(t) + default: + return nil, fmt.Errorf("cannot construct light client optimistic update from type %T", t) + } +} + +func NewOptimisticUpdateFromUpdate(update interfaces.LightClientUpdate) (interfaces.LightClientOptimisticUpdate, error) { + switch t := update.(type) { + case *updateAltair: + return &optimisticUpdateAltair{ + p: &pb.LightClientOptimisticUpdateAltair{ + AttestedHeader: t.p.AttestedHeader, + SyncAggregate: t.p.SyncAggregate, + SignatureSlot: t.p.SignatureSlot, + }, + attestedHeader: t.attestedHeader, + }, nil + case *updateCapella: + return &optimisticUpdateCapella{ + p: &pb.LightClientOptimisticUpdateCapella{ + AttestedHeader: t.p.AttestedHeader, + SyncAggregate: t.p.SyncAggregate, + SignatureSlot: t.p.SignatureSlot, + }, + attestedHeader: t.attestedHeader, + }, nil + case *updateDeneb: + return &optimisticUpdateDeneb{ + p: &pb.LightClientOptimisticUpdateDeneb{ + AttestedHeader: t.p.AttestedHeader, + SyncAggregate: t.p.SyncAggregate, + SignatureSlot: t.p.SignatureSlot, + }, + attestedHeader: t.attestedHeader, + }, nil + case *updateElectra: + return &optimisticUpdateDeneb{ + p: &pb.LightClientOptimisticUpdateDeneb{ + AttestedHeader: t.p.AttestedHeader, + SyncAggregate: t.p.SyncAggregate, + SignatureSlot: t.p.SignatureSlot, + }, + attestedHeader: t.attestedHeader, + }, nil + default: + return nil, fmt.Errorf("unsupported type %T", t) + } +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type optimisticUpdateAltair struct { + p *pb.LightClientOptimisticUpdateAltair + attestedHeader interfaces.LightClientHeader +} + +var _ interfaces.LightClientOptimisticUpdate = &optimisticUpdateAltair{} + +func NewWrappedOptimisticUpdateAltair(p *pb.LightClientOptimisticUpdateAltair) (interfaces.LightClientOptimisticUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + attestedHeader, err := NewWrappedHeaderAltair(p.AttestedHeader) + if err != nil { + return nil, err + } + + return &optimisticUpdateAltair{ + p: p, + attestedHeader: attestedHeader, + }, nil +} + +func (u *optimisticUpdateAltair) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *optimisticUpdateAltair) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *optimisticUpdateAltair) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *optimisticUpdateAltair) UnmarshalSSZ(buf []byte) error { + p := &pb.LightClientOptimisticUpdateAltair{} + if err := p.UnmarshalSSZ(buf); err != nil { + return err + } + updateInterface, err := NewWrappedOptimisticUpdateAltair(p) + if err != nil { + return err + } + update, ok := updateInterface.(*optimisticUpdateAltair) + if !ok { + return fmt.Errorf("unexpected update type %T", updateInterface) + } + *u = *update + return nil +} + +func (u *optimisticUpdateAltair) Proto() proto.Message { + return u.p +} + +func (u *optimisticUpdateAltair) Version() int { + return version.Altair +} + +func (u *optimisticUpdateAltair) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *optimisticUpdateAltair) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *optimisticUpdateAltair) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type optimisticUpdateCapella struct { + p *pb.LightClientOptimisticUpdateCapella + attestedHeader interfaces.LightClientHeader +} + +var _ interfaces.LightClientOptimisticUpdate = &optimisticUpdateCapella{} + +func NewWrappedOptimisticUpdateCapella(p *pb.LightClientOptimisticUpdateCapella) (interfaces.LightClientOptimisticUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + attestedHeader, err := NewWrappedHeaderCapella(p.AttestedHeader) + if err != nil { + return nil, err + } + + return &optimisticUpdateCapella{ + p: p, + attestedHeader: attestedHeader, + }, nil +} + +func (u *optimisticUpdateCapella) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *optimisticUpdateCapella) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *optimisticUpdateCapella) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *optimisticUpdateCapella) UnmarshalSSZ(buf []byte) error { + p := &pb.LightClientOptimisticUpdateCapella{} + if err := p.UnmarshalSSZ(buf); err != nil { + return err + } + updateInterface, err := NewWrappedOptimisticUpdateCapella(p) + if err != nil { + return err + } + update, ok := updateInterface.(*optimisticUpdateCapella) + if !ok { + return fmt.Errorf("unexpected update type %T", updateInterface) + } + *u = *update + return nil +} + +func (u *optimisticUpdateCapella) Proto() proto.Message { + return u.p +} + +func (u *optimisticUpdateCapella) Version() int { + return version.Capella +} + +func (u *optimisticUpdateCapella) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *optimisticUpdateCapella) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *optimisticUpdateCapella) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type optimisticUpdateDeneb struct { + p *pb.LightClientOptimisticUpdateDeneb + attestedHeader interfaces.LightClientHeader +} + +var _ interfaces.LightClientOptimisticUpdate = &optimisticUpdateDeneb{} + +func NewWrappedOptimisticUpdateDeneb(p *pb.LightClientOptimisticUpdateDeneb) (interfaces.LightClientOptimisticUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + attestedHeader, err := NewWrappedHeaderDeneb(p.AttestedHeader) + if err != nil { + return nil, err + } + + return &optimisticUpdateDeneb{ + p: p, + attestedHeader: attestedHeader, + }, nil +} + +func (u *optimisticUpdateDeneb) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *optimisticUpdateDeneb) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *optimisticUpdateDeneb) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *optimisticUpdateDeneb) UnmarshalSSZ(buf []byte) error { + p := &pb.LightClientOptimisticUpdateDeneb{} + if err := p.UnmarshalSSZ(buf); err != nil { + return err + } + updateInterface, err := NewWrappedOptimisticUpdateDeneb(p) + if err != nil { + return err + } + update, ok := updateInterface.(*optimisticUpdateDeneb) + if !ok { + return fmt.Errorf("unexpected update type %T", updateInterface) + } + *u = *update + return nil +} + +func (u *optimisticUpdateDeneb) Proto() proto.Message { + return u.p +} + +func (u *optimisticUpdateDeneb) Version() int { + return version.Deneb +} + +func (u *optimisticUpdateDeneb) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *optimisticUpdateDeneb) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *optimisticUpdateDeneb) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} diff --git a/consensus-types/light-client/update.go b/consensus-types/light-client/update.go new file mode 100644 index 000000000000..dfa6f1742cf3 --- /dev/null +++ b/consensus-types/light-client/update.go @@ -0,0 +1,701 @@ +package light_client + +import ( + "fmt" + + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "google.golang.org/protobuf/proto" +) + +func NewWrappedUpdate(m proto.Message) (interfaces.LightClientUpdate, error) { + if m == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + switch t := m.(type) { + case *pb.LightClientUpdateAltair: + return NewWrappedUpdateAltair(t) + case *pb.LightClientUpdateCapella: + return NewWrappedUpdateCapella(t) + case *pb.LightClientUpdateDeneb: + return NewWrappedUpdateDeneb(t) + case *pb.LightClientUpdateElectra: + return NewWrappedUpdateElectra(t) + default: + return nil, fmt.Errorf("cannot construct light client update from type %T", t) + } +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. + +type updateAltair struct { + p *pb.LightClientUpdateAltair + attestedHeader interfaces.LightClientHeader + nextSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch + finalizedHeader interfaces.LightClientHeader + finalityBranch interfaces.LightClientFinalityBranch +} + +var _ interfaces.LightClientUpdate = &updateAltair{} + +func NewWrappedUpdateAltair(p *pb.LightClientUpdateAltair) (interfaces.LightClientUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + + attestedHeader, err := NewWrappedHeader(p.AttestedHeader) + if err != nil { + return nil, err + } + + var finalizedHeader interfaces.LightClientHeader + if p.FinalizedHeader != nil { + finalizedHeader, err = NewWrappedHeader(p.FinalizedHeader) + if err != nil { + return nil, err + } + } + + scBranch, err := createBranch[interfaces.LightClientSyncCommitteeBranch]( + "sync committee", + p.NextSyncCommitteeBranch, + fieldparams.SyncCommitteeBranchDepth, + ) + if err != nil { + return nil, err + } + finalityBranch, err := createBranch[interfaces.LightClientFinalityBranch]( + "finality", + p.FinalityBranch, + fieldparams.FinalityBranchDepth, + ) + if err != nil { + return nil, err + } + + return &updateAltair{ + p: p, + attestedHeader: attestedHeader, + nextSyncCommitteeBranch: scBranch, + finalizedHeader: finalizedHeader, + finalityBranch: finalityBranch, + }, nil +} + +func (u *updateAltair) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *updateAltair) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *updateAltair) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *updateAltair) Proto() proto.Message { + return u.p +} + +func (u *updateAltair) Version() int { + return version.Altair +} + +func (u *updateAltair) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *updateAltair) SetAttestedHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderAltair) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderAltair{}) + } + u.p.AttestedHeader = p + u.attestedHeader = header + return nil +} + +func (u *updateAltair) NextSyncCommittee() *pb.SyncCommittee { + return u.p.NextSyncCommittee +} + +func (u *updateAltair) SetNextSyncCommittee(sc *pb.SyncCommittee) { + u.p.NextSyncCommittee = sc +} + +func (u *updateAltair) NextSyncCommitteeBranch() (interfaces.LightClientSyncCommitteeBranch, error) { + return u.nextSyncCommitteeBranch, nil +} + +func (u *updateAltair) SetNextSyncCommitteeBranch(branch [][]byte) error { + b, err := createBranch[interfaces.LightClientSyncCommitteeBranch]("sync committee", branch, fieldparams.SyncCommitteeBranchDepth) + if err != nil { + return err + } + u.nextSyncCommitteeBranch = b + + u.p.NextSyncCommitteeBranch = branch + + return nil +} + +func (u *updateAltair) NextSyncCommitteeBranchElectra() (interfaces.LightClientSyncCommitteeBranchElectra, error) { + return [6][32]byte{}, consensustypes.ErrNotSupported("NextSyncCommitteeBranchElectra", version.Altair) +} + +func (u *updateAltair) FinalizedHeader() interfaces.LightClientHeader { + return u.finalizedHeader +} + +func (u *updateAltair) SetFinalizedHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderAltair) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderAltair{}) + } + u.p.FinalizedHeader = p + u.finalizedHeader = header + return nil +} + +func (u *updateAltair) FinalityBranch() (interfaces.LightClientFinalityBranch, error) { + return u.finalityBranch, nil +} + +func (u *updateAltair) FinalityBranchElectra() (interfaces.LightClientFinalityBranchElectra, error) { + return interfaces.LightClientFinalityBranchElectra{}, consensustypes.ErrNotSupported("FinalityBranchElectra", version.Altair) +} + +func (u *updateAltair) SetFinalityBranch(branch [][]byte) error { + b, err := createBranch[interfaces.LightClientFinalityBranch]("finality", branch, fieldparams.FinalityBranchDepth) + if err != nil { + return err + } + u.finalityBranch = b + u.p.FinalityBranch = branch + return nil +} + +func (u *updateAltair) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *updateAltair) SetSyncAggregate(sa *pb.SyncAggregate) { + u.p.SyncAggregate = sa +} + +func (u *updateAltair) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +func (u *updateAltair) SetSignatureSlot(slot primitives.Slot) { + u.p.SignatureSlot = slot +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type updateCapella struct { + p *pb.LightClientUpdateCapella + attestedHeader interfaces.LightClientHeader + nextSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch + finalizedHeader interfaces.LightClientHeader + finalityBranch interfaces.LightClientFinalityBranch +} + +var _ interfaces.LightClientUpdate = &updateCapella{} + +func NewWrappedUpdateCapella(p *pb.LightClientUpdateCapella) (interfaces.LightClientUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + + attestedHeader, err := NewWrappedHeader(p.AttestedHeader) + if err != nil { + return nil, err + } + + var finalizedHeader interfaces.LightClientHeader + if p.FinalizedHeader != nil { + finalizedHeader, err = NewWrappedHeader(p.FinalizedHeader) + if err != nil { + return nil, err + } + } + + scBranch, err := createBranch[interfaces.LightClientSyncCommitteeBranch]( + "sync committee", + p.NextSyncCommitteeBranch, + fieldparams.SyncCommitteeBranchDepth, + ) + if err != nil { + return nil, err + } + finalityBranch, err := createBranch[interfaces.LightClientFinalityBranch]( + "finality", + p.FinalityBranch, + fieldparams.FinalityBranchDepth, + ) + if err != nil { + return nil, err + } + + return &updateCapella{ + p: p, + attestedHeader: attestedHeader, + nextSyncCommitteeBranch: scBranch, + finalizedHeader: finalizedHeader, + finalityBranch: finalityBranch, + }, nil +} + +func (u *updateCapella) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *updateCapella) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *updateCapella) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *updateCapella) Proto() proto.Message { + return u.p +} + +func (u *updateCapella) Version() int { + return version.Capella +} + +func (u *updateCapella) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *updateCapella) SetAttestedHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderCapella) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderCapella{}) + } + u.p.AttestedHeader = p + u.attestedHeader = header + return nil +} + +func (u *updateCapella) NextSyncCommittee() *pb.SyncCommittee { + return u.p.NextSyncCommittee +} + +func (u *updateCapella) SetNextSyncCommittee(sc *pb.SyncCommittee) { + u.p.NextSyncCommittee = sc +} + +func (u *updateCapella) NextSyncCommitteeBranch() (interfaces.LightClientSyncCommitteeBranch, error) { + return u.nextSyncCommitteeBranch, nil +} + +func (u *updateCapella) SetNextSyncCommitteeBranch(branch [][]byte) error { + b, err := createBranch[interfaces.LightClientSyncCommitteeBranch]("sync committee", branch, fieldparams.SyncCommitteeBranchDepth) + if err != nil { + return err + } + u.nextSyncCommitteeBranch = b + + u.p.NextSyncCommitteeBranch = branch + + return nil +} + +func (u *updateCapella) NextSyncCommitteeBranchElectra() (interfaces.LightClientSyncCommitteeBranchElectra, error) { + return [6][32]byte{}, consensustypes.ErrNotSupported("NextSyncCommitteeBranchElectra", version.Capella) +} + +func (u *updateCapella) FinalizedHeader() interfaces.LightClientHeader { + return u.finalizedHeader +} + +func (u *updateCapella) SetFinalizedHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderCapella) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderCapella{}) + } + u.p.FinalizedHeader = p + u.finalizedHeader = header + return nil +} + +func (u *updateCapella) FinalityBranch() (interfaces.LightClientFinalityBranch, error) { + return u.finalityBranch, nil +} + +func (u *updateCapella) FinalityBranchElectra() (interfaces.LightClientFinalityBranchElectra, error) { + return interfaces.LightClientFinalityBranchElectra{}, consensustypes.ErrNotSupported("FinalityBranchElectra", u.Version()) +} + +func (u *updateCapella) SetFinalityBranch(branch [][]byte) error { + b, err := createBranch[interfaces.LightClientFinalityBranch]("finality", branch, fieldparams.FinalityBranchDepth) + if err != nil { + return err + } + u.finalityBranch = b + u.p.FinalityBranch = branch + return nil +} + +func (u *updateCapella) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *updateCapella) SetSyncAggregate(sa *pb.SyncAggregate) { + u.p.SyncAggregate = sa +} + +func (u *updateCapella) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +func (u *updateCapella) SetSignatureSlot(slot primitives.Slot) { + u.p.SignatureSlot = slot +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type updateDeneb struct { + p *pb.LightClientUpdateDeneb + attestedHeader interfaces.LightClientHeader + nextSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranch + finalizedHeader interfaces.LightClientHeader + finalityBranch interfaces.LightClientFinalityBranch +} + +var _ interfaces.LightClientUpdate = &updateDeneb{} + +func NewWrappedUpdateDeneb(p *pb.LightClientUpdateDeneb) (interfaces.LightClientUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + + attestedHeader, err := NewWrappedHeader(p.AttestedHeader) + if err != nil { + return nil, err + } + + var finalizedHeader interfaces.LightClientHeader + if p.FinalizedHeader != nil { + finalizedHeader, err = NewWrappedHeader(p.FinalizedHeader) + if err != nil { + return nil, err + } + } + + scBranch, err := createBranch[interfaces.LightClientSyncCommitteeBranch]( + "sync committee", + p.NextSyncCommitteeBranch, + fieldparams.SyncCommitteeBranchDepth, + ) + if err != nil { + return nil, err + } + finalityBranch, err := createBranch[interfaces.LightClientFinalityBranch]( + "finality", + p.FinalityBranch, + fieldparams.FinalityBranchDepth, + ) + if err != nil { + return nil, err + } + + return &updateDeneb{ + p: p, + attestedHeader: attestedHeader, + nextSyncCommitteeBranch: scBranch, + finalizedHeader: finalizedHeader, + finalityBranch: finalityBranch, + }, nil +} + +func (u *updateDeneb) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *updateDeneb) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *updateDeneb) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *updateDeneb) Proto() proto.Message { + return u.p +} + +func (u *updateDeneb) Version() int { + return version.Deneb +} + +func (u *updateDeneb) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *updateDeneb) SetAttestedHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderDeneb{}) + } + u.p.AttestedHeader = p + u.attestedHeader = header + return nil +} + +func (u *updateDeneb) NextSyncCommittee() *pb.SyncCommittee { + return u.p.NextSyncCommittee +} + +func (u *updateDeneb) SetNextSyncCommittee(sc *pb.SyncCommittee) { + u.p.NextSyncCommittee = sc +} + +func (u *updateDeneb) NextSyncCommitteeBranch() (interfaces.LightClientSyncCommitteeBranch, error) { + return u.nextSyncCommitteeBranch, nil +} + +func (u *updateDeneb) SetNextSyncCommitteeBranch(branch [][]byte) error { + b, err := createBranch[interfaces.LightClientSyncCommitteeBranch]("sync committee", branch, fieldparams.SyncCommitteeBranchDepth) + if err != nil { + return err + } + u.nextSyncCommitteeBranch = b + + u.p.NextSyncCommitteeBranch = branch + + return nil +} + +func (u *updateDeneb) NextSyncCommitteeBranchElectra() (interfaces.LightClientSyncCommitteeBranchElectra, error) { + return [6][32]byte{}, consensustypes.ErrNotSupported("NextSyncCommitteeBranchElectra", version.Deneb) +} + +func (u *updateDeneb) FinalizedHeader() interfaces.LightClientHeader { + return u.finalizedHeader +} + +func (u *updateDeneb) SetFinalizedHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderDeneb{}) + } + u.p.FinalizedHeader = p + u.finalizedHeader = header + return nil +} + +func (u *updateDeneb) FinalityBranch() (interfaces.LightClientFinalityBranch, error) { + return u.finalityBranch, nil +} + +func (u *updateDeneb) FinalityBranchElectra() (interfaces.LightClientFinalityBranchElectra, error) { + return interfaces.LightClientFinalityBranchElectra{}, consensustypes.ErrNotSupported("FinalityBranchElectra", u.Version()) +} + +func (u *updateDeneb) SetFinalityBranch(branch [][]byte) error { + b, err := createBranch[interfaces.LightClientFinalityBranch]("finality", branch, fieldparams.FinalityBranchDepth) + if err != nil { + return err + } + u.finalityBranch = b + u.p.FinalityBranch = branch + return nil +} + +func (u *updateDeneb) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *updateDeneb) SetSyncAggregate(sa *pb.SyncAggregate) { + u.p.SyncAggregate = sa +} + +func (u *updateDeneb) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +func (u *updateDeneb) SetSignatureSlot(slot primitives.Slot) { + u.p.SignatureSlot = slot +} + +// In addition to the proto object being wrapped, we store some fields that have to be +// constructed from the proto, so that we don't have to reconstruct them every time +// in getters. +type updateElectra struct { + p *pb.LightClientUpdateElectra + attestedHeader interfaces.LightClientHeader + nextSyncCommitteeBranch interfaces.LightClientSyncCommitteeBranchElectra + finalizedHeader interfaces.LightClientHeader + finalityBranch interfaces.LightClientFinalityBranchElectra +} + +var _ interfaces.LightClientUpdate = &updateElectra{} + +func NewWrappedUpdateElectra(p *pb.LightClientUpdateElectra) (interfaces.LightClientUpdate, error) { + if p == nil { + return nil, consensustypes.ErrNilObjectWrapped + } + + attestedHeader, err := NewWrappedHeader(p.AttestedHeader) + if err != nil { + return nil, err + } + + var finalizedHeader interfaces.LightClientHeader + if p.FinalizedHeader != nil { + finalizedHeader, err = NewWrappedHeader(p.FinalizedHeader) + if err != nil { + return nil, err + } + } + + scBranch, err := createBranch[interfaces.LightClientSyncCommitteeBranchElectra]( + "sync committee", + p.NextSyncCommitteeBranch, + fieldparams.SyncCommitteeBranchDepthElectra, + ) + if err != nil { + return nil, err + } + + finalityBranch, err := createBranch[interfaces.LightClientFinalityBranchElectra]( + "finality", + p.FinalityBranch, + fieldparams.FinalityBranchDepthElectra, + ) + if err != nil { + return nil, err + } + + return &updateElectra{ + p: p, + attestedHeader: attestedHeader, + nextSyncCommitteeBranch: scBranch, + finalizedHeader: finalizedHeader, + finalityBranch: finalityBranch, + }, nil +} + +func (u *updateElectra) MarshalSSZTo(dst []byte) ([]byte, error) { + return u.p.MarshalSSZTo(dst) +} + +func (u *updateElectra) MarshalSSZ() ([]byte, error) { + return u.p.MarshalSSZ() +} + +func (u *updateElectra) SizeSSZ() int { + return u.p.SizeSSZ() +} + +func (u *updateElectra) Proto() proto.Message { + return u.p +} + +func (u *updateElectra) Version() int { + return version.Electra +} + +func (u *updateElectra) AttestedHeader() interfaces.LightClientHeader { + return u.attestedHeader +} + +func (u *updateElectra) SetAttestedHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderDeneb{}) + } + u.p.AttestedHeader = p + u.attestedHeader = header + return nil +} + +func (u *updateElectra) NextSyncCommittee() *pb.SyncCommittee { + return u.p.NextSyncCommittee +} + +func (u *updateElectra) SetNextSyncCommittee(sc *pb.SyncCommittee) { + u.p.NextSyncCommittee = sc +} + +func (u *updateElectra) NextSyncCommitteeBranch() (interfaces.LightClientSyncCommitteeBranch, error) { + return [5][32]byte{}, consensustypes.ErrNotSupported("NextSyncCommitteeBranch", version.Electra) +} + +func (u *updateElectra) SetNextSyncCommitteeBranch(branch [][]byte) error { + b, err := createBranch[interfaces.LightClientSyncCommitteeBranchElectra]("sync committee", branch, fieldparams.SyncCommitteeBranchDepthElectra) + if err != nil { + return err + } + u.nextSyncCommitteeBranch = b + + u.p.NextSyncCommitteeBranch = branch + + return nil +} + +func (u *updateElectra) NextSyncCommitteeBranchElectra() (interfaces.LightClientSyncCommitteeBranchElectra, error) { + return u.nextSyncCommitteeBranch, nil +} + +func (u *updateElectra) FinalizedHeader() interfaces.LightClientHeader { + return u.finalizedHeader +} + +func (u *updateElectra) SetFinalizedHeader(header interfaces.LightClientHeader) error { + p, ok := header.Proto().(*pb.LightClientHeaderDeneb) + if !ok { + return fmt.Errorf("header type %T is not %T", header.Proto(), &pb.LightClientHeaderDeneb{}) + } + u.p.FinalizedHeader = p + u.finalizedHeader = header + return nil +} + +func (u *updateElectra) FinalityBranch() (interfaces.LightClientFinalityBranch, error) { + return interfaces.LightClientFinalityBranch{}, consensustypes.ErrNotSupported("FinalityBranch", u.Version()) +} + +func (u *updateElectra) FinalityBranchElectra() (interfaces.LightClientFinalityBranchElectra, error) { + return u.finalityBranch, nil +} + +func (u *updateElectra) SetFinalityBranch(branch [][]byte) error { + b, err := createBranch[interfaces.LightClientFinalityBranchElectra]("finality", branch, fieldparams.FinalityBranchDepthElectra) + if err != nil { + return err + } + u.finalityBranch = b + u.p.FinalityBranch = branch + return nil +} + +func (u *updateElectra) SyncAggregate() *pb.SyncAggregate { + return u.p.SyncAggregate +} + +func (u *updateElectra) SetSyncAggregate(sa *pb.SyncAggregate) { + u.p.SyncAggregate = sa +} + +func (u *updateElectra) SignatureSlot() primitives.Slot { + return u.p.SignatureSlot +} + +func (u *updateElectra) SetSignatureSlot(slot primitives.Slot) { + u.p.SignatureSlot = slot +} diff --git a/consensus-types/mock/BUILD.bazel b/consensus-types/mock/BUILD.bazel index 08384eb05fcf..e7ce82febd6f 100644 --- a/consensus-types/mock/BUILD.bazel +++ b/consensus-types/mock/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "//config/fieldparams:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", + "//proto/engine/v1:go_default_library", "//proto/eth/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", diff --git a/consensus-types/mock/block.go b/consensus-types/mock/block.go index dade8e41c734..a0ad5fb8dcd7 100644 --- a/consensus-types/mock/block.go +++ b/consensus-types/mock/block.go @@ -5,6 +5,7 @@ import ( field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" @@ -162,10 +163,6 @@ func (BeaconBlock) SetParentRoot(_ []byte) { panic("implement me") } -func (BeaconBlock) Copy() (interfaces.ReadOnlyBeaconBlock, error) { - panic("implement me") -} - type BeaconBlockBody struct{} func (BeaconBlockBody) RandaoReveal() [field_params.BLSSignatureLength]byte { @@ -273,6 +270,10 @@ func (b *BeaconBlockBody) BlobKzgCommitments() ([][]byte, error) { panic("implement me") } +func (b *BeaconBlockBody) ExecutionRequests() (*enginev1.ExecutionRequests, error) { + panic("implement me") +} + func (b *BeaconBlockBody) Attestations() []eth.Att { panic("implement me") } diff --git a/consensus-types/payload-attribute/BUILD.bazel b/consensus-types/payload-attribute/BUILD.bazel index dc4d31bfc4df..6dc7e80e9712 100644 --- a/consensus-types/payload-attribute/BUILD.bazel +++ b/consensus-types/payload-attribute/BUILD.bazel @@ -10,8 +10,12 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/payload-attribute", visibility = ["//visibility:public"], deps = [ + "//beacon-chain/state:go_default_library", + "//config/fieldparams:go_default_library", "//consensus-types:go_default_library", "//consensus-types/blocks:go_default_library", + "//consensus-types/interfaces:go_default_library", + "//consensus-types/primitives:go_default_library", "//proto/engine/v1:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/consensus-types/payload-attribute/getters.go b/consensus-types/payload-attribute/getters.go index e32c72336e16..3eee54e14c83 100644 --- a/consensus-types/payload-attribute/getters.go +++ b/consensus-types/payload-attribute/getters.go @@ -38,6 +38,16 @@ func (a *data) Withdrawals() ([]*enginev1.Withdrawal, error) { return a.withdrawals, nil } +func (a *data) ParentBeaconBlockRoot() ([]byte, error) { + if len(a.parentBeaconBlockRoot) == 0 { + return nil, errNoParentRoot + } + if a.version < version.Deneb { + return nil, consensus_types.ErrNotSupported("ParentBeaconBlockRoot", a.version) + } + return a.parentBeaconBlockRoot, nil +} + // PbV1 returns the payload attribute in version 1. func (a *data) PbV1() (*enginev1.PayloadAttributes, error) { if a == nil { @@ -97,6 +107,9 @@ func (a *data) PbV3() (*enginev1.PayloadAttributesV3, error) { // IsEmpty returns whether the given payload attribute is empty func (a *data) IsEmpty() bool { + if a == nil { + return true + } if len(a.PrevRandao()) != 0 { return false } diff --git a/consensus-types/payload-attribute/interface.go b/consensus-types/payload-attribute/interface.go index c36e839e2eba..05f33fdf6283 100644 --- a/consensus-types/payload-attribute/interface.go +++ b/consensus-types/payload-attribute/interface.go @@ -10,6 +10,7 @@ type Attributer interface { Timestamp() uint64 SuggestedFeeRecipient() []byte Withdrawals() ([]*enginev1.Withdrawal, error) + ParentBeaconBlockRoot() ([]byte, error) PbV1() (*enginev1.PayloadAttributes, error) PbV2() (*enginev1.PayloadAttributesV2, error) PbV3() (*enginev1.PayloadAttributesV3, error) diff --git a/consensus-types/payload-attribute/types.go b/consensus-types/payload-attribute/types.go index dbb9c49d38b0..2e71f79615f7 100644 --- a/consensus-types/payload-attribute/types.go +++ b/consensus-types/payload-attribute/types.go @@ -2,7 +2,11 @@ package payloadattribute import ( "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" "github.com/prysmaticlabs/prysm/v5/runtime/version" ) @@ -23,6 +27,7 @@ type data struct { var ( errNilPayloadAttribute = errors.New("received nil payload attribute") errUnsupportedPayloadAttribute = errors.New("unsupported payload attribute") + errNoParentRoot = errors.New("parent root is empty") ) // New returns a new payload attribute with the given input object. @@ -89,3 +94,16 @@ func initPayloadAttributeFromV3(a *enginev1.PayloadAttributesV3) (Attributer, er parentBeaconBlockRoot: a.ParentBeaconBlockRoot, }, nil } + +// EventData holds the values for a PayloadAttributes event. +type EventData struct { + ProposerIndex primitives.ValidatorIndex + ProposalSlot primitives.Slot + ParentBlockNumber uint64 + ParentBlockRoot []byte + ParentBlockHash []byte + Attributer Attributer + HeadState state.BeaconState + HeadBlock interfaces.ReadOnlySignedBeaconBlock + HeadRoot [field_params.RootLength]byte +} diff --git a/consensus-types/primitives/BUILD.bazel b/consensus-types/primitives/BUILD.bazel index 96506f9315f3..f9258a41145c 100644 --- a/consensus-types/primitives/BUILD.bazel +++ b/consensus-types/primitives/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "domain.go", "epoch.go", "execution_address.go", + "kzg.go", "payload_id.go", "randao.go", "slot.go", @@ -21,6 +22,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//math:go_default_library", + "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], diff --git a/consensus-types/primitives/kzg.go b/consensus-types/primitives/kzg.go new file mode 100644 index 000000000000..c59b5557d52f --- /dev/null +++ b/consensus-types/primitives/kzg.go @@ -0,0 +1,15 @@ +package primitives + +import ( + "crypto/sha256" + + "github.com/ethereum/go-ethereum/common" +) + +const blobCommitmentVersionKZG uint8 = 0x01 + +func ConvertKzgCommitmentToVersionedHash(commitment []byte) common.Hash { + versionedHash := sha256.Sum256(commitment) + versionedHash[0] = blobCommitmentVersionKZG + return versionedHash +} diff --git a/consensus-types/wrapper/metadata.go b/consensus-types/wrapper/metadata.go index 824ffa6e95aa..589f365759f9 100644 --- a/consensus-types/wrapper/metadata.go +++ b/consensus-types/wrapper/metadata.go @@ -8,6 +8,9 @@ import ( "google.golang.org/protobuf/proto" ) +// MetadataV0 +// ---------- + // MetadataV0 is a convenience wrapper around our metadata protobuf object. type MetadataV0 struct { md *pb.MetaDataV0 @@ -28,6 +31,11 @@ func (m MetadataV0) AttnetsBitfield() bitfield.Bitvector64 { return m.md.Attnets } +// SyncnetsBitfield returns the bitfield stored in the metadata. +func (m MetadataV0) SyncnetsBitfield() bitfield.Bitvector4 { + return bitfield.Bitvector4{0} +} + // InnerObject returns the underlying metadata protobuf structure. func (m MetadataV0) InnerObject() interface{} { return m.md @@ -74,16 +82,19 @@ func (m MetadataV0) MetadataObjV0() *pb.MetaDataV0 { // MetadataObjV1 returns the inner metadata object in its type // specified form. If it doesn't exist then we return nothing. -func (_ MetadataV0) MetadataObjV1() *pb.MetaDataV1 { +func (MetadataV0) MetadataObjV1() *pb.MetaDataV1 { return nil } // Version returns the fork version of the underlying object. -func (_ MetadataV0) Version() int { +func (MetadataV0) Version() int { return version.Phase0 } -// MetadataV1 is a convenience wrapper around our metadata v2 protobuf object. +// MetadataV1 +// ---------- + +// MetadataV1 is a convenience wrapper around our metadata v1 protobuf object. type MetadataV1 struct { md *pb.MetaDataV1 } @@ -103,6 +114,11 @@ func (m MetadataV1) AttnetsBitfield() bitfield.Bitvector64 { return m.md.Attnets } +// SyncnetsBitfield returns the bitfield stored in the metadata. +func (m MetadataV1) SyncnetsBitfield() bitfield.Bitvector4 { + return m.md.Syncnets +} + // InnerObject returns the underlying metadata protobuf structure. func (m MetadataV1) InnerObject() interface{} { return m.md @@ -143,7 +159,7 @@ func (m MetadataV1) UnmarshalSSZ(buf []byte) error { // MetadataObjV0 returns the inner metadata object in its type // specified form. If it doesn't exist then we return nothing. -func (_ MetadataV1) MetadataObjV0() *pb.MetaDataV0 { +func (MetadataV1) MetadataObjV0() *pb.MetaDataV0 { return nil } @@ -154,6 +170,6 @@ func (m MetadataV1) MetadataObjV1() *pb.MetaDataV1 { } // Version returns the fork version of the underlying object. -func (_ MetadataV1) Version() int { +func (MetadataV1) Version() int { return version.Altair } diff --git a/container/slice/slice.go b/container/slice/slice.go index 1d6d6a99aa3a..638bc67d1d8e 100644 --- a/container/slice/slice.go +++ b/container/slice/slice.go @@ -79,10 +79,10 @@ func UnionUint64(s ...[]uint64) []uint64 { for i := 1; i < len(s); i++ { a := s[i-1] b := s[i] - for j := 0; j < len(a); j++ { + for j := range a { m[a[j]] = true } - for j := 0; j < len(b); j++ { + for j := range b { if _, found := m[b[j]]; !found { set = append(set, b[j]) } @@ -128,10 +128,10 @@ func NotUint64(a, b []uint64) []uint64 { set := make([]uint64, 0) m := make(map[uint64]bool) - for i := 0; i < len(a); i++ { + for i := range a { m[a[i]] = true } - for i := 0; i < len(b); i++ { + for i := range b { if _, found := m[b[i]]; !found { set = append(set, b[i]) } @@ -189,10 +189,10 @@ func UnionInt64(s ...[]int64) []int64 { for i := 1; i < len(s); i++ { a := s[i-1] b := s[i] - for j := 0; j < len(a); j++ { + for j := range a { m[a[j]] = true } - for j := 0; j < len(b); j++ { + for j := range b { if _, found := m[b[j]]; !found { set = append(set, b[j]) } @@ -209,10 +209,10 @@ func NotInt64(a, b []int64) []int64 { set := make([]int64, 0) m := make(map[int64]bool) - for i := 0; i < len(a); i++ { + for i := range a { m[a[i]] = true } - for i := 0; i < len(b); i++ { + for i := range b { if _, found := m[b[i]]; !found { set = append(set, b[i]) } @@ -236,10 +236,10 @@ func UnionByteSlices(s ...[][]byte) [][]byte { set := s[0] m := make(map[string]bool) for i := 1; i < len(s); i++ { - for j := 0; j < len(s[i-1]); j++ { + for j := range s[i-1] { m[string(s[i-1][j])] = true } - for j := 0; j < len(s[i]); j++ { + for j := range s[i] { if _, found := m[string(s[i][j])]; !found { set = append(set, s[i][j]) } @@ -336,10 +336,10 @@ func NotSlot(a, b []primitives.Slot) []primitives.Slot { set := make([]primitives.Slot, 0) m := make(map[primitives.Slot]bool) - for i := 0; i < len(a); i++ { + for i := range a { m[a[i]] = true } - for i := 0; i < len(b); i++ { + for i := range b { if _, found := m[b[i]]; !found { set = append(set, b[i]) } @@ -354,13 +354,13 @@ func IsInSlots(a primitives.Slot, b []primitives.Slot) bool { // Unique returns an array with duplicates filtered based on the type given func Unique[T comparable](a []T) []T { - if a == nil || len(a) <= 1 { + if len(a) <= 1 { return a } found := map[T]bool{} result := make([]T, len(a)) end := 0 - for i := 0; i < len(a); i++ { + for i := range a { if !found[a[i]] { found[a[i]] = true result[end] = a[i] @@ -380,8 +380,8 @@ func Reverse[E any](s []E) []E { } // VerifyMaxLength takes a slice and a maximum length and validates the length. -func VerifyMaxLength[T any](v []T, max int) error { - l := len(v) +func VerifyMaxLength[T any](v []T, max uint64) error { + l := uint64(len(v)) if l > max { return fmt.Errorf("length of %d exceeds max of %d", l, max) } diff --git a/container/trie/sparse_merkle.go b/container/trie/sparse_merkle.go index 6fbb3dc3a9ee..4aea824fba3a 100644 --- a/container/trie/sparse_merkle.go +++ b/container/trie/sparse_merkle.go @@ -259,3 +259,18 @@ func (m *SparseMerkleTrie) NumOfItems() int { } return len(m.originalItems) } + +// ProofFromMerkleLayers creates a proof starting at the leaf index of the merkle layers. +func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex int) [][]byte { + // The merkle tree structure looks as follows: + // [[r1, r2, r3, r4], [parent1, parent2], [root]] + proof := make([][]byte, 0) + currentIndex := startingLeafIndex + for i := 0; i < len(layers)-1; i++ { + neighborIdx := currentIndex ^ 1 + neighbor := layers[i][neighborIdx] + proof = append(proof, neighbor) + currentIndex = currentIndex / 2 + } + return proof +} diff --git a/contracts/deposit/contract_test.go b/contracts/deposit/contract_test.go index d163d07e6bba..892d36df8ee4 100644 --- a/contracts/deposit/contract_test.go +++ b/contracts/deposit/contract_test.go @@ -67,7 +67,7 @@ func TestValidatorRegister_OK(t *testing.T) { }, } - logs, err := testAccount.Backend.FilterLogs(context.Background(), query) + logs, err := testAccount.Backend.Client().FilterLogs(context.Background(), query) assert.NoError(t, err, "Unable to get logs of deposit contract") merkleTreeIndex := make([]uint64, 5) diff --git a/contracts/deposit/mock/BUILD.bazel b/contracts/deposit/mock/BUILD.bazel index 6ad8a6115305..328ec2ad63f5 100644 --- a/contracts/deposit/mock/BUILD.bazel +++ b/contracts/deposit/mock/BUILD.bazel @@ -10,10 +10,9 @@ go_library( "//contracts/deposit:go_default_library", "@com_github_ethereum_go_ethereum//accounts/abi:go_default_library", "@com_github_ethereum_go_ethereum//accounts/abi/bind:go_default_library", - "@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", - "@com_github_ethereum_go_ethereum//core:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_ethereum_go_ethereum//crypto:go_default_library", + "@com_github_ethereum_go_ethereum//ethclient/simulated:go_default_library", ], ) diff --git a/contracts/deposit/mock/mock.go b/contracts/deposit/mock/mock.go index 7e15eeed77b7..030482a2780d 100644 --- a/contracts/deposit/mock/mock.go +++ b/contracts/deposit/mock/mock.go @@ -8,11 +8,10 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient/simulated" "github.com/prysmaticlabs/prysm/v5/contracts/deposit" ) @@ -28,13 +27,13 @@ type TestAccount struct { Addr common.Address ContractAddr common.Address Contract *deposit.DepositContract - Backend *backends.SimulatedBackend + Backend *simulated.Backend TxOpts *bind.TransactOpts } // Setup creates the simulated backend with the deposit contract deployed func Setup() (*TestAccount, error) { - genesis := make(core.GenesisAlloc) + genesis := make(types.GenesisAlloc) privKey, err := crypto.GenerateKey() if err != nil { return nil, err @@ -55,10 +54,10 @@ func Setup() (*TestAccount, error) { return nil, err } startingBalance, _ := new(big.Int).SetString("100000000000000000000000000000000000000", 10) - genesis[addr] = core.GenesisAccount{Balance: startingBalance} - backend := backends.NewSimulatedBackend(genesis, 210000000000) + genesis[addr] = types.Account{Balance: startingBalance} + backend := simulated.NewBackend(genesis, simulated.WithBlockGasLimit(210000000000)) - contractAddr, _, contract, err := DeployDepositContract(txOpts, backend) + contractAddr, _, contract, err := DeployDepositContract(txOpts, backend.Client()) if err != nil { return nil, err } diff --git a/crypto/bls/signature_batch.go b/crypto/bls/signature_batch.go index 526d0c9430ba..607616e5950a 100644 --- a/crypto/bls/signature_batch.go +++ b/crypto/bls/signature_batch.go @@ -77,7 +77,7 @@ func (s *SignatureBatch) VerifyVerbosely() (bool, error) { } } - return false, errors.Errorf(errmsg) + return false, errors.New(errmsg) } // Copy the attached signature batch and return it diff --git a/deps.bzl b/deps.bzl index da7c8c7d02ff..71790e18c797 100644 --- a/deps.bzl +++ b/deps.bzl @@ -37,8 +37,8 @@ def prysm_deps(): go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", - sum = "h1:VUeHARd+9362HPYyFWjsRa6jBIAf2xWbDv6QXMRztbQ=", - version = "v0.5.0-0.dev.0.20231205170804-aef76f4feee2", + sum = "h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=", + version = "v0.5.1", ) go_repository( name = "com_github_aclements_go_moremath", @@ -148,18 +148,18 @@ def prysm_deps(): sum = "h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=", version = "v0.0.0-20180808171621-7fddfc383310", ) + go_repository( + name = "com_github_armon_go_socks5", + importpath = "github.com/armon/go-socks5", + sum = "h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=", + version = "v0.0.0-20160902184237-e75332964ef5", + ) go_repository( name = "com_github_aryann_difflib", importpath = "github.com/aryann/difflib", sum = "h1:pv34s756C4pEXnjgPfGYgdhg/ZdajGhyOvzx8k+23nw=", version = "v0.0.0-20170710044230-e206f873d14a", ) - go_repository( - name = "com_github_asaskevich_govalidator", - importpath = "github.com/asaskevich/govalidator", - sum = "h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=", - version = "v0.0.0-20190424111038-f61b66f89f4a", - ) go_repository( name = "com_github_aws_aws_lambda_go", importpath = "github.com/aws/aws-lambda-go", @@ -274,48 +274,6 @@ def prysm_deps(): sum = "h1:gggzg0SUMs6SQbEw+3LoSsYf9YMjkupeAnHMX8O9mmY=", version = "v1.2.0", ) - go_repository( - name = "com_github_azure_go_autorest", - importpath = "github.com/Azure/go-autorest", - sum = "h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=", - version = "v14.2.0+incompatible", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest", - importpath = "github.com/Azure/go-autorest/autorest", - sum = "h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ=", - version = "v0.11.1", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest_adal", - importpath = "github.com/Azure/go-autorest/autorest/adal", - sum = "h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0=", - version = "v0.9.5", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest_date", - importpath = "github.com/Azure/go-autorest/autorest/date", - sum = "h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=", - version = "v0.3.0", - ) - go_repository( - name = "com_github_azure_go_autorest_autorest_mocks", - importpath = "github.com/Azure/go-autorest/autorest/mocks", - sum = "h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=", - version = "v0.4.1", - ) - go_repository( - name = "com_github_azure_go_autorest_logger", - importpath = "github.com/Azure/go-autorest/logger", - sum = "h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=", - version = "v0.2.0", - ) - go_repository( - name = "com_github_azure_go_autorest_tracing", - importpath = "github.com/Azure/go-autorest/tracing", - sum = "h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=", - version = "v0.6.0", - ) go_repository( name = "com_github_bazelbuild_rules_go", importpath = "github.com/bazelbuild/rules_go", @@ -334,12 +292,6 @@ def prysm_deps(): sum = "h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=", version = "v1.0.1", ) - go_repository( - name = "com_github_bgentry_go_netrc", - importpath = "github.com/bgentry/go-netrc", - sum = "h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=", - version = "v0.0.0-20140422174119-9fd32a8b3d3d", - ) go_repository( name = "com_github_bgentry_speakeasy", importpath = "github.com/bgentry/speakeasy", @@ -349,14 +301,8 @@ def prysm_deps(): go_repository( name = "com_github_bits_and_blooms_bitset", importpath = "github.com/bits-and-blooms/bitset", - sum = "h1:RMyy2mBBShArUAhfVRZJ2xyBO58KCBCtZFShw3umo6k=", - version = "v1.11.0", - ) - go_repository( - name = "com_github_bketelsen_crypt", - importpath = "github.com/bketelsen/crypt", - sum = "h1:+0HFd5KSZ/mm3JmhmrDukiId5iR6w4+BdFtfSy4yWIc=", - version = "v0.0.3-0.20200106085610-5cbc8cc4026c", + sum = "h1:1X2TS7aHz1ELcC0yU1y2stUs/0ig5oMU6STFZGrhvHI=", + version = "v1.17.0", ) go_repository( name = "com_github_bradfitz_go_smtpd", @@ -373,8 +319,8 @@ def prysm_deps(): go_repository( name = "com_github_btcsuite_btcd_btcec_v2", importpath = "github.com/btcsuite/btcd/btcec/v2", - sum = "h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=", - version = "v2.3.2", + sum = "h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=", + version = "v2.3.4", ) go_repository( name = "com_github_btcsuite_btcd_chaincfg_chainhash", @@ -382,12 +328,6 @@ def prysm_deps(): sum = "h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=", version = "v1.0.1", ) - go_repository( - name = "com_github_bufbuild_buf", - importpath = "github.com/bufbuild/buf", - sum = "h1:11zJVA0D4uJVGOC9h+oOVHrKKoBgMYIqJJ0d1Xt6oeQ=", - version = "v0.37.0", - ) go_repository( name = "com_github_buger_jsonparser", importpath = "github.com/buger/jsonparser", @@ -397,8 +337,8 @@ def prysm_deps(): go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", - sum = "h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=", - version = "v1.3.2", + sum = "h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=", + version = "v1.4.1-0.20240526193622-a339e1f7089c", ) go_repository( name = "com_github_burntsushi_xgb", @@ -418,6 +358,12 @@ def prysm_deps(): sum = "h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=", version = "v2.2.1+incompatible", ) + go_repository( + name = "com_github_cenkalti_backoff_v4", + importpath = "github.com/cenkalti/backoff/v4", + sum = "h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=", + version = "v4.3.0", + ) go_repository( name = "com_github_census_instrumentation_opencensus_proto", importpath = "github.com/census-instrumentation/opencensus-proto", @@ -439,26 +385,8 @@ def prysm_deps(): go_repository( name = "com_github_cespare_xxhash_v2", importpath = "github.com/cespare/xxhash/v2", - sum = "h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=", - version = "v2.2.0", - ) - go_repository( - name = "com_github_chromedp_cdproto", - importpath = "github.com/chromedp/cdproto", - sum = "h1:aPflPkRFkVwbW6dmcVqfgwp1i+UWGFH6VgR1Jim5Ygc=", - version = "v0.0.0-20230802225258-3cf4e6d46a89", - ) - go_repository( - name = "com_github_chromedp_chromedp", - importpath = "github.com/chromedp/chromedp", - sum = "h1:dKtNz4kApb06KuSXoTQIyUC2TrA0fhGDwNZf3bcgfKw=", - version = "v0.9.2", - ) - go_repository( - name = "com_github_chromedp_sysutil", - importpath = "github.com/chromedp/sysutil", - sum = "h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=", - version = "v1.0.0", + sum = "h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=", + version = "v2.3.0", ) go_repository( name = "com_github_chzyer_logex", @@ -517,14 +445,14 @@ def prysm_deps(): go_repository( name = "com_github_cncf_udpa_go", importpath = "github.com/cncf/udpa/go", - sum = "h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=", - version = "v0.0.0-20220112060539-c52dc94e7fbe", + sum = "h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=", + version = "v0.0.0-20201120205902-5459f2c99403", ) go_repository( name = "com_github_cncf_xds_go", importpath = "github.com/cncf/xds/go", - sum = "h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=", - version = "v0.0.0-20230607035331-e9ce68804cb4", + sum = "h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI=", + version = "v0.0.0-20240905190251-b4127c9b8d78", ) go_repository( name = "com_github_cockroachdb_datadriven", @@ -536,8 +464,14 @@ def prysm_deps(): name = "com_github_cockroachdb_errors", build_file_proto_mode = "disable_global", importpath = "github.com/cockroachdb/errors", - sum = "h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8=", - version = "v1.11.1", + sum = "h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=", + version = "v1.11.3", + ) + go_repository( + name = "com_github_cockroachdb_fifo", + importpath = "github.com/cockroachdb/fifo", + sum = "h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=", + version = "v0.0.0-20240606204812-0bbfbd93a7ce", ) go_repository( name = "com_github_cockroachdb_logtags", @@ -548,8 +482,8 @@ def prysm_deps(): go_repository( name = "com_github_cockroachdb_pebble", importpath = "github.com/cockroachdb/pebble", - sum = "h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A=", - version = "v0.0.0-20230928194634-aa077af62593", + sum = "h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA=", + version = "v1.1.2", ) go_repository( name = "com_github_cockroachdb_redact", @@ -557,12 +491,6 @@ def prysm_deps(): sum = "h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=", version = "v1.1.5", ) - go_repository( - name = "com_github_cockroachdb_sentry_go", - importpath = "github.com/cockroachdb/sentry-go", - sum = "h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM=", - version = "v0.6.1-cockroachdb.2", - ) go_repository( name = "com_github_cockroachdb_tokenbucket", importpath = "github.com/cockroachdb/tokenbucket", @@ -584,14 +512,14 @@ def prysm_deps(): go_repository( name = "com_github_consensys_bavard", importpath = "github.com/consensys/bavard", - sum = "h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=", - version = "v0.1.13", + sum = "h1:Uw2CGvbXSZWhqK59X0VG/zOjpTFuOMcPLStrp1ihI0A=", + version = "v0.1.22", ) go_repository( name = "com_github_consensys_gnark_crypto", importpath = "github.com/consensys/gnark-crypto", - sum = "h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=", - version = "v0.12.1", + sum = "h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E=", + version = "v0.14.0", ) go_repository( name = "com_github_containerd_cgroups", @@ -600,23 +528,11 @@ def prysm_deps(): sum = "h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=", version = "v1.1.0", ) - go_repository( - name = "com_github_coreos_bbolt", - importpath = "github.com/coreos/bbolt", - sum = "h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=", - version = "v1.3.2", - ) - go_repository( - name = "com_github_coreos_etcd", - importpath = "github.com/coreos/etcd", - sum = "h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ=", - version = "v3.3.13+incompatible", - ) go_repository( name = "com_github_coreos_go_semver", importpath = "github.com/coreos/go-semver", - sum = "h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=", - version = "v0.3.0", + sum = "h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=", + version = "v0.2.0", ) go_repository( name = "com_github_coreos_go_systemd", @@ -633,8 +549,8 @@ def prysm_deps(): go_repository( name = "com_github_coreos_pkg", importpath = "github.com/coreos/pkg", - sum = "h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=", - version = "v0.0.0-20180928190104-399ea9e2e55f", + sum = "h1:CAKfRE2YtTUIjjh1bkBtyYFaUT/WmOqsJjgtihT0vMI=", + version = "v0.0.0-20160727233714-3ac0863d7acf", ) go_repository( name = "com_github_cpuguy83_go_md2man_v2", @@ -645,14 +561,14 @@ def prysm_deps(): go_repository( name = "com_github_crate_crypto_go_ipa", importpath = "github.com/crate-crypto/go-ipa", - sum = "h1:DuBDHVjgGMPki7bAyh91+3cF1Vh34sAEdH8JQgbc2R0=", - version = "v0.0.0-20230601170251-1830d0757c80", + sum = "h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=", + version = "v0.0.0-20240724233137-53bbb0ceb27a", ) go_repository( name = "com_github_crate_crypto_go_kzg_4844", importpath = "github.com/crate-crypto/go-kzg-4844", - sum = "h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA=", - version = "v0.7.0", + sum = "h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4=", + version = "v1.1.0", ) go_repository( name = "com_github_creack_pty", @@ -693,8 +609,8 @@ def prysm_deps(): go_repository( name = "com_github_deckarep_golang_set_v2", importpath = "github.com/deckarep/golang-set/v2", - sum = "h1:hn6cEZtQ0h3J8kFrHR/NrzyOoTnjgW1+FmNJzQ7y/sA=", - version = "v2.5.0", + sum = "h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=", + version = "v2.6.0", ) go_repository( name = "com_github_decred_dcrd_crypto_blake256", @@ -738,12 +654,6 @@ def prysm_deps(): sum = "h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=", version = "v0.0.0-20190423205320-6a90982ecee2", ) - go_repository( - name = "com_github_dgryski_go_sip13", - importpath = "github.com/dgryski/go-sip13", - sum = "h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4=", - version = "v0.0.0-20181026042036-e10d5fee7954", - ) go_repository( name = "com_github_dlclark_regexp2", importpath = "github.com/dlclark/regexp2", @@ -757,16 +667,10 @@ def prysm_deps(): version = "v0.5.0", ) go_repository( - name = "com_github_docker_spdystream", - importpath = "github.com/docker/spdystream", - sum = "h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=", - version = "v0.0.0-20160310174837-449fdfce4d96", - ) - go_repository( - name = "com_github_docopt_docopt_go", - importpath = "github.com/docopt/docopt-go", - sum = "h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=", - version = "v0.0.0-20180111231733-ee0de3bc6815", + name = "com_github_donovanhide_eventsource", + importpath = "github.com/donovanhide/eventsource", + sum = "h1:C7t6eeMaEQVy6e8CarIhscYQlNmw5e3G36y7l7Y21Ao=", + version = "v0.0.0-20210830082556-c59027999da0", ) go_repository( name = "com_github_dop251_goja", @@ -819,14 +723,8 @@ def prysm_deps(): go_repository( name = "com_github_elastic_gosigar", importpath = "github.com/elastic/gosigar", - sum = "h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=", - version = "v0.14.2", - ) - go_repository( - name = "com_github_elazarl_goproxy", - importpath = "github.com/elazarl/goproxy", - sum = "h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=", - version = "v0.0.0-20180725130230-947c36da3153", + sum = "h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo=", + version = "v0.14.3", ) go_repository( name = "com_github_emicklei_dot", @@ -835,22 +733,22 @@ def prysm_deps(): version = "v0.11.0", ) go_repository( - name = "com_github_emicklei_go_restful", - importpath = "github.com/emicklei/go-restful", - sum = "h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=", - version = "v0.0.0-20170410110728-ff4f55a20633", + name = "com_github_emicklei_go_restful_v3", + importpath = "github.com/emicklei/go-restful/v3", + sum = "h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=", + version = "v3.11.0", ) go_repository( name = "com_github_envoyproxy_go_control_plane", importpath = "github.com/envoyproxy/go-control-plane", - sum = "h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA=", - version = "v0.11.1-0.20230524094728-9239064ad72f", + sum = "h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE=", + version = "v0.13.1", ) go_repository( name = "com_github_envoyproxy_protoc_gen_validate", importpath = "github.com/envoyproxy/protoc-gen-validate", - sum = "h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=", - version = "v0.10.1", + sum = "h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=", + version = "v1.1.0", ) go_repository( name = "com_github_ethereum_c_kzg_4844", @@ -860,33 +758,40 @@ def prysm_deps(): importpath = "github.com/ethereum/c-kzg-4844", patch_args = ["-p1"], patches = ["//third_party:com_github_ethereum_c_kzg_4844.patch"], - sum = "h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY=", - version = "v0.4.0", + sum = "h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA=", + version = "v1.0.0", ) go_repository( name = "com_github_ethereum_go_ethereum", build_directives = [ "gazelle:resolve go github.com/karalabe/usb @prysm//third_party/usb:go_default_library", + "gazelle:resolve go github.com/karalabe/hid @prysm//third_party/hid:go_default_library", ], importpath = "github.com/ethereum/go-ethereum", patch_args = ["-p1"], patches = [ "//third_party:com_github_ethereum_go_ethereum_secp256k1.patch", ], - sum = "h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF3VbaFk=", - version = "v1.13.5", + sum = "h1:LLb2jCPsbJZcB4INw+E/MgzUX5wlR6SdwXcv09/1ME4=", + version = "v1.15.0", + ) + go_repository( + name = "com_github_ethereum_go_verkle", + importpath = "github.com/ethereum/go-verkle", + sum = "h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8=", + version = "v0.2.2", ) go_repository( name = "com_github_evanphx_json_patch", importpath = "github.com/evanphx/json-patch", - sum = "h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=", - version = "v4.9.0+incompatible", + sum = "h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=", + version = "v4.12.0+incompatible", ) go_repository( name = "com_github_fatih_color", importpath = "github.com/fatih/color", - sum = "h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=", - version = "v1.13.0", + sum = "h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=", + version = "v1.16.0", ) go_repository( name = "com_github_fatih_structs", @@ -900,23 +805,23 @@ def prysm_deps(): sum = "h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=", version = "v0.9.3", ) + go_repository( + name = "com_github_felixge_httpsnoop", + importpath = "github.com/felixge/httpsnoop", + sum = "h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=", + version = "v1.0.4", + ) go_repository( name = "com_github_ferranbt_fastssz", importpath = "github.com/ferranbt/fastssz", - sum = "h1:9VDpsWq096+oGMDTT/SgBD/VgZYf4pTF+KTPmZ+OaKM=", - version = "v0.0.0-20210120143747-11b9eff30ea9", + sum = "h1:ZI+z3JH05h4kgmFXdHuR1aWYsgrg7o+Fw7/NCzM16Mo=", + version = "v0.1.3", ) go_repository( name = "com_github_fjl_gencodec", importpath = "github.com/fjl/gencodec", - sum = "h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY=", - version = "v0.0.0-20230517082657-f9840df7b83e", - ) - go_repository( - name = "com_github_fjl_memsize", - importpath = "github.com/fjl/memsize", - sum = "h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=", - version = "v0.0.0-20190710130421-bcb5799ab5e5", + sum = "h1:B3K0xPfc52cw52BBgUbSPxYo+HlLfAgWMVKRWXUXBcs=", + version = "v0.1.0", ) go_repository( name = "com_github_flosch_pongo2_v4", @@ -936,12 +841,6 @@ def prysm_deps(): sum = "h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=", version = "v1.1.0", ) - go_repository( - name = "com_github_form3tech_oss_jwt_go", - importpath = "github.com/form3tech-oss/jwt-go", - sum = "h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=", - version = "v3.2.2+incompatible", - ) go_repository( name = "com_github_fortytw2_leaktest", importpath = "github.com/fortytw2/leaktest", @@ -978,6 +877,12 @@ def prysm_deps(): sum = "h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=", version = "v1.6.0", ) + go_repository( + name = "com_github_fxamacker_cbor_v2", + importpath = "github.com/fxamacker/cbor/v2", + sum = "h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA=", + version = "v2.6.0", + ) go_repository( name = "com_github_garslo_gogen", importpath = "github.com/garslo/gogen", @@ -999,20 +904,20 @@ def prysm_deps(): go_repository( name = "com_github_gballet_go_verkle", importpath = "github.com/gballet/go-verkle", - sum = "h1:vMT47RYsrftsHSTQhqXwC3BYflo38OLC3Y4LtXtLyU0=", - version = "v0.0.0-20230607174250-df487255f46b", + sum = "h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE=", + version = "v0.1.1-0.20231031103413-a67434b50f46", ) go_repository( name = "com_github_gdamore_encoding", importpath = "github.com/gdamore/encoding", - sum = "h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=", - version = "v1.0.0", + sum = "h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=", + version = "v1.0.1", ) go_repository( name = "com_github_gdamore_tcell_v2", importpath = "github.com/gdamore/tcell/v2", - sum = "h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg=", - version = "v2.6.0", + sum = "h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=", + version = "v2.7.4", ) go_repository( name = "com_github_getkin_kin_openapi", @@ -1023,8 +928,8 @@ def prysm_deps(): go_repository( name = "com_github_getsentry_sentry_go", importpath = "github.com/getsentry/sentry-go", - sum = "h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=", - version = "v0.25.0", + sum = "h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=", + version = "v0.27.0", ) go_repository( name = "com_github_ghemawat_stream", @@ -1101,8 +1006,14 @@ def prysm_deps(): go_repository( name = "com_github_go_logr_logr", importpath = "github.com/go-logr/logr", - sum = "h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=", - version = "v1.3.0", + sum = "h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=", + version = "v1.4.2", + ) + go_repository( + name = "com_github_go_logr_stdr", + importpath = "github.com/go-logr/stdr", + sum = "h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=", + version = "v1.2.2", ) go_repository( name = "com_github_go_martini_martini", @@ -1119,26 +1030,20 @@ def prysm_deps(): go_repository( name = "com_github_go_openapi_jsonpointer", importpath = "github.com/go-openapi/jsonpointer", - sum = "h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=", - version = "v0.19.5", + sum = "h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=", + version = "v0.19.6", ) go_repository( name = "com_github_go_openapi_jsonreference", importpath = "github.com/go-openapi/jsonreference", - sum = "h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=", - version = "v0.19.3", - ) - go_repository( - name = "com_github_go_openapi_spec", - importpath = "github.com/go-openapi/spec", - sum = "h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc=", - version = "v0.19.3", + sum = "h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=", + version = "v0.20.2", ) go_repository( name = "com_github_go_openapi_swag", importpath = "github.com/go-openapi/swag", - sum = "h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=", - version = "v0.19.5", + sum = "h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=", + version = "v0.22.3", ) go_repository( name = "com_github_go_playground_assert_v2", @@ -1188,30 +1093,18 @@ def prysm_deps(): sum = "h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=", version = "v0.0.0-20230315185526-52ccab3ef572", ) + go_repository( + name = "com_github_go_task_slim_sprig_v3", + importpath = "github.com/go-task/slim-sprig/v3", + sum = "h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=", + version = "v3.0.0", + ) go_repository( name = "com_github_go_yaml_yaml", importpath = "github.com/go-yaml/yaml", sum = "h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=", version = "v2.1.0+incompatible", ) - go_repository( - name = "com_github_gobwas_httphead", - importpath = "github.com/gobwas/httphead", - sum = "h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=", - version = "v0.1.0", - ) - go_repository( - name = "com_github_gobwas_pool", - importpath = "github.com/gobwas/pool", - sum = "h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=", - version = "v0.2.1", - ) - go_repository( - name = "com_github_gobwas_ws", - importpath = "github.com/gobwas/ws", - sum = "h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=", - version = "v1.2.1", - ) go_repository( name = "com_github_goccy_go_json", importpath = "github.com/goccy/go-json", @@ -1230,12 +1123,6 @@ def prysm_deps(): sum = "h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=", version = "v0.8.1", ) - go_repository( - name = "com_github_gofrs_uuid", - importpath = "github.com/gofrs/uuid", - sum = "h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=", - version = "v4.0.0+incompatible", - ) go_repository( name = "com_github_gogo_googleapis", importpath = "github.com/gogo/googleapis", @@ -1263,20 +1150,20 @@ def prysm_deps(): go_repository( name = "com_github_golang_glog", importpath = "github.com/golang/glog", - sum = "h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=", - version = "v1.1.0", + sum = "h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=", + version = "v1.2.2", ) go_repository( name = "com_github_golang_groupcache", importpath = "github.com/golang/groupcache", - sum = "h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=", - version = "v0.0.0-20200121045136-8c9f03a8e57e", + sum = "h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=", + version = "v0.0.0-20210331224755-41bb18bfe9da", ) go_repository( name = "com_github_golang_jwt_jwt_v4", importpath = "github.com/golang-jwt/jwt/v4", - sum = "h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=", - version = "v4.5.0", + sum = "h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=", + version = "v4.5.1", ) go_repository( name = "com_github_golang_lint", @@ -1287,8 +1174,8 @@ def prysm_deps(): go_repository( name = "com_github_golang_mock", importpath = "github.com/golang/mock", - sum = "h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=", - version = "v1.5.0", + sum = "h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=", + version = "v1.4.4", ) go_repository( name = "com_github_golang_protobuf", @@ -1301,8 +1188,8 @@ def prysm_deps(): go_repository( name = "com_github_golang_snappy", importpath = "github.com/golang/snappy", - sum = "h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=", - version = "v0.0.5-0.20220116011046-fa5810519dcb", + sum = "h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc=", + version = "v0.0.5-0.20231225225746-43d5d4cd4e0e", ) go_repository( name = "com_github_golangci_lint_1", @@ -1313,8 +1200,14 @@ def prysm_deps(): go_repository( name = "com_github_google_btree", importpath = "github.com/google/btree", - sum = "h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=", - version = "v1.0.0", + sum = "h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=", + version = "v1.0.1", + ) + go_repository( + name = "com_github_google_gnostic_models", + importpath = "github.com/google/gnostic-models", + sum = "h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=", + version = "v0.6.8", ) go_repository( name = "com_github_google_go_cmp", @@ -1361,8 +1254,8 @@ def prysm_deps(): go_repository( name = "com_github_google_pprof", importpath = "github.com/google/pprof", - sum = "h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=", - version = "v0.0.0-20240207164012-fb44976bdcd5", + sum = "h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=", + version = "v0.0.0-20240727154555-813a5fbdbec8", ) go_repository( name = "com_github_google_renameio", @@ -1379,8 +1272,8 @@ def prysm_deps(): go_repository( name = "com_github_google_uuid", importpath = "github.com/google/uuid", - sum = "h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=", - version = "v1.4.0", + sum = "h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=", + version = "v1.6.0", ) go_repository( name = "com_github_googleapis_gax_go", @@ -1394,34 +1287,24 @@ def prysm_deps(): sum = "h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=", version = "v2.0.5", ) - go_repository( - name = "com_github_googleapis_gnostic", - build_directives = [ - "gazelle:resolve go github.com/googleapis/gnostic/extensions //extensions:go_default_library", - ], - build_naming_convention = "go_default_library", - importpath = "github.com/googleapis/gnostic", - sum = "h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=", - version = "v0.4.1", - ) go_repository( name = "com_github_googleapis_google_cloud_go_testing", importpath = "github.com/googleapis/google-cloud-go-testing", sum = "h1:tlyzajkF3030q6M8SvmJSemC9DTHL/xaMa18b65+JM4=", version = "v0.0.0-20200911160855-bcd43fbb19e8", ) + go_repository( + name = "com_github_googlecloudplatform_opentelemetry_operations_go_detectors_gcp", + importpath = "github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp", + sum = "h1:cZpsGsWTIFKymTA0je7IIvi1O7Es7apb9CF3EQlOcfE=", + version = "v1.24.2", + ) go_repository( name = "com_github_gopherjs_gopherjs", importpath = "github.com/gopherjs/gopherjs", sum = "h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=", version = "v0.0.0-20181017120253-0766667cb4d1", ) - go_repository( - name = "com_github_gordonklaus_ineffassign", - importpath = "github.com/gordonklaus/ineffassign", - sum = "h1:vc7Dmrk4JwS0ZPS6WZvWlwDflgDTA26jItmbSj83nug=", - version = "v0.0.0-20200309095847-7953dde2c7bf", - ) go_repository( name = "com_github_gorilla_context", importpath = "github.com/gorilla/context", @@ -1491,16 +1374,8 @@ def prysm_deps(): go_repository( name = "com_github_grpc_ecosystem_grpc_gateway_v2", importpath = "github.com/grpc-ecosystem/grpc-gateway/v2", - patch_args = ["-p1"], - patches = [ - "//third_party:com_github_grpc_ecosystem_grpc_gateway_v2.patch", - "//third_party:com_github_grpc_ecosystem_grpc_gateway_v2_fix_emptypb.patch", - "//third_party:com_github_grpc_ecosystem_grpc_gateway_v2_prysm_v5.patch", - ], - replace = "github.com/prysmaticlabs/grpc-gateway/v2", - repo_mapping = {"@go_googleapis": "@googleapis"}, - sum = "h1:4wctORg/1TkgLgXejv9yOSAm3cDBJxoTzl/RNuZmX28=", - version = "v2.3.1-0.20230315201114-09284ba20446", + sum = "h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=", + version = "v2.25.1", ) go_repository( name = "com_github_guptarohit_asciigraph", @@ -1619,8 +1494,8 @@ def prysm_deps(): go_repository( name = "com_github_hashicorp_hcl", importpath = "github.com/hashicorp/hcl", - sum = "h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=", - version = "v1.0.0", + sum = "h1:LFTfzwAUSKPijQbJrMWZm/CysECsF/U1UUniUeXxzFw=", + version = "v0.0.0-20170914154624-68e816d1c783", ) go_repository( name = "com_github_hashicorp_logutils", @@ -1655,14 +1530,14 @@ def prysm_deps(): go_repository( name = "com_github_herumi_bls_eth_go_binary", importpath = "github.com/herumi/bls-eth-go-binary", - sum = "h1:wCMygKUQhmcQAjlk2Gquzq6dLmyMv2kF+llRspoRgrk=", - version = "v0.0.0-20210917013441-d37c07cfda4e", + sum = "h1:9eeW3EA4epCb7FIHt2luENpAW69MvKGL5jieHlBiP+w=", + version = "v1.31.0", ) go_repository( name = "com_github_holiman_billy", importpath = "github.com/holiman/billy", - sum = "h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw=", - version = "v0.0.0-20230718173358-1c7e68d277a7", + sum = "h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4=", + version = "v0.0.0-20240216141850-2abb0c79d3c4", ) go_repository( name = "com_github_holiman_bloomfilter_v2", @@ -1673,14 +1548,14 @@ def prysm_deps(): go_repository( name = "com_github_holiman_goevmlab", importpath = "github.com/holiman/goevmlab", - sum = "h1:J973NLskKmFIj3EGfpQ1ztUQKdwyJ+fG34638ief0eA=", - version = "v0.0.0-20231201084119-c73b3c97929c", + sum = "h1:JHZ8k9n9G9KXIo1qrvK5Cxah6ax5BR0qVTA9bFYl1oM=", + version = "v0.0.0-20241121133100-cfa6b078c8c4", ) go_repository( name = "com_github_holiman_uint256", importpath = "github.com/holiman/uint256", - sum = "h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=", - version = "v1.2.4", + sum = "h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=", + version = "v1.3.2", ) go_repository( name = "com_github_hpcloud_tail", @@ -1715,14 +1590,14 @@ def prysm_deps(): go_repository( name = "com_github_ianlancetaylor_demangle", importpath = "github.com/ianlancetaylor/demangle", - sum = "h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=", - version = "v0.0.0-20230524184225-eabc099b10ab", + sum = "h1:KwWnWVWCNtNq/ewIX7HIKnELmEx2nDP42yskD/pi7QE=", + version = "v0.0.0-20240312041847-bd984b5ce465", ) go_repository( name = "com_github_imdario_mergo", importpath = "github.com/imdario/mergo", - sum = "h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=", - version = "v0.3.5", + sum = "h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=", + version = "v0.3.6", ) go_repository( name = "com_github_inconshreveable_log15", @@ -1733,8 +1608,8 @@ def prysm_deps(): go_repository( name = "com_github_inconshreveable_mousetrap", importpath = "github.com/inconshreveable/mousetrap", - sum = "h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=", - version = "v1.0.0", + sum = "h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=", + version = "v1.1.0", ) go_repository( name = "com_github_influxdata_influxdb1_client", @@ -1833,12 +1708,6 @@ def prysm_deps(): sum = "h1:ujPKutqRlJtcfWk6toYVYagwra7HQHbXOaS171b4Tg8=", version = "v0.0.0-20150330215556-f50fe3d243e1", ) - go_repository( - name = "com_github_jhump_protoreflect", - importpath = "github.com/jhump/protoreflect", - sum = "h1:z7Ciiz3Bz37zSd485fbiTW8ABafIasyOWZI0N9EUUdo=", - version = "v1.8.1", - ) go_repository( name = "com_github_jmespath_go_jmespath", importpath = "github.com/jmespath/go-jmespath", @@ -1913,10 +1782,10 @@ def prysm_deps(): version = "v0.0.0-20180517002512-3bf9e2903213", ) go_repository( - name = "com_github_karalabe_usb", - importpath = "github.com/karalabe/usb", - sum = "h1:AqsttAyEyIEsNz5WLRwuRwjiT5CMDUfLk6cFJDVPebs=", - version = "v0.0.3-0.20230711191512-61db3e06439c", + name = "com_github_karalabe_hid", + importpath = "github.com/karalabe/hid", + sum = "h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I=", + version = "v1.0.1-0.20240306101548-573246063e52", ) go_repository( name = "com_github_kataras_blocks", @@ -1963,8 +1832,8 @@ def prysm_deps(): go_repository( name = "com_github_kisielk_errcheck", importpath = "github.com/kisielk/errcheck", - sum = "h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY=", - version = "v1.5.0", + sum = "h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg=", + version = "v1.8.0", ) go_repository( name = "com_github_kisielk_gotool", @@ -1975,8 +1844,8 @@ def prysm_deps(): go_repository( name = "com_github_klauspost_compress", importpath = "github.com/klauspost/compress", - sum = "h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=", - version = "v1.17.8", + sum = "h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=", + version = "v1.17.9", ) go_repository( name = "com_github_klauspost_cpuid", @@ -1987,14 +1856,8 @@ def prysm_deps(): go_repository( name = "com_github_klauspost_cpuid_v2", importpath = "github.com/klauspost/cpuid/v2", - sum = "h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=", - version = "v2.2.7", - ) - go_repository( - name = "com_github_klauspost_pgzip", - importpath = "github.com/klauspost/pgzip", - sum = "h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=", - version = "v1.2.5", + sum = "h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=", + version = "v2.2.8", ) go_repository( name = "com_github_klauspost_reedsolomon", @@ -2047,8 +1910,8 @@ def prysm_deps(): go_repository( name = "com_github_kr_pty", importpath = "github.com/kr/pty", - sum = "h1:hyz3dwM5QLc1Rfoz4FuWJQG5BN7tc6K1MndAUnGpQr4=", - version = "v1.1.5", + sum = "h1:/Um6a/ZmD5tF7peoOJ5oN5KMQ0DrGVQSXLNwyckutPk=", + version = "v1.1.3", ) go_repository( name = "com_github_kr_text", @@ -2077,8 +1940,8 @@ def prysm_deps(): go_repository( name = "com_github_leanovate_gopter", importpath = "github.com/leanovate/gopter", - sum = "h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=", - version = "v0.2.9", + sum = "h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=", + version = "v0.2.11", ) go_repository( name = "com_github_leodido_go_urn", @@ -2105,8 +1968,8 @@ def prysm_deps(): ], build_file_proto_mode = "disable_global", importpath = "github.com/libp2p/go-libp2p", - sum = "h1:287oHbuplkrLdAF+syB0n/qDgd50AUBtEODqS0e0HDs=", - version = "v0.35.2", + sum = "h1:DoABsaHO0VXwH6pwCs2F6XKAXWYjFMO4HFBoVxTnF9g=", + version = "v0.36.5", ) go_repository( name = "com_github_libp2p_go_libp2p_asn_util", @@ -2124,8 +1987,8 @@ def prysm_deps(): name = "com_github_libp2p_go_libp2p_pubsub", build_file_proto_mode = "disable_global", importpath = "github.com/libp2p/go-libp2p-pubsub", - sum = "h1:+JvS8Kty0OiyUiN0i8H5JbaCgjnJTRnTHe4rU88dLFc=", - version = "v0.11.0", + sum = "h1:RmFQ2XAy3zQtbt2iNPy7Tt0/3fwTnHpCQSSnmGnt1Ps=", + version = "v0.13.0", ) go_repository( name = "com_github_libp2p_go_libp2p_testing", @@ -2214,8 +2077,8 @@ def prysm_deps(): go_repository( name = "com_github_magiconair_properties", importpath = "github.com/magiconair/properties", - sum = "h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=", - version = "v1.8.1", + sum = "h1:SesWF0c8l/IKQX0NlsED38qoBhUpneg5HIHNdy5LyEE=", + version = "v1.7.4-0.20170902060319-8d7837e64d3c", ) go_repository( name = "com_github_mailgun_raymond_v2", @@ -2238,14 +2101,14 @@ def prysm_deps(): go_repository( name = "com_github_mariusvanderwijden_fuzzyvm", importpath = "github.com/MariusVanDerWijden/FuzzyVM", - sum = "h1:BwEuC3xavrv4HTUDH2fUrKgKooiH3Q/nSVnFGtnzpN0=", - version = "v0.0.0-20240209103030-ec53fa766bf8", + sum = "h1:RQtzNvriR3Yu5CvVBTJPwDmfItBT90TWZ3fFondhc08=", + version = "v0.0.0-20240516070431-7828990cad7d", ) go_repository( name = "com_github_mariusvanderwijden_tx_fuzz", importpath = "github.com/MariusVanDerWijden/tx-fuzz", - sum = "h1:QDTh0xHorSykJ4+2VccBADMeRAVUbnHaWrCPIMtN+Vc=", - version = "v1.3.3-0.20240227085032-f70dd7c85c97", + sum = "h1:Tq4lXivsR8mtoP4RpasUDIUpDLHfN1YhFge/kzrzK78=", + version = "v1.4.0", ) go_repository( name = "com_github_marten_seemann_tcp", @@ -2304,14 +2167,14 @@ def prysm_deps(): go_repository( name = "com_github_microsoft_go_winio", importpath = "github.com/Microsoft/go-winio", - sum = "h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=", - version = "v0.6.1", + sum = "h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=", + version = "v0.6.2", ) go_repository( name = "com_github_miekg_dns", importpath = "github.com/miekg/dns", - sum = "h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=", - version = "v1.1.58", + sum = "h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=", + version = "v1.1.62", ) go_repository( name = "com_github_mikioh_tcp", @@ -2364,8 +2227,8 @@ def prysm_deps(): go_repository( name = "com_github_mitchellh_go_homedir", importpath = "github.com/mitchellh/go-homedir", - sum = "h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=", - version = "v1.1.0", + sum = "h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=", + version = "v1.0.0", ) go_repository( name = "com_github_mitchellh_go_testing_interface", @@ -2409,6 +2272,12 @@ def prysm_deps(): sum = "h1:jhDmAqPyebOsVDOCICJoINoLb/AnLBaUw58nFzxWS2w=", version = "v0.1.1", ) + go_repository( + name = "com_github_moby_spdystream", + importpath = "github.com/moby/spdystream", + sum = "h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=", + version = "v0.2.0", + ) go_repository( name = "com_github_modern_go_concurrent", importpath = "github.com/modern-go/concurrent", @@ -2448,14 +2317,14 @@ def prysm_deps(): go_repository( name = "com_github_multiformats_go_multiaddr", importpath = "github.com/multiformats/go-multiaddr", - sum = "h1:rrKqpY9h+n80EwhhC/kkcunCZZ7URIF8yN1WEUt2Hvc=", - version = "v0.12.4", + sum = "h1:BCBzs61E3AGHcYYTv8dqRH43ZfyrqM8RXVPT8t13tLQ=", + version = "v0.13.0", ) go_repository( name = "com_github_multiformats_go_multiaddr_dns", importpath = "github.com/multiformats/go-multiaddr-dns", - sum = "h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=", - version = "v0.3.1", + sum = "h1:P76EJ3qzBXpUXZ3twdCDx/kvagMsNo0LMFXpyms/zgU=", + version = "v0.4.0", ) go_repository( name = "com_github_multiformats_go_multiaddr_fmt", @@ -2499,8 +2368,8 @@ def prysm_deps(): go_repository( name = "com_github_munnerz_goautoneg", importpath = "github.com/munnerz/goautoneg", - sum = "h1:7PxY7LVfSZm7PEeBTyK1rj1gABdCO2mbri6GKO1cMDs=", - version = "v0.0.0-20120707110453-a547fc61f48d", + sum = "h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=", + version = "v0.0.0-20191010083416-a7dc8b61c822", ) go_repository( name = "com_github_mwitkow_go_conntrack", @@ -2568,24 +2437,12 @@ def prysm_deps(): sum = "h1:eFXv9Nu1lGbrNbj619aWwZfVF5HBrm9Plte8aNptuTI=", version = "v0.0.0-20151028013722-8c68805598ab", ) - go_repository( - name = "com_github_nishanths_predeclared", - importpath = "github.com/nishanths/predeclared", - sum = "h1:3f0nxAmdj/VoCGN/ijdMy7bj6SBagaqYg1B0hu8clMA=", - version = "v0.0.0-20200524104333-86fad755b4d3", - ) go_repository( name = "com_github_nxadm_tail", importpath = "github.com/nxadm/tail", sum = "h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=", version = "v1.4.11", ) - go_repository( - name = "com_github_nytimes_gziphandler", - importpath = "github.com/NYTimes/gziphandler", - sum = "h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0=", - version = "v0.0.0-20170623195520-56545f4a5d46", - ) go_repository( name = "com_github_oklog_oklog", importpath = "github.com/oklog/oklog", @@ -2598,12 +2455,6 @@ def prysm_deps(): sum = "h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=", version = "v1.0.0", ) - go_repository( - name = "com_github_oklog_ulid", - importpath = "github.com/oklog/ulid", - sum = "h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=", - version = "v1.3.1", - ) go_repository( name = "com_github_olekukonko_tablewriter", importpath = "github.com/olekukonko/tablewriter", @@ -2625,14 +2476,14 @@ def prysm_deps(): go_repository( name = "com_github_onsi_ginkgo_v2", importpath = "github.com/onsi/ginkgo/v2", - sum = "h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=", - version = "v2.15.0", + sum = "h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw=", + version = "v2.20.0", ) go_repository( name = "com_github_onsi_gomega", importpath = "github.com/onsi/gomega", - sum = "h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=", - version = "v1.30.0", + sum = "h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=", + version = "v1.34.1", ) go_repository( name = "com_github_op_go_logging", @@ -2745,8 +2596,8 @@ def prysm_deps(): go_repository( name = "com_github_pelletier_go_toml", importpath = "github.com/pelletier/go-toml", - sum = "h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=", - version = "v1.2.0", + sum = "h1:6P7XZEBu/ZWizC/liUX4UYm4nEAACofmSkOzY39RBxM=", + version = "v1.0.1-0.20170904195809-1d6b12b7cb29", ) go_repository( name = "com_github_pelletier_go_toml_v2", @@ -2787,26 +2638,26 @@ def prysm_deps(): go_repository( name = "com_github_pion_datachannel", importpath = "github.com/pion/datachannel", - sum = "h1:1IxKJntfSlYkpUj8LlYRSWpYiTTC02nUrOE8T3DqGeg=", - version = "v1.5.6", + sum = "h1:ph1P1NsGkazkjrvyMfhRBUAWMxugJjq2HfQifaOoSNo=", + version = "v1.5.8", ) go_repository( name = "com_github_pion_dtls_v2", importpath = "github.com/pion/dtls/v2", - sum = "h1:9U/dpCYl1ySttROPWJgqWKEylUdT0fXp/xst6JwY5Ks=", - version = "v2.2.11", + sum = "h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=", + version = "v2.2.12", ) go_repository( name = "com_github_pion_ice_v2", importpath = "github.com/pion/ice/v2", - sum = "h1:M5rJA07dqhi3nobJIg+uPtcVjFECTrhcR3n0ns8kDZs=", - version = "v2.3.25", + sum = "h1:Ic1ppYCj4tUOcPAp76U6F3fVrlSw8A9JtRXLqw6BbUM=", + version = "v2.3.34", ) go_repository( name = "com_github_pion_interceptor", importpath = "github.com/pion/interceptor", - sum = "h1:39fsnlP1U8gw2JzOFWdfCU82vHvhW9o0rZnZF56wF+M=", - version = "v0.1.29", + sum = "h1:au5rlVHsgmxNi+v/mjOPazbW1SHzfx7/hYOEYQnUcxA=", + version = "v0.1.30", ) go_repository( name = "com_github_pion_logging", @@ -2835,14 +2686,14 @@ def prysm_deps(): go_repository( name = "com_github_pion_rtp", importpath = "github.com/pion/rtp", - sum = "h1:MTmn/b0aWWsAzux2AmP8WGllusBVw4NPYPVFFd7jUPw=", - version = "v1.8.6", + sum = "h1:E2HX740TZKaqdcPmf4pw6ZZuG8u5RlMMt+l3dxeu6Wk=", + version = "v1.8.9", ) go_repository( name = "com_github_pion_sctp", importpath = "github.com/pion/sctp", - sum = "h1:PKrMs+o9EMLRvFfXq59WFsC+V8mN1wnKzqrv+3D/gYY=", - version = "v1.8.16", + sum = "h1:dSE4wX6uTJBcNm8+YlMg7lw1wqyKHggsP5uKbdj+NZw=", + version = "v1.8.33", ) go_repository( name = "com_github_pion_sdp_v3", @@ -2853,8 +2704,8 @@ def prysm_deps(): go_repository( name = "com_github_pion_srtp_v2", importpath = "github.com/pion/srtp/v2", - sum = "h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo=", - version = "v2.0.18", + sum = "h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk=", + version = "v2.0.20", ) go_repository( name = "com_github_pion_stun", @@ -2862,17 +2713,23 @@ def prysm_deps(): sum = "h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=", version = "v0.6.1", ) + go_repository( + name = "com_github_pion_stun_v2", + importpath = "github.com/pion/stun/v2", + sum = "h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0=", + version = "v2.0.0", + ) go_repository( name = "com_github_pion_transport_v2", importpath = "github.com/pion/transport/v2", - sum = "h1:iyi25i/21gQck4hfRhomF6SktmUQjRsRW4WJdhfc3Kc=", - version = "v2.2.5", + sum = "h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=", + version = "v2.2.10", ) go_repository( name = "com_github_pion_transport_v3", importpath = "github.com/pion/transport/v3", - sum = "h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4=", - version = "v3.0.2", + sum = "h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=", + version = "v3.0.7", ) go_repository( name = "com_github_pion_turn_v2", @@ -2883,8 +2740,8 @@ def prysm_deps(): go_repository( name = "com_github_pion_webrtc_v3", importpath = "github.com/pion/webrtc/v3", - sum = "h1:Wtfi6AZMQg+624cvCXUuSmrKWepSB7zfgYDOYqsSOVU=", - version = "v3.2.40", + sum = "h1:Rf4u6n6U5t5sUxhYPQk/samzU/oDv7jk6BA5hyO2F9I=", + version = "v3.3.0", ) go_repository( name = "com_github_pkg_diff", @@ -2910,6 +2767,12 @@ def prysm_deps(): sum = "h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=", version = "v1.13.1", ) + go_repository( + name = "com_github_planetscale_vtprotobuf", + importpath = "github.com/planetscale/vtprotobuf", + sum = "h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=", + version = "v0.6.1-0.20240319094008-0393e58bdf10", + ) go_repository( name = "com_github_pmezard_go_difflib", importpath = "github.com/pmezard/go-difflib", @@ -2931,8 +2794,8 @@ def prysm_deps(): go_repository( name = "com_github_prometheus_client_golang", importpath = "github.com/prometheus/client_golang", - sum = "h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=", - version = "v1.19.1", + sum = "h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=", + version = "v1.20.0", ) go_repository( name = "com_github_prometheus_client_model", @@ -2943,14 +2806,14 @@ def prysm_deps(): go_repository( name = "com_github_prometheus_common", importpath = "github.com/prometheus/common", - sum = "h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=", - version = "v0.48.0", + sum = "h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=", + version = "v0.55.0", ) go_repository( name = "com_github_prometheus_procfs", importpath = "github.com/prometheus/procfs", - sum = "h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=", - version = "v0.12.0", + sum = "h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=", + version = "v0.15.1", ) go_repository( name = "com_github_prometheus_prom2json", @@ -2958,23 +2821,29 @@ def prysm_deps(): sum = "h1:BlqrtbT9lLH3ZsOVhXPsHzFrApCTKRifB7gjJuypu6Y=", version = "v1.3.0", ) - go_repository( - name = "com_github_prometheus_tsdb", - importpath = "github.com/prometheus/tsdb", - sum = "h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=", - version = "v0.7.1", - ) go_repository( name = "com_github_protolambda_bls12_381_util", importpath = "github.com/protolambda/bls12-381-util", - sum = "h1:cZC+usqsYgHtlBaGulVnZ1hfKAi8iWtujBnRLQE698c=", - version = "v0.0.0-20220416220906-d8552aa452c7", + sum = "h1:05DU2wJN7DTU7z28+Q+zejXkIsA/MF8JZQGhtBZZiWk=", + version = "v0.1.0", + ) + go_repository( + name = "com_github_protolambda_zrnt", + importpath = "github.com/protolambda/zrnt", + sum = "h1:KZ48T+3UhsPXNdtE/5QEvGc9DGjUaRI17nJaoznoIaM=", + version = "v0.32.2", + ) + go_repository( + name = "com_github_protolambda_ztyp", + importpath = "github.com/protolambda/ztyp", + sum = "h1:rVcL3vBu9W/aV646zF6caLS/dyn9BN8NYiuJzicLNyY=", + version = "v0.2.2", ) go_repository( name = "com_github_prysmaticlabs_fastssz", importpath = "github.com/prysmaticlabs/fastssz", - sum = "h1:0LZAwwHnsZFfXm4IK4rzFV4N5IVSKZKLmuBMA4kAlFk=", - version = "v0.0.0-20240620202422-a981b8ef89d3", + sum = "h1:xuVAdtz5ShYblG2sPyb4gw01DF8InbOI/kBCQjk7NiM=", + version = "v0.0.0-20241008181541-518c4ce73516", ) go_repository( name = "com_github_prysmaticlabs_go_bitfield", @@ -3000,26 +2869,14 @@ def prysm_deps(): sum = "h1:q9wE0ZZRdTUAAeyFP/w0SwBEnCqlVy2+on6X2/e+eAU=", version = "v0.0.0-20230228205207-28762a7b9294", ) - go_repository( - name = "com_github_puerkitobio_purell", - importpath = "github.com/PuerkitoBio/purell", - sum = "h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=", - version = "v1.1.1", - ) - go_repository( - name = "com_github_puerkitobio_urlesc", - importpath = "github.com/PuerkitoBio/urlesc", - sum = "h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=", - version = "v0.0.0-20170810143723-de5bf2ad4578", - ) go_repository( name = "com_github_quic_go_qpack", build_directives = [ "gazelle:exclude tools.go", ], importpath = "github.com/quic-go/qpack", - sum = "h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=", - version = "v0.4.0", + sum = "h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=", + version = "v0.5.1", ) go_repository( name = "com_github_quic_go_quic_go", @@ -3028,14 +2885,20 @@ def prysm_deps(): "gazelle:exclude tools.go", ], importpath = "github.com/quic-go/quic-go", - sum = "h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0=", - version = "v0.44.0", + sum = "h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=", + version = "v0.48.2", ) go_repository( name = "com_github_quic_go_webtransport_go", importpath = "github.com/quic-go/webtransport-go", - sum = "h1:HxSrwun11U+LlmwpgM1kEqIqH90IT4N8auv/cD7QFJg=", - version = "v0.8.0", + sum = "h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=", + version = "v0.8.1-0.20241018022711-4ac2c9250e66", + ) + go_repository( + name = "com_github_r3labs_sse_v2", + importpath = "github.com/r3labs/sse/v2", + sum = "h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=", + version = "v2.10.0", ) go_repository( name = "com_github_raulk_go_watchdog", @@ -3052,8 +2915,8 @@ def prysm_deps(): go_repository( name = "com_github_rivo_tview", importpath = "github.com/rivo/tview", - sum = "h1:7UMY2qN9VlcY+x9jlhpYe5Bf1zrdhvmfZyLMk2u65BM=", - version = "v0.0.0-20231126152417-33a1d271f2b6", + sum = "h1:HxvWMyQ3vKQBlYZq9wfFtjbUeA6UUYZoLJmmwWee43s=", + version = "v0.0.0-20240519200218-0ac5f73025a8", ) go_repository( name = "com_github_rivo_uniseg", @@ -3062,8 +2925,8 @@ def prysm_deps(): "gazelle:exclude gen_properties.go", ], importpath = "github.com/rivo/uniseg", - sum = "h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=", - version = "v0.4.4", + sum = "h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=", + version = "v0.4.7", ) go_repository( name = "com_github_rogpeppe_fastuuid", @@ -3074,8 +2937,8 @@ def prysm_deps(): go_repository( name = "com_github_rogpeppe_go_internal", importpath = "github.com/rogpeppe/go-internal", - sum = "h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=", - version = "v1.11.0", + sum = "h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=", + version = "v1.13.1", ) go_repository( name = "com_github_rs_cors", @@ -3302,8 +3165,8 @@ def prysm_deps(): go_repository( name = "com_github_sirupsen_logrus", importpath = "github.com/sirupsen/logrus", - sum = "h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=", - version = "v1.9.0", + sum = "h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=", + version = "v1.9.3", ) go_repository( name = "com_github_smartystreets_assertions", @@ -3356,20 +3219,20 @@ def prysm_deps(): go_repository( name = "com_github_spf13_cast", importpath = "github.com/spf13/cast", - sum = "h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=", - version = "v1.3.0", + sum = "h1:0Rhw4d6C8J9VPu6cjZLIhZ8+aAOHcDvGeKn+cq5Aq3k=", + version = "v1.1.0", ) go_repository( name = "com_github_spf13_cobra", importpath = "github.com/spf13/cobra", - sum = "h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=", - version = "v1.5.0", + sum = "h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=", + version = "v1.8.1", ) go_repository( name = "com_github_spf13_jwalterweatherman", importpath = "github.com/spf13/jwalterweatherman", - sum = "h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=", - version = "v1.0.0", + sum = "h1:zBoLErXXAvWnNsu+pWkRYl6Cx1KXmIfAVsIuYkPN6aY=", + version = "v0.0.0-20170901151539-12bd96e66386", ) go_repository( name = "com_github_spf13_pflag", @@ -3380,8 +3243,8 @@ def prysm_deps(): go_repository( name = "com_github_spf13_viper", importpath = "github.com/spf13/viper", - sum = "h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=", - version = "v1.7.0", + sum = "h1:RUA/ghS2i64rlnn4ydTfblY8Og8QzcPtCcHvgMn+w/I=", + version = "v1.0.0", ) go_repository( name = "com_github_stackexchange_wmi", @@ -3416,14 +3279,8 @@ def prysm_deps(): go_repository( name = "com_github_stretchr_testify", importpath = "github.com/stretchr/testify", - sum = "h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=", - version = "v1.9.0", - ) - go_repository( - name = "com_github_subosito_gotenv", - importpath = "github.com/subosito/gotenv", - sum = "h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=", - version = "v1.2.0", + sum = "h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=", + version = "v1.10.0", ) go_repository( name = "com_github_syndtr_goleveldb", @@ -3500,8 +3357,8 @@ def prysm_deps(): go_repository( name = "com_github_tmc_grpc_websocket_proxy", importpath = "github.com/tmc/grpc-websocket-proxy", - sum = "h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=", - version = "v0.0.0-20190109142713-0ad062ec5ee5", + sum = "h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE=", + version = "v0.0.0-20170815181823-89b8d40f7ca8", ) go_repository( name = "com_github_trailofbits_go_mutexasserts", @@ -3509,30 +3366,24 @@ def prysm_deps(): sum = "h1:+LynomhWB+14Plp/bOONEAZCtvCZk4leRbTvNzNVkL0=", version = "v0.0.0-20230328101604-8cdbc5f3d279", ) - go_repository( - name = "com_github_twitchtv_twirp", - importpath = "github.com/twitchtv/twirp", - sum = "h1:3fNSDoSPyq+fTrifIvGue9XM/tptzuhiGY83rxPVNUg=", - version = "v7.1.0+incompatible", - ) go_repository( name = "com_github_tyler_smith_go_bip39", importpath = "github.com/tyler-smith/go-bip39", sum = "h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=", version = "v1.1.0", ) - go_repository( - name = "com_github_uber_jaeger_client_go", - importpath = "github.com/uber/jaeger-client-go", - sum = "h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U=", - version = "v2.25.0+incompatible", - ) go_repository( name = "com_github_ugorji_go_codec", importpath = "github.com/ugorji/go/codec", sum = "h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=", version = "v1.2.7", ) + go_repository( + name = "com_github_umbracle_gohashtree", + importpath = "github.com/umbracle/gohashtree", + sum = "h1:CQh33pStIp/E30b7TxDlXfM0145bn2e8boI30IxAhTg=", + version = "v0.0.2-alpha.0.20230207094856-5b775a815c10", + ) go_repository( name = "com_github_urfave_cli", importpath = "github.com/urfave/cli", @@ -3542,8 +3393,8 @@ def prysm_deps(): go_repository( name = "com_github_urfave_cli_v2", importpath = "github.com/urfave/cli/v2", - sum = "h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=", - version = "v2.26.0", + sum = "h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=", + version = "v2.27.1", ) go_repository( name = "com_github_urfave_negroni", @@ -3623,8 +3474,8 @@ def prysm_deps(): "gazelle:resolve go github.com/herumi/bls-eth-go-binary/bls @herumi_bls_eth_go_binary//:go_default_library", ], importpath = "github.com/wealdtech/go-eth2-types/v2", - sum = "h1:tiA6T88M6XQIbrV5Zz53l1G5HtRERcxQfmET225V4Ls=", - version = "v2.5.2", + sum = "h1:b5aXlNBLKgjAg/Fft9VvGlqAUCQMP5LzYhlHRrr4yPg=", + version = "v2.8.2", ) go_repository( name = "com_github_wealdtech_go_eth2_util", @@ -3644,6 +3495,18 @@ def prysm_deps(): sum = "h1:264/meVYWt1wFw6Mtn+xwkZkXjID42gNra4rycoiDXI=", version = "v2.8.2", ) + go_repository( + name = "com_github_wlynxg_anet", + importpath = "github.com/wlynxg/anet", + sum = "h1:0de1OFQxnNqAu+x2FAKKCVIrnfGKQbs7FQz++tB0+Uw=", + version = "v0.0.4", + ) + go_repository( + name = "com_github_x448_float16", + importpath = "github.com/x448/float16", + sum = "h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=", + version = "v0.8.4", + ) go_repository( name = "com_github_xdg_scram", importpath = "github.com/xdg/scram", @@ -3863,14 +3726,14 @@ def prysm_deps(): go_repository( name = "com_google_cloud_go_compute", importpath = "cloud.google.com/go/compute", - sum = "h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=", - version = "v1.20.1", + sum = "h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ=", + version = "v1.19.0", ) go_repository( name = "com_google_cloud_go_compute_metadata", importpath = "cloud.google.com/go/compute/metadata", - sum = "h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=", - version = "v0.2.3", + sum = "h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=", + version = "v0.5.2", ) go_repository( name = "com_google_cloud_go_contactcenterinsights", @@ -4445,8 +4308,8 @@ def prysm_deps(): go_repository( name = "com_lukechampine_blake3", importpath = "lukechampine.com/blake3", - sum = "h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=", - version = "v1.2.1", + sum = "h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=", + version = "v1.3.0", ) go_repository( name = "com_shuralyov_dmitri_app_changes", @@ -4496,6 +4359,12 @@ def prysm_deps(): sum = "h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c=", version = "v0.0.0-20180604144634-d3ebe8f20ae4", ) + go_repository( + name = "dev_cel_expr", + importpath = "cel.dev/expr", + sum = "h1:RwRhoH17VhAu9U5CMvMhH1PDVgf0tuz9FT+24AfMLfU=", + version = "v0.16.2", + ) go_repository( name = "in_gopkg_alecthomas_kingpin_v2", importpath = "gopkg.in/alecthomas/kingpin.v2", @@ -4508,6 +4377,12 @@ def prysm_deps(): sum = "h1:stTHdEoWg1pQ8riaP5ROrjS6zy6wewH/Q2iwnLCQUXY=", version = "v1.0.0-20160220154919-db14e161995a", ) + go_repository( + name = "in_gopkg_cenkalti_backoff_v1", + importpath = "gopkg.in/cenkalti/backoff.v1", + sum = "h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=", + version = "v1.1.0", + ) go_repository( name = "in_gopkg_check_v1", importpath = "gopkg.in/check.v1", @@ -4589,8 +4464,8 @@ def prysm_deps(): go_repository( name = "in_gopkg_natefinch_lumberjack_v2", importpath = "gopkg.in/natefinch/lumberjack.v2", - sum = "h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=", - version = "v2.0.0", + sum = "h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=", + version = "v2.2.1", ) go_repository( name = "in_gopkg_redis_v4", @@ -4644,59 +4519,59 @@ def prysm_deps(): name = "io_k8s_api", build_file_proto_mode = "disable_global", importpath = "k8s.io/api", - sum = "h1:WwrYoZNM1W1aQEbyl8HNG+oWGzLpZQBlcerS9BQw9yI=", - version = "v0.20.0", + sum = "h1:XASIELmW8w8q0i1Y4124LqPoWMycLjyQti/fdYHYjCs=", + version = "v0.30.4", ) go_repository( name = "io_k8s_apimachinery", build_file_proto_mode = "disable_global", importpath = "k8s.io/apimachinery", - sum = "h1:jjzbTJRXk0unNS71L7h3lxGDH/2HPxMPaQY+MjECKL8=", - version = "v0.20.0", + sum = "h1:5QHQI2tInzr8LsT4kU/2+fSeibH1eIHswNx480cqIoY=", + version = "v0.30.4", ) go_repository( name = "io_k8s_client_go", build_extra_args = ["-exclude=vendor"], build_naming_convention = "go_default_library", importpath = "k8s.io/client-go", - sum = "h1:Xlax8PKbZsjX4gFvNtt4F5MoJ1V5prDvCuoq9B7iax0=", - version = "v0.20.0", - ) - go_repository( - name = "io_k8s_gengo", - importpath = "k8s.io/gengo", - sum = "h1:sAvhNk5RRuc6FNYGqe7Ygz3PSo/2wGWbulskmzRX8Vs=", - version = "v0.0.0-20200413195148-3a45101e95ac", + sum = "h1:eculUe+HPQoPbixfwmaSZGsKcOf7D288tH6hDAdd+wY=", + version = "v0.30.4", ) go_repository( name = "io_k8s_klog_v2", importpath = "k8s.io/klog/v2", - sum = "h1:lyJt0TWMPaGoODa8B8bUuxgHS3W/m/bNr2cca3brA/g=", - version = "v2.80.0", + sum = "h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=", + version = "v2.120.1", ) go_repository( name = "io_k8s_kube_openapi", importpath = "k8s.io/kube-openapi", - sum = "h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c=", - version = "v0.0.0-20201113171705-d219536bb9fd", + sum = "h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=", + version = "v0.0.0-20240228011516-70dd3763d340", + ) + go_repository( + name = "io_k8s_sigs_json", + importpath = "sigs.k8s.io/json", + sum = "h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=", + version = "v0.0.0-20221116044647-bc3834ca7abd", ) go_repository( name = "io_k8s_sigs_structured_merge_diff_v4", importpath = "sigs.k8s.io/structured-merge-diff/v4", - sum = "h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8=", - version = "v4.0.2", + sum = "h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=", + version = "v4.4.1", ) go_repository( name = "io_k8s_sigs_yaml", importpath = "sigs.k8s.io/yaml", - sum = "h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=", - version = "v1.2.0", + sum = "h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=", + version = "v1.3.0", ) go_repository( name = "io_k8s_utils", importpath = "k8s.io/utils", - sum = "h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=", - version = "v0.0.0-20201110183641-67b214c5f920", + sum = "h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=", + version = "v0.0.0-20230726121419-3b25d923346b", ) go_repository( name = "io_opencensus_go", @@ -4705,10 +4580,70 @@ def prysm_deps(): version = "v0.24.0", ) go_repository( - name = "io_opencensus_go_contrib_exporter_jaeger", - importpath = "contrib.go.opencensus.io/exporter/jaeger", - sum = "h1:yGBYzYMewVL0yO9qqJv3Z5+IRhPdU7e9o/2oKpX4YvI=", - version = "v0.2.1", + name = "io_opentelemetry_go_auto_sdk", + importpath = "go.opentelemetry.io/auto/sdk", + sum = "h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=", + version = "v1.1.0", + ) + go_repository( + name = "io_opentelemetry_go_contrib_detectors_gcp", + importpath = "go.opentelemetry.io/contrib/detectors/gcp", + sum = "h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA=", + version = "v1.31.0", + ) + go_repository( + name = "io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp", + importpath = "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", + sum = "h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=", + version = "v0.59.0", + ) + go_repository( + name = "io_opentelemetry_go_otel", + importpath = "go.opentelemetry.io/otel", + sum = "h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=", + version = "v1.34.0", + ) + go_repository( + name = "io_opentelemetry_go_otel_exporters_otlp_otlptrace", + importpath = "go.opentelemetry.io/otel/exporters/otlp/otlptrace", + sum = "h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=", + version = "v1.34.0", + ) + go_repository( + name = "io_opentelemetry_go_otel_exporters_otlp_otlptrace_otlptracehttp", + importpath = "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp", + sum = "h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs=", + version = "v1.34.0", + ) + go_repository( + name = "io_opentelemetry_go_otel_metric", + importpath = "go.opentelemetry.io/otel/metric", + sum = "h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=", + version = "v1.34.0", + ) + go_repository( + name = "io_opentelemetry_go_otel_sdk", + importpath = "go.opentelemetry.io/otel/sdk", + sum = "h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=", + version = "v1.34.0", + ) + go_repository( + name = "io_opentelemetry_go_otel_sdk_metric", + importpath = "go.opentelemetry.io/otel/sdk/metric", + sum = "h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=", + version = "v1.31.0", + ) + go_repository( + name = "io_opentelemetry_go_otel_trace", + importpath = "go.opentelemetry.io/otel/trace", + sum = "h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=", + version = "v1.34.0", + ) + go_repository( + name = "io_opentelemetry_go_proto_otlp", + importpath = "go.opentelemetry.io/proto/otlp", + sum = "h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=", + version = "v1.5.0", ) go_repository( name = "io_rsc_binaryregexp", @@ -4755,8 +4690,8 @@ def prysm_deps(): go_repository( name = "org_golang_google_api", importpath = "google.golang.org/api", - sum = "h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA=", - version = "v0.44.0", + sum = "h1:uWrpz12dpVPn7cojP82mk02XDgTJLDPc2KbVTxrWb4A=", + version = "v0.40.0", ) go_repository( name = "org_golang_google_appengine", @@ -4770,24 +4705,30 @@ def prysm_deps(): sum = "h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=", version = "v0.0.0-20230410155749-daa745c078e1", ) + go_repository( + name = "org_golang_google_genproto_googleapis_api", + importpath = "google.golang.org/genproto/googleapis/api", + sum = "h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=", + version = "v0.0.0-20250115164207-1a7da9e5054f", + ) + go_repository( + name = "org_golang_google_genproto_googleapis_rpc", + importpath = "google.golang.org/genproto/googleapis/rpc", + sum = "h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=", + version = "v0.0.0-20250115164207-1a7da9e5054f", + ) go_repository( name = "org_golang_google_grpc", build_file_proto_mode = "disable", importpath = "google.golang.org/grpc", - sum = "h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=", - version = "v1.56.3", - ) - go_repository( - name = "org_golang_google_grpc_cmd_protoc_gen_go_grpc", - importpath = "google.golang.org/grpc/cmd/protoc-gen-go-grpc", - sum = "h1:lQ+dE99pFsb8osbJB3oRfE5eW4Hx6a/lZQr8Jh+eoT4=", - version = "v1.0.0", + sum = "h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=", + version = "v1.69.4", ) go_repository( name = "org_golang_google_protobuf", importpath = "google.golang.org/protobuf", - sum = "h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=", - version = "v1.34.1", + sum = "h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=", + version = "v1.36.3", ) go_repository( name = "org_golang_x_build", @@ -4798,14 +4739,14 @@ def prysm_deps(): go_repository( name = "org_golang_x_crypto", importpath = "golang.org/x/crypto", - sum = "h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=", - version = "v0.23.0", + sum = "h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=", + version = "v0.32.0", ) go_repository( name = "org_golang_x_exp", importpath = "golang.org/x/exp", - sum = "h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=", - version = "v0.0.0-20240506185415-9bf2ced13842", + sum = "h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=", + version = "v0.0.0-20240808152545-0cdaa3abc0fa", ) go_repository( name = "org_golang_x_exp_typeparams", @@ -4834,20 +4775,20 @@ def prysm_deps(): go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", - sum = "h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=", - version = "v0.17.0", + sum = "h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=", + version = "v0.22.0", ) go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", - sum = "h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=", - version = "v0.25.0", + sum = "h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=", + version = "v0.34.0", ) go_repository( name = "org_golang_x_oauth2", importpath = "golang.org/x/oauth2", - sum = "h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=", - version = "v0.16.0", + sum = "h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=", + version = "v0.24.0", ) go_repository( name = "org_golang_x_perf", @@ -4858,32 +4799,32 @@ def prysm_deps(): go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", - sum = "h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=", - version = "v0.7.0", + sum = "h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=", + version = "v0.10.0", ) go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", - sum = "h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=", - version = "v0.20.0", + sum = "h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=", + version = "v0.29.0", ) go_repository( name = "org_golang_x_telemetry", importpath = "golang.org/x/telemetry", - sum = "h1:IRJeR9r1pYWsHKTRe/IInb7lYvbBVIqOgsX/u0mbOWY=", - version = "v0.0.0-20240228155512-f48c80bd79b2", + sum = "h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk=", + version = "v0.0.0-20240521205824-bda55230c457", ) go_repository( name = "org_golang_x_term", importpath = "golang.org/x/term", - sum = "h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=", - version = "v0.20.0", + sum = "h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=", + version = "v0.28.0", ) go_repository( name = "org_golang_x_text", importpath = "golang.org/x/text", - sum = "h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=", - version = "v0.15.0", + sum = "h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=", + version = "v0.21.0", ) go_repository( name = "org_golang_x_time", @@ -4894,8 +4835,8 @@ def prysm_deps(): go_repository( name = "org_golang_x_tools", importpath = "golang.org/x/tools", - sum = "h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=", - version = "v0.21.0", + sum = "h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=", + version = "v0.29.0", ) go_repository( name = "org_golang_x_xerrors", @@ -4923,14 +4864,14 @@ def prysm_deps(): go_repository( name = "org_uber_go_dig", importpath = "go.uber.org/dig", - sum = "h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=", - version = "v1.17.1", + sum = "h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=", + version = "v1.18.0", ) go_repository( name = "org_uber_go_fx", importpath = "go.uber.org/fx", - sum = "h1:nvvln7mwyT5s1q201YE29V/BFrGor6vMiDNpU/78Mys=", - version = "v1.22.1", + sum = "h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw=", + version = "v1.22.2", ) go_repository( name = "org_uber_go_goleak", @@ -4966,9 +4907,9 @@ def prysm_deps(): http_archive( name = "com_github_supranational_blst", urls = [ - "https://github.com/supranational/blst/archive/3dd0f804b1819e5d03fb22ca2e6fac105932043a.tar.gz", + "https://github.com/supranational/blst/archive/8c7db7fe8d2ce6e76dc398ebd4d475c0ec564355.tar.gz", ], - strip_prefix = "blst-3dd0f804b1819e5d03fb22ca2e6fac105932043a", + strip_prefix = "blst-8c7db7fe8d2ce6e76dc398ebd4d475c0ec564355", build_file = "//third_party:blst/blst.BUILD", - sha256 = "132124c074e59ead77e1828cc54b587a182ea67b781b72198e802af4696d78fe", + sha256 = "e9041d03594271c9739d22d9f013ea8b5c28403285a2e8938f6e41a2437c6ff8", ) diff --git a/encoding/bytesutil/bytes.go b/encoding/bytesutil/bytes.go index 5faebbf5265b..7dbd6f5609d8 100644 --- a/encoding/bytesutil/bytes.go +++ b/encoding/bytesutil/bytes.go @@ -3,6 +3,7 @@ package bytesutil import ( "fmt" + "unsafe" "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -145,3 +146,10 @@ func ReverseByteOrder(input []byte) []byte { } return b } + +// UnsafeCastToString casts a byte slice to a string object without performing a copy. Changes +// to byteSlice will also modify the contents of the string, so it is the caller's responsibility +// to ensure that the byte slice will not modified after the string is created. +func UnsafeCastToString(byteSlice []byte) string { + return *(*string)(unsafe.Pointer(&byteSlice)) // #nosec G103 +} diff --git a/encoding/bytesutil/bytes_test.go b/encoding/bytesutil/bytes_test.go index feffc01d310f..6e7c4cfcac29 100644 --- a/encoding/bytesutil/bytes_test.go +++ b/encoding/bytesutil/bytes_test.go @@ -217,6 +217,50 @@ func TestToBytes20(t *testing.T) { } } +func TestCastToString(t *testing.T) { + bSlice := []byte{'a', 'b', 'c'} + bString := bytesutil.UnsafeCastToString(bSlice) + + originalString := "abc" + + // Mutate original slice to make sure that a copy was not performed. + bSlice[0] = 'd' + assert.NotEqual(t, originalString, bString) + assert.Equal(t, "dbc", bString) +} + +func BenchmarkUnsafeCastToString(b *testing.B) { + data := []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + empty := []byte{} + var nilData []byte + + b.Run("string(b)", func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = string(data) + _ = string(empty) + _ = string(nilData) + } + }) + + b.Run("bytesutil.UnsafeCastToString(b)", func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = bytesutil.UnsafeCastToString(data) + _ = bytesutil.UnsafeCastToString(empty) + _ = bytesutil.UnsafeCastToString(nilData) + } + }) +} + +func FuzzUnsafeCastToString(f *testing.F) { + f.Fuzz(func(t *testing.T, input []byte) { + want := string(input) + result := bytesutil.UnsafeCastToString(input) + if result != want { + t.Fatalf("input (%v) result (%s) did not match expected (%s)", input, result, want) + } + }) +} + func BenchmarkToBytes32(b *testing.B) { x := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} for i := 0; i < b.N; i++ { diff --git a/encoding/bytesutil/hex.go b/encoding/bytesutil/hex.go index 049c10e93d17..3c9939e16798 100644 --- a/encoding/bytesutil/hex.go +++ b/encoding/bytesutil/hex.go @@ -34,7 +34,7 @@ func DecodeHexWithLength(s string, length int) ([]byte, error) { // DecodeHexWithMaxLength takes a string and a length in bytes, // and validates whether the string is a hex and has the correct length. -func DecodeHexWithMaxLength(s string, maxLength int) ([]byte, error) { +func DecodeHexWithMaxLength(s string, maxLength uint64) ([]byte, error) { bytes, err := hexutil.Decode(s) if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("%s is not a valid hex", s)) diff --git a/encoding/ssz/detect/configfork.go b/encoding/ssz/detect/configfork.go index 327b68198cd4..5678739dcfd6 100644 --- a/encoding/ssz/detect/configfork.go +++ b/encoding/ssz/detect/configfork.go @@ -88,6 +88,8 @@ func FromForkVersion(cv [fieldparams.VersionLength]byte) (*VersionedUnmarshaler, fork = version.Deneb case bytesutil.ToBytes4(cfg.ElectraForkVersion): fork = version.Electra + case bytesutil.ToBytes4(cfg.FuluForkVersion): + fork = version.Fulu default: return nil, errors.Wrapf(ErrForkNotFound, "version=%#x", cv) } @@ -163,6 +165,16 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconState(marshaled []byte) (s state. if err != nil { return nil, errors.Wrapf(err, "failed to init state trie from state, detected fork=%s", forkName) } + case version.Fulu: + st := ðpb.BeaconStateElectra{} + err = st.UnmarshalSSZ(marshaled) + if err != nil { + return nil, errors.Wrapf(err, "failed to unmarshal state, detected fork=%s", forkName) + } + s, err = state_native.InitializeFromProtoUnsafeFulu(st) + if err != nil { + return nil, errors.Wrapf(err, "failed to init state trie from state, detected fork=%s", forkName) + } default: return nil, fmt.Errorf("unable to initialize BeaconState for fork version=%s", forkName) } @@ -213,6 +225,8 @@ func (cf *VersionedUnmarshaler) UnmarshalBeaconBlock(marshaled []byte) (interfac blk = ðpb.SignedBeaconBlockDeneb{} case version.Electra: blk = ðpb.SignedBeaconBlockElectra{} + case version.Fulu: + blk = ðpb.SignedBeaconBlockFulu{} default: forkName := version.String(cf.Fork) return nil, fmt.Errorf("unable to initialize ReadOnlyBeaconBlock for fork version=%s at slot=%d", forkName, slot) @@ -250,6 +264,8 @@ func (cf *VersionedUnmarshaler) UnmarshalBlindedBeaconBlock(marshaled []byte) (i blk = ðpb.SignedBlindedBeaconBlockDeneb{} case version.Electra: blk = ðpb.SignedBlindedBeaconBlockElectra{} + case version.Fulu: + blk = ðpb.SignedBlindedBeaconBlockFulu{} default: forkName := version.String(cf.Fork) return nil, fmt.Errorf("unable to initialize ReadOnlyBeaconBlock for fork version=%s at slot=%d", forkName, slot) diff --git a/encoding/ssz/detect/configfork_test.go b/encoding/ssz/detect/configfork_test.go index d417eeeb1fd9..de7bdcac1375 100644 --- a/encoding/ssz/detect/configfork_test.go +++ b/encoding/ssz/detect/configfork_test.go @@ -46,8 +46,8 @@ func TestSlotFromBlock(t *testing.T) { } func TestByState(t *testing.T) { - undo := util.HackElectraMaxuint(t) - defer undo() + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() + bc := params.BeaconConfig() altairSlot, err := slots.EpochStart(bc.AltairForkEpoch) require.NoError(t, err) @@ -59,6 +59,8 @@ func TestByState(t *testing.T) { require.NoError(t, err) electraSlot, err := slots.EpochStart(bc.ElectraForkEpoch) require.NoError(t, err) + fuluSlot, err := slots.EpochStart(bc.FuluForkEpoch) + require.NoError(t, err) cases := []struct { name string version int @@ -101,6 +103,12 @@ func TestByState(t *testing.T) { slot: electraSlot, forkversion: bytesutil.ToBytes4(bc.ElectraForkVersion), }, + { + name: "fulu", + version: version.Fulu, + slot: fuluSlot, + forkversion: bytesutil.ToBytes4(bc.FuluForkVersion), + }, } for _, c := range cases { st, err := stateForVersion(c.version) @@ -135,6 +143,8 @@ func stateForVersion(v int) (state.BeaconState, error) { return util.NewBeaconStateDeneb() case version.Electra: return util.NewBeaconStateElectra() + case version.Fulu: + return util.NewBeaconStateFulu() default: return nil, fmt.Errorf("unrecognized version %d", v) } @@ -142,8 +152,8 @@ func stateForVersion(v int) (state.BeaconState, error) { func TestUnmarshalState(t *testing.T) { ctx := context.Background() - undo := util.HackElectraMaxuint(t) - defer undo() + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() + bc := params.BeaconConfig() altairSlot, err := slots.EpochStart(bc.AltairForkEpoch) require.NoError(t, err) @@ -155,6 +165,8 @@ func TestUnmarshalState(t *testing.T) { require.NoError(t, err) electraSlot, err := slots.EpochStart(bc.ElectraForkEpoch) require.NoError(t, err) + fuluSlot, err := slots.EpochStart(bc.FuluForkEpoch) + require.NoError(t, err) cases := []struct { name string version int @@ -197,6 +209,12 @@ func TestUnmarshalState(t *testing.T) { slot: electraSlot, forkversion: bytesutil.ToBytes4(bc.ElectraForkVersion), }, + { + name: "fulu", + version: version.Fulu, + slot: fuluSlot, + forkversion: bytesutil.ToBytes4(bc.FuluForkVersion), + }, } for _, c := range cases { st, err := stateForVersion(c.version) @@ -222,8 +240,8 @@ func TestUnmarshalState(t *testing.T) { } func TestDetectAndUnmarshalBlock(t *testing.T) { - undo := util.HackElectraMaxuint(t) - defer undo() + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() + altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch) require.NoError(t, err) bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) @@ -234,6 +252,8 @@ func TestDetectAndUnmarshalBlock(t *testing.T) { require.NoError(t, err) electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch) require.NoError(t, err) + fuluS, err := slots.EpochStart(params.BeaconConfig().FuluForkEpoch) + require.NoError(t, err) cases := []struct { b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock name string @@ -284,6 +304,11 @@ func TestDetectAndUnmarshalBlock(t *testing.T) { b: signedTestBlockElectra, slot: electraS, }, + { + name: "first slot of fulu", + b: signedTestBlockFulu, + slot: fuluS, + }, { name: "bellatrix block in altair slot", b: signedTestBlockBellatrix, @@ -320,14 +345,15 @@ func TestDetectAndUnmarshalBlock(t *testing.T) { } func TestUnmarshalBlock(t *testing.T) { - undo := util.HackElectraMaxuint(t) - defer undo() + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() + genv := bytesutil.ToBytes4(params.BeaconConfig().GenesisForkVersion) altairv := bytesutil.ToBytes4(params.BeaconConfig().AltairForkVersion) bellav := bytesutil.ToBytes4(params.BeaconConfig().BellatrixForkVersion) capellaV := bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion) denebV := bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion) electraV := bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion) + fuluV := bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion) altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch) require.NoError(t, err) bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) @@ -338,6 +364,8 @@ func TestUnmarshalBlock(t *testing.T) { require.NoError(t, err) electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch) require.NoError(t, err) + fuluS, err := slots.EpochStart(params.BeaconConfig().FuluForkEpoch) + require.NoError(t, err) cases := []struct { b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock name string @@ -398,6 +426,12 @@ func TestUnmarshalBlock(t *testing.T) { version: electraV, slot: electraS, }, + { + name: "first slot of fulu", + b: signedTestBlockFulu, + version: fuluV, + slot: fuluS, + }, { name: "bellatrix block in altair slot", b: signedTestBlockBellatrix, @@ -442,14 +476,15 @@ func TestUnmarshalBlock(t *testing.T) { } func TestUnmarshalBlindedBlock(t *testing.T) { - undo := util.HackElectraMaxuint(t) - defer undo() + defer util.HackForksMaxuint(t, []int{version.Electra, version.Fulu})() + genv := bytesutil.ToBytes4(params.BeaconConfig().GenesisForkVersion) altairv := bytesutil.ToBytes4(params.BeaconConfig().AltairForkVersion) bellav := bytesutil.ToBytes4(params.BeaconConfig().BellatrixForkVersion) capellaV := bytesutil.ToBytes4(params.BeaconConfig().CapellaForkVersion) denebV := bytesutil.ToBytes4(params.BeaconConfig().DenebForkVersion) electraV := bytesutil.ToBytes4(params.BeaconConfig().ElectraForkVersion) + fuluV := bytesutil.ToBytes4(params.BeaconConfig().FuluForkVersion) altairS, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch) require.NoError(t, err) bellaS, err := slots.EpochStart(params.BeaconConfig().BellatrixForkEpoch) @@ -460,6 +495,8 @@ func TestUnmarshalBlindedBlock(t *testing.T) { require.NoError(t, err) electraS, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch) require.NoError(t, err) + fuluS, err := slots.EpochStart(params.BeaconConfig().FuluForkEpoch) + require.NoError(t, err) cases := []struct { b func(*testing.T, primitives.Slot) interfaces.ReadOnlySignedBeaconBlock name string @@ -527,6 +564,12 @@ func TestUnmarshalBlindedBlock(t *testing.T) { version: electraV, slot: electraS, }, + { + name: "first slot of fulu", + b: signedTestBlindedBlockFulu, + version: fuluV, + slot: fuluS, + }, { name: "genesis block in altair slot", b: signedTestBlockGenesis, @@ -563,6 +606,10 @@ func TestUnmarshalBlindedBlock(t *testing.T) { } } +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + func signedTestBlockGenesis(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { b := util.NewBeaconBlock() b.Block.Slot = slot @@ -571,6 +618,10 @@ func signedTestBlockGenesis(t *testing.T, slot primitives.Slot) interfaces.ReadO return s } +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- + func signedTestBlockAltair(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { b := util.NewBeaconBlockAltair() b.Block.Slot = slot @@ -579,6 +630,10 @@ func signedTestBlockAltair(t *testing.T, slot primitives.Slot) interfaces.ReadOn return s } +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + func signedTestBlockBellatrix(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { b := util.NewBeaconBlockBellatrix() b.Block.Slot = slot @@ -595,6 +650,10 @@ func signedTestBlindedBlockBellatrix(t *testing.T, slot primitives.Slot) interfa return s } +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + func signedTestBlockCapella(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { b := util.NewBeaconBlockCapella() b.Block.Slot = slot @@ -611,6 +670,10 @@ func signedTestBlindedBlockCapella(t *testing.T, slot primitives.Slot) interface return s } +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + func signedTestBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { b := util.NewBeaconBlockDeneb() b.Block.Slot = slot @@ -619,6 +682,18 @@ func signedTestBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.ReadOnl return s } +func signedTestBlindedBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { + b := util.NewBlindedBeaconBlockDeneb() + b.Message.Slot = slot + s, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + return s +} + +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + func signedTestBlockElectra(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { b := util.NewBeaconBlockElectra() b.Block.Slot = slot @@ -627,16 +702,28 @@ func signedTestBlockElectra(t *testing.T, slot primitives.Slot) interfaces.ReadO return s } -func signedTestBlindedBlockDeneb(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { - b := util.NewBlindedBeaconBlockDeneb() +func signedTestBlindedBlockElectra(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { + b := util.NewBlindedBeaconBlockElectra() b.Message.Slot = slot s, err := blocks.NewSignedBeaconBlock(b) require.NoError(t, err) return s } -func signedTestBlindedBlockElectra(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { - b := util.NewBlindedBeaconBlockElectra() +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +func signedTestBlockFulu(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { + b := util.NewBeaconBlockFulu() + b.Block.Slot = slot + s, err := blocks.NewSignedBeaconBlock(b) + require.NoError(t, err) + return s +} + +func signedTestBlindedBlockFulu(t *testing.T, slot primitives.Slot) interfaces.ReadOnlySignedBeaconBlock { + b := util.NewBlindedBeaconBlockFulu() b.Message.Slot = slot s, err := blocks.NewSignedBeaconBlock(b) require.NoError(t, err) diff --git a/encoding/ssz/htrutils.go b/encoding/ssz/htrutils.go index d0581d47e809..3076adcbbcc4 100644 --- a/encoding/ssz/htrutils.go +++ b/encoding/ssz/htrutils.go @@ -141,7 +141,7 @@ func WithdrawalSliceRoot(withdrawals []*enginev1.Withdrawal, limit uint64) ([32] return MixInLength(bytesRoot, bytesRootBufRoot), nil } -// DepositRequestsSliceRoot computes the HTR of a slice of deposit receipts. +// DepositRequestsSliceRoot computes the HTR of a slice of deposit requests. // The limit parameter is used as input to the bitwise merkleization algorithm. func DepositRequestsSliceRoot(depositRequests []*enginev1.DepositRequest, limit uint64) ([32]byte, error) { return SliceRoot(depositRequests, limit) diff --git a/go.mod b/go.mod index 482659fb5423..cbd8d3eb83ad 100644 --- a/go.mod +++ b/go.mod @@ -1,53 +1,48 @@ module github.com/prysmaticlabs/prysm/v5 -go 1.22 - -toolchain go1.22.4 +go 1.23.5 require ( - contrib.go.opencensus.io/exporter/jaeger v0.2.1 - github.com/MariusVanDerWijden/FuzzyVM v0.0.0-20240209103030-ec53fa766bf8 - github.com/MariusVanDerWijden/tx-fuzz v1.3.3-0.20240227085032-f70dd7c85c97 + github.com/MariusVanDerWijden/FuzzyVM v0.0.0-20240516070431-7828990cad7d + github.com/MariusVanDerWijden/tx-fuzz v1.4.0 github.com/aristanetworks/goarista v0.0.0-20200805130819-fd197cf57d96 github.com/bazelbuild/rules_go v0.23.2 - github.com/btcsuite/btcd/btcec/v2 v2.3.2 - github.com/consensys/gnark-crypto v0.12.1 - github.com/crate-crypto/go-kzg-4844 v0.7.0 + github.com/btcsuite/btcd/btcec/v2 v2.3.4 + github.com/consensys/gnark-crypto v0.14.0 + github.com/crate-crypto/go-kzg-4844 v1.1.0 github.com/d4l3k/messagediff v1.2.1 github.com/dgraph-io/ristretto v0.0.4-0.20210318174700-74754f61e018 github.com/dustin/go-humanize v1.0.0 github.com/emicklei/dot v0.11.0 - github.com/ethereum/go-ethereum v1.13.5 - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 + github.com/ethereum/go-ethereum v1.15.0 github.com/fsnotify/fsnotify v1.6.0 github.com/ghodss/yaml v1.0.0 github.com/go-yaml/yaml v2.1.0+incompatible github.com/gogo/protobuf v1.3.2 - github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/golang-jwt/jwt/v4 v4.5.1 github.com/golang/gddo v0.0.0-20200528160355-8d077c1d8f4c github.com/golang/protobuf v1.5.4 - github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb + github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e github.com/google/go-cmp v0.6.0 github.com/google/gofuzz v1.2.0 - github.com/google/uuid v1.4.0 - github.com/gorilla/mux v1.8.0 + github.com/google/uuid v1.6.0 github.com/gostaticanalysis/comment v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d - github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e - github.com/holiman/uint256 v1.2.4 + github.com/herumi/bls-eth-go-binary v1.31.0 + github.com/holiman/uint256 v1.3.2 github.com/ianlancetaylor/cgosymbolizer v0.0.0-20200424224625-be1b05b0b279 github.com/ipfs/go-log/v2 v2.5.1 github.com/jedib0t/go-pretty/v6 v6.5.4 github.com/joonix/log v0.0.0-20200409080653-9c1d2ceb5f1d github.com/json-iterator/go v1.1.12 github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 + github.com/kisielk/errcheck v1.8.0 github.com/kr/pretty v0.3.1 - github.com/libp2p/go-libp2p v0.35.2 + github.com/libp2p/go-libp2p v0.36.5 github.com/libp2p/go-libp2p-mplex v0.9.0 - github.com/libp2p/go-libp2p-pubsub v0.11.0 + github.com/libp2p/go-libp2p-pubsub v0.13.0 github.com/libp2p/go-mplex v0.7.0 github.com/logrusorgru/aurora v2.0.3+incompatible github.com/manifoldco/promptui v0.7.0 @@ -55,107 +50,116 @@ require ( github.com/minio/highwayhash v1.0.2 github.com/minio/sha256-simd v1.0.1 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 - github.com/multiformats/go-multiaddr v0.12.4 - github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.30.0 + github.com/multiformats/go-multiaddr v0.13.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/paulbellamy/ratecounter v0.2.0 github.com/pborman/uuid v1.2.1 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.19.1 + github.com/prometheus/client_golang v1.20.0 github.com/prometheus/client_model v0.6.1 github.com/prometheus/prom2json v1.3.0 - github.com/prysmaticlabs/fastssz v0.0.0-20240620202422-a981b8ef89d3 + github.com/prysmaticlabs/fastssz v0.0.0-20241008181541-518c4ce73516 github.com/prysmaticlabs/go-bitfield v0.0.0-20240328144219-a1caa50c3a1e github.com/prysmaticlabs/prombbolt v0.0.0-20210126082820-9b7adba6db7c github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294 + github.com/r3labs/sse/v2 v2.10.0 github.com/rs/cors v1.7.0 github.com/schollz/progressbar/v3 v3.3.4 - github.com/sirupsen/logrus v1.9.0 + github.com/sirupsen/logrus v1.9.3 github.com/spf13/afero v1.10.0 github.com/status-im/keycard-go v0.2.0 - github.com/stretchr/testify v1.9.0 - github.com/supranational/blst v0.3.11 + github.com/stretchr/testify v1.10.0 + github.com/supranational/blst v0.3.14 github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e github.com/trailofbits/go-mutexasserts v0.0.0-20230328101604-8cdbc5f3d279 github.com/tyler-smith/go-bip39 v1.1.0 - github.com/urfave/cli/v2 v2.26.0 + github.com/urfave/cli/v2 v2.27.1 github.com/uudashr/gocognit v1.0.5 github.com/wealdtech/go-bytesutil v1.1.1 github.com/wealdtech/go-eth2-util v1.6.3 github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3 go.etcd.io/bbolt v1.3.6 go.opencensus.io v0.24.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 + go.opentelemetry.io/otel v1.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 + go.opentelemetry.io/otel/sdk v1.34.0 + go.opentelemetry.io/otel/trace v1.34.0 go.uber.org/automaxprocs v1.5.2 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.23.0 - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 - golang.org/x/mod v0.17.0 - golang.org/x/sync v0.7.0 - golang.org/x/tools v0.21.0 + golang.org/x/crypto v0.32.0 + golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa + golang.org/x/sync v0.10.0 + golang.org/x/tools v0.29.0 google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 - google.golang.org/grpc v1.56.3 - google.golang.org/protobuf v1.34.1 + google.golang.org/grpc v1.69.4 + google.golang.org/protobuf v1.36.3 gopkg.in/d4l3k/messagediff.v1 v1.2.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - honnef.co/go/tools v0.5.0-0.dev.0.20231205170804-aef76f4feee2 - k8s.io/apimachinery v0.20.0 - k8s.io/client-go v0.20.0 + honnef.co/go/tools v0.5.1 + k8s.io/apimachinery v0.30.4 + k8s.io/client-go v0.30.4 ) require ( - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect github.com/DataDog/zstd v1.5.5 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.11.0 // indirect + github.com/bits-and-blooms/bitset v1.17.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/cp v1.1.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect - github.com/cockroachdb/errors v1.11.1 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect + github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/bavard v0.1.22 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect - github.com/deckarep/golang-set/v2 v2.5.0 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/deepmap/oapi-codegen v1.8.2 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect - github.com/elastic/gosigar v0.14.2 // indirect - github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9 // indirect + github.com/elastic/gosigar v0.14.3 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect + github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/ferranbt/fastssz v0.1.3 // indirect github.com/flynn/noise v1.1.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect - github.com/getsentry/sentry-go v0.25.0 // indirect + github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/flock v0.8.1 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect + github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect + github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/goevmlab v0.0.0-20231201084119-c73b3c97929c // indirect + github.com/holiman/goevmlab v0.0.0-20241121133100-cfa6b078c8c4 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c // indirect @@ -164,9 +168,8 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect - github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c // indirect - github.com/klauspost/compress v1.17.8 // indirect - github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.2.3 // indirect @@ -184,7 +187,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/miekg/dns v1.1.58 // indirect + github.com/miekg/dns v1.1.62 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect @@ -196,44 +199,46 @@ require ( github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect + github.com/multiformats/go-multiaddr-dns v0.4.0 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multicodec v0.9.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-multistream v0.5.0 // indirect github.com/multiformats/go-varint v0.0.7 // indirect - github.com/nxadm/tail v1.4.11 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/onsi/ginkgo/v2 v2.15.0 // indirect + github.com/onsi/ginkgo/v2 v2.20.0 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pion/datachannel v1.5.6 // indirect - github.com/pion/dtls/v2 v2.2.11 // indirect - github.com/pion/ice/v2 v2.3.25 // indirect - github.com/pion/interceptor v0.1.29 // indirect + github.com/pion/datachannel v1.5.8 // indirect + github.com/pion/dtls/v2 v2.2.12 // indirect + github.com/pion/ice/v2 v2.3.34 // indirect + github.com/pion/interceptor v0.1.30 // indirect github.com/pion/logging v0.2.2 // indirect github.com/pion/mdns v0.0.12 // indirect github.com/pion/randutil v0.1.0 // indirect github.com/pion/rtcp v1.2.14 // indirect - github.com/pion/rtp v1.8.6 // indirect - github.com/pion/sctp v1.8.16 // indirect + github.com/pion/rtp v1.8.9 // indirect + github.com/pion/sctp v1.8.33 // indirect github.com/pion/sdp/v3 v3.0.9 // indirect - github.com/pion/srtp/v2 v2.0.18 // indirect + github.com/pion/srtp/v2 v2.0.20 // indirect github.com/pion/stun v0.6.1 // indirect - github.com/pion/transport/v2 v2.2.5 // indirect + github.com/pion/stun/v2 v2.0.0 // indirect + github.com/pion/transport/v2 v2.2.10 // indirect + github.com/pion/transport/v3 v3.0.7 // indirect github.com/pion/turn/v2 v2.1.6 // indirect - github.com/pion/webrtc/v3 v3.2.40 // indirect + github.com/pion/webrtc/v3 v3.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/quic-go v0.44.0 // indirect - github.com/quic-go/webtransport-go v0.8.0 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.48.2 // indirect + github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect @@ -241,46 +246,47 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tklauser/go-sysconf v0.3.13 // indirect github.com/tklauser/numcpus v0.7.0 // indirect - github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect - github.com/wealdtech/go-eth2-types/v2 v2.5.2 // indirect + github.com/wealdtech/go-eth2-types/v2 v2.8.2 // indirect + github.com/wlynxg/anet v0.0.4 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.uber.org/dig v1.17.1 // indirect - go.uber.org/fx v1.22.1 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/proto/otlp v1.5.0 // indirect + go.uber.org/dig v1.18.0 // indirect + go.uber.org/fx v1.22.2 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/term v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect + gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - lukechampine.com/blake3 v1.2.1 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + lukechampine.com/blake3 v1.3.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.0.2 // indirect - sigs.k8s.io/yaml v1.2.0 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) require ( github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf - github.com/fatih/color v1.13.0 // indirect + github.com/fatih/color v1.16.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-playground/validator/v10 v10.13.0 github.com/peterh/liner v1.2.0 // indirect github.com/prysmaticlabs/gohashtree v0.0.4-beta.0.20240624100937-73632381301b - golang.org/x/sys v0.20.0 // indirect - google.golang.org/api v0.44.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - k8s.io/klog/v2 v2.80.0 // indirect - k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect + golang.org/x/sys v0.29.0 // indirect + k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect ) replace github.com/json-iterator/go => github.com/prestonvanloon/go v1.1.7-0.20190722034630-4f2e55fcf87b - -// See https://github.com/prysmaticlabs/grpc-gateway/issues/2 -replace github.com/grpc-ecosystem/grpc-gateway/v2 => github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20230315201114-09284ba20446 diff --git a/go.sum b/go.sum index c15dec2fca65..a81dc7200dbe 100644 --- a/go.sum +++ b/go.sum @@ -20,9 +20,6 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -31,7 +28,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -42,41 +38,27 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -contrib.go.opencensus.io/exporter/jaeger v0.2.1 h1:yGBYzYMewVL0yO9qqJv3Z5+IRhPdU7e9o/2oKpX4YvI= -contrib.go.opencensus.io/exporter/jaeger v0.2.1/go.mod h1:Y8IsLgdxqh1QxYxPC5IgXVmBaeLUeQFfBeBi9PbeZd0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/MariusVanDerWijden/FuzzyVM v0.0.0-20240209103030-ec53fa766bf8 h1:BwEuC3xavrv4HTUDH2fUrKgKooiH3Q/nSVnFGtnzpN0= -github.com/MariusVanDerWijden/FuzzyVM v0.0.0-20240209103030-ec53fa766bf8/go.mod h1:L1QpLBqXlboJMOC2hndG95d1eiElzKsBhjzcuy8pxeM= -github.com/MariusVanDerWijden/tx-fuzz v1.3.3-0.20240227085032-f70dd7c85c97 h1:QDTh0xHorSykJ4+2VccBADMeRAVUbnHaWrCPIMtN+Vc= -github.com/MariusVanDerWijden/tx-fuzz v1.3.3-0.20240227085032-f70dd7c85c97/go.mod h1:xcjGtET6+7KeDHcwLQp3sIfyFALtoTjzZgY8Y+RUozM= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/MariusVanDerWijden/FuzzyVM v0.0.0-20240516070431-7828990cad7d h1:RQtzNvriR3Yu5CvVBTJPwDmfItBT90TWZ3fFondhc08= +github.com/MariusVanDerWijden/FuzzyVM v0.0.0-20240516070431-7828990cad7d/go.mod h1:gWTykV/ZinShgltWofTEJY4TsletuvGhB6l4+Ai2F+E= +github.com/MariusVanDerWijden/tx-fuzz v1.4.0 h1:Tq4lXivsR8mtoP4RpasUDIUpDLHfN1YhFge/kzrzK78= +github.com/MariusVanDerWijden/tx-fuzz v1.4.0/go.mod h1:gmOVECg7o5FY5VU3DQ/fY0zTk/ExBdMkUGz0vA8qqms= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= @@ -93,7 +75,6 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks= @@ -105,7 +86,6 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= @@ -119,29 +99,27 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.11.0 h1:RMyy2mBBShArUAhfVRZJ2xyBO58KCBCtZFShw3umo6k= -github.com/bits-and-blooms/bitset v1.11.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bits-and-blooms/bitset v1.17.0 h1:1X2TS7aHz1ELcC0yU1y2stUs/0ig5oMU6STFZGrhvHI= +github.com/bits-and-blooms/bitset v1.17.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= @@ -163,44 +141,43 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= -github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= +github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/pebble v1.1.2 h1:CUh2IPtR4swHlEj48Rhfzw6l/d0qA31fItcIszQVIsA= +github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/consensys/bavard v0.1.22 h1:Uw2CGvbXSZWhqK59X0VG/zOjpTFuOMcPLStrp1ihI0A= +github.com/consensys/bavard v0.1.22/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= +github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= +github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= -github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg= +github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM= +github.com/crate-crypto/go-kzg-4844 v1.1.0 h1:EN/u9k2TF6OWSHrCCDBBU6GLNMq88OspHHlMnHfoyU4= +github.com/crate-crypto/go-kzg-4844 v1.1.0/go.mod h1:JolLjpSff1tCCJKaJx4psrlEdlXuJEC996PL3tTAFks= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= @@ -211,8 +188,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/deckarep/golang-set/v2 v2.5.0 h1:hn6cEZtQ0h3J8kFrHR/NrzyOoTnjgW1+FmNJzQ7y/sA= -github.com/deckarep/golang-set/v2 v2.5.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= @@ -225,15 +202,12 @@ github.com/dgraph-io/ristretto v0.0.4-0.20210318174700-74754f61e018/go.mod h1:MI github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5RVoRccG8a5DhOdWdQ4zN62zzo= github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= @@ -248,36 +222,36 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= -github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo= +github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/emicklei/dot v0.11.0 h1:Ase39UD9T9fRBOb5ptgpixrxfx8abVzNWZi2+lr53PI= github.com/emicklei/dot v0.11.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= -github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.5 h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF3VbaFk= -github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.15.0 h1:LLb2jCPsbJZcB4INw+E/MgzUX5wlR6SdwXcv09/1ME4= +github.com/ethereum/go-ethereum v1.15.0/go.mod h1:4q+4t48P2C03sjqGvTXix5lEOplf5dz4CTosbjt5tGs= +github.com/ethereum/go-verkle v0.2.2 h1:I2W0WjnrFUIzzVPwm8ykY+7pL2d4VhlsePn4j7cnFk8= +github.com/ethereum/go-verkle v0.2.2/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9 h1:9VDpsWq096+oGMDTT/SgBD/VgZYf4pTF+KTPmZ+OaKM= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/ferranbt/fastssz v0.1.3 h1:ZI+z3JH05h4kgmFXdHuR1aWYsgrg7o+Fw7/NCzM16Mo= +github.com/ferranbt/fastssz v0.1.3/go.mod h1:0Y9TEd/9XuFlh7mskMPfXiI2Dkw4Ddg9EyXt1W7MRvE= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= @@ -295,9 +269,8 @@ github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8x github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= -github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= -github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -314,22 +287,22 @@ github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgO github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -343,21 +316,16 @@ github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5Nq github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -365,19 +333,17 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/gddo v0.0.0-20200528160355-8d077c1d8f4c h1:HoqgYR60VYu5+0BuG6pjeGp7LKEPZnHt+dUClx9PeIs= github.com/golang/gddo v0.0.0-20200528160355-8d077c1d8f4c/go.mod h1:sam69Hju0uq+5uvLJUMDlsKlQ21Vrs1Kd/1YFPNYdOU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -387,7 +353,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -403,19 +368,19 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc= +github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -428,12 +393,12 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= @@ -451,35 +416,28 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= -github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo= -github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= +github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= @@ -489,18 +447,16 @@ github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY4 github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= @@ -525,22 +481,21 @@ github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:i github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/herumi/bls-eth-go-binary v0.0.0-20210130185500-57372fb27371/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U= -github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e h1:wCMygKUQhmcQAjlk2Gquzq6dLmyMv2kF+llRspoRgrk= -github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/herumi/bls-eth-go-binary v1.31.0 h1:9eeW3EA4epCb7FIHt2luENpAW69MvKGL5jieHlBiP+w= +github.com/herumi/bls-eth-go-binary v1.31.0/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/goevmlab v0.0.0-20231201084119-c73b3c97929c h1:J973NLskKmFIj3EGfpQ1ztUQKdwyJ+fG34638ief0eA= -github.com/holiman/goevmlab v0.0.0-20231201084119-c73b3c97929c/go.mod h1:K6KFgcQq1U9ksldcRyLYcwtj4nUTPn4rEaZtX4Gjofc= -github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= -github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/holiman/goevmlab v0.0.0-20241121133100-cfa6b078c8c4 h1:JHZ8k9n9G9KXIo1qrvK5Cxah6ax5BR0qVTA9bFYl1oM= +github.com/holiman/goevmlab v0.0.0-20241121133100-cfa6b078c8c4/go.mod h1:+DBd7lup47uusCYWbkJPfHRG4LYjBHvyXU0c+z26/U4= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= @@ -550,7 +505,6 @@ github.com/ianlancetaylor/cgosymbolizer v0.0.0-20200424224625-be1b05b0b279/go.mo github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= @@ -573,11 +527,12 @@ github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/U github.com/jedib0t/go-pretty/v6 v6.5.4 h1:gOGo0613MoqUcf0xCj+h/V3sHDaZasfv152G6/5l91s= github.com/jedib0t/go-pretty/v6 v6.5.4/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jhump/protoreflect v1.8.1/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/joonix/log v0.0.0-20200409080653-9c1d2ceb5f1d h1:k+SfYbN66Ev/GDVq39wYOXVW5RNd5kzzairbCe9dK5Q= github.com/joonix/log v0.0.0-20200409080653-9c1d2ceb5f1d/go.mod h1:fS54ONkjDV71zS9CDx3V9K21gJg7byKSvI4ajuWFNJw= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= @@ -585,25 +540,22 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= -github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c h1:AqsttAyEyIEsNz5WLRwuRwjiT5CMDUfLk6cFJDVPebs= -github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg= +github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= -github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= -github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -620,7 +572,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -628,22 +579,22 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA= github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.35.2 h1:287oHbuplkrLdAF+syB0n/qDgd50AUBtEODqS0e0HDs= -github.com/libp2p/go-libp2p v0.35.2/go.mod h1:RKCDNt30IkFipGL0tl8wQW/3zVWEGFUZo8g2gAKxwjU= +github.com/libp2p/go-libp2p v0.36.5 h1:DoABsaHO0VXwH6pwCs2F6XKAXWYjFMO4HFBoVxTnF9g= +github.com/libp2p/go-libp2p v0.36.5/go.mod h1:CpszAtXxHYOcyvB7K8rSHgnNlh21eKjYbEfLoMerbEI= github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= github.com/libp2p/go-libp2p-mplex v0.9.0 h1:R58pDRAmuBXkYugbSSXR9wrTX3+1pFM1xP2bLuodIq8= github.com/libp2p/go-libp2p-mplex v0.9.0/go.mod h1:ro1i4kuwiFT+uMPbIDIFkcLs1KRbNp0QwnUXM+P64Og= -github.com/libp2p/go-libp2p-pubsub v0.11.0 h1:+JvS8Kty0OiyUiN0i8H5JbaCgjnJTRnTHe4rU88dLFc= -github.com/libp2p/go-libp2p-pubsub v0.11.0/go.mod h1:QEb+hEV9WL9wCiUAnpY29FZR6W3zK8qYlaml8R4q6gQ= +github.com/libp2p/go-libp2p-pubsub v0.13.0 h1:RmFQ2XAy3zQtbt2iNPy7Tt0/3fwTnHpCQSSnmGnt1Ps= +github.com/libp2p/go-libp2p-pubsub v0.13.0/go.mod h1:m0gpUOyrXKXdE7c8FNQ9/HLfWbxaEw7xku45w+PaqZo= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= @@ -667,10 +618,11 @@ github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+L github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4= github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= @@ -681,7 +633,6 @@ github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9v github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -706,9 +657,8 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= -github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= +github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= +github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -726,7 +676,6 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= @@ -758,11 +707,10 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.12.4 h1:rrKqpY9h+n80EwhhC/kkcunCZZ7URIF8yN1WEUt2Hvc= -github.com/multiformats/go-multiaddr v0.12.4/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= +github.com/multiformats/go-multiaddr v0.13.0 h1:BCBzs61E3AGHcYYTv8dqRH43ZfyrqM8RXVPT8t13tLQ= +github.com/multiformats/go-multiaddr v0.13.0/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= +github.com/multiformats/go-multiaddr-dns v0.4.0 h1:P76EJ3qzBXpUXZ3twdCDx/kvagMsNo0LMFXpyms/zgU= +github.com/multiformats/go-multiaddr-dns v0.4.0/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= @@ -774,13 +722,12 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE= github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= @@ -790,35 +737,29 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= -github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw= +github.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc= github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw= @@ -853,9 +794,7 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg= github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= @@ -863,15 +802,15 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= -github.com/pion/datachannel v1.5.6 h1:1IxKJntfSlYkpUj8LlYRSWpYiTTC02nUrOE8T3DqGeg= -github.com/pion/datachannel v1.5.6/go.mod h1:1eKT6Q85pRnr2mHiWHxJwO50SfZRtWHTsNIVb/NfGW4= +github.com/pion/datachannel v1.5.8 h1:ph1P1NsGkazkjrvyMfhRBUAWMxugJjq2HfQifaOoSNo= +github.com/pion/datachannel v1.5.8/go.mod h1:PgmdpoaNBLX9HNzNClmdki4DYW5JtI7Yibu8QzbL3tI= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/dtls/v2 v2.2.11 h1:9U/dpCYl1ySttROPWJgqWKEylUdT0fXp/xst6JwY5Ks= -github.com/pion/dtls/v2 v2.2.11/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= -github.com/pion/ice/v2 v2.3.25 h1:M5rJA07dqhi3nobJIg+uPtcVjFECTrhcR3n0ns8kDZs= -github.com/pion/ice/v2 v2.3.25/go.mod h1:KXJJcZK7E8WzrBEYnV4UtqEZsGeWfHxsNqhVcVvgjxw= -github.com/pion/interceptor v0.1.29 h1:39fsnlP1U8gw2JzOFWdfCU82vHvhW9o0rZnZF56wF+M= -github.com/pion/interceptor v0.1.29/go.mod h1:ri+LGNjRUc5xUNtDEPzfdkmSqISixVTBF/z/Zms/6T4= +github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= +github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= +github.com/pion/ice/v2 v2.3.34 h1:Ic1ppYCj4tUOcPAp76U6F3fVrlSw8A9JtRXLqw6BbUM= +github.com/pion/ice/v2 v2.3.34/go.mod h1:mBF7lnigdqgtB+YHkaY/Y6s6tsyRyo4u4rPGRuOjUBQ= +github.com/pion/interceptor v0.1.30 h1:au5rlVHsgmxNi+v/mjOPazbW1SHzfx7/hYOEYQnUcxA= +github.com/pion/interceptor v0.1.30/go.mod h1:RQuKT5HTdkP2Fi0cuOS5G5WNymTjzXaGF75J4k7z2nc= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8= @@ -882,38 +821,37 @@ github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9 github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE= github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= -github.com/pion/rtp v1.8.6 h1:MTmn/b0aWWsAzux2AmP8WGllusBVw4NPYPVFFd7jUPw= -github.com/pion/rtp v1.8.6/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= -github.com/pion/sctp v1.8.13/go.mod h1:YKSgO/bO/6aOMP9LCie1DuD7m+GamiK2yIiPM6vH+GA= -github.com/pion/sctp v1.8.16 h1:PKrMs+o9EMLRvFfXq59WFsC+V8mN1wnKzqrv+3D/gYY= -github.com/pion/sctp v1.8.16/go.mod h1:P6PbDVA++OJMrVNg2AL3XtYHV4uD6dvfyOovCgMs0PE= +github.com/pion/rtp v1.8.9 h1:E2HX740TZKaqdcPmf4pw6ZZuG8u5RlMMt+l3dxeu6Wk= +github.com/pion/rtp v1.8.9/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/sctp v1.8.33 h1:dSE4wX6uTJBcNm8+YlMg7lw1wqyKHggsP5uKbdj+NZw= +github.com/pion/sctp v1.8.33/go.mod h1:beTnqSzewI53KWoG3nqB282oDMGrhNxBdb+JZnkCwRM= github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= -github.com/pion/srtp/v2 v2.0.18 h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo= -github.com/pion/srtp/v2 v2.0.18/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= +github.com/pion/srtp/v2 v2.0.20 h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk= +github.com/pion/srtp/v2 v2.0.20/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= +github.com/pion/stun/v2 v2.0.0 h1:A5+wXKLAypxQri59+tmQKVs7+l6mMM+3d+eER9ifRU0= +github.com/pion/stun/v2 v2.0.0/go.mod h1:22qRSh08fSEttYUmJZGlriq9+03jtVmXNODgLccj8GQ= github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= -github.com/pion/transport/v2 v2.2.5 h1:iyi25i/21gQck4hfRhomF6SktmUQjRsRW4WJdhfc3Kc= -github.com/pion/transport/v2 v2.2.5/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= +github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q= +github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= -github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= -github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc= github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= -github.com/pion/webrtc/v3 v3.2.40 h1:Wtfi6AZMQg+624cvCXUuSmrKWepSB7zfgYDOYqsSOVU= -github.com/pion/webrtc/v3 v3.2.40/go.mod h1:M1RAe3TNTD1tzyvqHrbVODfwdPGSXOUo/OgpoGGJqFY= +github.com/pion/webrtc/v3 v3.3.0 h1:Rf4u6n6U5t5sUxhYPQk/samzU/oDv7jk6BA5hyO2F9I= +github.com/pion/webrtc/v3 v3.3.0/go.mod h1:hVmrDJvwhEertRWObeb1xzulzHGeVUoPlWvxdGzcfU0= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -925,14 +863,13 @@ github.com/prestonvanloon/go v1.1.7-0.20190722034630-4f2e55fcf87b/go.mod h1:KdQU github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -942,63 +879,58 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prom2json v1.3.0 h1:BlqrtbT9lLH3ZsOVhXPsHzFrApCTKRifB7gjJuypu6Y= github.com/prometheus/prom2json v1.3.0/go.mod h1:rMN7m0ApCowcoDlypBHlkNbp5eJQf/+1isKykIP5ZnM= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/prysmaticlabs/fastssz v0.0.0-20240620202422-a981b8ef89d3 h1:0LZAwwHnsZFfXm4IK4rzFV4N5IVSKZKLmuBMA4kAlFk= -github.com/prysmaticlabs/fastssz v0.0.0-20240620202422-a981b8ef89d3/go.mod h1:h2OlIZD/M6wFvV3YMZbW16lFgh3Rsye00G44J2cwLyU= +github.com/prysmaticlabs/fastssz v0.0.0-20241008181541-518c4ce73516 h1:xuVAdtz5ShYblG2sPyb4gw01DF8InbOI/kBCQjk7NiM= +github.com/prysmaticlabs/fastssz v0.0.0-20241008181541-518c4ce73516/go.mod h1:h2OlIZD/M6wFvV3YMZbW16lFgh3Rsye00G44J2cwLyU= github.com/prysmaticlabs/go-bitfield v0.0.0-20210108222456-8e92c3709aa0/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s= github.com/prysmaticlabs/go-bitfield v0.0.0-20240328144219-a1caa50c3a1e h1:ATgOe+abbzfx9kCPeXIW4fiWyDdxlwHw07j8UGhdTd4= github.com/prysmaticlabs/go-bitfield v0.0.0-20240328144219-a1caa50c3a1e/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4= github.com/prysmaticlabs/gohashtree v0.0.4-beta.0.20240624100937-73632381301b h1:VK7thFOnhxAZ/5aolr5Os4beiubuD08WiuiHyRqgwks= github.com/prysmaticlabs/gohashtree v0.0.4-beta.0.20240624100937-73632381301b/go.mod h1:HRuvtXLZ4WkaB1MItToVH2e8ZwKwZPY5/Rcby+CvvLY= -github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20230315201114-09284ba20446 h1:4wctORg/1TkgLgXejv9yOSAm3cDBJxoTzl/RNuZmX28= -github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20230315201114-09284ba20446/go.mod h1:IOyTYjcIO0rkmnGBfJTL0NJ11exy/Tc2QEuv7hCXp24= github.com/prysmaticlabs/prombbolt v0.0.0-20210126082820-9b7adba6db7c h1:9PHRCuO/VN0s9k+RmLykho7AjDxblNYI5bYKed16NPU= github.com/prysmaticlabs/prombbolt v0.0.0-20210126082820-9b7adba6db7c/go.mod h1:ZRws458tYHS/Zs936OQ6oCrL+Ict5O4Xpwve1UQ6C9M= github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294 h1:q9wE0ZZRdTUAAeyFP/w0SwBEnCqlVy2+on6X2/e+eAU= github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294/go.mod h1:ZVEbRdnMkGhp/pu35zq4SXxtvUwWK0J1MATtekZpH2Y= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/quic-go v0.44.0 h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0= -github.com/quic-go/quic-go v0.44.0/go.mod h1:z4cx/9Ny9UtGITIPzmPTXh1ULfOyWh4qGQlpnPcWmek= -github.com/quic-go/webtransport-go v0.8.0 h1:HxSrwun11U+LlmwpgM1kEqIqH90IT4N8auv/cD7QFJg= -github.com/quic-go/webtransport-go v0.8.0/go.mod h1:N99tjprW432Ut5ONql/aUhSLT0YVSlwHohQsuac9WaM= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE= +github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= +github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg= +github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw= +github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0= +github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -1041,8 +973,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1053,24 +985,16 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.0.1-0.20201006035406-b97b5ead31f7/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ= github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1078,7 +1002,6 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -1087,7 +1010,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -1095,11 +1017,11 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= +github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -1115,19 +1037,17 @@ github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5I github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/trailofbits/go-mutexasserts v0.0.0-20230328101604-8cdbc5f3d279 h1:+LynomhWB+14Plp/bOONEAZCtvCZk4leRbTvNzNVkL0= github.com/trailofbits/go-mutexasserts v0.0.0-20230328101604-8cdbc5f3d279/go.mod h1:GA3+Mq3kt3tYAfM0WZCu7ofy+GW9PuGysHfhr+6JX7s= -github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U= -github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/umbracle/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10 h1:CQh33pStIp/E30b7TxDlXfM0145bn2e8boI30IxAhTg= +github.com/umbracle/gohashtree v0.0.2-alpha.0.20230207094856-5b775a815c10/go.mod h1:x/Pa0FF5Te9kdrlZKJK82YmAkvL8+f989USgz6Jiw7M= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI= -github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= +github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4= github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -1137,14 +1057,18 @@ github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49u github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/wealdtech/go-bytesutil v1.1.1 h1:ocEg3Ke2GkZ4vQw5lp46rmO+pfqCCTgq35gqOy8JKVc= github.com/wealdtech/go-bytesutil v1.1.1/go.mod h1:jENeMqeTEU8FNZyDFRVc7KqBdRKSnJ9CCh26TcuNb9s= -github.com/wealdtech/go-eth2-types/v2 v2.5.2 h1:tiA6T88M6XQIbrV5Zz53l1G5HtRERcxQfmET225V4Ls= github.com/wealdtech/go-eth2-types/v2 v2.5.2/go.mod h1:8lkNUbgklSQ4LZ2oMSuxSdR7WwJW3L9ge1dcoCVyzws= +github.com/wealdtech/go-eth2-types/v2 v2.8.2 h1:b5aXlNBLKgjAg/Fft9VvGlqAUCQMP5LzYhlHRrr4yPg= +github.com/wealdtech/go-eth2-types/v2 v2.8.2/go.mod h1:IAz9Lz1NVTaHabQa+4zjk2QDKMv8LVYo0n46M9o/TXw= github.com/wealdtech/go-eth2-util v1.6.3 h1:2INPeOR35x5LdFFpSzyw954WzTD+DFyHe3yKlJnG5As= github.com/wealdtech/go-eth2-util v1.6.3/go.mod h1:0hFMj/qtio288oZFHmAbCnPQ9OB3c4WFzs5NVPKTY4k= github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3 h1:SxrDVSr+oXuT1x8kZt4uWqNCvv5xXEGV9zd7cuSrZS8= github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3/go.mod h1:qiIimacW5NhVRy8o+YxWo9YrecXqDAKKbL0+sOa0SJ4= github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.2 h1:264/meVYWt1wFw6Mtn+xwkZkXjID42gNra4rycoiDXI= github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.2/go.mod h1:k6kmiKWSWBTd4OxFifTEkPaBLhZspnO2KFD5XJY9nqg= +github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/wlynxg/anet v0.0.4 h1:0de1OFQxnNqAu+x2FAKKCVIrnfGKQbs7FQz++tB0+Uw= +github.com/wlynxg/anet v0.0.4/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -1160,7 +1084,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= @@ -1175,21 +1098,38 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= -go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= -go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/fx v1.22.1 h1:nvvln7mwyT5s1q201YE29V/BFrGor6vMiDNpU/78Mys= -go.uber.org/fx v1.22.1/go.mod h1:HT2M7d7RHo+ebKGh9NRcrsrHHfpZ60nW3QRubMRfv48= +go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw= +go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= +go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= +go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -1197,14 +1137,12 @@ go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1226,20 +1164,16 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1251,8 +1185,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 h1:1P7xPZEwZMoBoz0Yze5Nx2/4pxj6nw9ZqHWXqP0iRgQ= golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -1282,8 +1216,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1307,7 +1241,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1332,20 +1266,16 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1358,12 +1288,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1379,8 +1305,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1401,7 +1327,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1442,22 +1367,14 @@ golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1475,27 +1392,21 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1508,17 +1419,15 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -1538,7 +1447,6 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1546,7 +1454,6 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1570,10 +1477,8 @@ golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWc golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -1581,7 +1486,6 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1591,8 +1495,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= +golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1621,10 +1525,6 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1633,7 +1533,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1679,14 +1578,7 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210426193834-eac7f76ac494/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -1712,14 +1604,9 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0-dev.0.20201218190559-666aea1fb34c/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1730,14 +1617,14 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.25.1-0.20201208041424-160c7477e0e8/go.mod h1:hFxJC2f0epmp1elRCiEGJTKAWbwxZ2nvqZdHl3FQXCY= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610= +gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= +gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1751,14 +1638,13 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -1786,34 +1672,34 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.5.0-0.dev.0.20231205170804-aef76f4feee2 h1:VUeHARd+9362HPYyFWjsRa6jBIAf2xWbDv6QXMRztbQ= -honnef.co/go/tools v0.5.0-0.dev.0.20231205170804-aef76f4feee2/go.mod h1:J8YyqAvNy0yWpeKUOCONA1m2G4hH2CqUSo/5ZO2/5UA= -k8s.io/api v0.20.0 h1:WwrYoZNM1W1aQEbyl8HNG+oWGzLpZQBlcerS9BQw9yI= -k8s.io/api v0.20.0/go.mod h1:HyLC5l5eoS/ygQYl1BXBgFzWNlkHiAuyNAbevIn+FKg= -k8s.io/apimachinery v0.20.0 h1:jjzbTJRXk0unNS71L7h3lxGDH/2HPxMPaQY+MjECKL8= -k8s.io/apimachinery v0.20.0/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/client-go v0.20.0 h1:Xlax8PKbZsjX4gFvNtt4F5MoJ1V5prDvCuoq9B7iax0= -k8s.io/client-go v0.20.0/go.mod h1:4KWh/g+Ocd8KkCwKF8vUNnmqgv+EVnQDK4MBF4oB5tY= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.80.0 h1:lyJt0TWMPaGoODa8B8bUuxgHS3W/m/bNr2cca3brA/g= -k8s.io/klog/v2 v2.80.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= -lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= +honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= +k8s.io/api v0.30.4 h1:XASIELmW8w8q0i1Y4124LqPoWMycLjyQti/fdYHYjCs= +k8s.io/api v0.30.4/go.mod h1:ZqniWRKu7WIeLijbbzetF4U9qZ03cg5IRwl8YVs8mX0= +k8s.io/apimachinery v0.30.4 h1:5QHQI2tInzr8LsT4kU/2+fSeibH1eIHswNx480cqIoY= +k8s.io/apimachinery v0.30.4/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= +k8s.io/client-go v0.30.4 h1:eculUe+HPQoPbixfwmaSZGsKcOf7D288tH6hDAdd+wY= +k8s.io/client-go v0.30.4/go.mod h1:IBS0R/Mt0LHkNHF4E6n+SUDPG7+m2po6RZU7YHeOpzc= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= +lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/hack/README.md b/hack/README.md index 6720654d82f4..5cf3ec3b0350 100644 --- a/hack/README.md +++ b/hack/README.md @@ -5,6 +5,6 @@ This subproject contains useful bash scripts for working with our repository. We ## update-go-pbs.sh -This script generates the *.pb.go and *.pb.gw.go files from the *.proto files. -After running `update-go-pbs.sh` keep only the *.pb.go and *pb.gw.go for the protos that have changed before checking in. +This script generates the *.pb.go files from the *.proto files. +After running `update-go-pbs.sh` keep only the *.pb.go for the protos that have changed before checking in. *Note*: the generated files may not have imports correctly linted and will need to be fixed to remote associated errors. \ No newline at end of file diff --git a/hack/common.sh b/hack/common.sh index c4f1bf32c19d..06a70ed7a16d 100644 --- a/hack/common.sh +++ b/hack/common.sh @@ -19,7 +19,7 @@ cygwin*) system="windows" ;; esac readonly system -# Get locations of pb.go and pb.gw.go files. +# Get locations of pb.go files. findutil="find" # On OSX `find` is not GNU find compatible, so require "findutils" package. if [ "$system" == "darwin" ]; then diff --git a/hack/interop_start.sh b/hack/interop_start.sh deleted file mode 100755 index e6655f6d530a..000000000000 --- a/hack/interop_start.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/bash - -""" -2019/09/08 -- Interop start script. -This script is intended for dockerfile deployment for interop testing. -This script is fragile and subject to break as flags change. -Use at your own risk! - - -Use with interop.Dockerfile from the workspace root: - -docker build -f interop.Dockerfile . -""" - -# Flags -IDENTITY="" # P2P private key -PEERS="" # Comma separated list of peers -GEN_STATE="" # filepath to ssz encoded state. -PORT="8000" # port to serve p2p traffic -RPCPORT="8001" # port to serve rpc traffic -YAML_KEY_FILE="" # Path to yaml keyfile as defined here: https://github.com/ethereum/eth2.0-pm/tree/master/interop/mocked_start - -# Constants -BEACON_LOG_FILE="/tmp/beacon.log" -VALIDATOR_LOG_FILE="/tmp/validator.log" - -usage() { - echo "--identity=" - echo "--peer=" - echo "--num-validators=" - echo "--gen-state=" - echo "--port=" - echo "--rpcport=" -} - -while [ "$1" != "" ]; -do - PARAM=`echo $1 | awk -F= '{print $1}'` - VALUE=`echo $1 | sed 's/^[^=]*=//g'` - - case $PARAM in - --identity) - IDENTITY=$VALUE - ;; - --peers) - [ -z "$PEERS" ] && PEERS+="," - PEERS+="$VALUE" - ;; - --validator-keys) - YAML_KEY_FILE=$VALUE - ;; - --gen-state) - GEN_STATE=$VALUE - ;; - --port) - PORT=$VALUE - ;; - --rpcport) - RPCPORT=$VALUE - ;; - --help) - usage - exit - ;; - *) - echo "ERROR: unknown parameter \"$PARAM\"" - usage - exit 1 - ;; - esac - shift -done - - -echo "Converting hex yaml keys to a format that Prysm understands" - -# Expect YAML keys in hex encoded format. Convert this into the format the validator already understands. -./convert-keys $YAML_KEY_FILE /tmp/keys.json - -echo "Starting beacon chain and logging to $BEACON_LOG_FILE" - -echo -n "$IDENTITY" > /tmp/id.key - - - -BEACON_FLAGS="--bootstrap-node= \ - --deposit-contract=0xD775140349E6A5D12524C6ccc3d6A1d4519D4029 \ - --p2p-port=$PORT \ - --grpc-gateway-port=$RPCPORT \ - --peer=$PEERS \ - --interop-genesis-state=$GEN_STATE \ - --p2p-priv-key=/tmp/id.key \ - --log-file=$BEACON_LOG_FILE" - -./beacon-chain $BEACON_FLAGS & - -echo "Starting validator client and logging to $VALIDATOR_LOG_FILE" - -VALIDATOR_FLAGS="--monitoring-port=9091 \ - --unencrypted-keys /tmp/keys.json \ - --log-file=$VALIDATOR_LOG_FILE - -./validator- $VALIDATOR_FLAGS & - diff --git a/hack/update-go-pbs.sh b/hack/update-go-pbs.sh index 47a009eb9b10..6ab61ba22539 100755 --- a/hack/update-go-pbs.sh +++ b/hack/update-go-pbs.sh @@ -9,7 +9,7 @@ bazel query 'attr(testonly, 0, //proto/...)' | xargs bazel build $@ file_list=() while IFS= read -d $'\0' -r file; do file_list=("${file_list[@]}" "$file") -done < <($findutil -L "$(bazel info bazel-bin)"/proto -type f -regextype sed -regex ".*pb\.\(gw\.\)\?go$" -print0) +done < <($findutil -L "$(bazel info bazel-bin)"/proto -type f -regextype sed -regex ".*pb\.go$" -print0) arraylength=${#file_list[@]} searchstring="prysmaticlabs/prysm/v5/" diff --git a/hack/update-go-ssz.sh b/hack/update-go-ssz.sh index 3e48660f2bce..344cd521f918 100755 --- a/hack/update-go-ssz.sh +++ b/hack/update-go-ssz.sh @@ -20,5 +20,7 @@ for ((i = 0; i < arraylength; i++)); do destination=${file_list[i]#*$searchstring} color "34" "$destination" chmod 644 "$destination" - cp -R -L "${file_list[i]}" "$destination" + + # Copy to destination while removing the `// Hash: ...` line from the file header. + sed '/\/\/ Hash: /d' "${file_list[i]}" > "$destination" done diff --git a/monitoring/tracing/BUILD.bazel b/monitoring/tracing/BUILD.bazel index 9d132bba3e41..d3c6a681fd42 100644 --- a/monitoring/tracing/BUILD.bazel +++ b/monitoring/tracing/BUILD.bazel @@ -10,9 +10,17 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/monitoring/tracing", visibility = ["//visibility:public"], deps = [ - "//runtime/version:go_default_library", + "//monitoring/tracing/trace:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", - "@io_opencensus_go_contrib_exporter_jaeger//:go_default_library", + "@io_opentelemetry_go_otel//:go_default_library", + "@io_opentelemetry_go_otel//attribute:go_default_library", + "@io_opentelemetry_go_otel//codes:go_default_library", + "@io_opentelemetry_go_otel//propagation:go_default_library", + "@io_opentelemetry_go_otel//semconv/v1.17.0:go_default_library", + "@io_opentelemetry_go_otel_exporters_otlp_otlptrace_otlptracehttp//:go_default_library", + "@io_opentelemetry_go_otel_sdk//resource:go_default_library", + "@io_opentelemetry_go_otel_sdk//trace:go_default_library", + "@io_opentelemetry_go_otel_trace//:go_default_library", + "@io_opentelemetry_go_otel_trace//noop:go_default_library", ], ) diff --git a/monitoring/tracing/errors.go b/monitoring/tracing/errors.go index 642573104623..9fc6c72fa3da 100644 --- a/monitoring/tracing/errors.go +++ b/monitoring/tracing/errors.go @@ -2,17 +2,15 @@ package tracing import ( - "go.opencensus.io/trace" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" ) // AnnotateError on span. This should be used any time a particular span experiences an error. -func AnnotateError(span *trace.Span, err error) { +func AnnotateError(span trace.Span, err error) { if err == nil { return } - span.AddAttributes(trace.BoolAttribute("error", true)) - span.SetStatus(trace.Status{ - Code: trace.StatusCodeUnknown, - Message: err.Error(), - }) + span.RecordError(err) + span.SetStatus(codes.Error, err.Error()) } diff --git a/monitoring/tracing/recovery_interceptor_option.go b/monitoring/tracing/recovery_interceptor_option.go index a93146981162..e4317455bc58 100644 --- a/monitoring/tracing/recovery_interceptor_option.go +++ b/monitoring/tracing/recovery_interceptor_option.go @@ -7,8 +7,8 @@ import ( "runtime" "runtime/debug" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // RecoveryHandlerFunc is a function that recovers from the panic `p` by returning an `error`. @@ -16,7 +16,7 @@ import ( func RecoveryHandlerFunc(ctx context.Context, p interface{}) error { span := trace.FromContext(ctx) if span != nil { - span.AddAttributes(trace.StringAttribute("stack", string(debug.Stack()))) + span.SetAttributes(trace.StringAttribute("stack", string(debug.Stack()))) } var err error switch v := p.(type) { diff --git a/monitoring/tracing/trace/BUILD.bazel b/monitoring/tracing/trace/BUILD.bazel new file mode 100644 index 000000000000..ad876865aea0 --- /dev/null +++ b/monitoring/tracing/trace/BUILD.bazel @@ -0,0 +1,14 @@ +load("@prysm//tools/go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["span.go"], + importpath = "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace", + visibility = ["//visibility:public"], + deps = [ + "@io_opentelemetry_go_otel//:go_default_library", + "@io_opentelemetry_go_otel//attribute:go_default_library", + "@io_opentelemetry_go_otel_trace//:go_default_library", + "@io_opentelemetry_go_otel_trace//noop:go_default_library", + ], +) diff --git a/monitoring/tracing/trace/span.go b/monitoring/tracing/trace/span.go new file mode 100644 index 000000000000..6f2c15019c92 --- /dev/null +++ b/monitoring/tracing/trace/span.go @@ -0,0 +1,70 @@ +package trace + +import ( + "context" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel/trace/noop" +) + +// TracingEnabled tracks whether tracing is enabled in your application. +var TracingEnabled = false + +// StartSpan is a wrapper over the OpenTelemetry package method. This is to allow us to skip +// calling that particular method if tracing has been disabled. +func StartSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + if !TracingEnabled { + // Return an empty span if tracing has been disabled. + return ctx, noop.Span{} + } + tracer := otel.Tracer("") + ctx, span := tracer.Start(ctx, name, opts...) + return ctx, span +} + +// NewContext is a wrapper which returns back the parent context +// if tracing is disabled. +func NewContext(parent context.Context, s trace.Span) context.Context { + if !TracingEnabled { + return parent + } + return trace.ContextWithSpan(parent, s) +} + +// FromContext is a wrapper which returns a no-op span +// if tracing is disabled. +func FromContext(ctx context.Context) trace.Span { + if !TracingEnabled { + return noop.Span{} + } + span := trace.SpanFromContext(ctx) + return span +} + +// AddMessageSendEvent adds a message send event to the provided span. +// This function is useful for tracking the sending of messages within a trace. +func AddMessageSendEvent(span trace.Span, iid int64, uncompressedLen int64, compressedLen int64) trace.Span { + span.AddEvent("message_send", trace.WithAttributes( + attribute.Int64("message.id", iid), + attribute.Int64("message.uncompressed_size", uncompressedLen), + attribute.Int64("message.compressed_size", compressedLen), + )) + return span +} + +// Int64Attribute -- +func Int64Attribute(key string, value int64) attribute.KeyValue { + return attribute.Int64(key, value) +} + +// StringAttribute -- +func StringAttribute(key, value string) attribute.KeyValue { + return attribute.String(key, value) +} + +// BoolAttribute -- +func BoolAttribute(key string, value bool) attribute.KeyValue { + return attribute.Bool(key, value) +} diff --git a/monitoring/tracing/tracer.go b/monitoring/tracing/tracer.go index 28b78c1894ec..e8253b58c3f1 100644 --- a/monitoring/tracing/tracer.go +++ b/monitoring/tracing/tracer.go @@ -3,51 +3,60 @@ package tracing import ( + "context" "errors" + "time" - "contrib.go.opencensus.io/exporter/jaeger" - "github.com/prysmaticlabs/prysm/v5/runtime/version" + prysmTrace "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.17.0" + "go.opentelemetry.io/otel/trace/noop" ) var log = logrus.WithField("prefix", "tracing") -// Setup creates and initializes a new tracing configuration.. -func Setup(serviceName, processName, endpoint string, sampleFraction float64, enable bool) error { +// Setup creates and initializes a new Jaegar tracing configuration with opentelemetry. +func Setup(ctx context.Context, serviceName, processName, endpoint string, sampleFraction float64, enable bool) error { if !enable { - trace.ApplyConfig(trace.Config{DefaultSampler: trace.NeverSample()}) + otel.SetTracerProvider(noop.NewTracerProvider()) return nil } + prysmTrace.TracingEnabled = true if serviceName == "" { return errors.New("tracing service name cannot be empty") } - trace.ApplyConfig(trace.Config{ - DefaultSampler: trace.ProbabilitySampler(sampleFraction), - MaxMessageEventsPerSpan: 500, - }) - - log.Infof("Starting Jaeger exporter endpoint at address = %s", endpoint) - exporter, err := jaeger.NewExporter(jaeger.Options{ - CollectorEndpoint: endpoint, - Process: jaeger.Process{ - ServiceName: serviceName, - Tags: []jaeger.Tag{ - jaeger.StringTag("process_name", processName), - jaeger.StringTag("version", version.Version()), - }, - }, - BufferMaxCount: 10000, - OnError: func(err error) { - log.WithError(err).Error("Could not process span") - }, - }) + log.Infof("Starting otel exporter endpoint at address = %s", endpoint) + exporter, err := otlptracehttp.New(ctx, otlptracehttp.WithEndpointURL(endpoint)) if err != nil { return err } - trace.RegisterExporter(exporter) + tp := trace.NewTracerProvider( + trace.WithSampler(trace.TraceIDRatioBased(sampleFraction)), + trace.WithBatcher( + exporter, + trace.WithMaxExportBatchSize(trace.DefaultMaxExportBatchSize), + trace.WithBatchTimeout(trace.DefaultScheduleDelay*time.Millisecond), + trace.WithMaxExportBatchSize(trace.DefaultMaxExportBatchSize), + ), + trace.WithResource( + resource.NewWithAttributes( + semconv.SchemaURL, + semconv.ServiceNameKey.String(serviceName), + attribute.String("process_name", processName), + ), + ), + ) + + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) return nil } diff --git a/network/BUILD.bazel b/network/BUILD.bazel index 18ffb89e7c7e..ad28f692b4d4 100644 --- a/network/BUILD.bazel +++ b/network/BUILD.bazel @@ -15,6 +15,7 @@ go_library( "@com_github_golang_jwt_jwt_v4//:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", + "@io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp//:go_default_library", ], ) diff --git a/network/endpoint.go b/network/endpoint.go index 0012fff1e6d8..611b52c2d9b1 100644 --- a/network/endpoint.go +++ b/network/endpoint.go @@ -12,6 +12,7 @@ import ( gethRPC "github.com/ethereum/go-ethereum/rpc" "github.com/prysmaticlabs/prysm/v5/network/authorization" log "github.com/sirupsen/logrus" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) // Endpoint is an endpoint with authorization data. @@ -36,7 +37,7 @@ func (e Endpoint) Equals(other Endpoint) bool { // on the properties of the network endpoint. func (e Endpoint) HttpClient() *http.Client { if e.Auth.Method != authorization.Bearer { - return http.DefaultClient + return &http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)} } return NewHttpClientWithSecret(e.Auth.Value, e.Auth.JwtId) } @@ -121,7 +122,7 @@ func NewHttpClientWithSecret(secret, id string) *http.Client { } return &http.Client{ Timeout: DefaultRPCHTTPTimeout, - Transport: authTransport, + Transport: otelhttp.NewTransport(authTransport), } } diff --git a/network/forks/ordered.go b/network/forks/ordered.go index 6c080ee2bf20..13232fd7eed8 100644 --- a/network/forks/ordered.go +++ b/network/forks/ordered.go @@ -100,3 +100,26 @@ func NewOrderedSchedule(b *params.BeaconChainConfig) OrderedSchedule { sort.Sort(ofs) return ofs } + +// ForkForEpochFromConfig returns the fork data for the given epoch from the provided config. +func ForkForEpochFromConfig(cfg *params.BeaconChainConfig, epoch primitives.Epoch) (*ethpb.Fork, error) { + os := NewOrderedSchedule(cfg) + currentVersion, err := os.VersionForEpoch(epoch) + if err != nil { + return nil, err + } + prevVersion, err := os.Previous(currentVersion) + if err != nil { + if !errors.Is(err, ErrNoPreviousVersion) { + return nil, err + } + // use same version for both in the case of genesis + prevVersion = currentVersion + } + forkEpoch := cfg.ForkVersionSchedule[currentVersion] + return ðpb.Fork{ + PreviousVersion: prevVersion[:], + CurrentVersion: currentVersion[:], + Epoch: forkEpoch, + }, nil +} diff --git a/nogo_config.json b/nogo_config.json index 5902a89ae109..c2f3034b2aab 100644 --- a/nogo_config.json +++ b/nogo_config.json @@ -208,5 +208,11 @@ "external/.*": "Third party code", "rules_go_work-.*": "Third party code" } + }, + "loopclosure": { + "exclude_files": { + "external/com_github_ethereum_go_ethereum/.*": "Unsafe third party code", + "rules_go_work-.*": "Third party code" + } } } diff --git a/proto/dbval/dbval.pb.go b/proto/dbval/dbval.pb.go index f60a19748989..7fad68d204df 100755 --- a/proto/dbval/dbval.pb.go +++ b/proto/dbval/dbval.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/dbval/dbval.proto package dbval diff --git a/proto/dbval/dbval.proto b/proto/dbval/dbval.proto index b774a9ba86ae..5eccde83722f 100644 --- a/proto/dbval/dbval.proto +++ b/proto/dbval/dbval.proto @@ -4,20 +4,25 @@ package ethereum.eth.dbval; option go_package = "github.com/prysmaticlabs/prysm/v5/proto/dbval;dbval"; -// BackfillStatus is a value used to keep track of the progress of the process of backfilling blocks leading up to -// the origin block used to checkpoint sync a node. There is only one BackfillStatus value in the database. +// BackfillStatus is a value used to keep track of the progress of the process +// of backfilling blocks leading up to the origin block used to checkpoint sync +// a node. There is only one BackfillStatus value in the database. message BackfillStatus { - // low_slot is the slot of the last block that backfill will attempt to download and import. - // This is determined by MIN_EPOCHS_FOR_BLOCK_REQUESTS, or by a user-specified override. - uint64 low_slot = 1; - // low_root is the root of the last block that backfill will attempt to download and import. - bytes low_root = 2; - // low_parent_root is the parent_root of the block at low_root. This enables the backfill service to check - // that a block is the direct ancestor of the block for low_root without an additional db lookup. - bytes low_parent_root = 3; - // origin_slot is the slot of the origin block, which is the block used to initiate a checkpoint sync. - // Backfill uses the origin block as the reference point to determine canonical ancestors. - uint64 origin_slot = 4; - // origin_root is the root of the origin block. - bytes origin_root = 6; + // low_slot is the slot of the last block that backfill will attempt to + // download and import. This is determined by MIN_EPOCHS_FOR_BLOCK_REQUESTS, + // or by a user-specified override. + uint64 low_slot = 1; + // low_root is the root of the last block that backfill will attempt to + // download and import. + bytes low_root = 2; + // low_parent_root is the parent_root of the block at low_root. This enables + // the backfill service to check that a block is the direct ancestor of the + // block for low_root without an additional db lookup. + bytes low_parent_root = 3; + // origin_slot is the slot of the origin block, which is the block used to + // initiate a checkpoint sync. Backfill uses the origin block as the reference + // point to determine canonical ancestors. + uint64 origin_slot = 4; + // origin_root is the root of the origin block. + bytes origin_root = 6; } diff --git a/proto/engine/v1/BUILD.bazel b/proto/engine/v1/BUILD.bazel index a7c1615015f8..fad2e889531d 100644 --- a/proto/engine/v1/BUILD.bazel +++ b/proto/engine/v1/BUILD.bazel @@ -42,14 +42,13 @@ ssz_gen_marshal( "ExecutionPayloadHeaderCapella", "ExecutionPayloadHeaderDeneb", "ExecutionPayloadDeneb", - "ExecutionPayloadHeaderElectra", - "ExecutionPayloadElectra", "BlindedBlobsBundle", "BlobsBundle", "Withdrawal", "WithdrawalRequest", "DepositRequest", "ConsolidationRequest", + "ExecutionRequests", ], ) @@ -75,6 +74,7 @@ go_proto_library( go_library( name = "go_default_library", srcs = [ + "electra.go", "execution_engine.go", "json_marshal_unmarshal.go", ":ssz_generated_files", # keep @@ -111,6 +111,7 @@ ssz_proto_files( name = "ssz_proto_files", srcs = [ "execution_engine.proto", + "electra.proto", ], config = select({ "//conditions:default": "mainnet", diff --git a/proto/engine/v1/electra.go b/proto/engine/v1/electra.go new file mode 100644 index 000000000000..24b81dc0531f --- /dev/null +++ b/proto/engine/v1/electra.go @@ -0,0 +1,184 @@ +package enginev1 + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/config/params" +) + +var ( + drExample = &DepositRequest{} + drSize = drExample.SizeSSZ() + wrExample = &WithdrawalRequest{} + wrSize = wrExample.SizeSSZ() + crExample = &ConsolidationRequest{} + crSize = crExample.SizeSSZ() +) + +const ( + DepositRequestType = iota + WithdrawalRequestType + ConsolidationRequestType +) + +func (ebe *ExecutionBundleElectra) GetDecodedExecutionRequests() (*ExecutionRequests, error) { + requests := &ExecutionRequests{} + var prevTypeNum *uint8 + for i := range ebe.ExecutionRequests { + requestType, requestListInSSZBytes, err := decodeExecutionRequest(ebe.ExecutionRequests[i]) + if err != nil { + return nil, err + } + if prevTypeNum != nil && *prevTypeNum >= requestType { + return nil, errors.New("invalid execution request type order or duplicate requests, requests should be in sorted order and unique") + } + prevTypeNum = &requestType + switch requestType { + case DepositRequestType: + drs, err := unmarshalDeposits(requestListInSSZBytes) + if err != nil { + return nil, err + } + requests.Deposits = drs + case WithdrawalRequestType: + wrs, err := unmarshalWithdrawals(requestListInSSZBytes) + if err != nil { + return nil, err + } + requests.Withdrawals = wrs + case ConsolidationRequestType: + crs, err := unmarshalConsolidations(requestListInSSZBytes) + if err != nil { + return nil, err + } + requests.Consolidations = crs + default: + return nil, errors.Errorf("unsupported request type %d", requestType) + } + } + return requests, nil +} + +func unmarshalDeposits(requestListInSSZBytes []byte) ([]*DepositRequest, error) { + if len(requestListInSSZBytes) < drSize { + return nil, fmt.Errorf("invalid deposit requests SSZ size, got %d expected at least %d", len(requestListInSSZBytes), drSize) + } + maxSSZsize := uint64(drSize) * params.BeaconConfig().MaxDepositRequestsPerPayload + if uint64(len(requestListInSSZBytes)) > maxSSZsize { + return nil, fmt.Errorf("invalid deposit requests SSZ size, requests should not be more than the max per payload, got %d max %d", len(requestListInSSZBytes), maxSSZsize) + } + return unmarshalItems(requestListInSSZBytes, drSize, func() *DepositRequest { return &DepositRequest{} }) +} + +func unmarshalWithdrawals(requestListInSSZBytes []byte) ([]*WithdrawalRequest, error) { + if len(requestListInSSZBytes) < wrSize { + return nil, fmt.Errorf("invalid withdrawal requests SSZ size, got %d expected at least %d", len(requestListInSSZBytes), wrSize) + } + maxSSZsize := uint64(wrSize) * params.BeaconConfig().MaxWithdrawalRequestsPerPayload + if uint64(len(requestListInSSZBytes)) > maxSSZsize { + return nil, fmt.Errorf("invalid withdrawal requests SSZ size, requests should not be more than the max per payload, got %d max %d", len(requestListInSSZBytes), maxSSZsize) + } + return unmarshalItems(requestListInSSZBytes, wrSize, func() *WithdrawalRequest { return &WithdrawalRequest{} }) +} + +func unmarshalConsolidations(requestListInSSZBytes []byte) ([]*ConsolidationRequest, error) { + if len(requestListInSSZBytes) < crSize { + return nil, fmt.Errorf("invalid consolidation requests SSZ size, got %d expected at least %d", len(requestListInSSZBytes), crSize) + } + maxSSZsize := uint64(crSize) * params.BeaconConfig().MaxConsolidationsRequestsPerPayload + if uint64(len(requestListInSSZBytes)) > maxSSZsize { + return nil, fmt.Errorf("invalid consolidation requests SSZ size, requests should not be more than the max per payload, got %d max %d", len(requestListInSSZBytes), maxSSZsize) + } + return unmarshalItems(requestListInSSZBytes, crSize, func() *ConsolidationRequest { return &ConsolidationRequest{} }) +} + +func decodeExecutionRequest(req []byte) (typ uint8, data []byte, err error) { + if len(req) < 1 { + return 0, nil, errors.New("invalid execution request, length less than 1") + } + return req[0], req[1:], nil +} + +func EncodeExecutionRequests(requests *ExecutionRequests) ([]hexutil.Bytes, error) { + if requests == nil { + return nil, errors.New("invalid execution requests") + } + + requestsData := make([]hexutil.Bytes, 0) + + // request types MUST be in sorted order starting from 0 + if len(requests.Deposits) > 0 { + drBytes, err := marshalItems(requests.Deposits) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal deposit requests") + } + requestData := []byte{DepositRequestType} + requestData = append(requestData, drBytes...) + requestsData = append(requestsData, requestData) + } + if len(requests.Withdrawals) > 0 { + wrBytes, err := marshalItems(requests.Withdrawals) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal withdrawal requests") + } + requestData := []byte{WithdrawalRequestType} + requestData = append(requestData, wrBytes...) + requestsData = append(requestsData, requestData) + } + if len(requests.Consolidations) > 0 { + crBytes, err := marshalItems(requests.Consolidations) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal consolidation requests") + } + requestData := []byte{ConsolidationRequestType} + requestData = append(requestData, crBytes...) + requestsData = append(requestsData, requestData) + } + + return requestsData, nil +} + +type sszUnmarshaler interface { + UnmarshalSSZ([]byte) error +} + +type sszMarshaler interface { + MarshalSSZTo(buf []byte) ([]byte, error) + SizeSSZ() int +} + +func marshalItems[T sszMarshaler](items []T) ([]byte, error) { + if len(items) == 0 { + return []byte{}, nil + } + size := items[0].SizeSSZ() + buf := make([]byte, 0, size*len(items)) + var err error + for i, item := range items { + buf, err = item.MarshalSSZTo(buf) + if err != nil { + return nil, fmt.Errorf("failed to marshal item at index %d: %w", i, err) + } + } + return buf, nil +} + +// Generic function to unmarshal items +func unmarshalItems[T sszUnmarshaler](data []byte, itemSize int, newItem func() T) ([]T, error) { + if len(data)%itemSize != 0 { + return nil, fmt.Errorf("invalid data length: data size (%d) is not a multiple of item size (%d)", len(data), itemSize) + } + numItems := len(data) / itemSize + items := make([]T, numItems) + for i := range items { + itemBytes := data[i*itemSize : (i+1)*itemSize] + item := newItem() + if err := item.UnmarshalSSZ(itemBytes); err != nil { + return nil, fmt.Errorf("failed to unmarshal item at index %d: %w", i, err) + } + items[i] = item + } + return items, nil +} diff --git a/proto/engine/v1/electra.pb.go b/proto/engine/v1/electra.pb.go new file mode 100755 index 000000000000..d3a6c8295868 --- /dev/null +++ b/proto/engine/v1/electra.pb.go @@ -0,0 +1,582 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.7 +// source: proto/engine/v1/electra.proto + +package enginev1 + +import ( + reflect "reflect" + sync "sync" + + _ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type WithdrawalRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SourceAddress []byte `protobuf:"bytes,1,opt,name=source_address,json=sourceAddress,proto3" json:"source_address,omitempty" ssz-size:"20"` + ValidatorPubkey []byte `protobuf:"bytes,2,opt,name=validator_pubkey,json=validatorPubkey,proto3" json:"validator_pubkey,omitempty" ssz-size:"48"` + Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (x *WithdrawalRequest) Reset() { + *x = WithdrawalRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_engine_v1_electra_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WithdrawalRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WithdrawalRequest) ProtoMessage() {} + +func (x *WithdrawalRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_engine_v1_electra_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use WithdrawalRequest.ProtoReflect.Descriptor instead. +func (*WithdrawalRequest) Descriptor() ([]byte, []int) { + return file_proto_engine_v1_electra_proto_rawDescGZIP(), []int{0} +} + +func (x *WithdrawalRequest) GetSourceAddress() []byte { + if x != nil { + return x.SourceAddress + } + return nil +} + +func (x *WithdrawalRequest) GetValidatorPubkey() []byte { + if x != nil { + return x.ValidatorPubkey + } + return nil +} + +func (x *WithdrawalRequest) GetAmount() uint64 { + if x != nil { + return x.Amount + } + return 0 +} + +type DepositRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` + WithdrawalCredentials []byte `protobuf:"bytes,2,opt,name=withdrawal_credentials,json=withdrawalCredentials,proto3" json:"withdrawal_credentials,omitempty" ssz-size:"32"` + Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Index uint64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` +} + +func (x *DepositRequest) Reset() { + *x = DepositRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_engine_v1_electra_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DepositRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DepositRequest) ProtoMessage() {} + +func (x *DepositRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_engine_v1_electra_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DepositRequest.ProtoReflect.Descriptor instead. +func (*DepositRequest) Descriptor() ([]byte, []int) { + return file_proto_engine_v1_electra_proto_rawDescGZIP(), []int{1} +} + +func (x *DepositRequest) GetPubkey() []byte { + if x != nil { + return x.Pubkey + } + return nil +} + +func (x *DepositRequest) GetWithdrawalCredentials() []byte { + if x != nil { + return x.WithdrawalCredentials + } + return nil +} + +func (x *DepositRequest) GetAmount() uint64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *DepositRequest) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *DepositRequest) GetIndex() uint64 { + if x != nil { + return x.Index + } + return 0 +} + +type ConsolidationRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SourceAddress []byte `protobuf:"bytes,1,opt,name=source_address,json=sourceAddress,proto3" json:"source_address,omitempty" ssz-size:"20"` + SourcePubkey []byte `protobuf:"bytes,2,opt,name=source_pubkey,json=sourcePubkey,proto3" json:"source_pubkey,omitempty" ssz-size:"48"` + TargetPubkey []byte `protobuf:"bytes,3,opt,name=target_pubkey,json=targetPubkey,proto3" json:"target_pubkey,omitempty" ssz-size:"48"` +} + +func (x *ConsolidationRequest) Reset() { + *x = ConsolidationRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_engine_v1_electra_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ConsolidationRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConsolidationRequest) ProtoMessage() {} + +func (x *ConsolidationRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_engine_v1_electra_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConsolidationRequest.ProtoReflect.Descriptor instead. +func (*ConsolidationRequest) Descriptor() ([]byte, []int) { + return file_proto_engine_v1_electra_proto_rawDescGZIP(), []int{2} +} + +func (x *ConsolidationRequest) GetSourceAddress() []byte { + if x != nil { + return x.SourceAddress + } + return nil +} + +func (x *ConsolidationRequest) GetSourcePubkey() []byte { + if x != nil { + return x.SourcePubkey + } + return nil +} + +func (x *ConsolidationRequest) GetTargetPubkey() []byte { + if x != nil { + return x.TargetPubkey + } + return nil +} + +type ExecutionRequests struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Deposits []*DepositRequest `protobuf:"bytes,1,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"8192"` + Withdrawals []*WithdrawalRequest `protobuf:"bytes,2,rep,name=withdrawals,proto3" json:"withdrawals,omitempty" ssz-max:"16"` + Consolidations []*ConsolidationRequest `protobuf:"bytes,3,rep,name=consolidations,proto3" json:"consolidations,omitempty" ssz-max:"2"` +} + +func (x *ExecutionRequests) Reset() { + *x = ExecutionRequests{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_engine_v1_electra_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecutionRequests) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecutionRequests) ProtoMessage() {} + +func (x *ExecutionRequests) ProtoReflect() protoreflect.Message { + mi := &file_proto_engine_v1_electra_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecutionRequests.ProtoReflect.Descriptor instead. +func (*ExecutionRequests) Descriptor() ([]byte, []int) { + return file_proto_engine_v1_electra_proto_rawDescGZIP(), []int{3} +} + +func (x *ExecutionRequests) GetDeposits() []*DepositRequest { + if x != nil { + return x.Deposits + } + return nil +} + +func (x *ExecutionRequests) GetWithdrawals() []*WithdrawalRequest { + if x != nil { + return x.Withdrawals + } + return nil +} + +func (x *ExecutionRequests) GetConsolidations() []*ConsolidationRequest { + if x != nil { + return x.Consolidations + } + return nil +} + +type ExecutionBundleElectra struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Payload *ExecutionPayloadDeneb `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + BlobsBundle *BlobsBundle `protobuf:"bytes,3,opt,name=blobs_bundle,json=blobsBundle,proto3" json:"blobs_bundle,omitempty"` + ShouldOverrideBuilder bool `protobuf:"varint,4,opt,name=should_override_builder,json=shouldOverrideBuilder,proto3" json:"should_override_builder,omitempty"` + ExecutionRequests [][]byte `protobuf:"bytes,5,rep,name=execution_requests,json=executionRequests,proto3" json:"execution_requests,omitempty"` +} + +func (x *ExecutionBundleElectra) Reset() { + *x = ExecutionBundleElectra{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_engine_v1_electra_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecutionBundleElectra) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecutionBundleElectra) ProtoMessage() {} + +func (x *ExecutionBundleElectra) ProtoReflect() protoreflect.Message { + mi := &file_proto_engine_v1_electra_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecutionBundleElectra.ProtoReflect.Descriptor instead. +func (*ExecutionBundleElectra) Descriptor() ([]byte, []int) { + return file_proto_engine_v1_electra_proto_rawDescGZIP(), []int{4} +} + +func (x *ExecutionBundleElectra) GetPayload() *ExecutionPayloadDeneb { + if x != nil { + return x.Payload + } + return nil +} + +func (x *ExecutionBundleElectra) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} + +func (x *ExecutionBundleElectra) GetBlobsBundle() *BlobsBundle { + if x != nil { + return x.BlobsBundle + } + return nil +} + +func (x *ExecutionBundleElectra) GetShouldOverrideBuilder() bool { + if x != nil { + return x.ShouldOverrideBuilder + } + return false +} + +func (x *ExecutionBundleElectra) GetExecutionRequests() [][]byte { + if x != nil { + return x.ExecutionRequests + } + return nil +} + +var File_proto_engine_v1_electra_proto protoreflect.FileDescriptor + +var file_proto_engine_v1_electra_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, + 0x31, 0x2f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x12, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, + 0x2e, 0x76, 0x31, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, + 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, + 0x31, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8d, 0x01, 0x0a, 0x11, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, + 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0d, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x31, 0x0a, + 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, + 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc3, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x70, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x34, 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x16, 0x77, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x33, 0x32, 0x52, 0x15, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, + 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x9f, + 0x01, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2b, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x75, 0x62, + 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x34, 0x38, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x22, 0x87, 0x02, 0x0a, 0x11, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x48, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x08, 0x92, 0xb5, + 0x18, 0x04, 0x38, 0x31, 0x39, 0x32, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, + 0x12, 0x4f, 0x0a, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x06, 0x92, 0xb5, + 0x18, 0x02, 0x31, 0x36, 0x52, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, + 0x73, 0x12, 0x57, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x73, + 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x9e, 0x02, 0x0a, 0x16, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x45, 0x6c, + 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x43, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x6e, 0x65, + 0x62, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x42, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x62, + 0x73, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x6f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x12, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x42, 0x8e, 0x01, 0x0a, 0x16, + 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, + 0x76, 0x31, 0xaa, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x5c, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_engine_v1_electra_proto_rawDescOnce sync.Once + file_proto_engine_v1_electra_proto_rawDescData = file_proto_engine_v1_electra_proto_rawDesc +) + +func file_proto_engine_v1_electra_proto_rawDescGZIP() []byte { + file_proto_engine_v1_electra_proto_rawDescOnce.Do(func() { + file_proto_engine_v1_electra_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_engine_v1_electra_proto_rawDescData) + }) + return file_proto_engine_v1_electra_proto_rawDescData +} + +var file_proto_engine_v1_electra_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_proto_engine_v1_electra_proto_goTypes = []interface{}{ + (*WithdrawalRequest)(nil), // 0: ethereum.engine.v1.WithdrawalRequest + (*DepositRequest)(nil), // 1: ethereum.engine.v1.DepositRequest + (*ConsolidationRequest)(nil), // 2: ethereum.engine.v1.ConsolidationRequest + (*ExecutionRequests)(nil), // 3: ethereum.engine.v1.ExecutionRequests + (*ExecutionBundleElectra)(nil), // 4: ethereum.engine.v1.ExecutionBundleElectra + (*ExecutionPayloadDeneb)(nil), // 5: ethereum.engine.v1.ExecutionPayloadDeneb + (*BlobsBundle)(nil), // 6: ethereum.engine.v1.BlobsBundle +} +var file_proto_engine_v1_electra_proto_depIdxs = []int32{ + 1, // 0: ethereum.engine.v1.ExecutionRequests.deposits:type_name -> ethereum.engine.v1.DepositRequest + 0, // 1: ethereum.engine.v1.ExecutionRequests.withdrawals:type_name -> ethereum.engine.v1.WithdrawalRequest + 2, // 2: ethereum.engine.v1.ExecutionRequests.consolidations:type_name -> ethereum.engine.v1.ConsolidationRequest + 5, // 3: ethereum.engine.v1.ExecutionBundleElectra.payload:type_name -> ethereum.engine.v1.ExecutionPayloadDeneb + 6, // 4: ethereum.engine.v1.ExecutionBundleElectra.blobs_bundle:type_name -> ethereum.engine.v1.BlobsBundle + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_proto_engine_v1_electra_proto_init() } +func file_proto_engine_v1_electra_proto_init() { + if File_proto_engine_v1_electra_proto != nil { + return + } + file_proto_engine_v1_execution_engine_proto_init() + if !protoimpl.UnsafeEnabled { + file_proto_engine_v1_electra_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WithdrawalRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_engine_v1_electra_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DepositRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_engine_v1_electra_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ConsolidationRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_engine_v1_electra_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecutionRequests); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_engine_v1_electra_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecutionBundleElectra); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_engine_v1_electra_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_engine_v1_electra_proto_goTypes, + DependencyIndexes: file_proto_engine_v1_electra_proto_depIdxs, + MessageInfos: file_proto_engine_v1_electra_proto_msgTypes, + }.Build() + File_proto_engine_v1_electra_proto = out.File + file_proto_engine_v1_electra_proto_rawDesc = nil + file_proto_engine_v1_electra_proto_goTypes = nil + file_proto_engine_v1_electra_proto_depIdxs = nil +} diff --git a/proto/engine/v1/electra.proto b/proto/engine/v1/electra.proto new file mode 100644 index 000000000000..d52f3b58e34f --- /dev/null +++ b/proto/engine/v1/electra.proto @@ -0,0 +1,83 @@ +// Copyright 2024 Prysmatic Labs. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; + +package ethereum.engine.v1; + +import "proto/eth/ext/options.proto"; +import "proto/engine/v1/execution_engine.proto"; + +option csharp_namespace = "Ethereum.Engine.V1"; +option go_package = "github.com/prysmaticlabs/prysm/v5/proto/engine/v1;enginev1"; +option java_multiple_files = true; +option java_outer_classname = "ElectraProto"; +option java_package = "org.ethereum.engine.v1"; +option php_namespace = "Ethereum\\Engine\\v1"; + +// WithdrawalRequest is the message from the execution layer to trigger the +// withdrawal of a validator's balance to its withdrawal address new in Electra +message WithdrawalRequest { + // The execution address receiving the funds + bytes source_address = 1 [ (ethereum.eth.ext.ssz_size) = "20" ]; + + // 48 byte BLS public key of the validator. + bytes validator_pubkey = 2 [ (ethereum.eth.ext.ssz_size) = "48" ]; + + // Deposit amount in gwei. + uint64 amount = 3; +} + +// DepositRequest is the message from the execution layer to trigger the deposit +// of a validator's balance to its balance new in Electra +message DepositRequest { + bytes pubkey = 1 [ (ethereum.eth.ext.ssz_size) = "48" ]; + bytes withdrawal_credentials = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 amount = 3; + bytes signature = 4 [ (ethereum.eth.ext.ssz_size) = "96" ]; + uint64 index = 5; +} + +// ConsolidationRequest is the message from the execution layer to trigger the +// consolidation of one validator to another validator. +message ConsolidationRequest { + // Source address of account which originated the request. + bytes source_address = 1 [ (ethereum.eth.ext.ssz_size) = "20" ]; + // Funds will be moved from this public key. + bytes source_pubkey = 2 [ (ethereum.eth.ext.ssz_size) = "48" ]; + // Funds will be moved to this public key. + bytes target_pubkey = 3 [ (ethereum.eth.ext.ssz_size) = "48" ]; +} + +// ExecutionRequests is a container that contains all the requests from the +// execution layer to be included in a block +message ExecutionRequests { + repeated DepositRequest deposits = 1 + [ (ethereum.eth.ext.ssz_max) = "max_deposit_requests_per_payload.size" ]; + repeated WithdrawalRequest withdrawals = 2 + [ (ethereum.eth.ext.ssz_max) = + "max_withdrawal_requests_per_payload.size" ]; + repeated ConsolidationRequest consolidations = 3 + [ (ethereum.eth.ext.ssz_max) = + "max_consolidation_requests_per_payload.size" ]; +} + +// ExecutionBundleElectra is a container that builds on Payload V4 and includes +// execution requests sidecar needed post Electra +message ExecutionBundleElectra { + ExecutionPayloadDeneb payload = 1; + bytes value = 2; + BlobsBundle blobs_bundle = 3; + bool should_override_builder = 4; + repeated bytes execution_requests = 5; +} diff --git a/proto/engine/v1/electra_test.go b/proto/engine/v1/electra_test.go new file mode 100644 index 000000000000..f44aaca6d5c5 --- /dev/null +++ b/proto/engine/v1/electra_test.go @@ -0,0 +1,240 @@ +package enginev1_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +var depositRequestsSSZHex = "0x706b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077630000000000000000000000000000000000000000000000000000000000007b00000000000000736967000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c801000000000000706b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000776300000000000000000000000000000000000000000000000000000000000090010000000000007369670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000" + +func TestGetDecodedExecutionRequests(t *testing.T) { + t.Run("All requests decode successfully", func(t *testing.T) { + depositRequestBytes, err := hexutil.Decode("0x610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "620000000000000000000000000000000000000000000000000000000000000000" + + "4059730700000063000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + withdrawalRequestBytes, err := hexutil.Decode("0x6400000000000000000000000000000000000000" + + "6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040597307000000") + require.NoError(t, err) + consolidationRequestBytes, err := hexutil.Decode("0x6600000000000000000000000000000000000000" + + "670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{uint8(enginev1.DepositRequestType)}, depositRequestBytes...), + append([]byte{uint8(enginev1.WithdrawalRequestType)}, withdrawalRequestBytes...), + append([]byte{uint8(enginev1.ConsolidationRequestType)}, consolidationRequestBytes...)}, + } + requests, err := ebe.GetDecodedExecutionRequests() + require.NoError(t, err) + require.Equal(t, len(requests.Deposits), 1) + require.Equal(t, len(requests.Withdrawals), 1) + require.Equal(t, len(requests.Consolidations), 1) + }) + t.Run("Excluded requests still decode successfully when one request is missing", func(t *testing.T) { + depositRequestBytes, err := hexutil.Decode("0x610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "620000000000000000000000000000000000000000000000000000000000000000" + + "4059730700000063000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + consolidationRequestBytes, err := hexutil.Decode("0x6600000000000000000000000000000000000000" + + "670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{uint8(enginev1.DepositRequestType)}, depositRequestBytes...), append([]byte{uint8(enginev1.ConsolidationRequestType)}, consolidationRequestBytes...)}, + } + requests, err := ebe.GetDecodedExecutionRequests() + require.NoError(t, err) + require.Equal(t, len(requests.Deposits), 1) + require.Equal(t, len(requests.Withdrawals), 0) + require.Equal(t, len(requests.Consolidations), 1) + }) + t.Run("Decode execution requests should fail if ordering is not sorted", func(t *testing.T) { + depositRequestBytes, err := hexutil.Decode("0x610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "620000000000000000000000000000000000000000000000000000000000000000" + + "4059730700000063000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + consolidationRequestBytes, err := hexutil.Decode("0x6600000000000000000000000000000000000000" + + "670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{uint8(enginev1.ConsolidationRequestType)}, consolidationRequestBytes...), append([]byte{uint8(enginev1.DepositRequestType)}, depositRequestBytes...)}, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "invalid execution request type order", err) + }) + t.Run("Requests should error if the request type is shorter than 1 byte", func(t *testing.T) { + consolidationRequestBytes, err := hexutil.Decode("0x6600000000000000000000000000000000000000" + + "670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{}, []byte{}...), append([]byte{uint8(enginev1.ConsolidationRequestType)}, consolidationRequestBytes...)}, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "invalid execution request, length less than 1", err) + }) + t.Run("a duplicate request should fail", func(t *testing.T) { + withdrawalRequestBytes, err := hexutil.Decode("0x6400000000000000000000000000000000000000" + + "6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040597307000000") + require.NoError(t, err) + withdrawalRequestBytes2, err := hexutil.Decode("0x6400000000000000000000000000000000000000" + + "6500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040597307000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{uint8(enginev1.WithdrawalRequestType)}, withdrawalRequestBytes...), append([]byte{uint8(enginev1.WithdrawalRequestType)}, withdrawalRequestBytes2...)}, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "requests should be in sorted order and unique", err) + }) + t.Run("a duplicate withdrawals ( non 0 request type )request should fail", func(t *testing.T) { + depositRequestBytes, err := hexutil.Decode("0x610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "620000000000000000000000000000000000000000000000000000000000000000" + + "4059730700000063000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + depositRequestBytes2, err := hexutil.Decode("0x610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "620000000000000000000000000000000000000000000000000000000000000000" + + "4059730700000063000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{uint8(enginev1.DepositRequestType)}, depositRequestBytes...), append([]byte{uint8(enginev1.DepositRequestType)}, depositRequestBytes2...)}, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "requests should be in sorted order and unique", err) + }) + t.Run("If a request type is provided, but the request list is shorter than the ssz of 1 request we error", func(t *testing.T) { + consolidationRequestBytes, err := hexutil.Decode("0x6600000000000000000000000000000000000000" + + "670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{append([]byte{uint8(enginev1.DepositRequestType)}, []byte{}...), append([]byte{uint8(enginev1.ConsolidationRequestType)}, consolidationRequestBytes...)}, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "invalid deposit requests SSZ size", err) + }) + t.Run("If deposit requests are over the max allowed per payload then we should error", func(t *testing.T) { + requests := make([]*enginev1.DepositRequest, params.BeaconConfig().MaxDepositRequestsPerPayload+1) + for i := range requests { + requests[i] = &enginev1.DepositRequest{ + Pubkey: bytesutil.PadTo([]byte("pk"), 48), + WithdrawalCredentials: bytesutil.PadTo([]byte("wc"), 32), + Amount: 123, + Signature: bytesutil.PadTo([]byte("sig"), 96), + Index: 456, + } + } + by, err := enginev1.MarshalItems(requests) + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{ + append([]byte{uint8(enginev1.DepositRequestType)}, by...), + }, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "invalid deposit requests SSZ size, requests should not be more than the max per payload", err) + }) + t.Run("If withdrawal requests are over the max allowed per payload then we should error", func(t *testing.T) { + requests := make([]*enginev1.WithdrawalRequest, params.BeaconConfig().MaxWithdrawalRequestsPerPayload+1) + for i := range requests { + requests[i] = &enginev1.WithdrawalRequest{ + SourceAddress: bytesutil.PadTo([]byte("sa"), 20), + ValidatorPubkey: bytesutil.PadTo([]byte("pk"), 48), + Amount: 55555, + } + } + by, err := enginev1.MarshalItems(requests) + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{ + append([]byte{uint8(enginev1.WithdrawalRequestType)}, by...), + }, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "invalid withdrawal requests SSZ size, requests should not be more than the max per payload", err) + }) + t.Run("If consolidation requests are over the max allowed per payload then we should error", func(t *testing.T) { + requests := make([]*enginev1.ConsolidationRequest, params.BeaconConfig().MaxConsolidationsRequestsPerPayload+1) + for i := range requests { + requests[i] = &enginev1.ConsolidationRequest{ + SourceAddress: bytesutil.PadTo([]byte("sa"), 20), + SourcePubkey: bytesutil.PadTo([]byte("pk"), 48), + TargetPubkey: bytesutil.PadTo([]byte("pk"), 48), + } + } + by, err := enginev1.MarshalItems(requests) + require.NoError(t, err) + ebe := &enginev1.ExecutionBundleElectra{ + ExecutionRequests: [][]byte{ + append([]byte{uint8(enginev1.ConsolidationRequestType)}, by...), + }, + } + _, err = ebe.GetDecodedExecutionRequests() + require.ErrorContains(t, "invalid consolidation requests SSZ size, requests should not be more than the max per payload", err) + }) +} + +func TestEncodeExecutionRequests(t *testing.T) { + t.Run("Empty execution requests should return an empty response and not nil", func(t *testing.T) { + ebe := &enginev1.ExecutionRequests{} + b, err := enginev1.EncodeExecutionRequests(ebe) + require.NoError(t, err) + require.NotNil(t, b) + require.Equal(t, len(b), 0) + }) +} + +func TestUnmarshalItems_OK(t *testing.T) { + drb, err := hexutil.Decode(depositRequestsSSZHex) + require.NoError(t, err) + exampleRequest := &enginev1.DepositRequest{} + depositRequests, err := enginev1.UnmarshalItems(drb, exampleRequest.SizeSSZ(), func() *enginev1.DepositRequest { return &enginev1.DepositRequest{} }) + require.NoError(t, err) + + exampleRequest1 := &enginev1.DepositRequest{ + Pubkey: bytesutil.PadTo([]byte("pk"), 48), + WithdrawalCredentials: bytesutil.PadTo([]byte("wc"), 32), + Amount: 123, + Signature: bytesutil.PadTo([]byte("sig"), 96), + Index: 456, + } + exampleRequest2 := &enginev1.DepositRequest{ + Pubkey: bytesutil.PadTo([]byte("pk"), 48), + WithdrawalCredentials: bytesutil.PadTo([]byte("wc"), 32), + Amount: 400, + Signature: bytesutil.PadTo([]byte("sig"), 96), + Index: 32, + } + require.DeepEqual(t, depositRequests, []*enginev1.DepositRequest{exampleRequest1, exampleRequest2}) +} + +func TestMarshalItems_OK(t *testing.T) { + exampleRequest1 := &enginev1.DepositRequest{ + Pubkey: bytesutil.PadTo([]byte("pk"), 48), + WithdrawalCredentials: bytesutil.PadTo([]byte("wc"), 32), + Amount: 123, + Signature: bytesutil.PadTo([]byte("sig"), 96), + Index: 456, + } + exampleRequest2 := &enginev1.DepositRequest{ + Pubkey: bytesutil.PadTo([]byte("pk"), 48), + WithdrawalCredentials: bytesutil.PadTo([]byte("wc"), 32), + Amount: 400, + Signature: bytesutil.PadTo([]byte("sig"), 96), + Index: 32, + } + drbs, err := enginev1.MarshalItems([]*enginev1.DepositRequest{exampleRequest1, exampleRequest2}) + require.NoError(t, err) + require.DeepEqual(t, depositRequestsSSZHex, hexutil.Encode(drbs)) +} diff --git a/proto/engine/v1/engine.ssz.go b/proto/engine/v1/engine.ssz.go index 0f5488b9bbc2..b298fb0891a0 100644 --- a/proto/engine/v1/engine.ssz.go +++ b/proto/engine/v1/engine.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: d1cee811bee5b5cfcedf5be00dfff21d5e6caf432cd8fc42f551264f7b8e296c package enginev1 import ( @@ -7,409 +6,570 @@ import ( github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) -// MarshalSSZ ssz marshals the ExecutionPayload object -func (e *ExecutionPayload) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(e) +// MarshalSSZ ssz marshals the WithdrawalRequest object +func (w *WithdrawalRequest) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(w) } -// MarshalSSZTo ssz marshals the ExecutionPayload object to a target array -func (e *ExecutionPayload) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the WithdrawalRequest object to a target array +func (w *WithdrawalRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(508) - // Field (0) 'ParentHash' - if size := len(e.ParentHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentHash", size, 32) + // Field (0) 'SourceAddress' + if size := len(w.SourceAddress); size != 20 { + err = ssz.ErrBytesLengthFn("--.SourceAddress", size, 20) return } - dst = append(dst, e.ParentHash...) + dst = append(dst, w.SourceAddress...) - // Field (1) 'FeeRecipient' - if size := len(e.FeeRecipient); size != 20 { - err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20) + // Field (1) 'ValidatorPubkey' + if size := len(w.ValidatorPubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.ValidatorPubkey", size, 48) return } - dst = append(dst, e.FeeRecipient...) + dst = append(dst, w.ValidatorPubkey...) - // Field (2) 'StateRoot' - if size := len(e.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - dst = append(dst, e.StateRoot...) + // Field (2) 'Amount' + dst = ssz.MarshalUint64(dst, w.Amount) - // Field (3) 'ReceiptsRoot' - if size := len(e.ReceiptsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ReceiptsRoot", size, 32) - return + return +} + +// UnmarshalSSZ ssz unmarshals the WithdrawalRequest object +func (w *WithdrawalRequest) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 76 { + return ssz.ErrSize } - dst = append(dst, e.ReceiptsRoot...) - // Field (4) 'LogsBloom' - if size := len(e.LogsBloom); size != 256 { - err = ssz.ErrBytesLengthFn("--.LogsBloom", size, 256) - return + // Field (0) 'SourceAddress' + if cap(w.SourceAddress) == 0 { + w.SourceAddress = make([]byte, 0, len(buf[0:20])) } - dst = append(dst, e.LogsBloom...) + w.SourceAddress = append(w.SourceAddress, buf[0:20]...) - // Field (5) 'PrevRandao' - if size := len(e.PrevRandao); size != 32 { - err = ssz.ErrBytesLengthFn("--.PrevRandao", size, 32) - return + // Field (1) 'ValidatorPubkey' + if cap(w.ValidatorPubkey) == 0 { + w.ValidatorPubkey = make([]byte, 0, len(buf[20:68])) } - dst = append(dst, e.PrevRandao...) + w.ValidatorPubkey = append(w.ValidatorPubkey, buf[20:68]...) - // Field (6) 'BlockNumber' - dst = ssz.MarshalUint64(dst, e.BlockNumber) + // Field (2) 'Amount' + w.Amount = ssz.UnmarshallUint64(buf[68:76]) - // Field (7) 'GasLimit' - dst = ssz.MarshalUint64(dst, e.GasLimit) + return err +} - // Field (8) 'GasUsed' - dst = ssz.MarshalUint64(dst, e.GasUsed) +// SizeSSZ returns the ssz encoded size in bytes for the WithdrawalRequest object +func (w *WithdrawalRequest) SizeSSZ() (size int) { + size = 76 + return +} - // Field (9) 'Timestamp' - dst = ssz.MarshalUint64(dst, e.Timestamp) +// HashTreeRoot ssz hashes the WithdrawalRequest object +func (w *WithdrawalRequest) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(w) +} - // Offset (10) 'ExtraData' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.ExtraData) +// HashTreeRootWith ssz hashes the WithdrawalRequest object with a hasher +func (w *WithdrawalRequest) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() - // Field (11) 'BaseFeePerGas' - if size := len(e.BaseFeePerGas); size != 32 { - err = ssz.ErrBytesLengthFn("--.BaseFeePerGas", size, 32) + // Field (0) 'SourceAddress' + if size := len(w.SourceAddress); size != 20 { + err = ssz.ErrBytesLengthFn("--.SourceAddress", size, 20) return } - dst = append(dst, e.BaseFeePerGas...) + hh.PutBytes(w.SourceAddress) - // Field (12) 'BlockHash' - if size := len(e.BlockHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockHash", size, 32) + // Field (1) 'ValidatorPubkey' + if size := len(w.ValidatorPubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.ValidatorPubkey", size, 48) return } - dst = append(dst, e.BlockHash...) + hh.PutBytes(w.ValidatorPubkey) - // Offset (13) 'Transactions' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(e.Transactions); ii++ { - offset += 4 - offset += len(e.Transactions[ii]) - } + // Field (2) 'Amount' + hh.PutUint64(w.Amount) - // Field (10) 'ExtraData' - if size := len(e.ExtraData); size > 32 { - err = ssz.ErrBytesLengthFn("--.ExtraData", size, 32) + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the DepositRequest object +func (d *DepositRequest) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(d) +} + +// MarshalSSZTo ssz marshals the DepositRequest object to a target array +func (d *DepositRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Pubkey' + if size := len(d.Pubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48) return } - dst = append(dst, e.ExtraData...) + dst = append(dst, d.Pubkey...) - // Field (13) 'Transactions' - if size := len(e.Transactions); size > 1048576 { - err = ssz.ErrListTooBigFn("--.Transactions", size, 1048576) + // Field (1) 'WithdrawalCredentials' + if size := len(d.WithdrawalCredentials); size != 32 { + err = ssz.ErrBytesLengthFn("--.WithdrawalCredentials", size, 32) return } - { - offset = 4 * len(e.Transactions) - for ii := 0; ii < len(e.Transactions); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += len(e.Transactions[ii]) - } - } - for ii := 0; ii < len(e.Transactions); ii++ { - if size := len(e.Transactions[ii]); size > 1073741824 { - err = ssz.ErrBytesLengthFn("--.Transactions[ii]", size, 1073741824) - return - } - dst = append(dst, e.Transactions[ii]...) + dst = append(dst, d.WithdrawalCredentials...) + + // Field (2) 'Amount' + dst = ssz.MarshalUint64(dst, d.Amount) + + // Field (3) 'Signature' + if size := len(d.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return } + dst = append(dst, d.Signature...) + + // Field (4) 'Index' + dst = ssz.MarshalUint64(dst, d.Index) return } -// UnmarshalSSZ ssz unmarshals the ExecutionPayload object -func (e *ExecutionPayload) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the DepositRequest object +func (d *DepositRequest) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 508 { + if size != 192 { return ssz.ErrSize } - tail := buf - var o10, o13 uint64 - - // Field (0) 'ParentHash' - if cap(e.ParentHash) == 0 { - e.ParentHash = make([]byte, 0, len(buf[0:32])) - } - e.ParentHash = append(e.ParentHash, buf[0:32]...) - - // Field (1) 'FeeRecipient' - if cap(e.FeeRecipient) == 0 { - e.FeeRecipient = make([]byte, 0, len(buf[32:52])) + // Field (0) 'Pubkey' + if cap(d.Pubkey) == 0 { + d.Pubkey = make([]byte, 0, len(buf[0:48])) } - e.FeeRecipient = append(e.FeeRecipient, buf[32:52]...) + d.Pubkey = append(d.Pubkey, buf[0:48]...) - // Field (2) 'StateRoot' - if cap(e.StateRoot) == 0 { - e.StateRoot = make([]byte, 0, len(buf[52:84])) + // Field (1) 'WithdrawalCredentials' + if cap(d.WithdrawalCredentials) == 0 { + d.WithdrawalCredentials = make([]byte, 0, len(buf[48:80])) } - e.StateRoot = append(e.StateRoot, buf[52:84]...) + d.WithdrawalCredentials = append(d.WithdrawalCredentials, buf[48:80]...) - // Field (3) 'ReceiptsRoot' - if cap(e.ReceiptsRoot) == 0 { - e.ReceiptsRoot = make([]byte, 0, len(buf[84:116])) - } - e.ReceiptsRoot = append(e.ReceiptsRoot, buf[84:116]...) + // Field (2) 'Amount' + d.Amount = ssz.UnmarshallUint64(buf[80:88]) - // Field (4) 'LogsBloom' - if cap(e.LogsBloom) == 0 { - e.LogsBloom = make([]byte, 0, len(buf[116:372])) + // Field (3) 'Signature' + if cap(d.Signature) == 0 { + d.Signature = make([]byte, 0, len(buf[88:184])) } - e.LogsBloom = append(e.LogsBloom, buf[116:372]...) + d.Signature = append(d.Signature, buf[88:184]...) - // Field (5) 'PrevRandao' - if cap(e.PrevRandao) == 0 { - e.PrevRandao = make([]byte, 0, len(buf[372:404])) - } - e.PrevRandao = append(e.PrevRandao, buf[372:404]...) + // Field (4) 'Index' + d.Index = ssz.UnmarshallUint64(buf[184:192]) - // Field (6) 'BlockNumber' - e.BlockNumber = ssz.UnmarshallUint64(buf[404:412]) + return err +} - // Field (7) 'GasLimit' - e.GasLimit = ssz.UnmarshallUint64(buf[412:420]) +// SizeSSZ returns the ssz encoded size in bytes for the DepositRequest object +func (d *DepositRequest) SizeSSZ() (size int) { + size = 192 + return +} - // Field (8) 'GasUsed' - e.GasUsed = ssz.UnmarshallUint64(buf[420:428]) +// HashTreeRoot ssz hashes the DepositRequest object +func (d *DepositRequest) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(d) +} - // Field (9) 'Timestamp' - e.Timestamp = ssz.UnmarshallUint64(buf[428:436]) +// HashTreeRootWith ssz hashes the DepositRequest object with a hasher +func (d *DepositRequest) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() - // Offset (10) 'ExtraData' - if o10 = ssz.ReadOffset(buf[436:440]); o10 > size { - return ssz.ErrOffset + // Field (0) 'Pubkey' + if size := len(d.Pubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48) + return } + hh.PutBytes(d.Pubkey) - if o10 != 508 { - return ssz.ErrInvalidVariableOffset - } - - // Field (11) 'BaseFeePerGas' - if cap(e.BaseFeePerGas) == 0 { - e.BaseFeePerGas = make([]byte, 0, len(buf[440:472])) - } - e.BaseFeePerGas = append(e.BaseFeePerGas, buf[440:472]...) - - // Field (12) 'BlockHash' - if cap(e.BlockHash) == 0 { - e.BlockHash = make([]byte, 0, len(buf[472:504])) - } - e.BlockHash = append(e.BlockHash, buf[472:504]...) - - // Offset (13) 'Transactions' - if o13 = ssz.ReadOffset(buf[504:508]); o13 > size || o10 > o13 { - return ssz.ErrOffset + // Field (1) 'WithdrawalCredentials' + if size := len(d.WithdrawalCredentials); size != 32 { + err = ssz.ErrBytesLengthFn("--.WithdrawalCredentials", size, 32) + return } + hh.PutBytes(d.WithdrawalCredentials) - // Field (10) 'ExtraData' - { - buf = tail[o10:o13] - if len(buf) > 32 { - return ssz.ErrBytesLength - } - if cap(e.ExtraData) == 0 { - e.ExtraData = make([]byte, 0, len(buf)) - } - e.ExtraData = append(e.ExtraData, buf...) - } + // Field (2) 'Amount' + hh.PutUint64(d.Amount) - // Field (13) 'Transactions' - { - buf = tail[o13:] - num, err := ssz.DecodeDynamicLength(buf, 1048576) - if err != nil { - return err - } - e.Transactions = make([][]byte, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if len(buf) > 1073741824 { - return ssz.ErrBytesLength - } - if cap(e.Transactions[indx]) == 0 { - e.Transactions[indx] = make([]byte, 0, len(buf)) - } - e.Transactions[indx] = append(e.Transactions[indx], buf...) - return nil - }) - if err != nil { - return err - } + // Field (3) 'Signature' + if size := len(d.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayload object -func (e *ExecutionPayload) SizeSSZ() (size int) { - size = 508 - - // Field (10) 'ExtraData' - size += len(e.ExtraData) + hh.PutBytes(d.Signature) - // Field (13) 'Transactions' - for ii := 0; ii < len(e.Transactions); ii++ { - size += 4 - size += len(e.Transactions[ii]) - } + // Field (4) 'Index' + hh.PutUint64(d.Index) + hh.Merkleize(indx) return } -// HashTreeRoot ssz hashes the ExecutionPayload object -func (e *ExecutionPayload) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(e) +// MarshalSSZ ssz marshals the ConsolidationRequest object +func (c *ConsolidationRequest) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(c) } -// HashTreeRootWith ssz hashes the ExecutionPayload object with a hasher -func (e *ExecutionPayload) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() +// MarshalSSZTo ssz marshals the ConsolidationRequest object to a target array +func (c *ConsolidationRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf - // Field (0) 'ParentHash' - if size := len(e.ParentHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentHash", size, 32) + // Field (0) 'SourceAddress' + if size := len(c.SourceAddress); size != 20 { + err = ssz.ErrBytesLengthFn("--.SourceAddress", size, 20) return } - hh.PutBytes(e.ParentHash) + dst = append(dst, c.SourceAddress...) - // Field (1) 'FeeRecipient' - if size := len(e.FeeRecipient); size != 20 { - err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20) + // Field (1) 'SourcePubkey' + if size := len(c.SourcePubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.SourcePubkey", size, 48) return } - hh.PutBytes(e.FeeRecipient) + dst = append(dst, c.SourcePubkey...) - // Field (2) 'StateRoot' - if size := len(e.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + // Field (2) 'TargetPubkey' + if size := len(c.TargetPubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.TargetPubkey", size, 48) return } - hh.PutBytes(e.StateRoot) + dst = append(dst, c.TargetPubkey...) - // Field (3) 'ReceiptsRoot' - if size := len(e.ReceiptsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ReceiptsRoot", size, 32) - return + return +} + +// UnmarshalSSZ ssz unmarshals the ConsolidationRequest object +func (c *ConsolidationRequest) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 116 { + return ssz.ErrSize } - hh.PutBytes(e.ReceiptsRoot) - // Field (4) 'LogsBloom' - if size := len(e.LogsBloom); size != 256 { - err = ssz.ErrBytesLengthFn("--.LogsBloom", size, 256) - return + // Field (0) 'SourceAddress' + if cap(c.SourceAddress) == 0 { + c.SourceAddress = make([]byte, 0, len(buf[0:20])) } - hh.PutBytes(e.LogsBloom) + c.SourceAddress = append(c.SourceAddress, buf[0:20]...) - // Field (5) 'PrevRandao' - if size := len(e.PrevRandao); size != 32 { - err = ssz.ErrBytesLengthFn("--.PrevRandao", size, 32) - return + // Field (1) 'SourcePubkey' + if cap(c.SourcePubkey) == 0 { + c.SourcePubkey = make([]byte, 0, len(buf[20:68])) } - hh.PutBytes(e.PrevRandao) + c.SourcePubkey = append(c.SourcePubkey, buf[20:68]...) - // Field (6) 'BlockNumber' - hh.PutUint64(e.BlockNumber) + // Field (2) 'TargetPubkey' + if cap(c.TargetPubkey) == 0 { + c.TargetPubkey = make([]byte, 0, len(buf[68:116])) + } + c.TargetPubkey = append(c.TargetPubkey, buf[68:116]...) - // Field (7) 'GasLimit' - hh.PutUint64(e.GasLimit) + return err +} - // Field (8) 'GasUsed' - hh.PutUint64(e.GasUsed) +// SizeSSZ returns the ssz encoded size in bytes for the ConsolidationRequest object +func (c *ConsolidationRequest) SizeSSZ() (size int) { + size = 116 + return +} - // Field (9) 'Timestamp' - hh.PutUint64(e.Timestamp) +// HashTreeRoot ssz hashes the ConsolidationRequest object +func (c *ConsolidationRequest) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(c) +} - // Field (10) 'ExtraData' - { - elemIndx := hh.Index() - byteLen := uint64(len(e.ExtraData)) - if byteLen > 32 { - err = ssz.ErrIncorrectListSize - return - } - hh.PutBytes(e.ExtraData) - hh.MerkleizeWithMixin(elemIndx, byteLen, (32+31)/32) - } +// HashTreeRootWith ssz hashes the ConsolidationRequest object with a hasher +func (c *ConsolidationRequest) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() - // Field (11) 'BaseFeePerGas' - if size := len(e.BaseFeePerGas); size != 32 { - err = ssz.ErrBytesLengthFn("--.BaseFeePerGas", size, 32) + // Field (0) 'SourceAddress' + if size := len(c.SourceAddress); size != 20 { + err = ssz.ErrBytesLengthFn("--.SourceAddress", size, 20) return } - hh.PutBytes(e.BaseFeePerGas) + hh.PutBytes(c.SourceAddress) - // Field (12) 'BlockHash' - if size := len(e.BlockHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockHash", size, 32) + // Field (1) 'SourcePubkey' + if size := len(c.SourcePubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.SourcePubkey", size, 48) return } - hh.PutBytes(e.BlockHash) + hh.PutBytes(c.SourcePubkey) - // Field (13) 'Transactions' - { - subIndx := hh.Index() - num := uint64(len(e.Transactions)) - if num > 1048576 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.Transactions { - { - elemIndx := hh.Index() - byteLen := uint64(len(elem)) - if byteLen > 1073741824 { - err = ssz.ErrIncorrectListSize - return - } - hh.AppendBytes32(elem) - hh.MerkleizeWithMixin(elemIndx, byteLen, (1073741824+31)/32) - } - } - hh.MerkleizeWithMixin(subIndx, num, 1048576) + // Field (2) 'TargetPubkey' + if size := len(c.TargetPubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.TargetPubkey", size, 48) + return } + hh.PutBytes(c.TargetPubkey) hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the ExecutionPayloadCapella object -func (e *ExecutionPayloadCapella) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the ExecutionRequests object +func (e *ExecutionRequests) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(e) } -// MarshalSSZTo ssz marshals the ExecutionPayloadCapella object to a target array -func (e *ExecutionPayloadCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the ExecutionRequests object to a target array +func (e *ExecutionRequests) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(512) + offset := int(12) - // Field (0) 'ParentHash' - if size := len(e.ParentHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentHash", size, 32) - return - } - dst = append(dst, e.ParentHash...) + // Offset (0) 'Deposits' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.Deposits) * 192 - // Field (1) 'FeeRecipient' - if size := len(e.FeeRecipient); size != 20 { - err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20) + // Offset (1) 'Withdrawals' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.Withdrawals) * 76 + + // Offset (2) 'Consolidations' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.Consolidations) * 116 + + // Field (0) 'Deposits' + if size := len(e.Deposits); size > 8192 { + err = ssz.ErrListTooBigFn("--.Deposits", size, 8192) return } - dst = append(dst, e.FeeRecipient...) + for ii := 0; ii < len(e.Deposits); ii++ { + if dst, err = e.Deposits[ii].MarshalSSZTo(dst); err != nil { + return + } + } - // Field (2) 'StateRoot' - if size := len(e.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + // Field (1) 'Withdrawals' + if size := len(e.Withdrawals); size > 16 { + err = ssz.ErrListTooBigFn("--.Withdrawals", size, 16) return } - dst = append(dst, e.StateRoot...) + for ii := 0; ii < len(e.Withdrawals); ii++ { + if dst, err = e.Withdrawals[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (2) 'Consolidations' + if size := len(e.Consolidations); size > 2 { + err = ssz.ErrListTooBigFn("--.Consolidations", size, 2) + return + } + for ii := 0; ii < len(e.Consolidations); ii++ { + if dst, err = e.Consolidations[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + return +} + +// UnmarshalSSZ ssz unmarshals the ExecutionRequests object +func (e *ExecutionRequests) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 12 { + return ssz.ErrSize + } + + tail := buf + var o0, o1, o2 uint64 + + // Offset (0) 'Deposits' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 12 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (1) 'Withdrawals' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Offset (2) 'Consolidations' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { + return ssz.ErrOffset + } + + // Field (0) 'Deposits' + { + buf = tail[o0:o1] + num, err := ssz.DivideInt2(len(buf), 192, 8192) + if err != nil { + return err + } + e.Deposits = make([]*DepositRequest, num) + for ii := 0; ii < num; ii++ { + if e.Deposits[ii] == nil { + e.Deposits[ii] = new(DepositRequest) + } + if err = e.Deposits[ii].UnmarshalSSZ(buf[ii*192 : (ii+1)*192]); err != nil { + return err + } + } + } + + // Field (1) 'Withdrawals' + { + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 76, 16) + if err != nil { + return err + } + e.Withdrawals = make([]*WithdrawalRequest, num) + for ii := 0; ii < num; ii++ { + if e.Withdrawals[ii] == nil { + e.Withdrawals[ii] = new(WithdrawalRequest) + } + if err = e.Withdrawals[ii].UnmarshalSSZ(buf[ii*76 : (ii+1)*76]); err != nil { + return err + } + } + } + + // Field (2) 'Consolidations' + { + buf = tail[o2:] + num, err := ssz.DivideInt2(len(buf), 116, 2) + if err != nil { + return err + } + e.Consolidations = make([]*ConsolidationRequest, num) + for ii := 0; ii < num; ii++ { + if e.Consolidations[ii] == nil { + e.Consolidations[ii] = new(ConsolidationRequest) + } + if err = e.Consolidations[ii].UnmarshalSSZ(buf[ii*116 : (ii+1)*116]); err != nil { + return err + } + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the ExecutionRequests object +func (e *ExecutionRequests) SizeSSZ() (size int) { + size = 12 + + // Field (0) 'Deposits' + size += len(e.Deposits) * 192 + + // Field (1) 'Withdrawals' + size += len(e.Withdrawals) * 76 + + // Field (2) 'Consolidations' + size += len(e.Consolidations) * 116 + + return +} + +// HashTreeRoot ssz hashes the ExecutionRequests object +func (e *ExecutionRequests) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(e) +} + +// HashTreeRootWith ssz hashes the ExecutionRequests object with a hasher +func (e *ExecutionRequests) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Deposits' + { + subIndx := hh.Index() + num := uint64(len(e.Deposits)) + if num > 8192 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.Deposits { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 8192) + } + + // Field (1) 'Withdrawals' + { + subIndx := hh.Index() + num := uint64(len(e.Withdrawals)) + if num > 16 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.Withdrawals { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 16) + } + + // Field (2) 'Consolidations' + { + subIndx := hh.Index() + num := uint64(len(e.Consolidations)) + if num > 2 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.Consolidations { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 2) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the ExecutionPayload object +func (e *ExecutionPayload) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(e) +} + +// MarshalSSZTo ssz marshals the ExecutionPayload object to a target array +func (e *ExecutionPayload) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(508) + + // Field (0) 'ParentHash' + if size := len(e.ParentHash); size != 32 { + err = ssz.ErrBytesLengthFn("--.ParentHash", size, 32) + return + } + dst = append(dst, e.ParentHash...) + + // Field (1) 'FeeRecipient' + if size := len(e.FeeRecipient); size != 20 { + err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20) + return + } + dst = append(dst, e.FeeRecipient...) + + // Field (2) 'StateRoot' + if size := len(e.StateRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + return + } + dst = append(dst, e.StateRoot...) // Field (3) 'ReceiptsRoot' if size := len(e.ReceiptsRoot); size != 32 { @@ -469,10 +629,6 @@ func (e *ExecutionPayloadCapella) MarshalSSZTo(buf []byte) (dst []byte, err erro offset += len(e.Transactions[ii]) } - // Offset (14) 'Withdrawals' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.Withdrawals) * 44 - // Field (10) 'ExtraData' if size := len(e.ExtraData); size > 32 { err = ssz.ErrBytesLengthFn("--.ExtraData", size, 32) @@ -500,30 +656,19 @@ func (e *ExecutionPayloadCapella) MarshalSSZTo(buf []byte) (dst []byte, err erro dst = append(dst, e.Transactions[ii]...) } - // Field (14) 'Withdrawals' - if size := len(e.Withdrawals); size > 16 { - err = ssz.ErrListTooBigFn("--.Withdrawals", size, 16) - return - } - for ii := 0; ii < len(e.Withdrawals); ii++ { - if dst, err = e.Withdrawals[ii].MarshalSSZTo(dst); err != nil { - return - } - } - return } -// UnmarshalSSZ ssz unmarshals the ExecutionPayloadCapella object -func (e *ExecutionPayloadCapella) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the ExecutionPayload object +func (e *ExecutionPayload) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 512 { + if size < 508 { return ssz.ErrSize } tail := buf - var o10, o13, o14 uint64 + var o10, o13 uint64 // Field (0) 'ParentHash' if cap(e.ParentHash) == 0 { @@ -578,7 +723,7 @@ func (e *ExecutionPayloadCapella) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - if o10 != 512 { + if o10 != 508 { return ssz.ErrInvalidVariableOffset } @@ -599,11 +744,6 @@ func (e *ExecutionPayloadCapella) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - // Offset (14) 'Withdrawals' - if o14 = ssz.ReadOffset(buf[508:512]); o14 > size || o13 > o14 { - return ssz.ErrOffset - } - // Field (10) 'ExtraData' { buf = tail[o10:o13] @@ -618,7 +758,7 @@ func (e *ExecutionPayloadCapella) UnmarshalSSZ(buf []byte) error { // Field (13) 'Transactions' { - buf = tail[o13:o14] + buf = tail[o13:] num, err := ssz.DecodeDynamicLength(buf, 1048576) if err != nil { return err @@ -638,30 +778,12 @@ func (e *ExecutionPayloadCapella) UnmarshalSSZ(buf []byte) error { return err } } - - // Field (14) 'Withdrawals' - { - buf = tail[o14:] - num, err := ssz.DivideInt2(len(buf), 44, 16) - if err != nil { - return err - } - e.Withdrawals = make([]*Withdrawal, num) - for ii := 0; ii < num; ii++ { - if e.Withdrawals[ii] == nil { - e.Withdrawals[ii] = new(Withdrawal) - } - if err = e.Withdrawals[ii].UnmarshalSSZ(buf[ii*44 : (ii+1)*44]); err != nil { - return err - } - } - } return err } -// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadCapella object -func (e *ExecutionPayloadCapella) SizeSSZ() (size int) { - size = 512 +// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayload object +func (e *ExecutionPayload) SizeSSZ() (size int) { + size = 508 // Field (10) 'ExtraData' size += len(e.ExtraData) @@ -672,19 +794,16 @@ func (e *ExecutionPayloadCapella) SizeSSZ() (size int) { size += len(e.Transactions[ii]) } - // Field (14) 'Withdrawals' - size += len(e.Withdrawals) * 44 - return } -// HashTreeRoot ssz hashes the ExecutionPayloadCapella object -func (e *ExecutionPayloadCapella) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the ExecutionPayload object +func (e *ExecutionPayload) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(e) } -// HashTreeRootWith ssz hashes the ExecutionPayloadCapella object with a hasher -func (e *ExecutionPayloadCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the ExecutionPayload object with a hasher +func (e *ExecutionPayload) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field (0) 'ParentHash' @@ -790,35 +909,19 @@ func (e *ExecutionPayloadCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.MerkleizeWithMixin(subIndx, num, 1048576) } - // Field (14) 'Withdrawals' - { - subIndx := hh.Index() - num := uint64(len(e.Withdrawals)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.Withdrawals { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the ExecutionPayloadDeneb object -func (e *ExecutionPayloadDeneb) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the ExecutionPayloadCapella object +func (e *ExecutionPayloadCapella) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(e) } -// MarshalSSZTo ssz marshals the ExecutionPayloadDeneb object to a target array -func (e *ExecutionPayloadDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the ExecutionPayloadCapella object to a target array +func (e *ExecutionPayloadCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(528) + offset := int(512) // Field (0) 'ParentHash' if size := len(e.ParentHash); size != 32 { @@ -903,12 +1006,6 @@ func (e *ExecutionPayloadDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) dst = ssz.WriteOffset(dst, offset) offset += len(e.Withdrawals) * 44 - // Field (15) 'BlobGasUsed' - dst = ssz.MarshalUint64(dst, e.BlobGasUsed) - - // Field (16) 'ExcessBlobGas' - dst = ssz.MarshalUint64(dst, e.ExcessBlobGas) - // Field (10) 'ExtraData' if size := len(e.ExtraData); size > 32 { err = ssz.ErrBytesLengthFn("--.ExtraData", size, 32) @@ -950,11 +1047,11 @@ func (e *ExecutionPayloadDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) return } -// UnmarshalSSZ ssz unmarshals the ExecutionPayloadDeneb object -func (e *ExecutionPayloadDeneb) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the ExecutionPayloadCapella object +func (e *ExecutionPayloadCapella) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 528 { + if size < 512 { return ssz.ErrSize } @@ -1014,7 +1111,7 @@ func (e *ExecutionPayloadDeneb) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - if o10 != 528 { + if o10 != 512 { return ssz.ErrInvalidVariableOffset } @@ -1040,12 +1137,6 @@ func (e *ExecutionPayloadDeneb) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - // Field (15) 'BlobGasUsed' - e.BlobGasUsed = ssz.UnmarshallUint64(buf[512:520]) - - // Field (16) 'ExcessBlobGas' - e.ExcessBlobGas = ssz.UnmarshallUint64(buf[520:528]) - // Field (10) 'ExtraData' { buf = tail[o10:o13] @@ -1101,9 +1192,9 @@ func (e *ExecutionPayloadDeneb) UnmarshalSSZ(buf []byte) error { return err } -// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadDeneb object -func (e *ExecutionPayloadDeneb) SizeSSZ() (size int) { - size = 528 +// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadCapella object +func (e *ExecutionPayloadCapella) SizeSSZ() (size int) { + size = 512 // Field (10) 'ExtraData' size += len(e.ExtraData) @@ -1120,13 +1211,13 @@ func (e *ExecutionPayloadDeneb) SizeSSZ() (size int) { return } -// HashTreeRoot ssz hashes the ExecutionPayloadDeneb object -func (e *ExecutionPayloadDeneb) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the ExecutionPayloadCapella object +func (e *ExecutionPayloadCapella) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(e) } -// HashTreeRootWith ssz hashes the ExecutionPayloadDeneb object with a hasher -func (e *ExecutionPayloadDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the ExecutionPayloadCapella object with a hasher +func (e *ExecutionPayloadCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field (0) 'ParentHash' @@ -1248,25 +1339,19 @@ func (e *ExecutionPayloadDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.MerkleizeWithMixin(subIndx, num, 16) } - // Field (15) 'BlobGasUsed' - hh.PutUint64(e.BlobGasUsed) - - // Field (16) 'ExcessBlobGas' - hh.PutUint64(e.ExcessBlobGas) - hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the ExecutionPayloadElectra object -func (e *ExecutionPayloadElectra) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the ExecutionPayloadDeneb object +func (e *ExecutionPayloadDeneb) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(e) } -// MarshalSSZTo ssz marshals the ExecutionPayloadElectra object to a target array -func (e *ExecutionPayloadElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the ExecutionPayloadDeneb object to a target array +func (e *ExecutionPayloadDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(540) + offset := int(528) // Field (0) 'ParentHash' if size := len(e.ParentHash); size != 32 { @@ -1357,18 +1442,6 @@ func (e *ExecutionPayloadElectra) MarshalSSZTo(buf []byte) (dst []byte, err erro // Field (16) 'ExcessBlobGas' dst = ssz.MarshalUint64(dst, e.ExcessBlobGas) - // Offset (17) 'DepositRequests' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.DepositRequests) * 192 - - // Offset (18) 'WithdrawalRequests' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.WithdrawalRequests) * 76 - - // Offset (19) 'ConsolidationRequests' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.ConsolidationRequests) * 116 - // Field (10) 'ExtraData' if size := len(e.ExtraData); size > 32 { err = ssz.ErrBytesLengthFn("--.ExtraData", size, 32) @@ -1407,52 +1480,19 @@ func (e *ExecutionPayloadElectra) MarshalSSZTo(buf []byte) (dst []byte, err erro } } - // Field (17) 'DepositRequests' - if size := len(e.DepositRequests); size > 8192 { - err = ssz.ErrListTooBigFn("--.DepositRequests", size, 8192) - return - } - for ii := 0; ii < len(e.DepositRequests); ii++ { - if dst, err = e.DepositRequests[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (18) 'WithdrawalRequests' - if size := len(e.WithdrawalRequests); size > 16 { - err = ssz.ErrListTooBigFn("--.WithdrawalRequests", size, 16) - return - } - for ii := 0; ii < len(e.WithdrawalRequests); ii++ { - if dst, err = e.WithdrawalRequests[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (19) 'ConsolidationRequests' - if size := len(e.ConsolidationRequests); size > 1 { - err = ssz.ErrListTooBigFn("--.ConsolidationRequests", size, 1) - return - } - for ii := 0; ii < len(e.ConsolidationRequests); ii++ { - if dst, err = e.ConsolidationRequests[ii].MarshalSSZTo(dst); err != nil { - return - } - } - return } -// UnmarshalSSZ ssz unmarshals the ExecutionPayloadElectra object -func (e *ExecutionPayloadElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the ExecutionPayloadDeneb object +func (e *ExecutionPayloadDeneb) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 540 { + if size < 528 { return ssz.ErrSize } tail := buf - var o10, o13, o14, o17, o18, o19 uint64 + var o10, o13, o14 uint64 // Field (0) 'ParentHash' if cap(e.ParentHash) == 0 { @@ -1507,7 +1547,7 @@ func (e *ExecutionPayloadElectra) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - if o10 != 540 { + if o10 != 528 { return ssz.ErrInvalidVariableOffset } @@ -1539,21 +1579,6 @@ func (e *ExecutionPayloadElectra) UnmarshalSSZ(buf []byte) error { // Field (16) 'ExcessBlobGas' e.ExcessBlobGas = ssz.UnmarshallUint64(buf[520:528]) - // Offset (17) 'DepositRequests' - if o17 = ssz.ReadOffset(buf[528:532]); o17 > size || o14 > o17 { - return ssz.ErrOffset - } - - // Offset (18) 'WithdrawalRequests' - if o18 = ssz.ReadOffset(buf[532:536]); o18 > size || o17 > o18 { - return ssz.ErrOffset - } - - // Offset (19) 'ConsolidationRequests' - if o19 = ssz.ReadOffset(buf[536:540]); o19 > size || o18 > o19 { - return ssz.ErrOffset - } - // Field (10) 'ExtraData' { buf = tail[o10:o13] @@ -1591,7 +1616,7 @@ func (e *ExecutionPayloadElectra) UnmarshalSSZ(buf []byte) error { // Field (14) 'Withdrawals' { - buf = tail[o14:o17] + buf = tail[o14:] num, err := ssz.DivideInt2(len(buf), 44, 16) if err != nil { return err @@ -1606,66 +1631,12 @@ func (e *ExecutionPayloadElectra) UnmarshalSSZ(buf []byte) error { } } } - - // Field (17) 'DepositRequests' - { - buf = tail[o17:o18] - num, err := ssz.DivideInt2(len(buf), 192, 8192) - if err != nil { - return err - } - e.DepositRequests = make([]*DepositRequest, num) - for ii := 0; ii < num; ii++ { - if e.DepositRequests[ii] == nil { - e.DepositRequests[ii] = new(DepositRequest) - } - if err = e.DepositRequests[ii].UnmarshalSSZ(buf[ii*192 : (ii+1)*192]); err != nil { - return err - } - } - } - - // Field (18) 'WithdrawalRequests' - { - buf = tail[o18:o19] - num, err := ssz.DivideInt2(len(buf), 76, 16) - if err != nil { - return err - } - e.WithdrawalRequests = make([]*WithdrawalRequest, num) - for ii := 0; ii < num; ii++ { - if e.WithdrawalRequests[ii] == nil { - e.WithdrawalRequests[ii] = new(WithdrawalRequest) - } - if err = e.WithdrawalRequests[ii].UnmarshalSSZ(buf[ii*76 : (ii+1)*76]); err != nil { - return err - } - } - } - - // Field (19) 'ConsolidationRequests' - { - buf = tail[o19:] - num, err := ssz.DivideInt2(len(buf), 116, 1) - if err != nil { - return err - } - e.ConsolidationRequests = make([]*ConsolidationRequest, num) - for ii := 0; ii < num; ii++ { - if e.ConsolidationRequests[ii] == nil { - e.ConsolidationRequests[ii] = new(ConsolidationRequest) - } - if err = e.ConsolidationRequests[ii].UnmarshalSSZ(buf[ii*116 : (ii+1)*116]); err != nil { - return err - } - } - } return err } -// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadElectra object -func (e *ExecutionPayloadElectra) SizeSSZ() (size int) { - size = 540 +// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadDeneb object +func (e *ExecutionPayloadDeneb) SizeSSZ() (size int) { + size = 528 // Field (10) 'ExtraData' size += len(e.ExtraData) @@ -1679,25 +1650,16 @@ func (e *ExecutionPayloadElectra) SizeSSZ() (size int) { // Field (14) 'Withdrawals' size += len(e.Withdrawals) * 44 - // Field (17) 'DepositRequests' - size += len(e.DepositRequests) * 192 - - // Field (18) 'WithdrawalRequests' - size += len(e.WithdrawalRequests) * 76 - - // Field (19) 'ConsolidationRequests' - size += len(e.ConsolidationRequests) * 116 - return } -// HashTreeRoot ssz hashes the ExecutionPayloadElectra object -func (e *ExecutionPayloadElectra) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the ExecutionPayloadDeneb object +func (e *ExecutionPayloadDeneb) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(e) } -// HashTreeRootWith ssz hashes the ExecutionPayloadElectra object with a hasher -func (e *ExecutionPayloadElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the ExecutionPayloadDeneb object with a hasher +func (e *ExecutionPayloadDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field (0) 'ParentHash' @@ -1825,54 +1787,6 @@ func (e *ExecutionPayloadElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { // Field (16) 'ExcessBlobGas' hh.PutUint64(e.ExcessBlobGas) - // Field (17) 'DepositRequests' - { - subIndx := hh.Index() - num := uint64(len(e.DepositRequests)) - if num > 8192 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.DepositRequests { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 8192) - } - - // Field (18) 'WithdrawalRequests' - { - subIndx := hh.Index() - num := uint64(len(e.WithdrawalRequests)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.WithdrawalRequests { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (19) 'ConsolidationRequests' - { - subIndx := hh.Index() - num := uint64(len(e.ConsolidationRequests)) - if num > 1 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.ConsolidationRequests { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 1) - } - hh.Merkleize(indx) return } @@ -2862,1040 +2776,320 @@ func (e *ExecutionPayloadHeaderDeneb) HashTreeRootWith(hh *ssz.Hasher) (err erro return } -// MarshalSSZ ssz marshals the ExecutionPayloadHeaderElectra object -func (e *ExecutionPayloadHeaderElectra) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(e) +// MarshalSSZ ssz marshals the Withdrawal object +func (w *Withdrawal) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(w) } -// MarshalSSZTo ssz marshals the ExecutionPayloadHeaderElectra object to a target array -func (e *ExecutionPayloadHeaderElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the Withdrawal object to a target array +func (w *Withdrawal) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(680) - // Field (0) 'ParentHash' - if size := len(e.ParentHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentHash", size, 32) - return - } - dst = append(dst, e.ParentHash...) + // Field (0) 'Index' + dst = ssz.MarshalUint64(dst, w.Index) - // Field (1) 'FeeRecipient' - if size := len(e.FeeRecipient); size != 20 { - err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20) - return - } - dst = append(dst, e.FeeRecipient...) + // Field (1) 'ValidatorIndex' + dst = ssz.MarshalUint64(dst, uint64(w.ValidatorIndex)) - // Field (2) 'StateRoot' - if size := len(e.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + // Field (2) 'Address' + if size := len(w.Address); size != 20 { + err = ssz.ErrBytesLengthFn("--.Address", size, 20) return } - dst = append(dst, e.StateRoot...) + dst = append(dst, w.Address...) - // Field (3) 'ReceiptsRoot' - if size := len(e.ReceiptsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ReceiptsRoot", size, 32) - return - } - dst = append(dst, e.ReceiptsRoot...) + // Field (3) 'Amount' + dst = ssz.MarshalUint64(dst, w.Amount) - // Field (4) 'LogsBloom' - if size := len(e.LogsBloom); size != 256 { - err = ssz.ErrBytesLengthFn("--.LogsBloom", size, 256) - return - } - dst = append(dst, e.LogsBloom...) + return +} - // Field (5) 'PrevRandao' - if size := len(e.PrevRandao); size != 32 { - err = ssz.ErrBytesLengthFn("--.PrevRandao", size, 32) - return +// UnmarshalSSZ ssz unmarshals the Withdrawal object +func (w *Withdrawal) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 44 { + return ssz.ErrSize } - dst = append(dst, e.PrevRandao...) - // Field (6) 'BlockNumber' - dst = ssz.MarshalUint64(dst, e.BlockNumber) + // Field (0) 'Index' + w.Index = ssz.UnmarshallUint64(buf[0:8]) - // Field (7) 'GasLimit' - dst = ssz.MarshalUint64(dst, e.GasLimit) + // Field (1) 'ValidatorIndex' + w.ValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - // Field (8) 'GasUsed' - dst = ssz.MarshalUint64(dst, e.GasUsed) + // Field (2) 'Address' + if cap(w.Address) == 0 { + w.Address = make([]byte, 0, len(buf[16:36])) + } + w.Address = append(w.Address, buf[16:36]...) - // Field (9) 'Timestamp' - dst = ssz.MarshalUint64(dst, e.Timestamp) + // Field (3) 'Amount' + w.Amount = ssz.UnmarshallUint64(buf[36:44]) - // Offset (10) 'ExtraData' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.ExtraData) + return err +} - // Field (11) 'BaseFeePerGas' - if size := len(e.BaseFeePerGas); size != 32 { - err = ssz.ErrBytesLengthFn("--.BaseFeePerGas", size, 32) - return - } - dst = append(dst, e.BaseFeePerGas...) +// SizeSSZ returns the ssz encoded size in bytes for the Withdrawal object +func (w *Withdrawal) SizeSSZ() (size int) { + size = 44 + return +} - // Field (12) 'BlockHash' - if size := len(e.BlockHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockHash", size, 32) - return - } - dst = append(dst, e.BlockHash...) +// HashTreeRoot ssz hashes the Withdrawal object +func (w *Withdrawal) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(w) +} - // Field (13) 'TransactionsRoot' - if size := len(e.TransactionsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.TransactionsRoot", size, 32) - return - } - dst = append(dst, e.TransactionsRoot...) +// HashTreeRootWith ssz hashes the Withdrawal object with a hasher +func (w *Withdrawal) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() - // Field (14) 'WithdrawalsRoot' - if size := len(e.WithdrawalsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.WithdrawalsRoot", size, 32) + // Field (0) 'Index' + hh.PutUint64(w.Index) + + // Field (1) 'ValidatorIndex' + hh.PutUint64(uint64(w.ValidatorIndex)) + + // Field (2) 'Address' + if size := len(w.Address); size != 20 { + err = ssz.ErrBytesLengthFn("--.Address", size, 20) return } - dst = append(dst, e.WithdrawalsRoot...) + hh.PutBytes(w.Address) - // Field (15) 'BlobGasUsed' - dst = ssz.MarshalUint64(dst, e.BlobGasUsed) + // Field (3) 'Amount' + hh.PutUint64(w.Amount) - // Field (16) 'ExcessBlobGas' - dst = ssz.MarshalUint64(dst, e.ExcessBlobGas) + hh.Merkleize(indx) + return +} - // Field (17) 'DepositRequestsRoot' - if size := len(e.DepositRequestsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.DepositRequestsRoot", size, 32) - return - } - dst = append(dst, e.DepositRequestsRoot...) +// MarshalSSZ ssz marshals the BlobsBundle object +func (b *BlobsBundle) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BlobsBundle object to a target array +func (b *BlobsBundle) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(12) + + // Offset (0) 'KzgCommitments' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.KzgCommitments) * 48 + + // Offset (1) 'Proofs' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Proofs) * 48 + + // Offset (2) 'Blobs' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Blobs) * 131072 - // Field (18) 'WithdrawalRequestsRoot' - if size := len(e.WithdrawalRequestsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.WithdrawalRequestsRoot", size, 32) + // Field (0) 'KzgCommitments' + if size := len(b.KzgCommitments); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgCommitments", size, 4096) return } - dst = append(dst, e.WithdrawalRequestsRoot...) + for ii := 0; ii < len(b.KzgCommitments); ii++ { + if size := len(b.KzgCommitments[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgCommitments[ii]", size, 48) + return + } + dst = append(dst, b.KzgCommitments[ii]...) + } - // Field (19) 'ConsolidationRequestsRoot' - if size := len(e.ConsolidationRequestsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ConsolidationRequestsRoot", size, 32) + // Field (1) 'Proofs' + if size := len(b.Proofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Proofs", size, 4096) return } - dst = append(dst, e.ConsolidationRequestsRoot...) + for ii := 0; ii < len(b.Proofs); ii++ { + if size := len(b.Proofs[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.Proofs[ii]", size, 48) + return + } + dst = append(dst, b.Proofs[ii]...) + } - // Field (10) 'ExtraData' - if size := len(e.ExtraData); size > 32 { - err = ssz.ErrBytesLengthFn("--.ExtraData", size, 32) + // Field (2) 'Blobs' + if size := len(b.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) return } - dst = append(dst, e.ExtraData...) + for ii := 0; ii < len(b.Blobs); ii++ { + if size := len(b.Blobs[ii]); size != 131072 { + err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072) + return + } + dst = append(dst, b.Blobs[ii]...) + } return } -// UnmarshalSSZ ssz unmarshals the ExecutionPayloadHeaderElectra object -func (e *ExecutionPayloadHeaderElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the BlobsBundle object +func (b *BlobsBundle) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 680 { + if size < 12 { return ssz.ErrSize } tail := buf - var o10 uint64 - - // Field (0) 'ParentHash' - if cap(e.ParentHash) == 0 { - e.ParentHash = make([]byte, 0, len(buf[0:32])) - } - e.ParentHash = append(e.ParentHash, buf[0:32]...) - - // Field (1) 'FeeRecipient' - if cap(e.FeeRecipient) == 0 { - e.FeeRecipient = make([]byte, 0, len(buf[32:52])) - } - e.FeeRecipient = append(e.FeeRecipient, buf[32:52]...) - - // Field (2) 'StateRoot' - if cap(e.StateRoot) == 0 { - e.StateRoot = make([]byte, 0, len(buf[52:84])) - } - e.StateRoot = append(e.StateRoot, buf[52:84]...) - - // Field (3) 'ReceiptsRoot' - if cap(e.ReceiptsRoot) == 0 { - e.ReceiptsRoot = make([]byte, 0, len(buf[84:116])) - } - e.ReceiptsRoot = append(e.ReceiptsRoot, buf[84:116]...) - - // Field (4) 'LogsBloom' - if cap(e.LogsBloom) == 0 { - e.LogsBloom = make([]byte, 0, len(buf[116:372])) - } - e.LogsBloom = append(e.LogsBloom, buf[116:372]...) - - // Field (5) 'PrevRandao' - if cap(e.PrevRandao) == 0 { - e.PrevRandao = make([]byte, 0, len(buf[372:404])) - } - e.PrevRandao = append(e.PrevRandao, buf[372:404]...) - - // Field (6) 'BlockNumber' - e.BlockNumber = ssz.UnmarshallUint64(buf[404:412]) - - // Field (7) 'GasLimit' - e.GasLimit = ssz.UnmarshallUint64(buf[412:420]) - - // Field (8) 'GasUsed' - e.GasUsed = ssz.UnmarshallUint64(buf[420:428]) - - // Field (9) 'Timestamp' - e.Timestamp = ssz.UnmarshallUint64(buf[428:436]) + var o0, o1, o2 uint64 - // Offset (10) 'ExtraData' - if o10 = ssz.ReadOffset(buf[436:440]); o10 > size { + // Offset (0) 'KzgCommitments' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { return ssz.ErrOffset } - if o10 != 680 { + if o0 != 12 { return ssz.ErrInvalidVariableOffset } - // Field (11) 'BaseFeePerGas' - if cap(e.BaseFeePerGas) == 0 { - e.BaseFeePerGas = make([]byte, 0, len(buf[440:472])) - } - e.BaseFeePerGas = append(e.BaseFeePerGas, buf[440:472]...) - - // Field (12) 'BlockHash' - if cap(e.BlockHash) == 0 { - e.BlockHash = make([]byte, 0, len(buf[472:504])) - } - e.BlockHash = append(e.BlockHash, buf[472:504]...) - - // Field (13) 'TransactionsRoot' - if cap(e.TransactionsRoot) == 0 { - e.TransactionsRoot = make([]byte, 0, len(buf[504:536])) - } - e.TransactionsRoot = append(e.TransactionsRoot, buf[504:536]...) - - // Field (14) 'WithdrawalsRoot' - if cap(e.WithdrawalsRoot) == 0 { - e.WithdrawalsRoot = make([]byte, 0, len(buf[536:568])) + // Offset (1) 'Proofs' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset } - e.WithdrawalsRoot = append(e.WithdrawalsRoot, buf[536:568]...) - - // Field (15) 'BlobGasUsed' - e.BlobGasUsed = ssz.UnmarshallUint64(buf[568:576]) - - // Field (16) 'ExcessBlobGas' - e.ExcessBlobGas = ssz.UnmarshallUint64(buf[576:584]) - // Field (17) 'DepositRequestsRoot' - if cap(e.DepositRequestsRoot) == 0 { - e.DepositRequestsRoot = make([]byte, 0, len(buf[584:616])) + // Offset (2) 'Blobs' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { + return ssz.ErrOffset } - e.DepositRequestsRoot = append(e.DepositRequestsRoot, buf[584:616]...) - // Field (18) 'WithdrawalRequestsRoot' - if cap(e.WithdrawalRequestsRoot) == 0 { - e.WithdrawalRequestsRoot = make([]byte, 0, len(buf[616:648])) + // Field (0) 'KzgCommitments' + { + buf = tail[o0:o1] + num, err := ssz.DivideInt2(len(buf), 48, 4096) + if err != nil { + return err + } + b.KzgCommitments = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(b.KzgCommitments[ii]) == 0 { + b.KzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + } + b.KzgCommitments[ii] = append(b.KzgCommitments[ii], buf[ii*48:(ii+1)*48]...) + } } - e.WithdrawalRequestsRoot = append(e.WithdrawalRequestsRoot, buf[616:648]...) - // Field (19) 'ConsolidationRequestsRoot' - if cap(e.ConsolidationRequestsRoot) == 0 { - e.ConsolidationRequestsRoot = make([]byte, 0, len(buf[648:680])) + // Field (1) 'Proofs' + { + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 48, 4096) + if err != nil { + return err + } + b.Proofs = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(b.Proofs[ii]) == 0 { + b.Proofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + } + b.Proofs[ii] = append(b.Proofs[ii], buf[ii*48:(ii+1)*48]...) + } } - e.ConsolidationRequestsRoot = append(e.ConsolidationRequestsRoot, buf[648:680]...) - // Field (10) 'ExtraData' + // Field (2) 'Blobs' { - buf = tail[o10:] - if len(buf) > 32 { - return ssz.ErrBytesLength + buf = tail[o2:] + num, err := ssz.DivideInt2(len(buf), 131072, 4096) + if err != nil { + return err } - if cap(e.ExtraData) == 0 { - e.ExtraData = make([]byte, 0, len(buf)) + b.Blobs = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(b.Blobs[ii]) == 0 { + b.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072])) + } + b.Blobs[ii] = append(b.Blobs[ii], buf[ii*131072:(ii+1)*131072]...) } - e.ExtraData = append(e.ExtraData, buf...) } return err } -// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadHeaderElectra object -func (e *ExecutionPayloadHeaderElectra) SizeSSZ() (size int) { - size = 680 +// SizeSSZ returns the ssz encoded size in bytes for the BlobsBundle object +func (b *BlobsBundle) SizeSSZ() (size int) { + size = 12 - // Field (10) 'ExtraData' - size += len(e.ExtraData) + // Field (0) 'KzgCommitments' + size += len(b.KzgCommitments) * 48 + + // Field (1) 'Proofs' + size += len(b.Proofs) * 48 + + // Field (2) 'Blobs' + size += len(b.Blobs) * 131072 return } -// HashTreeRoot ssz hashes the ExecutionPayloadHeaderElectra object -func (e *ExecutionPayloadHeaderElectra) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(e) +// HashTreeRoot ssz hashes the BlobsBundle object +func (b *BlobsBundle) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) } -// HashTreeRootWith ssz hashes the ExecutionPayloadHeaderElectra object with a hasher -func (e *ExecutionPayloadHeaderElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the BlobsBundle object with a hasher +func (b *BlobsBundle) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'ParentHash' - if size := len(e.ParentHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentHash", size, 32) - return - } - hh.PutBytes(e.ParentHash) - - // Field (1) 'FeeRecipient' - if size := len(e.FeeRecipient); size != 20 { - err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20) - return - } - hh.PutBytes(e.FeeRecipient) - - // Field (2) 'StateRoot' - if size := len(e.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - hh.PutBytes(e.StateRoot) - - // Field (3) 'ReceiptsRoot' - if size := len(e.ReceiptsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ReceiptsRoot", size, 32) - return - } - hh.PutBytes(e.ReceiptsRoot) - - // Field (4) 'LogsBloom' - if size := len(e.LogsBloom); size != 256 { - err = ssz.ErrBytesLengthFn("--.LogsBloom", size, 256) - return - } - hh.PutBytes(e.LogsBloom) - - // Field (5) 'PrevRandao' - if size := len(e.PrevRandao); size != 32 { - err = ssz.ErrBytesLengthFn("--.PrevRandao", size, 32) - return - } - hh.PutBytes(e.PrevRandao) - - // Field (6) 'BlockNumber' - hh.PutUint64(e.BlockNumber) - - // Field (7) 'GasLimit' - hh.PutUint64(e.GasLimit) - - // Field (8) 'GasUsed' - hh.PutUint64(e.GasUsed) - - // Field (9) 'Timestamp' - hh.PutUint64(e.Timestamp) - - // Field (10) 'ExtraData' + // Field (0) 'KzgCommitments' { - elemIndx := hh.Index() - byteLen := uint64(len(e.ExtraData)) - if byteLen > 32 { - err = ssz.ErrIncorrectListSize + if size := len(b.KzgCommitments); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgCommitments", size, 4096) return } - hh.PutBytes(e.ExtraData) - hh.MerkleizeWithMixin(elemIndx, byteLen, (32+31)/32) - } - - // Field (11) 'BaseFeePerGas' - if size := len(e.BaseFeePerGas); size != 32 { - err = ssz.ErrBytesLengthFn("--.BaseFeePerGas", size, 32) - return - } - hh.PutBytes(e.BaseFeePerGas) - - // Field (12) 'BlockHash' - if size := len(e.BlockHash); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockHash", size, 32) - return - } - hh.PutBytes(e.BlockHash) - - // Field (13) 'TransactionsRoot' - if size := len(e.TransactionsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.TransactionsRoot", size, 32) - return - } - hh.PutBytes(e.TransactionsRoot) - - // Field (14) 'WithdrawalsRoot' - if size := len(e.WithdrawalsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.WithdrawalsRoot", size, 32) - return - } - hh.PutBytes(e.WithdrawalsRoot) - - // Field (15) 'BlobGasUsed' - hh.PutUint64(e.BlobGasUsed) - - // Field (16) 'ExcessBlobGas' - hh.PutUint64(e.ExcessBlobGas) - - // Field (17) 'DepositRequestsRoot' - if size := len(e.DepositRequestsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.DepositRequestsRoot", size, 32) - return - } - hh.PutBytes(e.DepositRequestsRoot) - - // Field (18) 'WithdrawalRequestsRoot' - if size := len(e.WithdrawalRequestsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.WithdrawalRequestsRoot", size, 32) - return - } - hh.PutBytes(e.WithdrawalRequestsRoot) - - // Field (19) 'ConsolidationRequestsRoot' - if size := len(e.ConsolidationRequestsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ConsolidationRequestsRoot", size, 32) - return - } - hh.PutBytes(e.ConsolidationRequestsRoot) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the Withdrawal object -func (w *Withdrawal) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(w) -} - -// MarshalSSZTo ssz marshals the Withdrawal object to a target array -func (w *Withdrawal) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Index' - dst = ssz.MarshalUint64(dst, w.Index) - - // Field (1) 'ValidatorIndex' - dst = ssz.MarshalUint64(dst, uint64(w.ValidatorIndex)) - - // Field (2) 'Address' - if size := len(w.Address); size != 20 { - err = ssz.ErrBytesLengthFn("--.Address", size, 20) - return - } - dst = append(dst, w.Address...) - - // Field (3) 'Amount' - dst = ssz.MarshalUint64(dst, w.Amount) - - return -} + subIndx := hh.Index() + for _, i := range b.KzgCommitments { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } -// UnmarshalSSZ ssz unmarshals the Withdrawal object -func (w *Withdrawal) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 44 { - return ssz.ErrSize + numItems := uint64(len(b.KzgCommitments)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) } - // Field (0) 'Index' - w.Index = ssz.UnmarshallUint64(buf[0:8]) - - // Field (1) 'ValidatorIndex' - w.ValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) + // Field (1) 'Proofs' + { + if size := len(b.Proofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Proofs", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range b.Proofs { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } - // Field (2) 'Address' - if cap(w.Address) == 0 { - w.Address = make([]byte, 0, len(buf[16:36])) + numItems := uint64(len(b.Proofs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) } - w.Address = append(w.Address, buf[16:36]...) - - // Field (3) 'Amount' - w.Amount = ssz.UnmarshallUint64(buf[36:44]) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the Withdrawal object -func (w *Withdrawal) SizeSSZ() (size int) { - size = 44 - return -} - -// HashTreeRoot ssz hashes the Withdrawal object -func (w *Withdrawal) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(w) -} - -// HashTreeRootWith ssz hashes the Withdrawal object with a hasher -func (w *Withdrawal) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - // Field (0) 'Index' - hh.PutUint64(w.Index) - - // Field (1) 'ValidatorIndex' - hh.PutUint64(uint64(w.ValidatorIndex)) + // Field (2) 'Blobs' + { + if size := len(b.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range b.Blobs { + if len(i) != 131072 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } - // Field (2) 'Address' - if size := len(w.Address); size != 20 { - err = ssz.ErrBytesLengthFn("--.Address", size, 20) - return + numItems := uint64(len(b.Blobs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) } - hh.PutBytes(w.Address) - - // Field (3) 'Amount' - hh.PutUint64(w.Amount) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BlobsBundle object -func (b *BlobsBundle) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlobsBundle object to a target array -func (b *BlobsBundle) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(12) - - // Offset (0) 'KzgCommitments' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.KzgCommitments) * 48 - - // Offset (1) 'Proofs' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Proofs) * 48 - - // Offset (2) 'Blobs' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Blobs) * 131072 - - // Field (0) 'KzgCommitments' - if size := len(b.KzgCommitments); size > 4096 { - err = ssz.ErrListTooBigFn("--.KzgCommitments", size, 4096) - return - } - for ii := 0; ii < len(b.KzgCommitments); ii++ { - if size := len(b.KzgCommitments[ii]); size != 48 { - err = ssz.ErrBytesLengthFn("--.KzgCommitments[ii]", size, 48) - return - } - dst = append(dst, b.KzgCommitments[ii]...) - } - - // Field (1) 'Proofs' - if size := len(b.Proofs); size > 4096 { - err = ssz.ErrListTooBigFn("--.Proofs", size, 4096) - return - } - for ii := 0; ii < len(b.Proofs); ii++ { - if size := len(b.Proofs[ii]); size != 48 { - err = ssz.ErrBytesLengthFn("--.Proofs[ii]", size, 48) - return - } - dst = append(dst, b.Proofs[ii]...) - } - - // Field (2) 'Blobs' - if size := len(b.Blobs); size > 4096 { - err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) - return - } - for ii := 0; ii < len(b.Blobs); ii++ { - if size := len(b.Blobs[ii]); size != 131072 { - err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072) - return - } - dst = append(dst, b.Blobs[ii]...) - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BlobsBundle object -func (b *BlobsBundle) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 12 { - return ssz.ErrSize - } - - tail := buf - var o0, o1, o2 uint64 - - // Offset (0) 'KzgCommitments' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 12 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (1) 'Proofs' - if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { - return ssz.ErrOffset - } - - // Offset (2) 'Blobs' - if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { - return ssz.ErrOffset - } - - // Field (0) 'KzgCommitments' - { - buf = tail[o0:o1] - num, err := ssz.DivideInt2(len(buf), 48, 4096) - if err != nil { - return err - } - b.KzgCommitments = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(b.KzgCommitments[ii]) == 0 { - b.KzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) - } - b.KzgCommitments[ii] = append(b.KzgCommitments[ii], buf[ii*48:(ii+1)*48]...) - } - } - - // Field (1) 'Proofs' - { - buf = tail[o1:o2] - num, err := ssz.DivideInt2(len(buf), 48, 4096) - if err != nil { - return err - } - b.Proofs = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(b.Proofs[ii]) == 0 { - b.Proofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) - } - b.Proofs[ii] = append(b.Proofs[ii], buf[ii*48:(ii+1)*48]...) - } - } - - // Field (2) 'Blobs' - { - buf = tail[o2:] - num, err := ssz.DivideInt2(len(buf), 131072, 4096) - if err != nil { - return err - } - b.Blobs = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(b.Blobs[ii]) == 0 { - b.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072])) - } - b.Blobs[ii] = append(b.Blobs[ii], buf[ii*131072:(ii+1)*131072]...) - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlobsBundle object -func (b *BlobsBundle) SizeSSZ() (size int) { - size = 12 - - // Field (0) 'KzgCommitments' - size += len(b.KzgCommitments) * 48 - - // Field (1) 'Proofs' - size += len(b.Proofs) * 48 - - // Field (2) 'Blobs' - size += len(b.Blobs) * 131072 - - return -} - -// HashTreeRoot ssz hashes the BlobsBundle object -func (b *BlobsBundle) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlobsBundle object with a hasher -func (b *BlobsBundle) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'KzgCommitments' - { - if size := len(b.KzgCommitments); size > 4096 { - err = ssz.ErrListTooBigFn("--.KzgCommitments", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range b.KzgCommitments { - if len(i) != 48 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(b.KzgCommitments)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - // Field (1) 'Proofs' - { - if size := len(b.Proofs); size > 4096 { - err = ssz.ErrListTooBigFn("--.Proofs", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range b.Proofs { - if len(i) != 48 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(b.Proofs)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - // Field (2) 'Blobs' - { - if size := len(b.Blobs); size > 4096 { - err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range b.Blobs { - if len(i) != 131072 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(b.Blobs)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the WithdrawalRequest object -func (w *WithdrawalRequest) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(w) -} - -// MarshalSSZTo ssz marshals the WithdrawalRequest object to a target array -func (w *WithdrawalRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'SourceAddress' - if size := len(w.SourceAddress); size != 20 { - err = ssz.ErrBytesLengthFn("--.SourceAddress", size, 20) - return - } - dst = append(dst, w.SourceAddress...) - - // Field (1) 'ValidatorPubkey' - if size := len(w.ValidatorPubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.ValidatorPubkey", size, 48) - return - } - dst = append(dst, w.ValidatorPubkey...) - - // Field (2) 'Amount' - dst = ssz.MarshalUint64(dst, w.Amount) - - return -} - -// UnmarshalSSZ ssz unmarshals the WithdrawalRequest object -func (w *WithdrawalRequest) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 76 { - return ssz.ErrSize - } - - // Field (0) 'SourceAddress' - if cap(w.SourceAddress) == 0 { - w.SourceAddress = make([]byte, 0, len(buf[0:20])) - } - w.SourceAddress = append(w.SourceAddress, buf[0:20]...) - - // Field (1) 'ValidatorPubkey' - if cap(w.ValidatorPubkey) == 0 { - w.ValidatorPubkey = make([]byte, 0, len(buf[20:68])) - } - w.ValidatorPubkey = append(w.ValidatorPubkey, buf[20:68]...) - - // Field (2) 'Amount' - w.Amount = ssz.UnmarshallUint64(buf[68:76]) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the WithdrawalRequest object -func (w *WithdrawalRequest) SizeSSZ() (size int) { - size = 76 - return -} - -// HashTreeRoot ssz hashes the WithdrawalRequest object -func (w *WithdrawalRequest) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(w) -} - -// HashTreeRootWith ssz hashes the WithdrawalRequest object with a hasher -func (w *WithdrawalRequest) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'SourceAddress' - if size := len(w.SourceAddress); size != 20 { - err = ssz.ErrBytesLengthFn("--.SourceAddress", size, 20) - return - } - hh.PutBytes(w.SourceAddress) - - // Field (1) 'ValidatorPubkey' - if size := len(w.ValidatorPubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.ValidatorPubkey", size, 48) - return - } - hh.PutBytes(w.ValidatorPubkey) - - // Field (2) 'Amount' - hh.PutUint64(w.Amount) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the DepositRequest object -func (d *DepositRequest) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(d) -} - -// MarshalSSZTo ssz marshals the DepositRequest object to a target array -func (d *DepositRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Pubkey' - if size := len(d.Pubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48) - return - } - dst = append(dst, d.Pubkey...) - - // Field (1) 'WithdrawalCredentials' - if size := len(d.WithdrawalCredentials); size != 32 { - err = ssz.ErrBytesLengthFn("--.WithdrawalCredentials", size, 32) - return - } - dst = append(dst, d.WithdrawalCredentials...) - - // Field (2) 'Amount' - dst = ssz.MarshalUint64(dst, d.Amount) - - // Field (3) 'Signature' - if size := len(d.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, d.Signature...) - - // Field (4) 'Index' - dst = ssz.MarshalUint64(dst, d.Index) - - return -} - -// UnmarshalSSZ ssz unmarshals the DepositRequest object -func (d *DepositRequest) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 192 { - return ssz.ErrSize - } - - // Field (0) 'Pubkey' - if cap(d.Pubkey) == 0 { - d.Pubkey = make([]byte, 0, len(buf[0:48])) - } - d.Pubkey = append(d.Pubkey, buf[0:48]...) - - // Field (1) 'WithdrawalCredentials' - if cap(d.WithdrawalCredentials) == 0 { - d.WithdrawalCredentials = make([]byte, 0, len(buf[48:80])) - } - d.WithdrawalCredentials = append(d.WithdrawalCredentials, buf[48:80]...) - - // Field (2) 'Amount' - d.Amount = ssz.UnmarshallUint64(buf[80:88]) - - // Field (3) 'Signature' - if cap(d.Signature) == 0 { - d.Signature = make([]byte, 0, len(buf[88:184])) - } - d.Signature = append(d.Signature, buf[88:184]...) - - // Field (4) 'Index' - d.Index = ssz.UnmarshallUint64(buf[184:192]) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the DepositRequest object -func (d *DepositRequest) SizeSSZ() (size int) { - size = 192 - return -} - -// HashTreeRoot ssz hashes the DepositRequest object -func (d *DepositRequest) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(d) -} - -// HashTreeRootWith ssz hashes the DepositRequest object with a hasher -func (d *DepositRequest) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Pubkey' - if size := len(d.Pubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48) - return - } - hh.PutBytes(d.Pubkey) - - // Field (1) 'WithdrawalCredentials' - if size := len(d.WithdrawalCredentials); size != 32 { - err = ssz.ErrBytesLengthFn("--.WithdrawalCredentials", size, 32) - return - } - hh.PutBytes(d.WithdrawalCredentials) - - // Field (2) 'Amount' - hh.PutUint64(d.Amount) - - // Field (3) 'Signature' - if size := len(d.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(d.Signature) - - // Field (4) 'Index' - hh.PutUint64(d.Index) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the ConsolidationRequest object -func (c *ConsolidationRequest) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(c) -} - -// MarshalSSZTo ssz marshals the ConsolidationRequest object to a target array -func (c *ConsolidationRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'SourceAddress' - if size := len(c.SourceAddress); size != 20 { - err = ssz.ErrBytesLengthFn("--.SourceAddress", size, 20) - return - } - dst = append(dst, c.SourceAddress...) - - // Field (1) 'SourcePubkey' - if size := len(c.SourcePubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.SourcePubkey", size, 48) - return - } - dst = append(dst, c.SourcePubkey...) - - // Field (2) 'TargetPubkey' - if size := len(c.TargetPubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.TargetPubkey", size, 48) - return - } - dst = append(dst, c.TargetPubkey...) - - return -} - -// UnmarshalSSZ ssz unmarshals the ConsolidationRequest object -func (c *ConsolidationRequest) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 116 { - return ssz.ErrSize - } - - // Field (0) 'SourceAddress' - if cap(c.SourceAddress) == 0 { - c.SourceAddress = make([]byte, 0, len(buf[0:20])) - } - c.SourceAddress = append(c.SourceAddress, buf[0:20]...) - - // Field (1) 'SourcePubkey' - if cap(c.SourcePubkey) == 0 { - c.SourcePubkey = make([]byte, 0, len(buf[20:68])) - } - c.SourcePubkey = append(c.SourcePubkey, buf[20:68]...) - - // Field (2) 'TargetPubkey' - if cap(c.TargetPubkey) == 0 { - c.TargetPubkey = make([]byte, 0, len(buf[68:116])) - } - c.TargetPubkey = append(c.TargetPubkey, buf[68:116]...) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the ConsolidationRequest object -func (c *ConsolidationRequest) SizeSSZ() (size int) { - size = 116 - return -} - -// HashTreeRoot ssz hashes the ConsolidationRequest object -func (c *ConsolidationRequest) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(c) -} - -// HashTreeRootWith ssz hashes the ConsolidationRequest object with a hasher -func (c *ConsolidationRequest) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'SourceAddress' - if size := len(c.SourceAddress); size != 20 { - err = ssz.ErrBytesLengthFn("--.SourceAddress", size, 20) - return - } - hh.PutBytes(c.SourceAddress) - - // Field (1) 'SourcePubkey' - if size := len(c.SourcePubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.SourcePubkey", size, 48) - return - } - hh.PutBytes(c.SourcePubkey) - - // Field (2) 'TargetPubkey' - if size := len(c.TargetPubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.TargetPubkey", size, 48) - return - } - hh.PutBytes(c.TargetPubkey) hh.Merkleize(indx) return diff --git a/proto/engine/v1/execution_engine.go b/proto/engine/v1/execution_engine.go index 5b9691184a5f..94aad2d9061d 100644 --- a/proto/engine/v1/execution_engine.go +++ b/proto/engine/v1/execution_engine.go @@ -67,35 +67,6 @@ func (cr *ConsolidationRequest) Copy() *ConsolidationRequest { } } -// Copy -- Electra -func (payload *ExecutionPayloadElectra) Copy() *ExecutionPayloadElectra { - if payload == nil { - return nil - } - return &ExecutionPayloadElectra{ - ParentHash: bytesutil.SafeCopyBytes(payload.ParentHash), - FeeRecipient: bytesutil.SafeCopyBytes(payload.FeeRecipient), - StateRoot: bytesutil.SafeCopyBytes(payload.StateRoot), - ReceiptsRoot: bytesutil.SafeCopyBytes(payload.ReceiptsRoot), - LogsBloom: bytesutil.SafeCopyBytes(payload.LogsBloom), - PrevRandao: bytesutil.SafeCopyBytes(payload.PrevRandao), - BlockNumber: payload.BlockNumber, - GasLimit: payload.GasLimit, - GasUsed: payload.GasUsed, - Timestamp: payload.Timestamp, - ExtraData: bytesutil.SafeCopyBytes(payload.ExtraData), - BaseFeePerGas: bytesutil.SafeCopyBytes(payload.BaseFeePerGas), - BlockHash: bytesutil.SafeCopyBytes(payload.BlockHash), - Transactions: bytesutil.SafeCopy2dBytes(payload.Transactions), - Withdrawals: copySlice(payload.Withdrawals), - BlobGasUsed: payload.BlobGasUsed, - ExcessBlobGas: payload.ExcessBlobGas, - DepositRequests: copySlice(payload.DepositRequests), - WithdrawalRequests: copySlice(payload.WithdrawalRequests), - ConsolidationRequests: copySlice(payload.ConsolidationRequests), - } -} - // Copy -- Deneb func (payload *ExecutionPayloadDeneb) Copy() *ExecutionPayloadDeneb { if payload == nil { @@ -171,36 +142,6 @@ func (payload *ExecutionPayload) Copy() *ExecutionPayload { } } -// Copy -- Electra -func (payload *ExecutionPayloadHeaderElectra) Copy() *ExecutionPayloadHeaderElectra { - if payload == nil { - return nil - } - - return &ExecutionPayloadHeaderElectra{ - ParentHash: bytesutil.SafeCopyBytes(payload.ParentHash), - FeeRecipient: bytesutil.SafeCopyBytes(payload.FeeRecipient), - StateRoot: bytesutil.SafeCopyBytes(payload.StateRoot), - ReceiptsRoot: bytesutil.SafeCopyBytes(payload.ReceiptsRoot), - LogsBloom: bytesutil.SafeCopyBytes(payload.LogsBloom), - PrevRandao: bytesutil.SafeCopyBytes(payload.PrevRandao), - BlockNumber: payload.BlockNumber, - GasLimit: payload.GasLimit, - GasUsed: payload.GasUsed, - Timestamp: payload.Timestamp, - ExtraData: bytesutil.SafeCopyBytes(payload.ExtraData), - BaseFeePerGas: bytesutil.SafeCopyBytes(payload.BaseFeePerGas), - BlockHash: bytesutil.SafeCopyBytes(payload.BlockHash), - TransactionsRoot: bytesutil.SafeCopyBytes(payload.TransactionsRoot), - WithdrawalsRoot: bytesutil.SafeCopyBytes(payload.WithdrawalsRoot), - BlobGasUsed: payload.BlobGasUsed, - ExcessBlobGas: payload.ExcessBlobGas, - DepositRequestsRoot: bytesutil.SafeCopyBytes(payload.DepositRequestsRoot), - WithdrawalRequestsRoot: bytesutil.SafeCopyBytes(payload.WithdrawalRequestsRoot), - ConsolidationRequestsRoot: bytesutil.SafeCopyBytes(payload.ConsolidationRequestsRoot), - } -} - // Copy -- Deneb func (payload *ExecutionPayloadHeaderDeneb) Copy() *ExecutionPayloadHeaderDeneb { if payload == nil { diff --git a/proto/engine/v1/execution_engine.pb.go b/proto/engine/v1/execution_engine.pb.go index f2edbf1c9597..3dc96423ecf2 100755 --- a/proto/engine/v1/execution_engine.pb.go +++ b/proto/engine/v1/execution_engine.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/engine/v1/execution_engine.proto package enginev1 @@ -78,7 +78,7 @@ func (x PayloadStatus_Status) Number() protoreflect.EnumNumber { // Deprecated: Use PayloadStatus_Status.Descriptor instead. func (PayloadStatus_Status) EnumDescriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{14, 0} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{11, 0} } type ExecutionPayload struct { @@ -566,276 +566,6 @@ func (x *ExecutionPayloadDeneb) GetExcessBlobGas() uint64 { return 0 } -type ExecutionPayloadElectra struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ParentHash []byte `protobuf:"bytes,1,opt,name=parent_hash,json=parentHash,proto3" json:"parent_hash,omitempty" ssz-size:"32"` - FeeRecipient []byte `protobuf:"bytes,2,opt,name=fee_recipient,json=feeRecipient,proto3" json:"fee_recipient,omitempty" ssz-size:"20"` - StateRoot []byte `protobuf:"bytes,3,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - ReceiptsRoot []byte `protobuf:"bytes,4,opt,name=receipts_root,json=receiptsRoot,proto3" json:"receipts_root,omitempty" ssz-size:"32"` - LogsBloom []byte `protobuf:"bytes,5,opt,name=logs_bloom,json=logsBloom,proto3" json:"logs_bloom,omitempty" ssz-size:"256"` - PrevRandao []byte `protobuf:"bytes,6,opt,name=prev_randao,json=prevRandao,proto3" json:"prev_randao,omitempty" ssz-size:"32"` - BlockNumber uint64 `protobuf:"varint,7,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` - GasLimit uint64 `protobuf:"varint,8,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` - GasUsed uint64 `protobuf:"varint,9,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` - Timestamp uint64 `protobuf:"varint,10,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - ExtraData []byte `protobuf:"bytes,11,opt,name=extra_data,json=extraData,proto3" json:"extra_data,omitempty" ssz-max:"32"` - BaseFeePerGas []byte `protobuf:"bytes,12,opt,name=base_fee_per_gas,json=baseFeePerGas,proto3" json:"base_fee_per_gas,omitempty" ssz-size:"32"` - BlockHash []byte `protobuf:"bytes,13,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty" ssz-size:"32"` - Transactions [][]byte `protobuf:"bytes,14,rep,name=transactions,proto3" json:"transactions,omitempty" ssz-max:"1048576,1073741824" ssz-size:"?,?"` - Withdrawals []*Withdrawal `protobuf:"bytes,15,rep,name=withdrawals,proto3" json:"withdrawals,omitempty" ssz-max:"16"` - BlobGasUsed uint64 `protobuf:"varint,16,opt,name=blob_gas_used,json=blobGasUsed,proto3" json:"blob_gas_used,omitempty"` - ExcessBlobGas uint64 `protobuf:"varint,17,opt,name=excess_blob_gas,json=excessBlobGas,proto3" json:"excess_blob_gas,omitempty"` - DepositRequests []*DepositRequest `protobuf:"bytes,18,rep,name=deposit_requests,json=depositRequests,proto3" json:"deposit_requests,omitempty" ssz-max:"8192"` - WithdrawalRequests []*WithdrawalRequest `protobuf:"bytes,19,rep,name=withdrawal_requests,json=withdrawalRequests,proto3" json:"withdrawal_requests,omitempty" ssz-max:"16"` - ConsolidationRequests []*ConsolidationRequest `protobuf:"bytes,20,rep,name=consolidation_requests,json=consolidationRequests,proto3" json:"consolidation_requests,omitempty" ssz-max:"1"` -} - -func (x *ExecutionPayloadElectra) Reset() { - *x = ExecutionPayloadElectra{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExecutionPayloadElectra) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExecutionPayloadElectra) ProtoMessage() {} - -func (x *ExecutionPayloadElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExecutionPayloadElectra.ProtoReflect.Descriptor instead. -func (*ExecutionPayloadElectra) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{3} -} - -func (x *ExecutionPayloadElectra) GetParentHash() []byte { - if x != nil { - return x.ParentHash - } - return nil -} - -func (x *ExecutionPayloadElectra) GetFeeRecipient() []byte { - if x != nil { - return x.FeeRecipient - } - return nil -} - -func (x *ExecutionPayloadElectra) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *ExecutionPayloadElectra) GetReceiptsRoot() []byte { - if x != nil { - return x.ReceiptsRoot - } - return nil -} - -func (x *ExecutionPayloadElectra) GetLogsBloom() []byte { - if x != nil { - return x.LogsBloom - } - return nil -} - -func (x *ExecutionPayloadElectra) GetPrevRandao() []byte { - if x != nil { - return x.PrevRandao - } - return nil -} - -func (x *ExecutionPayloadElectra) GetBlockNumber() uint64 { - if x != nil { - return x.BlockNumber - } - return 0 -} - -func (x *ExecutionPayloadElectra) GetGasLimit() uint64 { - if x != nil { - return x.GasLimit - } - return 0 -} - -func (x *ExecutionPayloadElectra) GetGasUsed() uint64 { - if x != nil { - return x.GasUsed - } - return 0 -} - -func (x *ExecutionPayloadElectra) GetTimestamp() uint64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *ExecutionPayloadElectra) GetExtraData() []byte { - if x != nil { - return x.ExtraData - } - return nil -} - -func (x *ExecutionPayloadElectra) GetBaseFeePerGas() []byte { - if x != nil { - return x.BaseFeePerGas - } - return nil -} - -func (x *ExecutionPayloadElectra) GetBlockHash() []byte { - if x != nil { - return x.BlockHash - } - return nil -} - -func (x *ExecutionPayloadElectra) GetTransactions() [][]byte { - if x != nil { - return x.Transactions - } - return nil -} - -func (x *ExecutionPayloadElectra) GetWithdrawals() []*Withdrawal { - if x != nil { - return x.Withdrawals - } - return nil -} - -func (x *ExecutionPayloadElectra) GetBlobGasUsed() uint64 { - if x != nil { - return x.BlobGasUsed - } - return 0 -} - -func (x *ExecutionPayloadElectra) GetExcessBlobGas() uint64 { - if x != nil { - return x.ExcessBlobGas - } - return 0 -} - -func (x *ExecutionPayloadElectra) GetDepositRequests() []*DepositRequest { - if x != nil { - return x.DepositRequests - } - return nil -} - -func (x *ExecutionPayloadElectra) GetWithdrawalRequests() []*WithdrawalRequest { - if x != nil { - return x.WithdrawalRequests - } - return nil -} - -func (x *ExecutionPayloadElectra) GetConsolidationRequests() []*ConsolidationRequest { - if x != nil { - return x.ConsolidationRequests - } - return nil -} - -type ExecutionPayloadElectraWithValueAndBlobsBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Payload *ExecutionPayloadElectra `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - BlobsBundle *BlobsBundle `protobuf:"bytes,3,opt,name=blobs_bundle,json=blobsBundle,proto3" json:"blobs_bundle,omitempty"` - ShouldOverrideBuilder bool `protobuf:"varint,4,opt,name=should_override_builder,json=shouldOverrideBuilder,proto3" json:"should_override_builder,omitempty"` -} - -func (x *ExecutionPayloadElectraWithValueAndBlobsBundle) Reset() { - *x = ExecutionPayloadElectraWithValueAndBlobsBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExecutionPayloadElectraWithValueAndBlobsBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExecutionPayloadElectraWithValueAndBlobsBundle) ProtoMessage() {} - -func (x *ExecutionPayloadElectraWithValueAndBlobsBundle) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExecutionPayloadElectraWithValueAndBlobsBundle.ProtoReflect.Descriptor instead. -func (*ExecutionPayloadElectraWithValueAndBlobsBundle) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{4} -} - -func (x *ExecutionPayloadElectraWithValueAndBlobsBundle) GetPayload() *ExecutionPayloadElectra { - if x != nil { - return x.Payload - } - return nil -} - -func (x *ExecutionPayloadElectraWithValueAndBlobsBundle) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -func (x *ExecutionPayloadElectraWithValueAndBlobsBundle) GetBlobsBundle() *BlobsBundle { - if x != nil { - return x.BlobsBundle - } - return nil -} - -func (x *ExecutionPayloadElectraWithValueAndBlobsBundle) GetShouldOverrideBuilder() bool { - if x != nil { - return x.ShouldOverrideBuilder - } - return false -} - type ExecutionPayloadCapellaWithValue struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -848,7 +578,7 @@ type ExecutionPayloadCapellaWithValue struct { func (x *ExecutionPayloadCapellaWithValue) Reset() { *x = ExecutionPayloadCapellaWithValue{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[5] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -861,7 +591,7 @@ func (x *ExecutionPayloadCapellaWithValue) String() string { func (*ExecutionPayloadCapellaWithValue) ProtoMessage() {} func (x *ExecutionPayloadCapellaWithValue) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[5] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -874,7 +604,7 @@ func (x *ExecutionPayloadCapellaWithValue) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecutionPayloadCapellaWithValue.ProtoReflect.Descriptor instead. func (*ExecutionPayloadCapellaWithValue) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{5} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{3} } func (x *ExecutionPayloadCapellaWithValue) GetPayload() *ExecutionPayloadCapella { @@ -905,7 +635,7 @@ type ExecutionPayloadDenebWithValueAndBlobsBundle struct { func (x *ExecutionPayloadDenebWithValueAndBlobsBundle) Reset() { *x = ExecutionPayloadDenebWithValueAndBlobsBundle{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[6] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -918,7 +648,7 @@ func (x *ExecutionPayloadDenebWithValueAndBlobsBundle) String() string { func (*ExecutionPayloadDenebWithValueAndBlobsBundle) ProtoMessage() {} func (x *ExecutionPayloadDenebWithValueAndBlobsBundle) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[6] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -931,7 +661,7 @@ func (x *ExecutionPayloadDenebWithValueAndBlobsBundle) ProtoReflect() protorefle // Deprecated: Use ExecutionPayloadDenebWithValueAndBlobsBundle.ProtoReflect.Descriptor instead. func (*ExecutionPayloadDenebWithValueAndBlobsBundle) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{6} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{4} } func (x *ExecutionPayloadDenebWithValueAndBlobsBundle) GetPayload() *ExecutionPayloadDeneb { @@ -986,7 +716,7 @@ type ExecutionPayloadHeader struct { func (x *ExecutionPayloadHeader) Reset() { *x = ExecutionPayloadHeader{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[7] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -999,7 +729,7 @@ func (x *ExecutionPayloadHeader) String() string { func (*ExecutionPayloadHeader) ProtoMessage() {} func (x *ExecutionPayloadHeader) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[7] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1012,7 +742,7 @@ func (x *ExecutionPayloadHeader) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecutionPayloadHeader.ProtoReflect.Descriptor instead. func (*ExecutionPayloadHeader) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{7} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{5} } func (x *ExecutionPayloadHeader) GetParentHash() []byte { @@ -1138,7 +868,7 @@ type ExecutionPayloadHeaderCapella struct { func (x *ExecutionPayloadHeaderCapella) Reset() { *x = ExecutionPayloadHeaderCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[8] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1151,7 +881,7 @@ func (x *ExecutionPayloadHeaderCapella) String() string { func (*ExecutionPayloadHeaderCapella) ProtoMessage() {} func (x *ExecutionPayloadHeaderCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[8] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1164,7 +894,7 @@ func (x *ExecutionPayloadHeaderCapella) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecutionPayloadHeaderCapella.ProtoReflect.Descriptor instead. func (*ExecutionPayloadHeaderCapella) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{8} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{6} } func (x *ExecutionPayloadHeaderCapella) GetParentHash() []byte { @@ -1299,7 +1029,7 @@ type ExecutionPayloadHeaderDeneb struct { func (x *ExecutionPayloadHeaderDeneb) Reset() { *x = ExecutionPayloadHeaderDeneb{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[9] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1312,7 +1042,7 @@ func (x *ExecutionPayloadHeaderDeneb) String() string { func (*ExecutionPayloadHeaderDeneb) ProtoMessage() {} func (x *ExecutionPayloadHeaderDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[9] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1325,7 +1055,7 @@ func (x *ExecutionPayloadHeaderDeneb) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecutionPayloadHeaderDeneb.ProtoReflect.Descriptor instead. func (*ExecutionPayloadHeaderDeneb) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{9} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{7} } func (x *ExecutionPayloadHeaderDeneb) GetParentHash() []byte { @@ -1447,50 +1177,33 @@ func (x *ExecutionPayloadHeaderDeneb) GetExcessBlobGas() uint64 { return 0 } -type ExecutionPayloadHeaderElectra struct { +type PayloadAttributes struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ParentHash []byte `protobuf:"bytes,1,opt,name=parent_hash,json=parentHash,proto3" json:"parent_hash,omitempty" ssz-size:"32"` - FeeRecipient []byte `protobuf:"bytes,2,opt,name=fee_recipient,json=feeRecipient,proto3" json:"fee_recipient,omitempty" ssz-size:"20"` - StateRoot []byte `protobuf:"bytes,3,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - ReceiptsRoot []byte `protobuf:"bytes,4,opt,name=receipts_root,json=receiptsRoot,proto3" json:"receipts_root,omitempty" ssz-size:"32"` - LogsBloom []byte `protobuf:"bytes,5,opt,name=logs_bloom,json=logsBloom,proto3" json:"logs_bloom,omitempty" ssz-size:"256"` - PrevRandao []byte `protobuf:"bytes,6,opt,name=prev_randao,json=prevRandao,proto3" json:"prev_randao,omitempty" ssz-size:"32"` - BlockNumber uint64 `protobuf:"varint,7,opt,name=block_number,json=blockNumber,proto3" json:"block_number,omitempty"` - GasLimit uint64 `protobuf:"varint,8,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` - GasUsed uint64 `protobuf:"varint,9,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"` - Timestamp uint64 `protobuf:"varint,10,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - ExtraData []byte `protobuf:"bytes,11,opt,name=extra_data,json=extraData,proto3" json:"extra_data,omitempty" ssz-max:"32"` - BaseFeePerGas []byte `protobuf:"bytes,12,opt,name=base_fee_per_gas,json=baseFeePerGas,proto3" json:"base_fee_per_gas,omitempty" ssz-size:"32"` - BlockHash []byte `protobuf:"bytes,13,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty" ssz-size:"32"` - TransactionsRoot []byte `protobuf:"bytes,14,opt,name=transactions_root,json=transactionsRoot,proto3" json:"transactions_root,omitempty" ssz-size:"32"` - WithdrawalsRoot []byte `protobuf:"bytes,15,opt,name=withdrawals_root,json=withdrawalsRoot,proto3" json:"withdrawals_root,omitempty" ssz-size:"32"` - BlobGasUsed uint64 `protobuf:"varint,16,opt,name=blob_gas_used,json=blobGasUsed,proto3" json:"blob_gas_used,omitempty"` - ExcessBlobGas uint64 `protobuf:"varint,17,opt,name=excess_blob_gas,json=excessBlobGas,proto3" json:"excess_blob_gas,omitempty"` - DepositRequestsRoot []byte `protobuf:"bytes,18,opt,name=deposit_requests_root,json=depositRequestsRoot,proto3" json:"deposit_requests_root,omitempty" ssz-size:"32"` - WithdrawalRequestsRoot []byte `protobuf:"bytes,19,opt,name=withdrawal_requests_root,json=withdrawalRequestsRoot,proto3" json:"withdrawal_requests_root,omitempty" ssz-size:"32"` - ConsolidationRequestsRoot []byte `protobuf:"bytes,20,opt,name=consolidation_requests_root,json=consolidationRequestsRoot,proto3" json:"consolidation_requests_root,omitempty" ssz-size:"32"` -} - -func (x *ExecutionPayloadHeaderElectra) Reset() { - *x = ExecutionPayloadHeaderElectra{} + Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + PrevRandao []byte `protobuf:"bytes,2,opt,name=prev_randao,json=prevRandao,proto3" json:"prev_randao,omitempty" ssz-size:"32"` + SuggestedFeeRecipient []byte `protobuf:"bytes,3,opt,name=suggested_fee_recipient,json=suggestedFeeRecipient,proto3" json:"suggested_fee_recipient,omitempty" ssz-size:"20"` +} + +func (x *PayloadAttributes) Reset() { + *x = PayloadAttributes{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[10] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *ExecutionPayloadHeaderElectra) String() string { +func (x *PayloadAttributes) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ExecutionPayloadHeaderElectra) ProtoMessage() {} +func (*PayloadAttributes) ProtoMessage() {} -func (x *ExecutionPayloadHeaderElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[10] +func (x *PayloadAttributes) ProtoReflect() protoreflect.Message { + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1501,201 +1214,19 @@ func (x *ExecutionPayloadHeaderElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ExecutionPayloadHeaderElectra.ProtoReflect.Descriptor instead. -func (*ExecutionPayloadHeaderElectra) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{10} +// Deprecated: Use PayloadAttributes.ProtoReflect.Descriptor instead. +func (*PayloadAttributes) Descriptor() ([]byte, []int) { + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{8} } -func (x *ExecutionPayloadHeaderElectra) GetParentHash() []byte { +func (x *PayloadAttributes) GetTimestamp() uint64 { if x != nil { - return x.ParentHash + return x.Timestamp } - return nil + return 0 } -func (x *ExecutionPayloadHeaderElectra) GetFeeRecipient() []byte { - if x != nil { - return x.FeeRecipient - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetReceiptsRoot() []byte { - if x != nil { - return x.ReceiptsRoot - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetLogsBloom() []byte { - if x != nil { - return x.LogsBloom - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetPrevRandao() []byte { - if x != nil { - return x.PrevRandao - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetBlockNumber() uint64 { - if x != nil { - return x.BlockNumber - } - return 0 -} - -func (x *ExecutionPayloadHeaderElectra) GetGasLimit() uint64 { - if x != nil { - return x.GasLimit - } - return 0 -} - -func (x *ExecutionPayloadHeaderElectra) GetGasUsed() uint64 { - if x != nil { - return x.GasUsed - } - return 0 -} - -func (x *ExecutionPayloadHeaderElectra) GetTimestamp() uint64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *ExecutionPayloadHeaderElectra) GetExtraData() []byte { - if x != nil { - return x.ExtraData - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetBaseFeePerGas() []byte { - if x != nil { - return x.BaseFeePerGas - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetBlockHash() []byte { - if x != nil { - return x.BlockHash - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetTransactionsRoot() []byte { - if x != nil { - return x.TransactionsRoot - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetWithdrawalsRoot() []byte { - if x != nil { - return x.WithdrawalsRoot - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetBlobGasUsed() uint64 { - if x != nil { - return x.BlobGasUsed - } - return 0 -} - -func (x *ExecutionPayloadHeaderElectra) GetExcessBlobGas() uint64 { - if x != nil { - return x.ExcessBlobGas - } - return 0 -} - -func (x *ExecutionPayloadHeaderElectra) GetDepositRequestsRoot() []byte { - if x != nil { - return x.DepositRequestsRoot - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetWithdrawalRequestsRoot() []byte { - if x != nil { - return x.WithdrawalRequestsRoot - } - return nil -} - -func (x *ExecutionPayloadHeaderElectra) GetConsolidationRequestsRoot() []byte { - if x != nil { - return x.ConsolidationRequestsRoot - } - return nil -} - -type PayloadAttributes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Timestamp uint64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - PrevRandao []byte `protobuf:"bytes,2,opt,name=prev_randao,json=prevRandao,proto3" json:"prev_randao,omitempty" ssz-size:"32"` - SuggestedFeeRecipient []byte `protobuf:"bytes,3,opt,name=suggested_fee_recipient,json=suggestedFeeRecipient,proto3" json:"suggested_fee_recipient,omitempty" ssz-size:"20"` -} - -func (x *PayloadAttributes) Reset() { - *x = PayloadAttributes{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PayloadAttributes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PayloadAttributes) ProtoMessage() {} - -func (x *PayloadAttributes) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PayloadAttributes.ProtoReflect.Descriptor instead. -func (*PayloadAttributes) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{11} -} - -func (x *PayloadAttributes) GetTimestamp() uint64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *PayloadAttributes) GetPrevRandao() []byte { +func (x *PayloadAttributes) GetPrevRandao() []byte { if x != nil { return x.PrevRandao } @@ -1723,7 +1254,7 @@ type PayloadAttributesV2 struct { func (x *PayloadAttributesV2) Reset() { *x = PayloadAttributesV2{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[12] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1736,7 +1267,7 @@ func (x *PayloadAttributesV2) String() string { func (*PayloadAttributesV2) ProtoMessage() {} func (x *PayloadAttributesV2) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[12] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1749,7 +1280,7 @@ func (x *PayloadAttributesV2) ProtoReflect() protoreflect.Message { // Deprecated: Use PayloadAttributesV2.ProtoReflect.Descriptor instead. func (*PayloadAttributesV2) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{12} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{9} } func (x *PayloadAttributesV2) GetTimestamp() uint64 { @@ -1795,7 +1326,7 @@ type PayloadAttributesV3 struct { func (x *PayloadAttributesV3) Reset() { *x = PayloadAttributesV3{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[13] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1808,7 +1339,7 @@ func (x *PayloadAttributesV3) String() string { func (*PayloadAttributesV3) ProtoMessage() {} func (x *PayloadAttributesV3) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[13] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1821,7 +1352,7 @@ func (x *PayloadAttributesV3) ProtoReflect() protoreflect.Message { // Deprecated: Use PayloadAttributesV3.ProtoReflect.Descriptor instead. func (*PayloadAttributesV3) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{13} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{10} } func (x *PayloadAttributesV3) GetTimestamp() uint64 { @@ -1872,7 +1403,7 @@ type PayloadStatus struct { func (x *PayloadStatus) Reset() { *x = PayloadStatus{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[14] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1885,7 +1416,7 @@ func (x *PayloadStatus) String() string { func (*PayloadStatus) ProtoMessage() {} func (x *PayloadStatus) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[14] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1898,7 +1429,7 @@ func (x *PayloadStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use PayloadStatus.ProtoReflect.Descriptor instead. func (*PayloadStatus) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{14} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{11} } func (x *PayloadStatus) GetStatus() PayloadStatus_Status { @@ -1935,7 +1466,7 @@ type ForkchoiceState struct { func (x *ForkchoiceState) Reset() { *x = ForkchoiceState{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[15] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1948,7 +1479,7 @@ func (x *ForkchoiceState) String() string { func (*ForkchoiceState) ProtoMessage() {} func (x *ForkchoiceState) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[15] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1961,7 +1492,7 @@ func (x *ForkchoiceState) ProtoReflect() protoreflect.Message { // Deprecated: Use ForkchoiceState.ProtoReflect.Descriptor instead. func (*ForkchoiceState) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{15} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{12} } func (x *ForkchoiceState) GetHeadBlockHash() []byte { @@ -1999,7 +1530,7 @@ type Withdrawal struct { func (x *Withdrawal) Reset() { *x = Withdrawal{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[16] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2012,7 +1543,7 @@ func (x *Withdrawal) String() string { func (*Withdrawal) ProtoMessage() {} func (x *Withdrawal) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[16] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2025,7 +1556,7 @@ func (x *Withdrawal) ProtoReflect() protoreflect.Message { // Deprecated: Use Withdrawal.ProtoReflect.Descriptor instead. func (*Withdrawal) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{16} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{13} } func (x *Withdrawal) GetIndex() uint64 { @@ -2069,7 +1600,7 @@ type BlobsBundle struct { func (x *BlobsBundle) Reset() { *x = BlobsBundle{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[17] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2082,7 +1613,7 @@ func (x *BlobsBundle) String() string { func (*BlobsBundle) ProtoMessage() {} func (x *BlobsBundle) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[17] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2095,7 +1626,7 @@ func (x *BlobsBundle) ProtoReflect() protoreflect.Message { // Deprecated: Use BlobsBundle.ProtoReflect.Descriptor instead. func (*BlobsBundle) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{17} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{14} } func (x *BlobsBundle) GetKzgCommitments() [][]byte { @@ -2130,7 +1661,7 @@ type Blob struct { func (x *Blob) Reset() { *x = Blob{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[18] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2143,7 +1674,7 @@ func (x *Blob) String() string { func (*Blob) ProtoMessage() {} func (x *Blob) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[18] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2156,7 +1687,7 @@ func (x *Blob) ProtoReflect() protoreflect.Message { // Deprecated: Use Blob.ProtoReflect.Descriptor instead. func (*Blob) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{18} + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{15} } func (x *Blob) GetData() []byte { @@ -2166,80 +1697,32 @@ func (x *Blob) GetData() []byte { return nil } -type ExchangeCapabilities struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SupportedMethods []string `protobuf:"bytes,1,rep,name=supported_methods,json=supportedMethods,proto3" json:"supported_methods,omitempty"` -} - -func (x *ExchangeCapabilities) Reset() { - *x = ExchangeCapabilities{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ExchangeCapabilities) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ExchangeCapabilities) ProtoMessage() {} - -func (x *ExchangeCapabilities) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ExchangeCapabilities.ProtoReflect.Descriptor instead. -func (*ExchangeCapabilities) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{19} -} - -func (x *ExchangeCapabilities) GetSupportedMethods() []string { - if x != nil { - return x.SupportedMethods - } - return nil -} - -type WithdrawalRequest struct { +type BlobAndProof struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SourceAddress []byte `protobuf:"bytes,1,opt,name=source_address,json=sourceAddress,proto3" json:"source_address,omitempty" ssz-size:"20"` - ValidatorPubkey []byte `protobuf:"bytes,2,opt,name=validator_pubkey,json=validatorPubkey,proto3" json:"validator_pubkey,omitempty" ssz-size:"48"` - Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + Blob []byte `protobuf:"bytes,1,opt,name=blob,proto3" json:"blob,omitempty" ssz-size:"131072"` + KzgProof []byte `protobuf:"bytes,2,opt,name=kzg_proof,json=kzgProof,proto3" json:"kzg_proof,omitempty" ssz-size:"48"` } -func (x *WithdrawalRequest) Reset() { - *x = WithdrawalRequest{} +func (x *BlobAndProof) Reset() { + *x = BlobAndProof{} if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[20] + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *WithdrawalRequest) String() string { +func (x *BlobAndProof) String() string { return protoimpl.X.MessageStringOf(x) } -func (*WithdrawalRequest) ProtoMessage() {} +func (*BlobAndProof) ProtoMessage() {} -func (x *WithdrawalRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[20] +func (x *BlobAndProof) ProtoReflect() protoreflect.Message { + mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2250,175 +1733,26 @@ func (x *WithdrawalRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use WithdrawalRequest.ProtoReflect.Descriptor instead. -func (*WithdrawalRequest) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{20} +// Deprecated: Use BlobAndProof.ProtoReflect.Descriptor instead. +func (*BlobAndProof) Descriptor() ([]byte, []int) { + return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{16} } -func (x *WithdrawalRequest) GetSourceAddress() []byte { +func (x *BlobAndProof) GetBlob() []byte { if x != nil { - return x.SourceAddress + return x.Blob } return nil } -func (x *WithdrawalRequest) GetValidatorPubkey() []byte { +func (x *BlobAndProof) GetKzgProof() []byte { if x != nil { - return x.ValidatorPubkey + return x.KzgProof } return nil } -func (x *WithdrawalRequest) GetAmount() uint64 { - if x != nil { - return x.Amount - } - return 0 -} - -type DepositRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` - WithdrawalCredentials []byte `protobuf:"bytes,2,opt,name=withdrawal_credentials,json=withdrawalCredentials,proto3" json:"withdrawal_credentials,omitempty" ssz-size:"32"` - Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` - Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` - Index uint64 `protobuf:"varint,5,opt,name=index,proto3" json:"index,omitempty"` -} - -func (x *DepositRequest) Reset() { - *x = DepositRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DepositRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DepositRequest) ProtoMessage() {} - -func (x *DepositRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DepositRequest.ProtoReflect.Descriptor instead. -func (*DepositRequest) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{21} -} - -func (x *DepositRequest) GetPubkey() []byte { - if x != nil { - return x.Pubkey - } - return nil -} - -func (x *DepositRequest) GetWithdrawalCredentials() []byte { - if x != nil { - return x.WithdrawalCredentials - } - return nil -} - -func (x *DepositRequest) GetAmount() uint64 { - if x != nil { - return x.Amount - } - return 0 -} - -func (x *DepositRequest) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -func (x *DepositRequest) GetIndex() uint64 { - if x != nil { - return x.Index - } - return 0 -} - -type ConsolidationRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SourceAddress []byte `protobuf:"bytes,1,opt,name=source_address,json=sourceAddress,proto3" json:"source_address,omitempty" ssz-size:"20"` - SourcePubkey []byte `protobuf:"bytes,2,opt,name=source_pubkey,json=sourcePubkey,proto3" json:"source_pubkey,omitempty" ssz-size:"48"` - TargetPubkey []byte `protobuf:"bytes,3,opt,name=target_pubkey,json=targetPubkey,proto3" json:"target_pubkey,omitempty" ssz-size:"48"` -} - -func (x *ConsolidationRequest) Reset() { - *x = ConsolidationRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConsolidationRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConsolidationRequest) ProtoMessage() {} - -func (x *ConsolidationRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConsolidationRequest.ProtoReflect.Descriptor instead. -func (*ConsolidationRequest) Descriptor() ([]byte, []int) { - return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{22} -} - -func (x *ConsolidationRequest) GetSourceAddress() []byte { - if x != nil { - return x.SourceAddress - } - return nil -} - -func (x *ConsolidationRequest) GetSourcePubkey() []byte { - if x != nil { - return x.SourcePubkey - } - return nil -} - -func (x *ConsolidationRequest) GetTargetPubkey() []byte { - if x != nil { - return x.TargetPubkey - } - return nil -} - -var File_proto_engine_v1_execution_engine_proto protoreflect.FileDescriptor +var File_proto_engine_v1_execution_engine_proto protoreflect.FileDescriptor var file_proto_engine_v1_execution_engine_proto_rawDesc = []byte{ 0x0a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, @@ -2551,191 +1885,70 @@ var file_proto_engine_v1_execution_engine_proto_rawDesc = []byte{ 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, 0x42, - 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x22, 0x86, 0x08, 0x0a, 0x17, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, - 0x72, 0x61, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x0d, 0x66, - 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, - 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, - 0x2b, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, - 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x26, 0x0a, 0x0a, - 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x07, 0x8a, 0xb5, 0x18, 0x03, 0x32, 0x35, 0x36, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x73, 0x42, - 0x6c, 0x6f, 0x6f, 0x6d, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, - 0x64, 0x61, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x21, 0x0a, - 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x25, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, - 0x33, 0x32, 0x52, 0x09, 0x65, 0x78, 0x74, 0x72, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, - 0x10, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x67, 0x61, - 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x0d, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x50, 0x65, 0x72, 0x47, 0x61, 0x73, 0x12, 0x25, - 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x41, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x1d, 0x8a, 0xb5, 0x18, - 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18, 0x12, 0x31, 0x30, 0x34, 0x38, 0x35, 0x37, 0x36, 0x2c, - 0x31, 0x30, 0x37, 0x33, 0x37, 0x34, 0x31, 0x38, 0x32, 0x34, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x48, 0x0a, 0x0b, 0x77, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x42, 0x06, 0x92, - 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, - 0x6c, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x75, - 0x73, 0x65, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x47, - 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0d, 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, 0x42, 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x12, 0x57, - 0x0a, 0x10, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x08, 0x92, 0xb5, - 0x18, 0x04, 0x38, 0x31, 0x39, 0x32, 0x52, 0x0f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x5e, 0x0a, 0x13, 0x77, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x13, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, - 0x02, 0x31, 0x36, 0x52, 0x12, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x66, 0x0a, 0x16, 0x63, 0x6f, 0x6e, 0x73, 0x6f, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, - 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x31, 0x52, 0x15, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, - 0x89, 0x02, 0x0a, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x57, 0x69, 0x74, 0x68, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x41, 0x6e, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, - 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x42, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x73, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x6f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x22, 0x7f, 0x0a, 0x20, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, - 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x57, 0x69, 0x74, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x45, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x07, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x85, 0x02, 0x0a, - 0x2c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x57, 0x69, 0x74, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x41, - 0x6e, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x43, 0x0a, - 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x42, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x62, - 0x73, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, - 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x36, 0x0a, 0x17, - 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x73, - 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x75, 0x69, - 0x6c, 0x64, 0x65, 0x72, 0x22, 0xc0, 0x04, 0x0a, 0x16, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, - 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, - 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x0d, - 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x72, 0x65, 0x63, - 0x65, 0x69, 0x70, 0x74, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, - 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x07, 0x8a, - 0xb5, 0x18, 0x03, 0x32, 0x35, 0x36, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x73, 0x42, 0x6c, 0x6f, 0x6f, - 0x6d, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, - 0x70, 0x72, 0x65, 0x76, 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x0a, - 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, - 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, - 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x12, 0x25, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x09, 0x65, 0x78, 0x74, 0x72, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x10, 0x62, 0x61, - 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x0c, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x62, 0x61, - 0x73, 0x65, 0x46, 0x65, 0x65, 0x50, 0x65, 0x72, 0x47, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x33, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xfa, 0x04, 0x0a, 0x1d, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, - 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, - 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, - 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x52, - 0x6f, 0x6f, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x6f, - 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x07, 0x8a, 0xb5, 0x18, 0x03, 0x32, 0x35, 0x36, - 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x73, 0x42, 0x6c, 0x6f, 0x6f, 0x6d, 0x12, 0x27, 0x0a, 0x0b, 0x70, - 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x52, 0x61, - 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, - 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, - 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, - 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x25, 0x0a, - 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x65, 0x78, 0x74, 0x72, 0x61, - 0x44, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x10, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, - 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x50, - 0x65, 0x72, 0x47, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x33, 0x0a, 0x11, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x6f, 0x6f, - 0x74, 0x12, 0x31, 0x0a, 0x10, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x0f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xc4, 0x05, 0x0a, 0x1b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, - 0x65, 0x6e, 0x65, 0x62, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, + 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x22, 0x7f, 0x0a, 0x20, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, + 0x61, 0x57, 0x69, 0x74, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x85, 0x02, 0x0a, 0x2c, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x6e, 0x65, + 0x62, 0x57, 0x69, 0x74, 0x68, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x41, 0x6e, 0x64, 0x42, 0x6c, 0x6f, + 0x62, 0x73, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x43, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, + 0x65, 0x6e, 0x65, 0x62, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x42, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x5f, 0x62, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x62, + 0x73, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x68, 0x6f, 0x75, 0x6c, + 0x64, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x22, + 0xc0, 0x04, 0x0a, 0x16, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x32, 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, + 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x65, 0x69, + 0x70, 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, + 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x62, 0x6c, 0x6f, + 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x07, 0x8a, 0xb5, 0x18, 0x03, 0x32, 0x35, + 0x36, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x73, 0x42, 0x6c, 0x6f, 0x6f, 0x6d, 0x12, 0x27, 0x0a, 0x0b, + 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x52, + 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, + 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x25, + 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x65, 0x78, 0x74, 0x72, + 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x10, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, + 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, + 0x50, 0x65, 0x72, 0x47, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, + 0x68, 0x61, 0x73, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x33, 0x0a, + 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x72, 0x6f, + 0x6f, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x6f, + 0x6f, 0x74, 0x22, 0xfa, 0x04, 0x0a, 0x1d, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, + 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, @@ -2772,212 +1985,165 @@ var file_proto_engine_v1_execution_engine_proto_rawDesc = []byte{ 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x31, 0x0a, 0x10, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, - 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, - 0x22, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x55, - 0x73, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x62, 0x6c, - 0x6f, 0x62, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x78, - 0x63, 0x65, 0x73, 0x73, 0x42, 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x22, 0x8c, 0x07, 0x0a, 0x1d, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x27, 0x0a, - 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, - 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x65, - 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x70, 0x74, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x73, 0x5f, - 0x62, 0x6c, 0x6f, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x07, 0x8a, 0xb5, 0x18, - 0x03, 0x32, 0x35, 0x36, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x73, 0x42, 0x6c, 0x6f, 0x6f, 0x6d, 0x12, - 0x27, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x72, - 0x65, 0x76, 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x67, - 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, - 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, 0x73, 0x5f, - 0x75, 0x73, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, 0x73, 0x55, - 0x73, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x25, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x65, - 0x78, 0x74, 0x72, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x10, 0x62, 0x61, 0x73, 0x65, - 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x62, 0x61, 0x73, 0x65, - 0x46, 0x65, 0x65, 0x50, 0x65, 0x72, 0x47, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, - 0x12, 0x33, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x31, 0x0a, 0x10, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x62, - 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x26, 0x0a, 0x0f, - 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x67, 0x61, 0x73, 0x18, - 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, 0x42, 0x6c, 0x6f, - 0x62, 0x47, 0x61, 0x73, 0x12, 0x3a, 0x0a, 0x15, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x13, 0x64, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x52, 0x6f, 0x6f, 0x74, - 0x12, 0x40, 0x0a, 0x18, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x13, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x16, 0x77, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x52, 0x6f, - 0x6f, 0x74, 0x12, 0x46, 0x0a, 0x1b, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x19, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x9a, 0x01, 0x0a, 0x11, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x27, - 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x72, 0x65, - 0x76, 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x3e, 0x0a, 0x17, 0x73, 0x75, 0x67, 0x67, 0x65, - 0x73, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, - 0x52, 0x15, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x46, 0x65, 0x65, 0x52, 0x65, - 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x22, 0xe6, 0x01, 0x0a, 0x13, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x56, 0x32, 0x12, - 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x27, 0x0a, - 0x0b, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, - 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x3e, 0x0a, 0x17, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, - 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, - 0x15, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x48, 0x0a, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x42, 0x06, 0x92, 0xb5, 0x18, - 0x02, 0x31, 0x36, 0x52, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, - 0x22, 0xa7, 0x02, 0x0a, 0x13, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x56, 0x33, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, - 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, - 0x3e, 0x0a, 0x17, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x65, - 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x15, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, - 0x74, 0x65, 0x64, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, - 0x48, 0x0a, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0b, 0x77, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x12, 0x3f, 0x0a, 0x18, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x15, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x92, 0x02, 0x0a, 0x0d, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x40, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x32, - 0x0a, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x60, 0x0a, - 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, - 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x01, 0x12, - 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, - 0x53, 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, - 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x56, 0x41, 0x4c, - 0x49, 0x44, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x05, 0x22, - 0xab, 0x01, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x6b, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x68, 0x65, 0x61, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, - 0x61, 0x73, 0x68, 0x12, 0x2e, 0x0a, 0x0f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x73, 0x61, 0x66, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, - 0x61, 0x73, 0x68, 0x12, 0x38, 0x0a, 0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0xd6, 0x01, - 0x0a, 0x0a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, - 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x62, 0x73, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x0f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, - 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, - 0x36, 0x52, 0x0e, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x28, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, - 0x30, 0x39, 0x36, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, - 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, - 0x3f, 0x2c, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, - 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0x26, 0x0a, 0x04, 0x42, 0x6c, 0x6f, 0x62, 0x12, - 0x1e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0x8a, - 0xb5, 0x18, 0x06, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, - 0x43, 0x0a, 0x14, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x61, 0x70, 0x61, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, - 0x72, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x11, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x0e, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x31, 0x0a, 0x10, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0f, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc3, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, - 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x15, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, 0x72, 0x65, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x9f, 0x01, 0x0a, 0x14, 0x43, - 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x32, 0x30, 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x2b, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, - 0x38, 0x52, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, - 0x2b, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0c, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x42, 0x96, 0x01, 0x0a, - 0x16, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, - 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, - 0x76, 0x31, 0x3b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x76, 0x31, 0xaa, 0x02, 0x12, 0x45, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x56, 0x31, - 0xca, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, + 0xc4, 0x05, 0x0a, 0x1b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, + 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, + 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, + 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, + 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, + 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x0d, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x72, 0x65, 0x63, + 0x65, 0x69, 0x70, 0x74, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, + 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x07, 0x8a, + 0xb5, 0x18, 0x03, 0x32, 0x35, 0x36, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x73, 0x42, 0x6c, 0x6f, 0x6f, + 0x6d, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, + 0x70, 0x72, 0x65, 0x76, 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x0a, + 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x61, + 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x67, 0x61, + 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x25, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, + 0x09, 0x65, 0x78, 0x74, 0x72, 0x61, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x10, 0x62, 0x61, + 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x67, 0x61, 0x73, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x62, 0x61, + 0x73, 0x65, 0x46, 0x65, 0x65, 0x50, 0x65, 0x72, 0x47, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, + 0x73, 0x68, 0x12, 0x33, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x31, 0x0a, 0x10, 0x77, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x77, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x6c, + 0x6f, 0x62, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x26, + 0x0a, 0x0f, 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x67, 0x61, + 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x65, 0x73, 0x73, 0x42, + 0x6c, 0x6f, 0x62, 0x47, 0x61, 0x73, 0x22, 0x9a, 0x01, 0x0a, 0x11, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x72, + 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x52, 0x61, 0x6e, + 0x64, 0x61, 0x6f, 0x12, 0x3e, 0x0a, 0x17, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, + 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x15, 0x73, 0x75, + 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x22, 0xe6, 0x01, 0x0a, 0x13, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x56, 0x32, 0x12, 0x1c, 0x0a, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x72, 0x65, + 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x52, 0x61, 0x6e, 0x64, + 0x61, 0x6f, 0x12, 0x3e, 0x0a, 0x17, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, + 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x15, 0x73, 0x75, 0x67, + 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x12, 0x48, 0x0a, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, + 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x22, 0xa7, 0x02, 0x0a, + 0x13, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x56, 0x33, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x61, 0x6e, 0x64, 0x61, + 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, + 0x0a, 0x70, 0x72, 0x65, 0x76, 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x12, 0x3e, 0x0a, 0x17, 0x73, + 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, + 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x32, 0x30, 0x52, 0x15, 0x73, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x65, 0x64, 0x46, + 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x48, 0x0a, 0x0b, 0x77, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, + 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0b, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, + 0x61, 0x77, 0x61, 0x6c, 0x73, 0x12, 0x3f, 0x0a, 0x18, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, + 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, + 0x15, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x92, 0x02, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x40, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x32, 0x0a, 0x11, 0x6c, 0x61, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x29, + 0x0a, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x60, 0x0a, 0x06, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x09, 0x0a, 0x05, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x49, + 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x59, 0x4e, 0x43, + 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, + 0x44, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x42, + 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x05, 0x22, 0xab, 0x01, 0x0a, 0x0f, + 0x46, 0x6f, 0x72, 0x6b, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x2e, 0x0a, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x0d, 0x68, 0x65, 0x61, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x2e, 0x0a, 0x0f, 0x73, 0x61, 0x66, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x0d, 0x73, 0x61, 0x66, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x38, 0x0a, 0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x22, 0xd6, 0x01, 0x0a, 0x0a, 0x57, 0x69, + 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x78, + 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, + 0x30, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x0f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, + 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x0e, 0x6b, + 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x28, 0x0a, + 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, + 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, + 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, + 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, + 0x6f, 0x62, 0x73, 0x22, 0x26, 0x0a, 0x04, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x1e, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x06, 0x31, + 0x33, 0x31, 0x30, 0x37, 0x32, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x53, 0x0a, 0x0c, 0x42, + 0x6c, 0x6f, 0x62, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x1e, 0x0a, 0x04, 0x62, + 0x6c, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x06, 0x31, + 0x33, 0x31, 0x30, 0x37, 0x32, 0x52, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x12, 0x23, 0x0a, 0x09, 0x6b, + 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x08, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, + 0x42, 0x96, 0x01, 0x0a, 0x16, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x76, 0x31, 0xaa, + 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e, + 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, + 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -2993,53 +2159,41 @@ func file_proto_engine_v1_execution_engine_proto_rawDescGZIP() []byte { } var file_proto_engine_v1_execution_engine_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_engine_v1_execution_engine_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_proto_engine_v1_execution_engine_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_proto_engine_v1_execution_engine_proto_goTypes = []interface{}{ - (PayloadStatus_Status)(0), // 0: ethereum.engine.v1.PayloadStatus.Status - (*ExecutionPayload)(nil), // 1: ethereum.engine.v1.ExecutionPayload - (*ExecutionPayloadCapella)(nil), // 2: ethereum.engine.v1.ExecutionPayloadCapella - (*ExecutionPayloadDeneb)(nil), // 3: ethereum.engine.v1.ExecutionPayloadDeneb - (*ExecutionPayloadElectra)(nil), // 4: ethereum.engine.v1.ExecutionPayloadElectra - (*ExecutionPayloadElectraWithValueAndBlobsBundle)(nil), // 5: ethereum.engine.v1.ExecutionPayloadElectraWithValueAndBlobsBundle - (*ExecutionPayloadCapellaWithValue)(nil), // 6: ethereum.engine.v1.ExecutionPayloadCapellaWithValue - (*ExecutionPayloadDenebWithValueAndBlobsBundle)(nil), // 7: ethereum.engine.v1.ExecutionPayloadDenebWithValueAndBlobsBundle - (*ExecutionPayloadHeader)(nil), // 8: ethereum.engine.v1.ExecutionPayloadHeader - (*ExecutionPayloadHeaderCapella)(nil), // 9: ethereum.engine.v1.ExecutionPayloadHeaderCapella - (*ExecutionPayloadHeaderDeneb)(nil), // 10: ethereum.engine.v1.ExecutionPayloadHeaderDeneb - (*ExecutionPayloadHeaderElectra)(nil), // 11: ethereum.engine.v1.ExecutionPayloadHeaderElectra - (*PayloadAttributes)(nil), // 12: ethereum.engine.v1.PayloadAttributes - (*PayloadAttributesV2)(nil), // 13: ethereum.engine.v1.PayloadAttributesV2 - (*PayloadAttributesV3)(nil), // 14: ethereum.engine.v1.PayloadAttributesV3 - (*PayloadStatus)(nil), // 15: ethereum.engine.v1.PayloadStatus - (*ForkchoiceState)(nil), // 16: ethereum.engine.v1.ForkchoiceState - (*Withdrawal)(nil), // 17: ethereum.engine.v1.Withdrawal - (*BlobsBundle)(nil), // 18: ethereum.engine.v1.BlobsBundle - (*Blob)(nil), // 19: ethereum.engine.v1.Blob - (*ExchangeCapabilities)(nil), // 20: ethereum.engine.v1.ExchangeCapabilities - (*WithdrawalRequest)(nil), // 21: ethereum.engine.v1.WithdrawalRequest - (*DepositRequest)(nil), // 22: ethereum.engine.v1.DepositRequest - (*ConsolidationRequest)(nil), // 23: ethereum.engine.v1.ConsolidationRequest + (PayloadStatus_Status)(0), // 0: ethereum.engine.v1.PayloadStatus.Status + (*ExecutionPayload)(nil), // 1: ethereum.engine.v1.ExecutionPayload + (*ExecutionPayloadCapella)(nil), // 2: ethereum.engine.v1.ExecutionPayloadCapella + (*ExecutionPayloadDeneb)(nil), // 3: ethereum.engine.v1.ExecutionPayloadDeneb + (*ExecutionPayloadCapellaWithValue)(nil), // 4: ethereum.engine.v1.ExecutionPayloadCapellaWithValue + (*ExecutionPayloadDenebWithValueAndBlobsBundle)(nil), // 5: ethereum.engine.v1.ExecutionPayloadDenebWithValueAndBlobsBundle + (*ExecutionPayloadHeader)(nil), // 6: ethereum.engine.v1.ExecutionPayloadHeader + (*ExecutionPayloadHeaderCapella)(nil), // 7: ethereum.engine.v1.ExecutionPayloadHeaderCapella + (*ExecutionPayloadHeaderDeneb)(nil), // 8: ethereum.engine.v1.ExecutionPayloadHeaderDeneb + (*PayloadAttributes)(nil), // 9: ethereum.engine.v1.PayloadAttributes + (*PayloadAttributesV2)(nil), // 10: ethereum.engine.v1.PayloadAttributesV2 + (*PayloadAttributesV3)(nil), // 11: ethereum.engine.v1.PayloadAttributesV3 + (*PayloadStatus)(nil), // 12: ethereum.engine.v1.PayloadStatus + (*ForkchoiceState)(nil), // 13: ethereum.engine.v1.ForkchoiceState + (*Withdrawal)(nil), // 14: ethereum.engine.v1.Withdrawal + (*BlobsBundle)(nil), // 15: ethereum.engine.v1.BlobsBundle + (*Blob)(nil), // 16: ethereum.engine.v1.Blob + (*BlobAndProof)(nil), // 17: ethereum.engine.v1.BlobAndProof } var file_proto_engine_v1_execution_engine_proto_depIdxs = []int32{ - 17, // 0: ethereum.engine.v1.ExecutionPayloadCapella.withdrawals:type_name -> ethereum.engine.v1.Withdrawal - 17, // 1: ethereum.engine.v1.ExecutionPayloadDeneb.withdrawals:type_name -> ethereum.engine.v1.Withdrawal - 17, // 2: ethereum.engine.v1.ExecutionPayloadElectra.withdrawals:type_name -> ethereum.engine.v1.Withdrawal - 22, // 3: ethereum.engine.v1.ExecutionPayloadElectra.deposit_requests:type_name -> ethereum.engine.v1.DepositRequest - 21, // 4: ethereum.engine.v1.ExecutionPayloadElectra.withdrawal_requests:type_name -> ethereum.engine.v1.WithdrawalRequest - 23, // 5: ethereum.engine.v1.ExecutionPayloadElectra.consolidation_requests:type_name -> ethereum.engine.v1.ConsolidationRequest - 4, // 6: ethereum.engine.v1.ExecutionPayloadElectraWithValueAndBlobsBundle.payload:type_name -> ethereum.engine.v1.ExecutionPayloadElectra - 18, // 7: ethereum.engine.v1.ExecutionPayloadElectraWithValueAndBlobsBundle.blobs_bundle:type_name -> ethereum.engine.v1.BlobsBundle - 2, // 8: ethereum.engine.v1.ExecutionPayloadCapellaWithValue.payload:type_name -> ethereum.engine.v1.ExecutionPayloadCapella - 3, // 9: ethereum.engine.v1.ExecutionPayloadDenebWithValueAndBlobsBundle.payload:type_name -> ethereum.engine.v1.ExecutionPayloadDeneb - 18, // 10: ethereum.engine.v1.ExecutionPayloadDenebWithValueAndBlobsBundle.blobs_bundle:type_name -> ethereum.engine.v1.BlobsBundle - 17, // 11: ethereum.engine.v1.PayloadAttributesV2.withdrawals:type_name -> ethereum.engine.v1.Withdrawal - 17, // 12: ethereum.engine.v1.PayloadAttributesV3.withdrawals:type_name -> ethereum.engine.v1.Withdrawal - 0, // 13: ethereum.engine.v1.PayloadStatus.status:type_name -> ethereum.engine.v1.PayloadStatus.Status - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 14, // 0: ethereum.engine.v1.ExecutionPayloadCapella.withdrawals:type_name -> ethereum.engine.v1.Withdrawal + 14, // 1: ethereum.engine.v1.ExecutionPayloadDeneb.withdrawals:type_name -> ethereum.engine.v1.Withdrawal + 2, // 2: ethereum.engine.v1.ExecutionPayloadCapellaWithValue.payload:type_name -> ethereum.engine.v1.ExecutionPayloadCapella + 3, // 3: ethereum.engine.v1.ExecutionPayloadDenebWithValueAndBlobsBundle.payload:type_name -> ethereum.engine.v1.ExecutionPayloadDeneb + 15, // 4: ethereum.engine.v1.ExecutionPayloadDenebWithValueAndBlobsBundle.blobs_bundle:type_name -> ethereum.engine.v1.BlobsBundle + 14, // 5: ethereum.engine.v1.PayloadAttributesV2.withdrawals:type_name -> ethereum.engine.v1.Withdrawal + 14, // 6: ethereum.engine.v1.PayloadAttributesV3.withdrawals:type_name -> ethereum.engine.v1.Withdrawal + 0, // 7: ethereum.engine.v1.PayloadStatus.status:type_name -> ethereum.engine.v1.PayloadStatus.Status + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_proto_engine_v1_execution_engine_proto_init() } @@ -3085,30 +2239,6 @@ func file_proto_engine_v1_execution_engine_proto_init() { } } file_proto_engine_v1_execution_engine_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExecutionPayloadElectra); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_engine_v1_execution_engine_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExecutionPayloadElectraWithValueAndBlobsBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_engine_v1_execution_engine_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExecutionPayloadCapellaWithValue); i { case 0: return &v.state @@ -3120,7 +2250,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExecutionPayloadDenebWithValueAndBlobsBundle); i { case 0: return &v.state @@ -3132,7 +2262,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExecutionPayloadHeader); i { case 0: return &v.state @@ -3144,7 +2274,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExecutionPayloadHeaderCapella); i { case 0: return &v.state @@ -3156,7 +2286,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExecutionPayloadHeaderDeneb); i { case 0: return &v.state @@ -3168,19 +2298,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExecutionPayloadHeaderElectra); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_engine_v1_execution_engine_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PayloadAttributes); i { case 0: return &v.state @@ -3192,7 +2310,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PayloadAttributesV2); i { case 0: return &v.state @@ -3204,7 +2322,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PayloadAttributesV3); i { case 0: return &v.state @@ -3216,7 +2334,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PayloadStatus); i { case 0: return &v.state @@ -3228,7 +2346,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ForkchoiceState); i { case 0: return &v.state @@ -3240,7 +2358,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Withdrawal); i { case 0: return &v.state @@ -3252,7 +2370,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlobsBundle); i { case 0: return &v.state @@ -3264,7 +2382,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_proto_engine_v1_execution_engine_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Blob); i { case 0: return &v.state @@ -3276,44 +2394,8 @@ func file_proto_engine_v1_execution_engine_proto_init() { return nil } } - file_proto_engine_v1_execution_engine_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExchangeCapabilities); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_engine_v1_execution_engine_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WithdrawalRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_engine_v1_execution_engine_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DepositRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_engine_v1_execution_engine_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConsolidationRequest); i { + file_proto_engine_v1_execution_engine_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlobAndProof); i { case 0: return &v.state case 1: @@ -3331,7 +2413,7 @@ func file_proto_engine_v1_execution_engine_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_engine_v1_execution_engine_proto_rawDesc, NumEnums: 1, - NumMessages: 23, + NumMessages: 17, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/engine/v1/execution_engine.proto b/proto/engine/v1/execution_engine.proto index 33e3464410eb..70960d0adf27 100644 --- a/proto/engine/v1/execution_engine.proto +++ b/proto/engine/v1/execution_engine.proto @@ -25,293 +25,232 @@ option java_package = "org.ethereum.engine.v1"; option php_namespace = "Ethereum\\Engine\\v1"; message ExecutionPayload { - bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"]; - bytes state_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes receipts_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes logs_bloom = 5 [(ethereum.eth.ext.ssz_size) = "logs_bloom.size"]; - bytes prev_randao = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 block_number = 7; - uint64 gas_limit = 8; - uint64 gas_used = 9; - uint64 timestamp = 10; - bytes extra_data = 11 [(ethereum.eth.ext.ssz_max) = "extra_data.size"]; - bytes base_fee_per_gas = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes block_hash = 13 [(ethereum.eth.ext.ssz_size) = "32"]; - repeated bytes transactions = 14 [(ethereum.eth.ext.ssz_size) = "?,?", (ethereum.eth.ext.ssz_max) = "1048576,1073741824"]; + bytes parent_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes fee_recipient = 2 [ (ethereum.eth.ext.ssz_size) = "20" ]; + bytes state_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes receipts_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes logs_bloom = 5 [ (ethereum.eth.ext.ssz_size) = "logs_bloom.size" ]; + bytes prev_randao = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 block_number = 7; + uint64 gas_limit = 8; + uint64 gas_used = 9; + uint64 timestamp = 10; + bytes extra_data = 11 [ (ethereum.eth.ext.ssz_max) = "extra_data.size" ]; + bytes base_fee_per_gas = 12 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes block_hash = 13 [ (ethereum.eth.ext.ssz_size) = "32" ]; + repeated bytes transactions = 14 [ + (ethereum.eth.ext.ssz_size) = "?,?", + (ethereum.eth.ext.ssz_max) = "1048576,1073741824" + ]; } message ExecutionPayloadCapella { - bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"]; - bytes state_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes receipts_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes logs_bloom = 5 [(ethereum.eth.ext.ssz_size) = "logs_bloom.size"]; - bytes prev_randao = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 block_number = 7; - uint64 gas_limit = 8; - uint64 gas_used = 9; - uint64 timestamp = 10; - bytes extra_data = 11 [(ethereum.eth.ext.ssz_max) = "extra_data.size"]; - bytes base_fee_per_gas = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes block_hash = 13 [(ethereum.eth.ext.ssz_size) = "32"]; - repeated bytes transactions = 14 [(ethereum.eth.ext.ssz_size) = "?,?", (ethereum.eth.ext.ssz_max) = "1048576,1073741824"]; - // MAX_WITHDRAWALS_PER_PAYLOAD - repeated Withdrawal withdrawals = 15 [(ethereum.eth.ext.ssz_max) = "withdrawal.size"]; // New in Capella. + bytes parent_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes fee_recipient = 2 [ (ethereum.eth.ext.ssz_size) = "20" ]; + bytes state_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes receipts_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes logs_bloom = 5 [ (ethereum.eth.ext.ssz_size) = "logs_bloom.size" ]; + bytes prev_randao = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 block_number = 7; + uint64 gas_limit = 8; + uint64 gas_used = 9; + uint64 timestamp = 10; + bytes extra_data = 11 [ (ethereum.eth.ext.ssz_max) = "extra_data.size" ]; + bytes base_fee_per_gas = 12 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes block_hash = 13 [ (ethereum.eth.ext.ssz_size) = "32" ]; + repeated bytes transactions = 14 [ + (ethereum.eth.ext.ssz_size) = "?,?", + (ethereum.eth.ext.ssz_max) = "1048576,1073741824" + ]; + // MAX_WITHDRAWALS_PER_PAYLOAD + repeated Withdrawal withdrawals = 15 + [ (ethereum.eth.ext.ssz_max) = "withdrawal.size" ]; // New in Capella. } message ExecutionPayloadDeneb { - bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"]; - bytes state_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes receipts_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes logs_bloom = 5 [(ethereum.eth.ext.ssz_size) = "logs_bloom.size"]; - bytes prev_randao = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 block_number = 7; - uint64 gas_limit = 8; - uint64 gas_used = 9; - uint64 timestamp = 10; - bytes extra_data = 11 [(ethereum.eth.ext.ssz_max) = "extra_data.size"]; - bytes base_fee_per_gas = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes block_hash = 13 [(ethereum.eth.ext.ssz_size) = "32"]; - repeated bytes transactions = 14 [(ethereum.eth.ext.ssz_size) = "?,?", (ethereum.eth.ext.ssz_max) = "1048576,1073741824"]; - // MAX_WITHDRAWALS_PER_PAYLOAD - repeated Withdrawal withdrawals = 15 [(ethereum.eth.ext.ssz_max) = "withdrawal.size"]; - uint64 blob_gas_used = 16; - uint64 excess_blob_gas = 17; -} - -message ExecutionPayloadElectra { - bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"]; - bytes state_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes receipts_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes logs_bloom = 5 [(ethereum.eth.ext.ssz_size) = "logs_bloom.size"]; - bytes prev_randao = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 block_number = 7; - uint64 gas_limit = 8; - uint64 gas_used = 9; - uint64 timestamp = 10; - bytes extra_data = 11 [(ethereum.eth.ext.ssz_max) = "extra_data.size"]; - bytes base_fee_per_gas = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes block_hash = 13 [(ethereum.eth.ext.ssz_size) = "32"]; - repeated bytes transactions = 14 [(ethereum.eth.ext.ssz_size) = "?,?", (ethereum.eth.ext.ssz_max) = "1048576,1073741824"]; - // MAX_WITHDRAWALS_PER_PAYLOAD - repeated Withdrawal withdrawals = 15 [(ethereum.eth.ext.ssz_max) = "withdrawal.size"]; - uint64 blob_gas_used = 16; - uint64 excess_blob_gas = 17; - repeated DepositRequest deposit_requests = 18 [(ethereum.eth.ext.ssz_max) = "max_deposit_requests_per_payload.size"]; // new in electra, eip6110 - repeated WithdrawalRequest withdrawal_requests = 19 [(ethereum.eth.ext.ssz_max) = "max_withdrawal_requests_per_payload.size"]; // new in electra, eip7002, eip7251 - repeated ConsolidationRequest consolidation_requests = 20 [(ethereum.eth.ext.ssz_max) = "max_consolidation_requests_per_payload.size"]; // new in electra, eip6110 -} - -message ExecutionPayloadElectraWithValueAndBlobsBundle { - ExecutionPayloadElectra payload = 1; - bytes value = 2; - BlobsBundle blobs_bundle = 3; - bool should_override_builder = 4; + bytes parent_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes fee_recipient = 2 [ (ethereum.eth.ext.ssz_size) = "20" ]; + bytes state_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes receipts_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes logs_bloom = 5 [ (ethereum.eth.ext.ssz_size) = "logs_bloom.size" ]; + bytes prev_randao = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 block_number = 7; + uint64 gas_limit = 8; + uint64 gas_used = 9; + uint64 timestamp = 10; + bytes extra_data = 11 [ (ethereum.eth.ext.ssz_max) = "extra_data.size" ]; + bytes base_fee_per_gas = 12 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes block_hash = 13 [ (ethereum.eth.ext.ssz_size) = "32" ]; + repeated bytes transactions = 14 [ + (ethereum.eth.ext.ssz_size) = "?,?", + (ethereum.eth.ext.ssz_max) = "1048576,1073741824" + ]; + // MAX_WITHDRAWALS_PER_PAYLOAD + repeated Withdrawal withdrawals = 15 + [ (ethereum.eth.ext.ssz_max) = "withdrawal.size" ]; + uint64 blob_gas_used = 16; + uint64 excess_blob_gas = 17; } message ExecutionPayloadCapellaWithValue { - ExecutionPayloadCapella payload = 1; - bytes value = 2; + ExecutionPayloadCapella payload = 1; + bytes value = 2; } message ExecutionPayloadDenebWithValueAndBlobsBundle { - ExecutionPayloadDeneb payload = 1; - bytes value = 2; - BlobsBundle blobs_bundle = 3; - bool should_override_builder = 4; + ExecutionPayloadDeneb payload = 1; + bytes value = 2; + BlobsBundle blobs_bundle = 3; + bool should_override_builder = 4; } - message ExecutionPayloadHeader { - bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"]; - bytes state_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes receipts_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes logs_bloom = 5 [(ethereum.eth.ext.ssz_size) = "logs_bloom.size"]; - bytes prev_randao = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 block_number = 7; - uint64 gas_limit = 8; - uint64 gas_used = 9; - uint64 timestamp = 10; - bytes extra_data = 11 [(ethereum.eth.ext.ssz_max) = "extra_data.size"]; - bytes base_fee_per_gas = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes block_hash = 13 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes transactions_root = 14 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes parent_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes fee_recipient = 2 [ (ethereum.eth.ext.ssz_size) = "20" ]; + bytes state_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes receipts_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes logs_bloom = 5 [ (ethereum.eth.ext.ssz_size) = "logs_bloom.size" ]; + bytes prev_randao = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 block_number = 7; + uint64 gas_limit = 8; + uint64 gas_used = 9; + uint64 timestamp = 10; + bytes extra_data = 11 [ (ethereum.eth.ext.ssz_max) = "extra_data.size" ]; + bytes base_fee_per_gas = 12 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes block_hash = 13 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes transactions_root = 14 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message ExecutionPayloadHeaderCapella { - bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"]; - bytes state_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes receipts_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes logs_bloom = 5 [(ethereum.eth.ext.ssz_size) = "logs_bloom.size"]; - bytes prev_randao = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 block_number = 7; - uint64 gas_limit = 8; - uint64 gas_used = 9; - uint64 timestamp = 10; - bytes extra_data = 11 [(ethereum.eth.ext.ssz_max) = "extra_data.size"]; - bytes base_fee_per_gas = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes block_hash = 13 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes transactions_root = 14 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes withdrawals_root = 15 [(ethereum.eth.ext.ssz_size) = "32"]; // New in Capella. + bytes parent_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes fee_recipient = 2 [ (ethereum.eth.ext.ssz_size) = "20" ]; + bytes state_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes receipts_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes logs_bloom = 5 [ (ethereum.eth.ext.ssz_size) = "logs_bloom.size" ]; + bytes prev_randao = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 block_number = 7; + uint64 gas_limit = 8; + uint64 gas_used = 9; + uint64 timestamp = 10; + bytes extra_data = 11 [ (ethereum.eth.ext.ssz_max) = "extra_data.size" ]; + bytes base_fee_per_gas = 12 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes block_hash = 13 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes transactions_root = 14 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes withdrawals_root = 15 + [ (ethereum.eth.ext.ssz_size) = "32" ]; // New in Capella. } message ExecutionPayloadHeaderDeneb { - bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"]; - bytes state_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes receipts_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes logs_bloom = 5 [(ethereum.eth.ext.ssz_size) = "logs_bloom.size"]; - bytes prev_randao = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 block_number = 7; - uint64 gas_limit = 8; - uint64 gas_used = 9; - uint64 timestamp = 10; - bytes extra_data = 11 [(ethereum.eth.ext.ssz_max) = "extra_data.size"]; - bytes base_fee_per_gas = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes block_hash = 13 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes transactions_root = 14 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes withdrawals_root = 15 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 blob_gas_used = 16; - uint64 excess_blob_gas = 17; -} - -message ExecutionPayloadHeaderElectra { - bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"]; - bytes state_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes receipts_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes logs_bloom = 5 [(ethereum.eth.ext.ssz_size) = "logs_bloom.size"]; - bytes prev_randao = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 block_number = 7; - uint64 gas_limit = 8; - uint64 gas_used = 9; - uint64 timestamp = 10; - bytes extra_data = 11 [(ethereum.eth.ext.ssz_max) = "extra_data.size"]; - bytes base_fee_per_gas = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes block_hash = 13 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes transactions_root = 14 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes withdrawals_root = 15 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 blob_gas_used = 16; - uint64 excess_blob_gas = 17; - bytes deposit_requests_root = 18 [(ethereum.eth.ext.ssz_size) = "32"]; // new in electra, eip6110 - bytes withdrawal_requests_root = 19 [(ethereum.eth.ext.ssz_size) = "32"]; // new in electra, eip7002, eip7251 - bytes consolidation_requests_root = 20 [(ethereum.eth.ext.ssz_size) = "32"]; // new in electra, eip7251 + bytes parent_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes fee_recipient = 2 [ (ethereum.eth.ext.ssz_size) = "20" ]; + bytes state_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes receipts_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes logs_bloom = 5 [ (ethereum.eth.ext.ssz_size) = "logs_bloom.size" ]; + bytes prev_randao = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 block_number = 7; + uint64 gas_limit = 8; + uint64 gas_used = 9; + uint64 timestamp = 10; + bytes extra_data = 11 [ (ethereum.eth.ext.ssz_max) = "extra_data.size" ]; + bytes base_fee_per_gas = 12 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes block_hash = 13 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes transactions_root = 14 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes withdrawals_root = 15 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 blob_gas_used = 16; + uint64 excess_blob_gas = 17; } message PayloadAttributes { - uint64 timestamp = 1; - bytes prev_randao = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes suggested_fee_recipient = 3 [(ethereum.eth.ext.ssz_size) = "20"]; + uint64 timestamp = 1; + bytes prev_randao = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes suggested_fee_recipient = 3 [ (ethereum.eth.ext.ssz_size) = "20" ]; } message PayloadAttributesV2 { - uint64 timestamp = 1; - bytes prev_randao = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes suggested_fee_recipient = 3 [(ethereum.eth.ext.ssz_size) = "20"]; - repeated Withdrawal withdrawals = 4 [(ethereum.eth.ext.ssz_max) = "withdrawal.size"]; // New in Capella. + uint64 timestamp = 1; + bytes prev_randao = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes suggested_fee_recipient = 3 [ (ethereum.eth.ext.ssz_size) = "20" ]; + repeated Withdrawal withdrawals = 4 + [ (ethereum.eth.ext.ssz_max) = "withdrawal.size" ]; // New in Capella. } message PayloadAttributesV3 { - uint64 timestamp = 1; - bytes prev_randao = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes suggested_fee_recipient = 3 [(ethereum.eth.ext.ssz_size) = "20"]; - repeated Withdrawal withdrawals = 4 [(ethereum.eth.ext.ssz_max) = "withdrawal.size"]; - bytes parent_beacon_block_root = 5 [(ethereum.eth.ext.ssz_size) = "32"]; + uint64 timestamp = 1; + bytes prev_randao = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes suggested_fee_recipient = 3 [ (ethereum.eth.ext.ssz_size) = "20" ]; + repeated Withdrawal withdrawals = 4 + [ (ethereum.eth.ext.ssz_max) = "withdrawal.size" ]; + bytes parent_beacon_block_root = 5 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message PayloadStatus { - Status status = 1; - bytes latest_valid_hash = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - string validation_error = 3; - enum Status { - UNKNOWN = 0; - VALID = 1; - INVALID = 2; - SYNCING = 3; - ACCEPTED = 4; - INVALID_BLOCK_HASH = 5; - } + Status status = 1; + bytes latest_valid_hash = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + string validation_error = 3; + enum Status { + UNKNOWN = 0; + VALID = 1; + INVALID = 2; + SYNCING = 3; + ACCEPTED = 4; + INVALID_BLOCK_HASH = 5; + } } message ForkchoiceState { - bytes head_block_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes safe_block_hash = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes finalized_block_hash = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes head_block_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes safe_block_hash = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes finalized_block_hash = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; } // The withdrawal receipt with the recipient address and amount withdrawn message Withdrawal { - // Withdrawal index for accounting purposes - uint64 index = 1; + // Withdrawal index for accounting purposes + uint64 index = 1; - // Validator index for the withdrawal - uint64 validator_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index for the withdrawal + uint64 validator_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; - // The execution address receiving the funds - bytes address = 3 [(ethereum.eth.ext.ssz_size) = "20"]; + // The execution address receiving the funds + bytes address = 3 [ (ethereum.eth.ext.ssz_size) = "20" ]; - // The withdrawn amount in Gwei - uint64 amount = 4; + // The withdrawn amount in Gwei + uint64 amount = 4; } // BlobsBundle is retrieved through engine-api from the execution layer client. -// It consists of the necessary components for constructing a blobs sidecar object to gossip through p2p. +// It consists of the necessary components for constructing a blobs sidecar +// object to gossip through p2p. message BlobsBundle { - // The KZG commitments of the blobs. - repeated bytes kzg_commitments = 1 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; - - // The proofs of the blobs. - repeated bytes proofs = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; - - // The blobs itself. - repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,blob.size", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; + // The KZG commitments of the blobs. + repeated bytes kzg_commitments = 1 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; + + // The proofs of the blobs. + repeated bytes proofs = 2 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; + + // The blobs itself. + repeated bytes blobs = 3 [ + (ethereum.eth.ext.ssz_size) = "?,blob.size", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; } // Blob contains the data that is to be committed on chain. message Blob { - // The blob bytes. - bytes data = 1 [(ethereum.eth.ext.ssz_size) = "blob.size"]; -} - -message ExchangeCapabilities { - repeated string supported_methods = 1; -} - -// WithdrawalRequest is the message from the execution layer to trigger the withdrawal of a validator's balance to its withdrawal address -// new in Electra -message WithdrawalRequest { - // The execution address receiving the funds - bytes source_address = 1 [(ethereum.eth.ext.ssz_size) = "20"]; - - // 48 byte BLS public key of the validator. - bytes validator_pubkey = 2 [(ethereum.eth.ext.ssz_size) = "48"]; - - // Deposit amount in gwei. - uint64 amount = 3; -} - -// DepositRequest is the message from the execution layer to trigger the deposit of a validator's balance to its balance -// new in Electra -message DepositRequest { - bytes pubkey = 1 [(ethereum.eth.ext.ssz_size) = "48"]; - bytes withdrawal_credentials = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 amount = 3; - bytes signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; - uint64 index = 5; + // The blob bytes. + bytes data = 1 [ (ethereum.eth.ext.ssz_size) = "blob.size" ]; } -// ConsolidationRequest is the message from the execution layer to trigger the consolidation of one -// validator to another validator. -message ConsolidationRequest { - // Source address of account which originated the request. - bytes source_address = 1 [(ethereum.eth.ext.ssz_size) = "20"]; - // Funds will be moved from this public key. - bytes source_pubkey = 2 [(ethereum.eth.ext.ssz_size) = "48"]; - // Funds will be moved to this public key. - bytes target_pubkey = 3 [(ethereum.eth.ext.ssz_size) = "48"]; +message BlobAndProof { + bytes blob = 1 [ (ethereum.eth.ext.ssz_size) = "blob.size" ]; + bytes kzg_proof = 2 [ (ethereum.eth.ext.ssz_size) = "48" ]; } diff --git a/proto/engine/v1/execution_engine_fuzz_test.go b/proto/engine/v1/execution_engine_fuzz_test.go index fbed9d9b6141..1a39a4f13b1a 100644 --- a/proto/engine/v1/execution_engine_fuzz_test.go +++ b/proto/engine/v1/execution_engine_fuzz_test.go @@ -10,14 +10,12 @@ import ( ) func TestCopyExecutionPayload_Fuzz(t *testing.T) { - fuzzCopies(t, &enginev1.ExecutionPayloadElectra{}) fuzzCopies(t, &enginev1.ExecutionPayloadDeneb{}) fuzzCopies(t, &enginev1.ExecutionPayloadCapella{}) fuzzCopies(t, &enginev1.ExecutionPayload{}) } func TestCopyExecutionPayloadHeader_Fuzz(t *testing.T) { - fuzzCopies(t, &enginev1.ExecutionPayloadHeaderElectra{}) fuzzCopies(t, &enginev1.ExecutionPayloadHeaderDeneb{}) fuzzCopies(t, &enginev1.ExecutionPayloadHeaderCapella{}) fuzzCopies(t, &enginev1.ExecutionPayloadHeader{}) diff --git a/proto/engine/v1/export_test.go b/proto/engine/v1/export_test.go index 17f4cde64607..2466b7fa44d1 100644 --- a/proto/engine/v1/export_test.go +++ b/proto/engine/v1/export_test.go @@ -1,3 +1,11 @@ package enginev1 type Copier[T any] copier[T] + +func MarshalItems[T sszMarshaler](items []T) ([]byte, error) { + return marshalItems(items) +} + +func UnmarshalItems[T sszUnmarshaler](data []byte, itemSize int, newItem func() T) ([]T, error) { + return unmarshalItems(data, itemSize, newItem) +} diff --git a/proto/engine/v1/json_marshal_unmarshal.go b/proto/engine/v1/json_marshal_unmarshal.go index 3a7de3a5efe4..1d1dcd1c0270 100644 --- a/proto/engine/v1/json_marshal_unmarshal.go +++ b/proto/engine/v1/json_marshal_unmarshal.go @@ -298,34 +298,11 @@ type GetPayloadV3ResponseJson struct { } type GetPayloadV4ResponseJson struct { - ExecutionPayload *ExecutionPayloadElectraJSON `json:"executionPayload"` - BlockValue string `json:"blockValue"` - BlobsBundle *BlobBundleJSON `json:"blobsBundle"` - ShouldOverrideBuilder bool `json:"shouldOverrideBuilder"` -} - -// ExecutionPayloadElectraJSON represents the engine API ExecutionPayloadV4 type. -type ExecutionPayloadElectraJSON struct { - ParentHash *common.Hash `json:"parentHash"` - FeeRecipient *common.Address `json:"feeRecipient"` - StateRoot *common.Hash `json:"stateRoot"` - ReceiptsRoot *common.Hash `json:"receiptsRoot"` - LogsBloom *hexutil.Bytes `json:"logsBloom"` - PrevRandao *common.Hash `json:"prevRandao"` - BlockNumber *hexutil.Uint64 `json:"blockNumber"` - GasLimit *hexutil.Uint64 `json:"gasLimit"` - GasUsed *hexutil.Uint64 `json:"gasUsed"` - Timestamp *hexutil.Uint64 `json:"timestamp"` - ExtraData hexutil.Bytes `json:"extraData"` - BaseFeePerGas string `json:"baseFeePerGas"` - BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` - ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` - BlockHash *common.Hash `json:"blockHash"` - Transactions []hexutil.Bytes `json:"transactions"` - Withdrawals []*Withdrawal `json:"withdrawals"` - WithdrawalRequests []WithdrawalRequestV1 `json:"withdrawalRequests"` - DepositRequests []DepositRequestV1 `json:"depositRequests"` - ConsolidationRequests []ConsolidationRequestV1 `json:"consolidationRequests"` + ExecutionPayload *ExecutionPayloadDenebJSON `json:"executionPayload"` + BlockValue string `json:"blockValue"` + BlobsBundle *BlobBundleJSON `json:"blobsBundle"` + ShouldOverrideBuilder bool `json:"shouldOverrideBuilder"` + ExecutionRequests []hexutil.Bytes `json:"executionRequests"` } // ExecutionPayloadBody represents the engine API ExecutionPayloadV1 or ExecutionPayloadV2 type. @@ -337,64 +314,6 @@ type ExecutionPayloadBody struct { ConsolidationRequests []ConsolidationRequestV1 `json:"consolidationRequests"` } -// Validate returns an error if key fields in GetPayloadV4ResponseJson are nil or invalid. -func (j *GetPayloadV4ResponseJson) Validate() error { - if j.ExecutionPayload == nil { - return errors.New("nil ExecutionPayload") - } - return j.ExecutionPayload.Validate() -} - -// Validate returns an error if key fields in ExecutionPayloadElectraJSON are nil or invalid. -func (j *ExecutionPayloadElectraJSON) Validate() error { - if j.ParentHash == nil { - return errors.New("missing required field 'parentHash' for ExecutionPayload") - } - if j.FeeRecipient == nil { - return errors.New("missing required field 'feeRecipient' for ExecutionPayload") - } - if j.StateRoot == nil { - return errors.New("missing required field 'stateRoot' for ExecutionPayload") - } - if j.ReceiptsRoot == nil { - return errors.New("missing required field 'receiptsRoot' for ExecutableDataV1") - } - if j.LogsBloom == nil { - return errors.New("missing required field 'logsBloom' for ExecutionPayload") - } - if j.PrevRandao == nil { - return errors.New("missing required field 'prevRandao' for ExecutionPayload") - } - if j.ExtraData == nil { - return errors.New("missing required field 'extraData' for ExecutionPayload") - } - if j.BlockHash == nil { - return errors.New("missing required field 'blockHash' for ExecutionPayload") - } - if j.Transactions == nil { - return errors.New("missing required field 'transactions' for ExecutionPayload") - } - if j.BlockNumber == nil { - return errors.New("missing required field 'blockNumber' for ExecutionPayload") - } - if j.Timestamp == nil { - return errors.New("missing required field 'timestamp' for ExecutionPayload") - } - if j.GasUsed == nil { - return errors.New("missing required field 'gasUsed' for ExecutionPayload") - } - if j.GasLimit == nil { - return errors.New("missing required field 'gasLimit' for ExecutionPayload") - } - if j.BlobGasUsed == nil { - return errors.New("missing required field 'blobGasUsed' for ExecutionPayload") - } - if j.ExcessBlobGas == nil { - return errors.New("missing required field 'excessBlobGas' for ExecutionPayload") - } - return nil -} - type ExecutionPayloadDenebJSON struct { ParentHash *common.Hash `json:"parentHash"` FeeRecipient *common.Address `json:"feeRecipient"` @@ -919,6 +838,11 @@ func (b BlobBundleJSON) ToProto() *BlobsBundle { } } +type BlobAndProofJson struct { + Blob hexutil.Bytes `json:"blob"` + KzgProof hexutil.Bytes `json:"proof"` +} + // MarshalJSON -- func (e *ExecutionPayloadDeneb) MarshalJSON() ([]byte, error) { transactions := make([]hexutil.Bytes, len(e.Transactions)) @@ -966,55 +890,6 @@ func (e *ExecutionPayloadDeneb) MarshalJSON() ([]byte, error) { }) } -func (e *ExecutionPayloadElectra) MarshalJSON() ([]byte, error) { - transactions := make([]hexutil.Bytes, len(e.Transactions)) - for i, tx := range e.Transactions { - transactions[i] = tx - } - baseFee := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(e.BaseFeePerGas)) - baseFeeHex := hexutil.EncodeBig(baseFee) - pHash := common.BytesToHash(e.ParentHash) - sRoot := common.BytesToHash(e.StateRoot) - recRoot := common.BytesToHash(e.ReceiptsRoot) - prevRan := common.BytesToHash(e.PrevRandao) - bHash := common.BytesToHash(e.BlockHash) - blockNum := hexutil.Uint64(e.BlockNumber) - gasLimit := hexutil.Uint64(e.GasLimit) - gasUsed := hexutil.Uint64(e.GasUsed) - timeStamp := hexutil.Uint64(e.Timestamp) - recipient := common.BytesToAddress(e.FeeRecipient) - logsBloom := hexutil.Bytes(e.LogsBloom) - withdrawals := e.Withdrawals - if withdrawals == nil { - withdrawals = make([]*Withdrawal, 0) - } - blobGasUsed := hexutil.Uint64(e.BlobGasUsed) - excessBlobGas := hexutil.Uint64(e.ExcessBlobGas) - - return json.Marshal(ExecutionPayloadElectraJSON{ - ParentHash: &pHash, - FeeRecipient: &recipient, - StateRoot: &sRoot, - ReceiptsRoot: &recRoot, - LogsBloom: &logsBloom, - PrevRandao: &prevRan, - BlockNumber: &blockNum, - GasLimit: &gasLimit, - GasUsed: &gasUsed, - Timestamp: &timeStamp, - ExtraData: e.ExtraData, - BaseFeePerGas: baseFeeHex, - BlockHash: &bHash, - Transactions: transactions, - Withdrawals: withdrawals, - BlobGasUsed: &blobGasUsed, - ExcessBlobGas: &excessBlobGas, - WithdrawalRequests: ProtoWithdrawalRequestsToJson(e.WithdrawalRequests), - DepositRequests: ProtoDepositRequestsToJson(e.DepositRequests), - ConsolidationRequests: ProtoConsolidationRequestsToJson(e.ConsolidationRequests), - }) -} - func JsonDepositRequestsToProto(j []DepositRequestV1) ([]*DepositRequest, error) { reqs := make([]*DepositRequest, len(j)) @@ -1128,114 +1003,130 @@ func ProtoConsolidationRequestsToJson(reqs []*ConsolidationRequest) []Consolidat return j } -func (j *ExecutionPayloadElectraJSON) ElectraPayload() (*ExecutionPayloadElectra, error) { - baseFeeBigEnd, err := hexutil.DecodeBig(j.BaseFeePerGas) - if err != nil { - return nil, err +func (e *ExecutionPayloadDenebWithValueAndBlobsBundle) UnmarshalJSON(enc []byte) error { + dec := GetPayloadV3ResponseJson{} + if err := json.Unmarshal(enc, &dec); err != nil { + return err } - baseFee := bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFeeBigEnd.Bytes()), fieldparams.RootLength) - transactions := make([][]byte, len(j.Transactions)) - for i, tx := range j.Transactions { - transactions[i] = tx + if dec.ExecutionPayload.ParentHash == nil { + return errors.New("missing required field 'parentHash' for ExecutionPayload") } - if j.Withdrawals == nil { - j.Withdrawals = make([]*Withdrawal, 0) + if dec.ExecutionPayload.FeeRecipient == nil { + return errors.New("missing required field 'feeRecipient' for ExecutionPayload") } - dr, err := JsonDepositRequestsToProto(j.DepositRequests) - if err != nil { - return nil, err + if dec.ExecutionPayload.StateRoot == nil { + return errors.New("missing required field 'stateRoot' for ExecutionPayload") + } + if dec.ExecutionPayload.ReceiptsRoot == nil { + return errors.New("missing required field 'receiptsRoot' for ExecutableDataV1") + } + if dec.ExecutionPayload.LogsBloom == nil { + return errors.New("missing required field 'logsBloom' for ExecutionPayload") + } + if dec.ExecutionPayload.PrevRandao == nil { + return errors.New("missing required field 'prevRandao' for ExecutionPayload") } - wr, err := JsonWithdrawalRequestsToProto(j.WithdrawalRequests) + if dec.ExecutionPayload.ExtraData == nil { + return errors.New("missing required field 'extraData' for ExecutionPayload") + } + if dec.ExecutionPayload.BlockHash == nil { + return errors.New("missing required field 'blockHash' for ExecutionPayload") + } + if dec.ExecutionPayload.Transactions == nil { + return errors.New("missing required field 'transactions' for ExecutionPayload") + } + if dec.ExecutionPayload.BlockNumber == nil { + return errors.New("missing required field 'blockNumber' for ExecutionPayload") + } + if dec.ExecutionPayload.Timestamp == nil { + return errors.New("missing required field 'timestamp' for ExecutionPayload") + } + if dec.ExecutionPayload.GasUsed == nil { + return errors.New("missing required field 'gasUsed' for ExecutionPayload") + } + if dec.ExecutionPayload.GasLimit == nil { + return errors.New("missing required field 'gasLimit' for ExecutionPayload") + } + if dec.ExecutionPayload.BlobGasUsed == nil { + return errors.New("missing required field 'blobGasUsed' for ExecutionPayload") + } + if dec.ExecutionPayload.ExcessBlobGas == nil { + return errors.New("missing required field 'excessBlobGas' for ExecutionPayload") + } + + *e = ExecutionPayloadDenebWithValueAndBlobsBundle{Payload: &ExecutionPayloadDeneb{}} + e.Payload.ParentHash = dec.ExecutionPayload.ParentHash.Bytes() + e.Payload.FeeRecipient = dec.ExecutionPayload.FeeRecipient.Bytes() + e.Payload.StateRoot = dec.ExecutionPayload.StateRoot.Bytes() + e.Payload.ReceiptsRoot = dec.ExecutionPayload.ReceiptsRoot.Bytes() + e.Payload.LogsBloom = *dec.ExecutionPayload.LogsBloom + e.Payload.PrevRandao = dec.ExecutionPayload.PrevRandao.Bytes() + e.Payload.BlockNumber = uint64(*dec.ExecutionPayload.BlockNumber) + e.Payload.GasLimit = uint64(*dec.ExecutionPayload.GasLimit) + e.Payload.GasUsed = uint64(*dec.ExecutionPayload.GasUsed) + e.Payload.Timestamp = uint64(*dec.ExecutionPayload.Timestamp) + e.Payload.ExtraData = dec.ExecutionPayload.ExtraData + baseFee, err := hexutil.DecodeBig(dec.ExecutionPayload.BaseFeePerGas) if err != nil { - return nil, err + return err + } + e.Payload.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength) + + e.Payload.ExcessBlobGas = uint64(*dec.ExecutionPayload.ExcessBlobGas) + e.Payload.BlobGasUsed = uint64(*dec.ExecutionPayload.BlobGasUsed) + + e.Payload.BlockHash = dec.ExecutionPayload.BlockHash.Bytes() + transactions := make([][]byte, len(dec.ExecutionPayload.Transactions)) + for i, tx := range dec.ExecutionPayload.Transactions { + transactions[i] = tx } - cr, err := JsonConsolidationRequestsToProto(j.ConsolidationRequests) + e.Payload.Transactions = transactions + if dec.ExecutionPayload.Withdrawals == nil { + dec.ExecutionPayload.Withdrawals = make([]*Withdrawal, 0) + } + e.Payload.Withdrawals = dec.ExecutionPayload.Withdrawals + + v, err := hexutil.DecodeBig(dec.BlockValue) if err != nil { - return nil, err + return err } - return &ExecutionPayloadElectra{ - ParentHash: j.ParentHash.Bytes(), - FeeRecipient: j.FeeRecipient.Bytes(), - StateRoot: j.StateRoot.Bytes(), - ReceiptsRoot: j.ReceiptsRoot.Bytes(), - LogsBloom: *j.LogsBloom, - PrevRandao: j.PrevRandao.Bytes(), - BlockNumber: uint64(*j.BlockNumber), - GasLimit: uint64(*j.GasLimit), - GasUsed: uint64(*j.GasUsed), - Timestamp: uint64(*j.Timestamp), - ExtraData: j.ExtraData, - BaseFeePerGas: baseFee, - BlockHash: j.BlockHash.Bytes(), - Transactions: transactions, - Withdrawals: j.Withdrawals, - BlobGasUsed: uint64(*j.BlobGasUsed), - ExcessBlobGas: uint64(*j.ExcessBlobGas), - DepositRequests: dr, - WithdrawalRequests: wr, - ConsolidationRequests: cr, - }, nil -} + e.Value = bytesutil.PadTo(bytesutil.ReverseByteOrder(v.Bytes()), fieldparams.RootLength) -func (j *BlobBundleJSON) ElectraBlobsBundle() *BlobsBundle { - if j == nil { + if dec.BlobsBundle == nil { return nil } + e.BlobsBundle = &BlobsBundle{} - commitments := make([][]byte, len(j.Commitments)) - for i, kzg := range j.Commitments { + commitments := make([][]byte, len(dec.BlobsBundle.Commitments)) + for i, kzg := range dec.BlobsBundle.Commitments { k := kzg commitments[i] = bytesutil.PadTo(k[:], fieldparams.BLSPubkeyLength) } + e.BlobsBundle.KzgCommitments = commitments - proofs := make([][]byte, len(j.Proofs)) - for i, proof := range j.Proofs { + proofs := make([][]byte, len(dec.BlobsBundle.Proofs)) + for i, proof := range dec.BlobsBundle.Proofs { p := proof proofs[i] = bytesutil.PadTo(p[:], fieldparams.BLSPubkeyLength) } + e.BlobsBundle.Proofs = proofs - blobs := make([][]byte, len(j.Blobs)) - for i, blob := range j.Blobs { + blobs := make([][]byte, len(dec.BlobsBundle.Blobs)) + for i, blob := range dec.BlobsBundle.Blobs { b := make([]byte, fieldparams.BlobLength) copy(b, blob) blobs[i] = b } + e.BlobsBundle.Blobs = blobs - return &BlobsBundle{ - KzgCommitments: commitments, - Proofs: proofs, - Blobs: blobs, - } -} - -func (e *ExecutionPayloadElectraWithValueAndBlobsBundle) UnmarshalJSON(enc []byte) error { - dec := &GetPayloadV4ResponseJson{} - if err := json.Unmarshal(enc, dec); err != nil { - return err - } - if err := dec.Validate(); err != nil { - return err - } - - *e = ExecutionPayloadElectraWithValueAndBlobsBundle{Payload: &ExecutionPayloadElectra{}} e.ShouldOverrideBuilder = dec.ShouldOverrideBuilder - blockValueBigEnd, err := hexutil.DecodeBig(dec.BlockValue) - if err != nil { - return errors.Wrapf(err, "failed to parse blockValue=%s", dec.BlockValue) - } - e.Value = bytesutil.PadTo(bytesutil.ReverseByteOrder(blockValueBigEnd.Bytes()), fieldparams.RootLength) - e.Payload, err = dec.ExecutionPayload.ElectraPayload() - if err != nil { - return err - } - e.BlobsBundle = dec.BlobsBundle.ElectraBlobsBundle() return nil } -func (e *ExecutionPayloadDenebWithValueAndBlobsBundle) UnmarshalJSON(enc []byte) error { - dec := GetPayloadV3ResponseJson{} +func (e *ExecutionBundleElectra) UnmarshalJSON(enc []byte) error { + dec := GetPayloadV4ResponseJson{} if err := json.Unmarshal(enc, &dec); err != nil { return err } @@ -1286,7 +1177,7 @@ func (e *ExecutionPayloadDenebWithValueAndBlobsBundle) UnmarshalJSON(enc []byte) return errors.New("missing required field 'excessBlobGas' for ExecutionPayload") } - *e = ExecutionPayloadDenebWithValueAndBlobsBundle{Payload: &ExecutionPayloadDeneb{}} + *e = ExecutionBundleElectra{Payload: &ExecutionPayloadDeneb{}} e.Payload.ParentHash = dec.ExecutionPayload.ParentHash.Bytes() e.Payload.FeeRecipient = dec.ExecutionPayload.FeeRecipient.Bytes() e.Payload.StateRoot = dec.ExecutionPayload.StateRoot.Bytes() @@ -1353,6 +1244,15 @@ func (e *ExecutionPayloadDenebWithValueAndBlobsBundle) UnmarshalJSON(enc []byte) e.ShouldOverrideBuilder = dec.ShouldOverrideBuilder + requests := make([][]byte, len(dec.ExecutionRequests)) + for i, request := range dec.ExecutionRequests { + r := make([]byte, len(request)) + copy(r, request) + requests[i] = r + } + + e.ExecutionRequests = requests + return nil } @@ -1364,3 +1264,21 @@ func RecastHexutilByteSlice(h []hexutil.Bytes) [][]byte { } return r } + +// UnmarshalJSON implements the json unmarshaler interface for BlobAndProof. +func (b *BlobAndProof) UnmarshalJSON(enc []byte) error { + var dec *BlobAndProofJson + if err := json.Unmarshal(enc, &dec); err != nil { + return err + } + + blob := make([]byte, fieldparams.BlobLength) + copy(blob, dec.Blob) + b.Blob = blob + + proof := make([]byte, fieldparams.BLSPubkeyLength) + copy(proof, dec.KzgProof) + b.KzgProof = proof + + return nil +} diff --git a/proto/engine/v1/json_marshal_unmarshal_test.go b/proto/engine/v1/json_marshal_unmarshal_test.go index bc1d8dab6fd6..a3104f42fef9 100644 --- a/proto/engine/v1/json_marshal_unmarshal_test.go +++ b/proto/engine/v1/json_marshal_unmarshal_test.go @@ -273,161 +273,6 @@ func TestJsonMarshalUnmarshal(t *testing.T) { bytesutil.PadTo([]byte{'k'}, 131072), bytesutil.PadTo([]byte{'l'}, 131072)}, pb.BlobsBundle.Blobs) }) - t.Run("execution payload electra", func(t *testing.T) { - parentHash := common.BytesToHash([]byte("parent")) - feeRecipient := common.BytesToAddress([]byte("feeRecipient")) - stateRoot := common.BytesToHash([]byte("stateRoot")) - receiptsRoot := common.BytesToHash([]byte("receiptsRoot")) - logsBloom := hexutil.Bytes(bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)) - random := common.BytesToHash([]byte("random")) - extra := common.BytesToHash([]byte("extra")) - hash := common.BytesToHash([]byte("hash")) - bn := hexutil.Uint64(1) - gl := hexutil.Uint64(2) - gu := hexutil.Uint64(3) - ts := hexutil.Uint64(4) - bgu := hexutil.Uint64(5) - ebg := hexutil.Uint64(6) - - withdrawalReq := []*enginev1.WithdrawalRequest{ - { - SourceAddress: bytesutil.PadTo([]byte("sourceAddress-1"), 20), - ValidatorPubkey: bytesutil.PadTo([]byte("pubKey-1"), 48), - Amount: 1, - }, - { - SourceAddress: bytesutil.PadTo([]byte("sourceAddress-2"), 20), - ValidatorPubkey: bytesutil.PadTo([]byte("pubKey-2"), 48), - Amount: 2, - }, - { - SourceAddress: bytesutil.PadTo([]byte("sourceAddress-3"), 20), - ValidatorPubkey: bytesutil.PadTo([]byte("pubKey-3"), 48), - Amount: 3, - }, - } - depositReq := []*enginev1.DepositRequest{ - { - Pubkey: bytesutil.PadTo([]byte("pubKey-1"), 48), - WithdrawalCredentials: bytesutil.PadTo([]byte("creds-1"), 32), - Amount: 1, - Signature: bytesutil.PadTo([]byte("sig-1"), 96), - Index: 11, - }, - { - Pubkey: bytesutil.PadTo([]byte("pubKey-2"), 48), - WithdrawalCredentials: bytesutil.PadTo([]byte("creds-2"), 32), - Amount: 2, - Signature: bytesutil.PadTo([]byte("sig-2"), 96), - Index: 12, - }, - { - Pubkey: bytesutil.PadTo([]byte("pubKey-3"), 48), - WithdrawalCredentials: bytesutil.PadTo([]byte("creds-3"), 32), - Amount: 3, - Signature: bytesutil.PadTo([]byte("sig-3"), 96), - Index: 13, - }, - } - - consolidationReq := []*enginev1.ConsolidationRequest{ - { - SourceAddress: bytesutil.PadTo([]byte("sourceAddress-1"), 20), - SourcePubkey: bytesutil.PadTo([]byte("s-pubKey-1"), 48), - TargetPubkey: bytesutil.PadTo([]byte("t-pubKey-1"), 48), - }, - } - - resp := &enginev1.GetPayloadV4ResponseJson{ - BlobsBundle: &enginev1.BlobBundleJSON{ - Commitments: []hexutil.Bytes{{'a'}, {'b'}, {'c'}, {'d'}}, - Proofs: []hexutil.Bytes{{'e'}, {'f'}, {'g'}, {'h'}}, - Blobs: []hexutil.Bytes{{'i'}, {'j'}, {'k'}, {'l'}}, - }, - BlockValue: "0x123", - ExecutionPayload: &enginev1.ExecutionPayloadElectraJSON{ - ParentHash: &parentHash, - FeeRecipient: &feeRecipient, - StateRoot: &stateRoot, - ReceiptsRoot: &receiptsRoot, - LogsBloom: &logsBloom, - PrevRandao: &random, - BlockNumber: &bn, - GasLimit: &gl, - GasUsed: &gu, - Timestamp: &ts, - ExtraData: hexutil.Bytes(extra[:]), - BaseFeePerGas: "0x123", - BlockHash: &hash, - Transactions: []hexutil.Bytes{{}}, - Withdrawals: []*enginev1.Withdrawal{{ - Index: 1, - ValidatorIndex: 1, - Address: bytesutil.PadTo([]byte("address"), 20), - Amount: 1, - }}, - BlobGasUsed: &bgu, - ExcessBlobGas: &ebg, - WithdrawalRequests: enginev1.ProtoWithdrawalRequestsToJson(withdrawalReq), - DepositRequests: enginev1.ProtoDepositRequestsToJson(depositReq), - ConsolidationRequests: enginev1.ProtoConsolidationRequestsToJson(consolidationReq), - }, - } - enc, err := json.Marshal(resp) - require.NoError(t, err) - pb := &enginev1.ExecutionPayloadElectraWithValueAndBlobsBundle{} - require.NoError(t, json.Unmarshal(enc, pb)) - require.DeepEqual(t, parentHash.Bytes(), pb.Payload.ParentHash) - require.DeepEqual(t, feeRecipient.Bytes(), pb.Payload.FeeRecipient) - require.DeepEqual(t, stateRoot.Bytes(), pb.Payload.StateRoot) - require.DeepEqual(t, receiptsRoot.Bytes(), pb.Payload.ReceiptsRoot) - require.DeepEqual(t, logsBloom, hexutil.Bytes(pb.Payload.LogsBloom)) - require.DeepEqual(t, random.Bytes(), pb.Payload.PrevRandao) - require.DeepEqual(t, uint64(1), pb.Payload.BlockNumber) - require.DeepEqual(t, uint64(2), pb.Payload.GasLimit) - require.DeepEqual(t, uint64(3), pb.Payload.GasUsed) - require.DeepEqual(t, uint64(4), pb.Payload.Timestamp) - require.DeepEqual(t, uint64(5), pb.Payload.BlobGasUsed) - require.DeepEqual(t, uint64(6), pb.Payload.ExcessBlobGas) - require.DeepEqual(t, extra.Bytes(), pb.Payload.ExtraData) - feePerGas := new(big.Int).SetBytes(pb.Payload.BaseFeePerGas) - require.Equal(t, "15832716547479101977395928904157292820330083199902421483727713169783165812736", feePerGas.String()) - require.DeepEqual(t, hash.Bytes(), pb.Payload.BlockHash) - require.DeepEqual(t, [][]byte{{}}, pb.Payload.Transactions) - require.Equal(t, 1, len(pb.Payload.Withdrawals)) - withdrawal := pb.Payload.Withdrawals[0] - require.Equal(t, uint64(1), withdrawal.Index) - require.Equal(t, primitives.ValidatorIndex(1), withdrawal.ValidatorIndex) - require.DeepEqual(t, bytesutil.PadTo([]byte("address"), 20), withdrawal.Address) - require.Equal(t, uint64(1), withdrawal.Amount) - require.DeepEqual(t, [][]byte{ - bytesutil.PadTo([]byte{'e'}, 48), - bytesutil.PadTo([]byte{'f'}, 48), - bytesutil.PadTo([]byte{'g'}, 48), - bytesutil.PadTo([]byte{'h'}, 48)}, pb.BlobsBundle.Proofs) - require.DeepEqual(t, [][]byte{ - bytesutil.PadTo([]byte{'a'}, 48), - bytesutil.PadTo([]byte{'b'}, 48), - bytesutil.PadTo([]byte{'c'}, 48), - bytesutil.PadTo([]byte{'d'}, 48)}, pb.BlobsBundle.KzgCommitments) - require.DeepEqual(t, [][]byte{ - bytesutil.PadTo([]byte{'i'}, 131072), - bytesutil.PadTo([]byte{'j'}, 131072), - bytesutil.PadTo([]byte{'k'}, 131072), - bytesutil.PadTo([]byte{'l'}, 131072)}, pb.BlobsBundle.Blobs) - require.Equal(t, len(pb.Payload.WithdrawalRequests), len(withdrawalReq)) - for i := range pb.Payload.WithdrawalRequests { - require.DeepEqual(t, pb.Payload.WithdrawalRequests[i], withdrawalReq[i]) - } - require.Equal(t, len(pb.Payload.DepositRequests), len(depositReq)) - for i := range pb.Payload.DepositRequests { - require.DeepEqual(t, pb.Payload.DepositRequests[i], depositReq[i]) - } - require.Equal(t, len(pb.Payload.ConsolidationRequests), len(consolidationReq)) - for i := range pb.Payload.ConsolidationRequests { - require.DeepEqual(t, pb.Payload.ConsolidationRequests[i], consolidationReq[i]) - } - }) t.Run("execution block", func(t *testing.T) { baseFeePerGas := big.NewInt(1770307273) want := &gethtypes.Header{ @@ -762,6 +607,9 @@ func TestJsonMarshalUnmarshal(t *testing.T) { // Expect no transaction objects in the unmarshaled data. require.Equal(t, 0, len(payloadPb.Transactions)) }) + t.Run("execution bundle electra with deneb payload, blob data, and execution requests", func(t *testing.T) { + // TODO #14351: update this test when geth updates + }) } func TestPayloadIDBytes_MarshalUnmarshalJSON(t *testing.T) { diff --git a/proto/eth/ext/options.pb.go b/proto/eth/ext/options.pb.go index 00596e6c4561..b416e1feb89e 100755 --- a/proto/eth/ext/options.pb.go +++ b/proto/eth/ext/options.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/eth/ext/options.proto package ext diff --git a/proto/eth/v1/BUILD.bazel b/proto/eth/v1/BUILD.bazel index 670f614a9ba9..af9c03a76e4c 100644 --- a/proto/eth/v1/BUILD.bazel +++ b/proto/eth/v1/BUILD.bazel @@ -84,24 +84,13 @@ go_proto_library( ], ) -go_proto_library( - name = "go_grpc_gateway_library", - compilers = [ - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway", - ], - embed = [":go_proto"], - importpath = "github.com/prysmaticlabs/prysm/v5/proto/eth/v1", - protos = [":proto"], - visibility = ["//proto:__subpackages__"], -) - go_library( name = "go_default_library", srcs = [ ":ssz_generated_files", ], embed = [ - ":go_grpc_gateway_library", + ":go_proto", ], importpath = "github.com/prysmaticlabs/prysm/v5/proto/eth/v1", visibility = ["//visibility:public"], diff --git a/proto/eth/v1/README.md b/proto/eth/v1/README.md deleted file mode 100644 index af9cfcca7034..000000000000 --- a/proto/eth/v1/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# gRPC Gateway - -This package is contains generated files for applications that wish to use eth/v1alpha as a -[gRPC gateway](https://github.com/grpc-ecosystem/grpc-gateway). \ No newline at end of file diff --git a/proto/eth/v1/attestation.pb.go b/proto/eth/v1/attestation.pb.go index 80b3ed9e6517..d48e9f254660 100755 --- a/proto/eth/v1/attestation.pb.go +++ b/proto/eth/v1/attestation.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/eth/v1/attestation.proto package v1 diff --git a/proto/eth/v1/attestation.pb.gw.go b/proto/eth/v1/attestation.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v1/attestation.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v1/attestation.proto b/proto/eth/v1/attestation.proto index 2b63ae05887d..bebfaa06d0d2 100644 --- a/proto/eth/v1/attestation.proto +++ b/proto/eth/v1/attestation.proto @@ -26,62 +26,79 @@ option java_package = "org.ethereum.eth.v1"; option php_namespace = "Ethereum\\Eth\\v1"; message Attestation { - // A bitfield representation of validator indices that have voted exactly - // the same vote and have been aggregated into this attestation. - bytes aggregation_bits = 1 [(ethereum.eth.ext.ssz_max) = "2048", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitlist"]; - - AttestationData data = 2; - - // 96 byte BLS aggregate signature. - bytes signature = 3 [(ethereum.eth.ext.ssz_size) = "96"]; + // A bitfield representation of validator indices that have voted exactly + // the same vote and have been aggregated into this attestation. + bytes aggregation_bits = 1 [ + (ethereum.eth.ext.ssz_max) = "2048", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitlist" + ]; + + AttestationData data = 2; + + // 96 byte BLS aggregate signature. + bytes signature = 3 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message AggregateAttestationAndProof { - // The aggregator index that submitted this aggregated attestation and proof. - uint64 aggregator_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // The aggregated attestation that was submitted. - Attestation aggregate = 3; - - // 96 byte selection proof signed by the aggregator, which is the signature of the slot to aggregate. - bytes selection_proof = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // The aggregator index that submitted this aggregated attestation and proof. + uint64 aggregator_index = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // The aggregated attestation that was submitted. + Attestation aggregate = 3; + + // 96 byte selection proof signed by the aggregator, which is the signature of + // the slot to aggregate. + bytes selection_proof = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message SignedAggregateAttestationAndProof { - // The aggregated attestation and selection proof itself. - AggregateAttestationAndProof message = 1; + // The aggregated attestation and selection proof itself. + AggregateAttestationAndProof message = 1; - // 96 byte BLS aggregate signature signed by the aggregator over the message. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS aggregate signature signed by the aggregator over the message. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message AttestationData { - // Attestation data includes information on Casper the Friendly Finality Gadget's votes - // See: https://arxiv.org/pdf/1710.09437.pdf + // Attestation data includes information on Casper the Friendly Finality + // Gadget's votes See: https://arxiv.org/pdf/1710.09437.pdf - // Slot of the attestation attesting for. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Slot of the attestation attesting for. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // The committee index that submitted this attestation. - uint64 index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; + // The committee index that submitted this attestation. + uint64 index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.CommitteeIndex" ]; - // 32 byte root of the LMD GHOST block vote. - bytes beacon_block_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the LMD GHOST block vote. + bytes beacon_block_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The most recent justified checkpoint in the beacon state - Checkpoint source = 4; + // The most recent justified checkpoint in the beacon state + Checkpoint source = 4; - // The checkpoint attempting to be justified for the current epoch and its epoch boundary block - Checkpoint target = 5; + // The checkpoint attempting to be justified for the current epoch and its + // epoch boundary block + Checkpoint target = 5; } message Checkpoint { - // A checkpoint is every epoch's first slot. The goal of Casper FFG - // is to link the check points together for justification and finalization. + // A checkpoint is every epoch's first slot. The goal of Casper FFG + // is to link the check points together for justification and finalization. - // Epoch the checkpoint references. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // Epoch the checkpoint references. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; - // Block root of the checkpoint references. - bytes root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + // Block root of the checkpoint references. + bytes root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; } diff --git a/proto/eth/v1/beacon_block.pb.go b/proto/eth/v1/beacon_block.pb.go index e9c8955e8e98..a0ccb16cb5f8 100755 --- a/proto/eth/v1/beacon_block.pb.go +++ b/proto/eth/v1/beacon_block.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/eth/v1/beacon_block.proto package v1 diff --git a/proto/eth/v1/beacon_block.pb.gw.go b/proto/eth/v1/beacon_block.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v1/beacon_block.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v1/beacon_block.proto b/proto/eth/v1/beacon_block.proto index 2cb1f213b10c..d21275a3aed5 100644 --- a/proto/eth/v1/beacon_block.proto +++ b/proto/eth/v1/beacon_block.proto @@ -26,140 +26,158 @@ option java_outer_classname = "BeaconBlockProto"; option java_package = "org.ethereum.eth.v1"; option php_namespace = "Ethereum\\Eth\\v1"; -// The Ethereum consensus beacon block. The message does not contain a validator signature. +// The Ethereum consensus beacon block. The message does not contain a validator +// signature. message BeaconBlock { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The block body itself. - BeaconBlockBody body = 5; + // The block body itself. + BeaconBlockBody body = 5; } // The signed version of beacon block. message SignedBeaconBlock { - // The unsigned beacon block itself. - BeaconBlock block = 1; + // The unsigned beacon block itself. + BeaconBlock block = 1; - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } // The block body of an Ethereum consensus beacon block. message BeaconBlockBody { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block + // Block operations + // Refer to spec constants at + // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; } // Proposer slashings are proofs that a slashable offense has been committed by // proposing two conflicting blocks from the same validator. message ProposerSlashing { - // First conflicting signed block header. - SignedBeaconBlockHeader signed_header_1 = 2; + // First conflicting signed block header. + SignedBeaconBlockHeader signed_header_1 = 2; - // Second conflicting signed block header. - SignedBeaconBlockHeader signed_header_2 = 3; + // Second conflicting signed block header. + SignedBeaconBlockHeader signed_header_2 = 3; } // Attestor slashings are proofs that a slashable offense has been committed by // attesting to two conflicting pieces of information by the same validator. message AttesterSlashing { - // First conflicting attestation. - IndexedAttestation attestation_1 = 1; + // First conflicting attestation. + IndexedAttestation attestation_1 = 1; - // Second conflicting attestation. - IndexedAttestation attestation_2 = 2; + // Second conflicting attestation. + IndexedAttestation attestation_2 = 2; } // Deposit into the Ethereum consensus from the Ethereum 1.x deposit contract. message Deposit { - message Data { - // 48 byte BLS public key of the validator. - bytes pubkey = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; + message Data { + // 48 byte BLS public key of the validator. + bytes pubkey = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; - // A 32 byte hash of the withdrawal address public key. - bytes withdrawal_credentials = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + // A 32 byte hash of the withdrawal address public key. + bytes withdrawal_credentials = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // Deposit amount in gwei. - uint64 amount = 3; + // Deposit amount in gwei. + uint64 amount = 3; - // 96 byte signature from the validators public key. - bytes signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; - } + // 96 byte signature from the validators public key. + bytes signature = 4 [ (ethereum.eth.ext.ssz_size) = "96" ]; + } - // 32 byte roots in the deposit tree branch. - repeated bytes proof = 1 [(ethereum.eth.ext.ssz_size) = "33,32"]; + // 32 byte roots in the deposit tree branch. + repeated bytes proof = 1 [ (ethereum.eth.ext.ssz_size) = "33,32" ]; - Data data = 2; + Data data = 2; } - // A message that represents a validator signaling that they want to voluntarily // withdraw from the active validator set. The message does not contain a // validator signature. message VoluntaryExit { - // The epoch on when exit request becomes valid. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Index of the exiting validator. - uint64 validator_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // The epoch on when exit request becomes valid. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Index of the exiting validator. + uint64 validator_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } // The signed version of voluntary exit. message SignedVoluntaryExit { - // The unsigned voluntary exit itself. - VoluntaryExit message = 1; + // The unsigned voluntary exit itself. + VoluntaryExit message = 1; - // Validator's 96 byte signature - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // Validator's 96 byte signature + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } // Eth1Data represents references to the Ethereum 1.x deposit contract. message Eth1Data { - // The 32 byte deposit tree root for the last deposit included in this - // block. - bytes deposit_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + // The 32 byte deposit tree root for the last deposit included in this + // block. + bytes deposit_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The total number of deposits included in the beacon chain since genesis - // including the deposits in this block. - uint64 deposit_count = 2; + // The total number of deposits included in the beacon chain since genesis + // including the deposits in this block. + uint64 deposit_count = 2; - // The 32 byte block hash of the Ethereum 1.x block considered for deposit - // inclusion. - bytes block_hash = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // The 32 byte block hash of the Ethereum 1.x block considered for deposit + // inclusion. + bytes block_hash = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; } // A beacon block header is essentially a beacon block with only a reference to @@ -167,45 +185,54 @@ message Eth1Data { // lightweight than a full beacon block. The message does not contain // a validator signature. message BeaconBlockHeader { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 32 byte merkle tree root of the parent ssz encoded block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // 32 byte merkle tree root of the resulting ssz encoded state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - - // 32 byte merkle tree root of the ssz encoded block body. - bytes body_root = 5 [(ethereum.eth.ext.ssz_size) = "32"]; + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; + + // 32 byte merkle tree root of the parent ssz encoded block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // 32 byte merkle tree root of the resulting ssz encoded state after + // processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // 32 byte merkle tree root of the ssz encoded block body. + bytes body_root = 5 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message SignedBeaconBlockHeader { - // The unsigned beacon block header itself. - BeaconBlockHeader message = 1; + // The unsigned beacon block header itself. + BeaconBlockHeader message = 1; - // 96 byte BLS signature from the validator that produced this block header. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this block header. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message IndexedAttestation { - repeated uint64 attesting_indices = 1 [(ethereum.eth.ext.ssz_max) = "2048"]; + repeated uint64 attesting_indices = 1 [ (ethereum.eth.ext.ssz_max) = "2048" ]; - AttestationData data = 2; + AttestationData data = 2; - // 96 bytes aggregate signature. - bytes signature = 3 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 bytes aggregate signature. + bytes signature = 3 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -// The sync aggregate object for the beacon chain to track sync committee votes and to -// support light client infra. +// The sync aggregate object for the beacon chain to track sync committee votes +// and to support light client infra. message SyncAggregate { - // Sync committee bits as Bitvector to track votes. - bytes sync_committee_bits = 1 [(ethereum.eth.ext.ssz_size) = "sync_committee_bytes.size", (ethereum.eth.ext.cast_type) = "sync_committee_bits.type"]; - - // BLS aggregated signature of the sync committee for the ones that voted. - bytes sync_committee_signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // Sync committee bits as Bitvector to track votes. + bytes sync_committee_bits = 1 [ + (ethereum.eth.ext.ssz_size) = "sync_committee_bytes.size", + (ethereum.eth.ext.cast_type) = "sync_committee_bits.type" + ]; + + // BLS aggregated signature of the sync committee for the ones that voted. + bytes sync_committee_signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } diff --git a/proto/eth/v1/beacon_chain.pb.go b/proto/eth/v1/beacon_chain.pb.go index 01b2948ea073..45d171a9263f 100755 --- a/proto/eth/v1/beacon_chain.pb.go +++ b/proto/eth/v1/beacon_chain.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/eth/v1/beacon_chain.proto package v1 diff --git a/proto/eth/v1/beacon_chain.pb.gw.go b/proto/eth/v1/beacon_chain.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v1/beacon_chain.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v1/beacon_chain.proto b/proto/eth/v1/beacon_chain.proto index 9658957c6699..ecb98f6a477f 100644 --- a/proto/eth/v1/beacon_chain.proto +++ b/proto/eth/v1/beacon_chain.proto @@ -27,7 +27,8 @@ option php_namespace = "Ethereum\\Eth\\v1"; // Beacon State API related messages. message StateRequest { - // The state id which can be any of: "head" (canonical head in node's view), - // "genesis", "finalized", "justified", , . - bytes state_id = 1; + // The state id which can be any of: "head" (canonical head in node's view), + // "genesis", "finalized", "justified", , . + bytes state_id = 1; } diff --git a/proto/eth/v1/events.pb.go b/proto/eth/v1/events.pb.go index ad03eb3c9bff..04831bd0a1f3 100755 --- a/proto/eth/v1/events.pb.go +++ b/proto/eth/v1/events.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/eth/v1/events.proto package v1 diff --git a/proto/eth/v1/events.pb.gw.go b/proto/eth/v1/events.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v1/events.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v1/events.proto b/proto/eth/v1/events.proto index 71123e1b3632..fda37ff13172 100644 --- a/proto/eth/v1/events.proto +++ b/proto/eth/v1/events.proto @@ -27,22 +27,25 @@ option php_namespace = "Ethereum\\Eth\\v1"; message EventHead { // Slot of the new chain head. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; // Block root of the new chain head. - bytes block = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes block = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; // State root of the new chain head. - bytes state = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes state = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Whether or not the new chain head is at an epoch transition. bool epoch_transition = 4; // The previous dependent root. - bytes previous_duty_dependent_root = 5 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes previous_duty_dependent_root = 5 [ (ethereum.eth.ext.ssz_size) = "32" ]; // The current dependent root. - bytes current_duty_dependent_root = 6 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes current_duty_dependent_root = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Information about optimistic sync. bool execution_optimistic = 7; @@ -50,10 +53,13 @@ message EventHead { message EventBlock { // The slot of the observed block. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; // The root of the observed block. - bytes block = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes block = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Information about optimistic sync. bool execution_optimistic = 3; @@ -61,25 +67,31 @@ message EventBlock { message EventChainReorg { // The slot of the observed reorg. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; // Depth of the reorg in slots. uint64 depth = 2; // Block root of the old head. - bytes old_head_block = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes old_head_block = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Block root of the new head. - bytes new_head_block = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes new_head_block = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; // State root of the old state. - bytes old_head_state = 5 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes old_head_state = 5 [ (ethereum.eth.ext.ssz_size) = "32" ]; // State root of the new state. - bytes new_head_state = 6 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes new_head_state = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Epoch of the observed reorg. - uint64 epoch = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + uint64 epoch = 7 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; // Information about optimistic sync. bool execution_optimistic = 8; @@ -87,13 +99,16 @@ message EventChainReorg { message EventFinalizedCheckpoint { // Block root of the finalized checkpoint. - bytes block = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes block = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; // State root of the finalized checkpoint. - bytes state = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes state = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Epoch the checkpoint references. - uint64 epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + uint64 epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; // Information about optimistic sync. bool execution_optimistic = 4; diff --git a/proto/eth/v1/gateway.ssz.go b/proto/eth/v1/gateway.ssz.go index 630663138b11..d423f91d3ab7 100644 --- a/proto/eth/v1/gateway.ssz.go +++ b/proto/eth/v1/gateway.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: dc11029a7f019f6c900b35f68bbe0a9ff6ca31ba1f7d8c18518cad810690300d package v1 import ( @@ -2395,7 +2394,10 @@ func (v *Validator) UnmarshalSSZ(buf []byte) error { v.EffectiveBalance = ssz.UnmarshallUint64(buf[80:88]) // Field (3) 'Slashed' - v.Slashed = ssz.UnmarshalBool(buf[88:89]) + v.Slashed, err = ssz.DecodeBool(buf[88:89]) + if err != nil { + return err + } // Field (4) 'ActivationEligibilityEpoch' v.ActivationEligibilityEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[89:97])) diff --git a/proto/eth/v1/node.pb.go b/proto/eth/v1/node.pb.go index dedfdde0f8fe..e5a259a4054a 100755 --- a/proto/eth/v1/node.pb.go +++ b/proto/eth/v1/node.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/eth/v1/node.proto package v1 diff --git a/proto/eth/v1/node.pb.gw.go b/proto/eth/v1/node.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v1/node.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v1/node.proto b/proto/eth/v1/node.proto index 7fcf45ef52b2..63a4785241f8 100644 --- a/proto/eth/v1/node.proto +++ b/proto/eth/v1/node.proto @@ -33,7 +33,8 @@ message Peer { // The address of the peer, as a full multiaddr, for example: // /ip4/37.221.192.134/tcp/13000/p2p/16Uiu2HAm8maLMjag1TAUM52zPfmLbVMGFdwUAWgoHu1HDQLR6e17 string last_seen_p2p_address = 3; - // The connection state of the peer at the moment of the request. (e.g. Connecting) + // The connection state of the peer at the moment of the request. (e.g. + // Connecting) ConnectionState state = 4; // The direction of the connection (inbound/outbound). PeerDirection direction = 5; diff --git a/proto/eth/v1/validator.pb.go b/proto/eth/v1/validator.pb.go index 5af1f1f2acdd..b33c563d72b3 100755 --- a/proto/eth/v1/validator.pb.go +++ b/proto/eth/v1/validator.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/eth/v1/validator.proto package v1 diff --git a/proto/eth/v1/validator.pb.gw.go b/proto/eth/v1/validator.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v1/validator.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v1/validator.proto b/proto/eth/v1/validator.proto index 0285b141a84b..8d8e36d0e864 100644 --- a/proto/eth/v1/validator.proto +++ b/proto/eth/v1/validator.proto @@ -29,69 +29,88 @@ option php_namespace = "Ethereum\\Eth\\v1"; // An Ethereum validator. message Validator { - // 48 byte BLS public key used for the validator's activities. - bytes pubkey = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; - - // 32 byte hash of the withdrawal destination public key. - bytes withdrawal_credentials = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The validators current effective balance in gwei. - uint64 effective_balance = 3; - - // Whether or not the validator has been slashed. - bool slashed = 4; - - // Epoch when the validator became eligible for activation. This field may - // be zero if the validator was present in the Ethereum proof of stake genesis. This - // field is FAR_FUTURE_EPOCH if the validator has not been activated. - uint64 activation_eligibility_epoch = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Epoch when the validator was activated. This field may be zero if the - // validator was present in the Ethereum proof of stake genesis. This field is - // FAR_FUTURE_EPOCH if the validator has not been activated. - uint64 activation_epoch = 6 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Epoch when the validator was exited. This field is FAR_FUTURE_EPOCH if - // the validator has not exited. - // FAR_FUTURE_EPOCH is a constant defined by the official Ethereum Beacon Chain specification: - // https://github.com/ethereum/consensus-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#constants - uint64 exit_epoch = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Epoch when the validator is eligible to withdraw their funds. This field - // is FAR_FUTURE_EPOCH if the validator has not exited. - // FAR_FUTURE_EPOCH is a constant defined by the official Ethereum Beacon Chain specification: - // https://github.com/ethereum/consensus-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#constants - uint64 withdrawable_epoch = 8 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // 48 byte BLS public key used for the validator's activities. + bytes pubkey = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; + + // 32 byte hash of the withdrawal destination public key. + bytes withdrawal_credentials = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // The validators current effective balance in gwei. + uint64 effective_balance = 3; + + // Whether or not the validator has been slashed. + bool slashed = 4; + + // Epoch when the validator became eligible for activation. This field may + // be zero if the validator was present in the Ethereum proof of stake + // genesis. This field is FAR_FUTURE_EPOCH if the validator has not been + // activated. + uint64 activation_eligibility_epoch = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Epoch when the validator was activated. This field may be zero if the + // validator was present in the Ethereum proof of stake genesis. This field is + // FAR_FUTURE_EPOCH if the validator has not been activated. + uint64 activation_epoch = 6 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Epoch when the validator was exited. This field is FAR_FUTURE_EPOCH if + // the validator has not exited. + // FAR_FUTURE_EPOCH is a constant defined by the official Ethereum Beacon + // Chain specification: + // https://github.com/ethereum/consensus-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#constants + uint64 exit_epoch = 7 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Epoch when the validator is eligible to withdraw their funds. This field + // is FAR_FUTURE_EPOCH if the validator has not exited. + // FAR_FUTURE_EPOCH is a constant defined by the official Ethereum Beacon + // Chain specification: + // https://github.com/ethereum/consensus-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#constants + uint64 withdrawable_epoch = 8 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; } enum ValidatorStatus { - PENDING_INITIALIZED = 0; - PENDING_QUEUED = 1; - ACTIVE_ONGOING = 2; - ACTIVE_EXITING = 3; - ACTIVE_SLASHED = 4; - EXITED_UNSLASHED = 5; - EXITED_SLASHED = 6; - WITHDRAWAL_POSSIBLE = 7; - WITHDRAWAL_DONE = 8; - ACTIVE = 9; - PENDING = 10; - EXITED = 11; - WITHDRAWAL = 12; + PENDING_INITIALIZED = 0; + PENDING_QUEUED = 1; + ACTIVE_ONGOING = 2; + ACTIVE_EXITING = 3; + ACTIVE_SLASHED = 4; + EXITED_UNSLASHED = 5; + EXITED_SLASHED = 6; + WITHDRAWAL_POSSIBLE = 7; + WITHDRAWAL_DONE = 8; + ACTIVE = 9; + PENDING = 10; + EXITED = 11; + WITHDRAWAL = 12; } message ProduceBlockRequest { - // The slot to request a block for. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 2 [(ethereum.eth.ext.ssz_size) = "96"]; - - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - optional bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // The slot to request a block for. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; + + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + optional bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; } -message ProduceBlockResponse { - BeaconBlock data = 1; -} \ No newline at end of file +message ProduceBlockResponse { BeaconBlock data = 1; } \ No newline at end of file diff --git a/proto/eth/v2/BUILD.bazel b/proto/eth/v2/BUILD.bazel deleted file mode 100644 index f5a6728a6e9f..000000000000 --- a/proto/eth/v2/BUILD.bazel +++ /dev/null @@ -1,112 +0,0 @@ -############################################################################## -# Common -############################################################################## - -load("@rules_proto//proto:defs.bzl", "proto_library") - -# gazelle:ignore -proto_library( - name = "proto", - srcs = [ - "ssz.proto", - "version.proto", - ":ssz_proto_files", - ], - visibility = ["//visibility:public"], - deps = [ - "//proto/engine/v1:proto", - "//proto/eth/ext:proto", - "//proto/eth/v1:proto", - ], -) - -############################################################################## -# Go -############################################################################## -load("@io_bazel_rules_go//go:def.bzl", "go_library") -load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") -load("//proto:ssz_proto_library.bzl", "ssz_proto_files") -load("//tools:ssz.bzl", "SSZ_DEPS", "ssz_gen_marshal") - -ssz_gen_marshal( - name = "ssz_generated_files", - go_proto = ":go_proto", - out = "grpc.ssz.go", - includes = [ - "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", - "//proto/eth/v1:go_default_library", - ], - objs = [ - "BlsToExecutionChange", - "SignedBeaconBlockAltair", - "SignedBeaconBlockBellatrix", - "SignedBlindedBeaconBlockBellatrix", - "SignedBeaconBlockCapella", - "SignedBlindedBeaconBlockCapella", - "SignedBeaconBlockDeneb", - "SignedBlindedBeaconBlockDeneb", - "BlsToExecutionChange", - "SignedBlsToExecutionChange", - "SignedBeaconBlockContentsDeneb", - "BeaconBlockContentsDeneb", - "SyncCommittee", - "BlobIdentifier", - ], -) - -go_proto_library( - name = "go_proto", - compilers = [ - "@com_github_prysmaticlabs_protoc_gen_go_cast//:go_cast_grpc", - ], - importpath = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2", - proto = ":proto", - visibility = ["//visibility:public"], - deps = [ - "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", - "//proto/eth/ext:go_default_library", - "//proto/eth/v1:go_default_library", - "@com_github_golang_protobuf//proto:go_default_library", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - ], -) - -go_proto_library( - name = "go_grpc_gateway_library", - compilers = [ - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway", - ], - embed = [":go_proto"], - importpath = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2", - protos = [":proto"], - visibility = ["//proto:__subpackages__"], -) - -go_library( - name = "go_default_library", - srcs = [ - ":ssz_generated_files", - ], - embed = [":go_grpc_gateway_library"], - importpath = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2", - visibility = ["//visibility:public"], - deps = SSZ_DEPS, -) - -ssz_proto_files( - name = "ssz_proto_files", - srcs = [ - "beacon_block.proto", - "beacon_lightclient.proto", - "sync_committee.proto", - "validator.proto", - "withdrawals.proto", - ], - config = select({ - "//conditions:default": "mainnet", - "//proto:ssz_mainnet": "mainnet", - "//proto:ssz_minimal": "minimal", - }), -) diff --git a/proto/eth/v2/beacon_block.pb.go b/proto/eth/v2/beacon_block.pb.go deleted file mode 100755 index d499629d898d..000000000000 --- a/proto/eth/v2/beacon_block.pb.go +++ /dev/null @@ -1,4192 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 -// source: proto/eth/v2/beacon_block.proto - -package eth - -import ( - reflect "reflect" - sync "sync" - - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" - _ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext" - v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type BeaconBlockContainerV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Block: - // - // *BeaconBlockContainerV2_Phase0Block - // *BeaconBlockContainerV2_AltairBlock - // *BeaconBlockContainerV2_BellatrixBlock - // *BeaconBlockContainerV2_CapellaBlock - // *BeaconBlockContainerV2_DenebContents - Block isBeaconBlockContainerV2_Block `protobuf_oneof:"block"` -} - -func (x *BeaconBlockContainerV2) Reset() { - *x = BeaconBlockContainerV2{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockContainerV2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockContainerV2) ProtoMessage() {} - -func (x *BeaconBlockContainerV2) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockContainerV2.ProtoReflect.Descriptor instead. -func (*BeaconBlockContainerV2) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{0} -} - -func (m *BeaconBlockContainerV2) GetBlock() isBeaconBlockContainerV2_Block { - if m != nil { - return m.Block - } - return nil -} - -func (x *BeaconBlockContainerV2) GetPhase0Block() *v1.BeaconBlock { - if x, ok := x.GetBlock().(*BeaconBlockContainerV2_Phase0Block); ok { - return x.Phase0Block - } - return nil -} - -func (x *BeaconBlockContainerV2) GetAltairBlock() *BeaconBlockAltair { - if x, ok := x.GetBlock().(*BeaconBlockContainerV2_AltairBlock); ok { - return x.AltairBlock - } - return nil -} - -func (x *BeaconBlockContainerV2) GetBellatrixBlock() *BeaconBlockBellatrix { - if x, ok := x.GetBlock().(*BeaconBlockContainerV2_BellatrixBlock); ok { - return x.BellatrixBlock - } - return nil -} - -func (x *BeaconBlockContainerV2) GetCapellaBlock() *BeaconBlockCapella { - if x, ok := x.GetBlock().(*BeaconBlockContainerV2_CapellaBlock); ok { - return x.CapellaBlock - } - return nil -} - -func (x *BeaconBlockContainerV2) GetDenebContents() *BeaconBlockContentsDeneb { - if x, ok := x.GetBlock().(*BeaconBlockContainerV2_DenebContents); ok { - return x.DenebContents - } - return nil -} - -type isBeaconBlockContainerV2_Block interface { - isBeaconBlockContainerV2_Block() -} - -type BeaconBlockContainerV2_Phase0Block struct { - Phase0Block *v1.BeaconBlock `protobuf:"bytes,1,opt,name=phase0_block,json=phase0Block,proto3,oneof"` -} - -type BeaconBlockContainerV2_AltairBlock struct { - AltairBlock *BeaconBlockAltair `protobuf:"bytes,2,opt,name=altair_block,json=altairBlock,proto3,oneof"` -} - -type BeaconBlockContainerV2_BellatrixBlock struct { - BellatrixBlock *BeaconBlockBellatrix `protobuf:"bytes,3,opt,name=bellatrix_block,json=bellatrixBlock,proto3,oneof"` -} - -type BeaconBlockContainerV2_CapellaBlock struct { - CapellaBlock *BeaconBlockCapella `protobuf:"bytes,4,opt,name=capella_block,json=capellaBlock,proto3,oneof"` -} - -type BeaconBlockContainerV2_DenebContents struct { - DenebContents *BeaconBlockContentsDeneb `protobuf:"bytes,5,opt,name=deneb_contents,json=denebContents,proto3,oneof"` -} - -func (*BeaconBlockContainerV2_Phase0Block) isBeaconBlockContainerV2_Block() {} - -func (*BeaconBlockContainerV2_AltairBlock) isBeaconBlockContainerV2_Block() {} - -func (*BeaconBlockContainerV2_BellatrixBlock) isBeaconBlockContainerV2_Block() {} - -func (*BeaconBlockContainerV2_CapellaBlock) isBeaconBlockContainerV2_Block() {} - -func (*BeaconBlockContainerV2_DenebContents) isBeaconBlockContainerV2_Block() {} - -type SignedBeaconBlockContainer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Message: - // - // *SignedBeaconBlockContainer_Phase0Block - // *SignedBeaconBlockContainer_AltairBlock - // *SignedBeaconBlockContainer_BellatrixBlock - // *SignedBeaconBlockContainer_CapellaBlock - // *SignedBeaconBlockContainer_DenebBlock - Message isSignedBeaconBlockContainer_Message `protobuf_oneof:"message"` - Signature []byte `protobuf:"bytes,6,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBeaconBlockContainer) Reset() { - *x = SignedBeaconBlockContainer{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockContainer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockContainer) ProtoMessage() {} - -func (x *SignedBeaconBlockContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockContainer.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockContainer) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{1} -} - -func (m *SignedBeaconBlockContainer) GetMessage() isSignedBeaconBlockContainer_Message { - if m != nil { - return m.Message - } - return nil -} - -func (x *SignedBeaconBlockContainer) GetPhase0Block() *v1.BeaconBlock { - if x, ok := x.GetMessage().(*SignedBeaconBlockContainer_Phase0Block); ok { - return x.Phase0Block - } - return nil -} - -func (x *SignedBeaconBlockContainer) GetAltairBlock() *BeaconBlockAltair { - if x, ok := x.GetMessage().(*SignedBeaconBlockContainer_AltairBlock); ok { - return x.AltairBlock - } - return nil -} - -func (x *SignedBeaconBlockContainer) GetBellatrixBlock() *BeaconBlockBellatrix { - if x, ok := x.GetMessage().(*SignedBeaconBlockContainer_BellatrixBlock); ok { - return x.BellatrixBlock - } - return nil -} - -func (x *SignedBeaconBlockContainer) GetCapellaBlock() *BeaconBlockCapella { - if x, ok := x.GetMessage().(*SignedBeaconBlockContainer_CapellaBlock); ok { - return x.CapellaBlock - } - return nil -} - -func (x *SignedBeaconBlockContainer) GetDenebBlock() *BeaconBlockDeneb { - if x, ok := x.GetMessage().(*SignedBeaconBlockContainer_DenebBlock); ok { - return x.DenebBlock - } - return nil -} - -func (x *SignedBeaconBlockContainer) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type isSignedBeaconBlockContainer_Message interface { - isSignedBeaconBlockContainer_Message() -} - -type SignedBeaconBlockContainer_Phase0Block struct { - Phase0Block *v1.BeaconBlock `protobuf:"bytes,1,opt,name=phase0_block,json=phase0Block,proto3,oneof"` -} - -type SignedBeaconBlockContainer_AltairBlock struct { - AltairBlock *BeaconBlockAltair `protobuf:"bytes,2,opt,name=altair_block,json=altairBlock,proto3,oneof"` -} - -type SignedBeaconBlockContainer_BellatrixBlock struct { - BellatrixBlock *BeaconBlockBellatrix `protobuf:"bytes,3,opt,name=bellatrix_block,json=bellatrixBlock,proto3,oneof"` -} - -type SignedBeaconBlockContainer_CapellaBlock struct { - CapellaBlock *BeaconBlockCapella `protobuf:"bytes,4,opt,name=capella_block,json=capellaBlock,proto3,oneof"` -} - -type SignedBeaconBlockContainer_DenebBlock struct { - DenebBlock *BeaconBlockDeneb `protobuf:"bytes,5,opt,name=deneb_block,json=denebBlock,proto3,oneof"` -} - -func (*SignedBeaconBlockContainer_Phase0Block) isSignedBeaconBlockContainer_Message() {} - -func (*SignedBeaconBlockContainer_AltairBlock) isSignedBeaconBlockContainer_Message() {} - -func (*SignedBeaconBlockContainer_BellatrixBlock) isSignedBeaconBlockContainer_Message() {} - -func (*SignedBeaconBlockContainer_CapellaBlock) isSignedBeaconBlockContainer_Message() {} - -func (*SignedBeaconBlockContainer_DenebBlock) isSignedBeaconBlockContainer_Message() {} - -type SignedBeaconBlockContentsContainer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Message: - // - // *SignedBeaconBlockContentsContainer_Phase0Block - // *SignedBeaconBlockContentsContainer_AltairBlock - // *SignedBeaconBlockContentsContainer_BellatrixBlock - // *SignedBeaconBlockContentsContainer_CapellaBlock - // *SignedBeaconBlockContentsContainer_DenebContents - Message isSignedBeaconBlockContentsContainer_Message `protobuf_oneof:"message"` -} - -func (x *SignedBeaconBlockContentsContainer) Reset() { - *x = SignedBeaconBlockContentsContainer{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockContentsContainer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockContentsContainer) ProtoMessage() {} - -func (x *SignedBeaconBlockContentsContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockContentsContainer.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockContentsContainer) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{2} -} - -func (m *SignedBeaconBlockContentsContainer) GetMessage() isSignedBeaconBlockContentsContainer_Message { - if m != nil { - return m.Message - } - return nil -} - -func (x *SignedBeaconBlockContentsContainer) GetPhase0Block() *v1.SignedBeaconBlock { - if x, ok := x.GetMessage().(*SignedBeaconBlockContentsContainer_Phase0Block); ok { - return x.Phase0Block - } - return nil -} - -func (x *SignedBeaconBlockContentsContainer) GetAltairBlock() *SignedBeaconBlockAltair { - if x, ok := x.GetMessage().(*SignedBeaconBlockContentsContainer_AltairBlock); ok { - return x.AltairBlock - } - return nil -} - -func (x *SignedBeaconBlockContentsContainer) GetBellatrixBlock() *SignedBeaconBlockBellatrix { - if x, ok := x.GetMessage().(*SignedBeaconBlockContentsContainer_BellatrixBlock); ok { - return x.BellatrixBlock - } - return nil -} - -func (x *SignedBeaconBlockContentsContainer) GetCapellaBlock() *SignedBeaconBlockCapella { - if x, ok := x.GetMessage().(*SignedBeaconBlockContentsContainer_CapellaBlock); ok { - return x.CapellaBlock - } - return nil -} - -func (x *SignedBeaconBlockContentsContainer) GetDenebContents() *SignedBeaconBlockContentsDeneb { - if x, ok := x.GetMessage().(*SignedBeaconBlockContentsContainer_DenebContents); ok { - return x.DenebContents - } - return nil -} - -type isSignedBeaconBlockContentsContainer_Message interface { - isSignedBeaconBlockContentsContainer_Message() -} - -type SignedBeaconBlockContentsContainer_Phase0Block struct { - Phase0Block *v1.SignedBeaconBlock `protobuf:"bytes,1,opt,name=phase0_block,json=phase0Block,proto3,oneof"` -} - -type SignedBeaconBlockContentsContainer_AltairBlock struct { - AltairBlock *SignedBeaconBlockAltair `protobuf:"bytes,2,opt,name=altair_block,json=altairBlock,proto3,oneof"` -} - -type SignedBeaconBlockContentsContainer_BellatrixBlock struct { - BellatrixBlock *SignedBeaconBlockBellatrix `protobuf:"bytes,3,opt,name=bellatrix_block,json=bellatrixBlock,proto3,oneof"` -} - -type SignedBeaconBlockContentsContainer_CapellaBlock struct { - CapellaBlock *SignedBeaconBlockCapella `protobuf:"bytes,4,opt,name=capella_block,json=capellaBlock,proto3,oneof"` -} - -type SignedBeaconBlockContentsContainer_DenebContents struct { - DenebContents *SignedBeaconBlockContentsDeneb `protobuf:"bytes,5,opt,name=deneb_contents,json=denebContents,proto3,oneof"` -} - -func (*SignedBeaconBlockContentsContainer_Phase0Block) isSignedBeaconBlockContentsContainer_Message() { -} - -func (*SignedBeaconBlockContentsContainer_AltairBlock) isSignedBeaconBlockContentsContainer_Message() { -} - -func (*SignedBeaconBlockContentsContainer_BellatrixBlock) isSignedBeaconBlockContentsContainer_Message() { -} - -func (*SignedBeaconBlockContentsContainer_CapellaBlock) isSignedBeaconBlockContentsContainer_Message() { -} - -func (*SignedBeaconBlockContentsContainer_DenebContents) isSignedBeaconBlockContentsContainer_Message() { -} - -type BlindedBeaconBlockContainer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Block: - // - // *BlindedBeaconBlockContainer_Phase0Block - // *BlindedBeaconBlockContainer_AltairBlock - // *BlindedBeaconBlockContainer_BellatrixBlock - // *BlindedBeaconBlockContainer_CapellaBlock - // *BlindedBeaconBlockContainer_DenebBlock - Block isBlindedBeaconBlockContainer_Block `protobuf_oneof:"block"` -} - -func (x *BlindedBeaconBlockContainer) Reset() { - *x = BlindedBeaconBlockContainer{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlindedBeaconBlockContainer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlindedBeaconBlockContainer) ProtoMessage() {} - -func (x *BlindedBeaconBlockContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlindedBeaconBlockContainer.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockContainer) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{3} -} - -func (m *BlindedBeaconBlockContainer) GetBlock() isBlindedBeaconBlockContainer_Block { - if m != nil { - return m.Block - } - return nil -} - -func (x *BlindedBeaconBlockContainer) GetPhase0Block() *v1.BeaconBlock { - if x, ok := x.GetBlock().(*BlindedBeaconBlockContainer_Phase0Block); ok { - return x.Phase0Block - } - return nil -} - -func (x *BlindedBeaconBlockContainer) GetAltairBlock() *BeaconBlockAltair { - if x, ok := x.GetBlock().(*BlindedBeaconBlockContainer_AltairBlock); ok { - return x.AltairBlock - } - return nil -} - -func (x *BlindedBeaconBlockContainer) GetBellatrixBlock() *BlindedBeaconBlockBellatrix { - if x, ok := x.GetBlock().(*BlindedBeaconBlockContainer_BellatrixBlock); ok { - return x.BellatrixBlock - } - return nil -} - -func (x *BlindedBeaconBlockContainer) GetCapellaBlock() *BlindedBeaconBlockCapella { - if x, ok := x.GetBlock().(*BlindedBeaconBlockContainer_CapellaBlock); ok { - return x.CapellaBlock - } - return nil -} - -func (x *BlindedBeaconBlockContainer) GetDenebBlock() *BlindedBeaconBlockDeneb { - if x, ok := x.GetBlock().(*BlindedBeaconBlockContainer_DenebBlock); ok { - return x.DenebBlock - } - return nil -} - -type isBlindedBeaconBlockContainer_Block interface { - isBlindedBeaconBlockContainer_Block() -} - -type BlindedBeaconBlockContainer_Phase0Block struct { - Phase0Block *v1.BeaconBlock `protobuf:"bytes,1,opt,name=phase0_block,json=phase0Block,proto3,oneof"` -} - -type BlindedBeaconBlockContainer_AltairBlock struct { - AltairBlock *BeaconBlockAltair `protobuf:"bytes,2,opt,name=altair_block,json=altairBlock,proto3,oneof"` -} - -type BlindedBeaconBlockContainer_BellatrixBlock struct { - BellatrixBlock *BlindedBeaconBlockBellatrix `protobuf:"bytes,3,opt,name=bellatrix_block,json=bellatrixBlock,proto3,oneof"` -} - -type BlindedBeaconBlockContainer_CapellaBlock struct { - CapellaBlock *BlindedBeaconBlockCapella `protobuf:"bytes,4,opt,name=capella_block,json=capellaBlock,proto3,oneof"` -} - -type BlindedBeaconBlockContainer_DenebBlock struct { - DenebBlock *BlindedBeaconBlockDeneb `protobuf:"bytes,5,opt,name=deneb_block,json=denebBlock,proto3,oneof"` -} - -func (*BlindedBeaconBlockContainer_Phase0Block) isBlindedBeaconBlockContainer_Block() {} - -func (*BlindedBeaconBlockContainer_AltairBlock) isBlindedBeaconBlockContainer_Block() {} - -func (*BlindedBeaconBlockContainer_BellatrixBlock) isBlindedBeaconBlockContainer_Block() {} - -func (*BlindedBeaconBlockContainer_CapellaBlock) isBlindedBeaconBlockContainer_Block() {} - -func (*BlindedBeaconBlockContainer_DenebBlock) isBlindedBeaconBlockContainer_Block() {} - -type SignedBlindedBeaconBlockContainer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Message: - // - // *SignedBlindedBeaconBlockContainer_Phase0Block - // *SignedBlindedBeaconBlockContainer_AltairBlock - // *SignedBlindedBeaconBlockContainer_BellatrixBlock - // *SignedBlindedBeaconBlockContainer_CapellaBlock - // *SignedBlindedBeaconBlockContainer_DenebBlock - Message isSignedBlindedBeaconBlockContainer_Message `protobuf_oneof:"message"` - Signature []byte `protobuf:"bytes,6,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBlindedBeaconBlockContainer) Reset() { - *x = SignedBlindedBeaconBlockContainer{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBlindedBeaconBlockContainer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBlindedBeaconBlockContainer) ProtoMessage() {} - -func (x *SignedBlindedBeaconBlockContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBlindedBeaconBlockContainer.ProtoReflect.Descriptor instead. -func (*SignedBlindedBeaconBlockContainer) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{4} -} - -func (m *SignedBlindedBeaconBlockContainer) GetMessage() isSignedBlindedBeaconBlockContainer_Message { - if m != nil { - return m.Message - } - return nil -} - -func (x *SignedBlindedBeaconBlockContainer) GetPhase0Block() *v1.BeaconBlock { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContainer_Phase0Block); ok { - return x.Phase0Block - } - return nil -} - -func (x *SignedBlindedBeaconBlockContainer) GetAltairBlock() *BeaconBlockAltair { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContainer_AltairBlock); ok { - return x.AltairBlock - } - return nil -} - -func (x *SignedBlindedBeaconBlockContainer) GetBellatrixBlock() *BlindedBeaconBlockBellatrix { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContainer_BellatrixBlock); ok { - return x.BellatrixBlock - } - return nil -} - -func (x *SignedBlindedBeaconBlockContainer) GetCapellaBlock() *BlindedBeaconBlockCapella { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContainer_CapellaBlock); ok { - return x.CapellaBlock - } - return nil -} - -func (x *SignedBlindedBeaconBlockContainer) GetDenebBlock() *BlindedBeaconBlockDeneb { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContainer_DenebBlock); ok { - return x.DenebBlock - } - return nil -} - -func (x *SignedBlindedBeaconBlockContainer) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type isSignedBlindedBeaconBlockContainer_Message interface { - isSignedBlindedBeaconBlockContainer_Message() -} - -type SignedBlindedBeaconBlockContainer_Phase0Block struct { - Phase0Block *v1.BeaconBlock `protobuf:"bytes,1,opt,name=phase0_block,json=phase0Block,proto3,oneof"` -} - -type SignedBlindedBeaconBlockContainer_AltairBlock struct { - AltairBlock *BeaconBlockAltair `protobuf:"bytes,2,opt,name=altair_block,json=altairBlock,proto3,oneof"` -} - -type SignedBlindedBeaconBlockContainer_BellatrixBlock struct { - BellatrixBlock *BlindedBeaconBlockBellatrix `protobuf:"bytes,3,opt,name=bellatrix_block,json=bellatrixBlock,proto3,oneof"` -} - -type SignedBlindedBeaconBlockContainer_CapellaBlock struct { - CapellaBlock *BlindedBeaconBlockCapella `protobuf:"bytes,4,opt,name=capella_block,json=capellaBlock,proto3,oneof"` -} - -type SignedBlindedBeaconBlockContainer_DenebBlock struct { - DenebBlock *BlindedBeaconBlockDeneb `protobuf:"bytes,5,opt,name=deneb_block,json=denebBlock,proto3,oneof"` -} - -func (*SignedBlindedBeaconBlockContainer_Phase0Block) isSignedBlindedBeaconBlockContainer_Message() {} - -func (*SignedBlindedBeaconBlockContainer_AltairBlock) isSignedBlindedBeaconBlockContainer_Message() {} - -func (*SignedBlindedBeaconBlockContainer_BellatrixBlock) isSignedBlindedBeaconBlockContainer_Message() { -} - -func (*SignedBlindedBeaconBlockContainer_CapellaBlock) isSignedBlindedBeaconBlockContainer_Message() { -} - -func (*SignedBlindedBeaconBlockContainer_DenebBlock) isSignedBlindedBeaconBlockContainer_Message() {} - -type SignedBlindedBeaconBlockContentsContainer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Message: - // - // *SignedBlindedBeaconBlockContentsContainer_Phase0Block - // *SignedBlindedBeaconBlockContentsContainer_AltairBlock - // *SignedBlindedBeaconBlockContentsContainer_BellatrixBlock - // *SignedBlindedBeaconBlockContentsContainer_CapellaBlock - // *SignedBlindedBeaconBlockContentsContainer_DenebBlock - Message isSignedBlindedBeaconBlockContentsContainer_Message `protobuf_oneof:"message"` -} - -func (x *SignedBlindedBeaconBlockContentsContainer) Reset() { - *x = SignedBlindedBeaconBlockContentsContainer{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBlindedBeaconBlockContentsContainer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBlindedBeaconBlockContentsContainer) ProtoMessage() {} - -func (x *SignedBlindedBeaconBlockContentsContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBlindedBeaconBlockContentsContainer.ProtoReflect.Descriptor instead. -func (*SignedBlindedBeaconBlockContentsContainer) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{5} -} - -func (m *SignedBlindedBeaconBlockContentsContainer) GetMessage() isSignedBlindedBeaconBlockContentsContainer_Message { - if m != nil { - return m.Message - } - return nil -} - -func (x *SignedBlindedBeaconBlockContentsContainer) GetPhase0Block() *v1.SignedBeaconBlock { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContentsContainer_Phase0Block); ok { - return x.Phase0Block - } - return nil -} - -func (x *SignedBlindedBeaconBlockContentsContainer) GetAltairBlock() *SignedBeaconBlockAltair { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContentsContainer_AltairBlock); ok { - return x.AltairBlock - } - return nil -} - -func (x *SignedBlindedBeaconBlockContentsContainer) GetBellatrixBlock() *SignedBlindedBeaconBlockBellatrix { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContentsContainer_BellatrixBlock); ok { - return x.BellatrixBlock - } - return nil -} - -func (x *SignedBlindedBeaconBlockContentsContainer) GetCapellaBlock() *SignedBlindedBeaconBlockCapella { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContentsContainer_CapellaBlock); ok { - return x.CapellaBlock - } - return nil -} - -func (x *SignedBlindedBeaconBlockContentsContainer) GetDenebBlock() *SignedBlindedBeaconBlockDeneb { - if x, ok := x.GetMessage().(*SignedBlindedBeaconBlockContentsContainer_DenebBlock); ok { - return x.DenebBlock - } - return nil -} - -type isSignedBlindedBeaconBlockContentsContainer_Message interface { - isSignedBlindedBeaconBlockContentsContainer_Message() -} - -type SignedBlindedBeaconBlockContentsContainer_Phase0Block struct { - Phase0Block *v1.SignedBeaconBlock `protobuf:"bytes,1,opt,name=phase0_block,json=phase0Block,proto3,oneof"` -} - -type SignedBlindedBeaconBlockContentsContainer_AltairBlock struct { - AltairBlock *SignedBeaconBlockAltair `protobuf:"bytes,2,opt,name=altair_block,json=altairBlock,proto3,oneof"` -} - -type SignedBlindedBeaconBlockContentsContainer_BellatrixBlock struct { - BellatrixBlock *SignedBlindedBeaconBlockBellatrix `protobuf:"bytes,3,opt,name=bellatrix_block,json=bellatrixBlock,proto3,oneof"` -} - -type SignedBlindedBeaconBlockContentsContainer_CapellaBlock struct { - CapellaBlock *SignedBlindedBeaconBlockCapella `protobuf:"bytes,4,opt,name=capella_block,json=capellaBlock,proto3,oneof"` -} - -type SignedBlindedBeaconBlockContentsContainer_DenebBlock struct { - DenebBlock *SignedBlindedBeaconBlockDeneb `protobuf:"bytes,5,opt,name=deneb_block,json=denebBlock,proto3,oneof"` -} - -func (*SignedBlindedBeaconBlockContentsContainer_Phase0Block) isSignedBlindedBeaconBlockContentsContainer_Message() { -} - -func (*SignedBlindedBeaconBlockContentsContainer_AltairBlock) isSignedBlindedBeaconBlockContentsContainer_Message() { -} - -func (*SignedBlindedBeaconBlockContentsContainer_BellatrixBlock) isSignedBlindedBeaconBlockContentsContainer_Message() { -} - -func (*SignedBlindedBeaconBlockContentsContainer_CapellaBlock) isSignedBlindedBeaconBlockContentsContainer_Message() { -} - -func (*SignedBlindedBeaconBlockContentsContainer_DenebBlock) isSignedBlindedBeaconBlockContentsContainer_Message() { -} - -type SignedBeaconBlockAltair struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BeaconBlockAltair `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBeaconBlockAltair) Reset() { - *x = SignedBeaconBlockAltair{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockAltair) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockAltair) ProtoMessage() {} - -func (x *SignedBeaconBlockAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockAltair.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockAltair) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{6} -} - -func (x *SignedBeaconBlockAltair) GetMessage() *BeaconBlockAltair { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBeaconBlockAltair) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type SignedBeaconBlockBellatrix struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BeaconBlockBellatrix `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBeaconBlockBellatrix) Reset() { - *x = SignedBeaconBlockBellatrix{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockBellatrix) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockBellatrix) ProtoMessage() {} - -func (x *SignedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{7} -} - -func (x *SignedBeaconBlockBellatrix) GetMessage() *BeaconBlockBellatrix { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBeaconBlockBellatrix) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type SignedBeaconBlockCapella struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BeaconBlockCapella `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBeaconBlockCapella) Reset() { - *x = SignedBeaconBlockCapella{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockCapella) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockCapella) ProtoMessage() {} - -func (x *SignedBeaconBlockCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockCapella.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockCapella) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{8} -} - -func (x *SignedBeaconBlockCapella) GetMessage() *BeaconBlockCapella { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBeaconBlockCapella) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type SignedBeaconBlockDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BeaconBlockDeneb `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBeaconBlockDeneb) Reset() { - *x = SignedBeaconBlockDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockDeneb) ProtoMessage() {} - -func (x *SignedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockDeneb.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockDeneb) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{9} -} - -func (x *SignedBeaconBlockDeneb) GetMessage() *BeaconBlockDeneb { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBeaconBlockDeneb) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type SignedBlindedBeaconBlockBellatrix struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BlindedBeaconBlockBellatrix `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBlindedBeaconBlockBellatrix) Reset() { - *x = SignedBlindedBeaconBlockBellatrix{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBlindedBeaconBlockBellatrix) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBlindedBeaconBlockBellatrix) ProtoMessage() {} - -func (x *SignedBlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBlindedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. -func (*SignedBlindedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{10} -} - -func (x *SignedBlindedBeaconBlockBellatrix) GetMessage() *BlindedBeaconBlockBellatrix { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBlindedBeaconBlockBellatrix) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type SignedBlindedBeaconBlockCapella struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BlindedBeaconBlockCapella `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBlindedBeaconBlockCapella) Reset() { - *x = SignedBlindedBeaconBlockCapella{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBlindedBeaconBlockCapella) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBlindedBeaconBlockCapella) ProtoMessage() {} - -func (x *SignedBlindedBeaconBlockCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBlindedBeaconBlockCapella.ProtoReflect.Descriptor instead. -func (*SignedBlindedBeaconBlockCapella) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{11} -} - -func (x *SignedBlindedBeaconBlockCapella) GetMessage() *BlindedBeaconBlockCapella { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBlindedBeaconBlockCapella) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type SignedBlindedBeaconBlockDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BlindedBeaconBlockDeneb `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBlindedBeaconBlockDeneb) Reset() { - *x = SignedBlindedBeaconBlockDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBlindedBeaconBlockDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBlindedBeaconBlockDeneb) ProtoMessage() {} - -func (x *SignedBlindedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBlindedBeaconBlockDeneb.ProtoReflect.Descriptor instead. -func (*SignedBlindedBeaconBlockDeneb) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{12} -} - -func (x *SignedBlindedBeaconBlockDeneb) GetMessage() *BlindedBeaconBlockDeneb { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBlindedBeaconBlockDeneb) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type BeaconBlockAltair struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyAltair `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BeaconBlockAltair) Reset() { - *x = BeaconBlockAltair{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockAltair) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockAltair) ProtoMessage() {} - -func (x *BeaconBlockAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockAltair.ProtoReflect.Descriptor instead. -func (*BeaconBlockAltair) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{13} -} - -func (x *BeaconBlockAltair) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BeaconBlockAltair) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BeaconBlockAltair) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BeaconBlockAltair) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *BeaconBlockAltair) GetBody() *BeaconBlockBodyAltair { - if x != nil { - return x.Body - } - return nil -} - -type BeaconBlockBellatrix struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyBellatrix `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BeaconBlockBellatrix) Reset() { - *x = BeaconBlockBellatrix{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockBellatrix) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockBellatrix) ProtoMessage() {} - -func (x *BeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockBellatrix.ProtoReflect.Descriptor instead. -func (*BeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{14} -} - -func (x *BeaconBlockBellatrix) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BeaconBlockBellatrix) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BeaconBlockBellatrix) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BeaconBlockBellatrix) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *BeaconBlockBellatrix) GetBody() *BeaconBlockBodyBellatrix { - if x != nil { - return x.Body - } - return nil -} - -type BlindedBeaconBlockBellatrix struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BlindedBeaconBlockBodyBellatrix `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BlindedBeaconBlockBellatrix) Reset() { - *x = BlindedBeaconBlockBellatrix{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlindedBeaconBlockBellatrix) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlindedBeaconBlockBellatrix) ProtoMessage() {} - -func (x *BlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlindedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{15} -} - -func (x *BlindedBeaconBlockBellatrix) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BlindedBeaconBlockBellatrix) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BlindedBeaconBlockBellatrix) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BlindedBeaconBlockBellatrix) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *BlindedBeaconBlockBellatrix) GetBody() *BlindedBeaconBlockBodyBellatrix { - if x != nil { - return x.Body - } - return nil -} - -type BeaconBlockCapella struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyCapella `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BeaconBlockCapella) Reset() { - *x = BeaconBlockCapella{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockCapella) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockCapella) ProtoMessage() {} - -func (x *BeaconBlockCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockCapella.ProtoReflect.Descriptor instead. -func (*BeaconBlockCapella) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{16} -} - -func (x *BeaconBlockCapella) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BeaconBlockCapella) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BeaconBlockCapella) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BeaconBlockCapella) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *BeaconBlockCapella) GetBody() *BeaconBlockBodyCapella { - if x != nil { - return x.Body - } - return nil -} - -type BlindedBeaconBlockCapella struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BlindedBeaconBlockBodyCapella `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BlindedBeaconBlockCapella) Reset() { - *x = BlindedBeaconBlockCapella{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlindedBeaconBlockCapella) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlindedBeaconBlockCapella) ProtoMessage() {} - -func (x *BlindedBeaconBlockCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlindedBeaconBlockCapella.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockCapella) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{17} -} - -func (x *BlindedBeaconBlockCapella) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BlindedBeaconBlockCapella) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BlindedBeaconBlockCapella) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BlindedBeaconBlockCapella) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *BlindedBeaconBlockCapella) GetBody() *BlindedBeaconBlockBodyCapella { - if x != nil { - return x.Body - } - return nil -} - -type BeaconBlockDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyDeneb `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BeaconBlockDeneb) Reset() { - *x = BeaconBlockDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockDeneb) ProtoMessage() {} - -func (x *BeaconBlockDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockDeneb.ProtoReflect.Descriptor instead. -func (*BeaconBlockDeneb) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{18} -} - -func (x *BeaconBlockDeneb) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BeaconBlockDeneb) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BeaconBlockDeneb) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BeaconBlockDeneb) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *BeaconBlockDeneb) GetBody() *BeaconBlockBodyDeneb { - if x != nil { - return x.Body - } - return nil -} - -type BlindedBeaconBlockDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BlindedBeaconBlockBodyDeneb `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BlindedBeaconBlockDeneb) Reset() { - *x = BlindedBeaconBlockDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlindedBeaconBlockDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlindedBeaconBlockDeneb) ProtoMessage() {} - -func (x *BlindedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlindedBeaconBlockDeneb.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockDeneb) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{19} -} - -func (x *BlindedBeaconBlockDeneb) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BlindedBeaconBlockDeneb) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BlindedBeaconBlockDeneb) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BlindedBeaconBlockDeneb) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} - -func (x *BlindedBeaconBlockDeneb) GetBody() *BlindedBeaconBlockBodyDeneb { - if x != nil { - return x.Body - } - return nil -} - -type BeaconBlockBodyAltair struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *v1.Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*v1.ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*v1.AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*v1.Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*v1.Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*v1.SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` -} - -func (x *BeaconBlockBodyAltair) Reset() { - *x = BeaconBlockBodyAltair{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockBodyAltair) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockBodyAltair) ProtoMessage() {} - -func (x *BeaconBlockBodyAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockBodyAltair.ProtoReflect.Descriptor instead. -func (*BeaconBlockBodyAltair) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{20} -} - -func (x *BeaconBlockBodyAltair) GetRandaoReveal() []byte { - if x != nil { - return x.RandaoReveal - } - return nil -} - -func (x *BeaconBlockBodyAltair) GetEth1Data() *v1.Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BeaconBlockBodyAltair) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BeaconBlockBodyAltair) GetProposerSlashings() []*v1.ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BeaconBlockBodyAltair) GetAttesterSlashings() []*v1.AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BeaconBlockBodyAltair) GetAttestations() []*v1.Attestation { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BeaconBlockBodyAltair) GetDeposits() []*v1.Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BeaconBlockBodyAltair) GetVoluntaryExits() []*v1.SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} - -func (x *BeaconBlockBodyAltair) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -type BeaconBlockBodyBellatrix struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *v1.Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*v1.ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*v1.AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*v1.Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*v1.Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*v1.SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayload *v11.ExecutionPayload `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` -} - -func (x *BeaconBlockBodyBellatrix) Reset() { - *x = BeaconBlockBodyBellatrix{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockBodyBellatrix) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockBodyBellatrix) ProtoMessage() {} - -func (x *BeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockBodyBellatrix.ProtoReflect.Descriptor instead. -func (*BeaconBlockBodyBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{21} -} - -func (x *BeaconBlockBodyBellatrix) GetRandaoReveal() []byte { - if x != nil { - return x.RandaoReveal - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetEth1Data() *v1.Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetProposerSlashings() []*v1.ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetAttesterSlashings() []*v1.AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetAttestations() []*v1.Attestation { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetDeposits() []*v1.Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetVoluntaryExits() []*v1.SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *BeaconBlockBodyBellatrix) GetExecutionPayload() *v11.ExecutionPayload { - if x != nil { - return x.ExecutionPayload - } - return nil -} - -type BlindedBeaconBlockBodyBellatrix struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *v1.Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*v1.ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*v1.AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*v1.Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*v1.Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*v1.SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayloadHeader *v11.ExecutionPayloadHeader `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` -} - -func (x *BlindedBeaconBlockBodyBellatrix) Reset() { - *x = BlindedBeaconBlockBodyBellatrix{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlindedBeaconBlockBodyBellatrix) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlindedBeaconBlockBodyBellatrix) ProtoMessage() {} - -func (x *BlindedBeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlindedBeaconBlockBodyBellatrix.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockBodyBellatrix) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{22} -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetRandaoReveal() []byte { - if x != nil { - return x.RandaoReveal - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetEth1Data() *v1.Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetProposerSlashings() []*v1.ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetAttesterSlashings() []*v1.AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetAttestations() []*v1.Attestation { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetDeposits() []*v1.Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetVoluntaryExits() []*v1.SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *BlindedBeaconBlockBodyBellatrix) GetExecutionPayloadHeader() *v11.ExecutionPayloadHeader { - if x != nil { - return x.ExecutionPayloadHeader - } - return nil -} - -type BeaconBlockBodyCapella struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *v1.Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*v1.ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*v1.AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*v1.Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*v1.Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*v1.SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayload *v11.ExecutionPayloadCapella `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` - BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` -} - -func (x *BeaconBlockBodyCapella) Reset() { - *x = BeaconBlockBodyCapella{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockBodyCapella) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockBodyCapella) ProtoMessage() {} - -func (x *BeaconBlockBodyCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockBodyCapella.ProtoReflect.Descriptor instead. -func (*BeaconBlockBodyCapella) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{23} -} - -func (x *BeaconBlockBodyCapella) GetRandaoReveal() []byte { - if x != nil { - return x.RandaoReveal - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetEth1Data() *v1.Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetProposerSlashings() []*v1.ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetAttesterSlashings() []*v1.AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetAttestations() []*v1.Attestation { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetDeposits() []*v1.Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetVoluntaryExits() []*v1.SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetExecutionPayload() *v11.ExecutionPayloadCapella { - if x != nil { - return x.ExecutionPayload - } - return nil -} - -func (x *BeaconBlockBodyCapella) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { - if x != nil { - return x.BlsToExecutionChanges - } - return nil -} - -type BlindedBeaconBlockBodyCapella struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *v1.Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*v1.ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*v1.AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*v1.Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*v1.Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*v1.SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayloadHeader *v11.ExecutionPayloadHeaderCapella `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` - BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` -} - -func (x *BlindedBeaconBlockBodyCapella) Reset() { - *x = BlindedBeaconBlockBodyCapella{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlindedBeaconBlockBodyCapella) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlindedBeaconBlockBodyCapella) ProtoMessage() {} - -func (x *BlindedBeaconBlockBodyCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlindedBeaconBlockBodyCapella.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockBodyCapella) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{24} -} - -func (x *BlindedBeaconBlockBodyCapella) GetRandaoReveal() []byte { - if x != nil { - return x.RandaoReveal - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetEth1Data() *v1.Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetProposerSlashings() []*v1.ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetAttesterSlashings() []*v1.AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetAttestations() []*v1.Attestation { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetDeposits() []*v1.Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetVoluntaryExits() []*v1.SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetExecutionPayloadHeader() *v11.ExecutionPayloadHeaderCapella { - if x != nil { - return x.ExecutionPayloadHeader - } - return nil -} - -func (x *BlindedBeaconBlockBodyCapella) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { - if x != nil { - return x.BlsToExecutionChanges - } - return nil -} - -type BlindedBeaconBlockBodyDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *v1.Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*v1.ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*v1.AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*v1.Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*v1.Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*v1.SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayloadHeader *v11.ExecutionPayloadHeaderDeneb `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` - BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` - BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` -} - -func (x *BlindedBeaconBlockBodyDeneb) Reset() { - *x = BlindedBeaconBlockBodyDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlindedBeaconBlockBodyDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlindedBeaconBlockBodyDeneb) ProtoMessage() {} - -func (x *BlindedBeaconBlockBodyDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlindedBeaconBlockBodyDeneb.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockBodyDeneb) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{25} -} - -func (x *BlindedBeaconBlockBodyDeneb) GetRandaoReveal() []byte { - if x != nil { - return x.RandaoReveal - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetEth1Data() *v1.Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetProposerSlashings() []*v1.ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetAttesterSlashings() []*v1.AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetAttestations() []*v1.Attestation { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetDeposits() []*v1.Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetVoluntaryExits() []*v1.SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetExecutionPayloadHeader() *v11.ExecutionPayloadHeaderDeneb { - if x != nil { - return x.ExecutionPayloadHeader - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { - if x != nil { - return x.BlsToExecutionChanges - } - return nil -} - -func (x *BlindedBeaconBlockBodyDeneb) GetBlobKzgCommitments() [][]byte { - if x != nil { - return x.BlobKzgCommitments - } - return nil -} - -type BeaconBlockBodyDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *v1.Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*v1.ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*v1.AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*v1.Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*v1.Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*v1.SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayload *v11.ExecutionPayloadDeneb `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` - BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` - BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` -} - -func (x *BeaconBlockBodyDeneb) Reset() { - *x = BeaconBlockBodyDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockBodyDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockBodyDeneb) ProtoMessage() {} - -func (x *BeaconBlockBodyDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockBodyDeneb.ProtoReflect.Descriptor instead. -func (*BeaconBlockBodyDeneb) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{26} -} - -func (x *BeaconBlockBodyDeneb) GetRandaoReveal() []byte { - if x != nil { - return x.RandaoReveal - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetEth1Data() *v1.Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetProposerSlashings() []*v1.ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetAttesterSlashings() []*v1.AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetAttestations() []*v1.Attestation { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetDeposits() []*v1.Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetVoluntaryExits() []*v1.SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetExecutionPayload() *v11.ExecutionPayloadDeneb { - if x != nil { - return x.ExecutionPayload - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { - if x != nil { - return x.BlsToExecutionChanges - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetBlobKzgCommitments() [][]byte { - if x != nil { - return x.BlobKzgCommitments - } - return nil -} - -type SignedBeaconBlockContentsDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - SignedBlock *SignedBeaconBlockDeneb `protobuf:"bytes,1,opt,name=signed_block,json=signedBlock,proto3" json:"signed_block,omitempty"` - KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` - Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` -} - -func (x *SignedBeaconBlockContentsDeneb) Reset() { - *x = SignedBeaconBlockContentsDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockContentsDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockContentsDeneb) ProtoMessage() {} - -func (x *SignedBeaconBlockContentsDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockContentsDeneb.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockContentsDeneb) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{27} -} - -func (x *SignedBeaconBlockContentsDeneb) GetSignedBlock() *SignedBeaconBlockDeneb { - if x != nil { - return x.SignedBlock - } - return nil -} - -func (x *SignedBeaconBlockContentsDeneb) GetKzgProofs() [][]byte { - if x != nil { - return x.KzgProofs - } - return nil -} - -func (x *SignedBeaconBlockContentsDeneb) GetBlobs() [][]byte { - if x != nil { - return x.Blobs - } - return nil -} - -type BeaconBlockContentsDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Block *BeaconBlockDeneb `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` - Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` -} - -func (x *BeaconBlockContentsDeneb) Reset() { - *x = BeaconBlockContentsDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockContentsDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockContentsDeneb) ProtoMessage() {} - -func (x *BeaconBlockContentsDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockContentsDeneb.ProtoReflect.Descriptor instead. -func (*BeaconBlockContentsDeneb) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{28} -} - -func (x *BeaconBlockContentsDeneb) GetBlock() *BeaconBlockDeneb { - if x != nil { - return x.Block - } - return nil -} - -func (x *BeaconBlockContentsDeneb) GetKzgProofs() [][]byte { - if x != nil { - return x.KzgProofs - } - return nil -} - -func (x *BeaconBlockContentsDeneb) GetBlobs() [][]byte { - if x != nil { - return x.Blobs - } - return nil -} - -type BlobIdentifier struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BlockRoot []byte `protobuf:"bytes,1,opt,name=block_root,json=blockRoot,proto3" json:"block_root,omitempty" ssz-size:"32"` - Index uint64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` -} - -func (x *BlobIdentifier) Reset() { - *x = BlobIdentifier{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlobIdentifier) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlobIdentifier) ProtoMessage() {} - -func (x *BlobIdentifier) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_block_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlobIdentifier.ProtoReflect.Descriptor instead. -func (*BlobIdentifier) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_block_proto_rawDescGZIP(), []int{29} -} - -func (x *BlobIdentifier) GetBlockRoot() []byte { - if x != nil { - return x.BlockRoot - } - return nil -} - -func (x *BlobIdentifier) GetIndex() uint64 { - if x != nil { - return x.Index - } - return 0 -} - -var File_proto_eth_v2_beacon_block_proto protoreflect.FileDescriptor - -var file_proto_eth_v2_beacon_block_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, - 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x1e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x1e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x77, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, - 0x31, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9f, 0x03, 0x0a, 0x16, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x56, 0x32, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, - 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, - 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, - 0x50, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, - 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x4a, 0x0a, 0x0d, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x48, 0x00, 0x52, - 0x0c, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x52, 0x0a, - 0x0e, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x44, 0x65, 0x6e, 0x65, 0x62, - 0x48, 0x00, 0x52, 0x0d, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0xbd, 0x03, 0x0a, 0x1a, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, - 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, - 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, - 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x50, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, - 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, - 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, - 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, - 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x4a, 0x0a, 0x0d, 0x63, 0x61, 0x70, 0x65, 0x6c, - 0x6c, 0x61, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, - 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, - 0x6c, 0x6c, 0x61, 0x48, 0x00, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x12, 0x44, 0x0a, 0x0b, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x48, 0x00, 0x52, 0x0a, 0x64, - 0x65, 0x6e, 0x65, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, - 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xcb, 0x03, 0x0a, 0x22, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x12, 0x47, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, - 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x4d, 0x0a, 0x0c, 0x61, 0x6c, - 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, - 0x74, 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x56, 0x0a, 0x0f, 0x62, 0x65, 0x6c, - 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, - 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x50, 0x0a, 0x0d, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, - 0x6c, 0x6c, 0x61, 0x48, 0x00, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x12, 0x58, 0x0a, 0x0e, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x48, 0x00, 0x52, 0x0d, - 0x64, 0x65, 0x6e, 0x65, 0x62, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x09, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xab, 0x03, 0x0a, 0x1b, 0x42, 0x6c, 0x69, - 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, - 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, - 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x47, 0x0a, 0x0c, 0x61, - 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, - 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x57, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, - 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x62, - 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x51, 0x0a, - 0x0d, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, - 0x48, 0x00, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x12, 0x4b, 0x0a, 0x0b, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x48, - 0x00, 0x52, 0x0a, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x07, 0x0a, - 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0xd9, 0x03, 0x0a, 0x21, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0c, - 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, - 0x47, 0x0a, 0x0c, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, - 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x57, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, - 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, - 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x51, 0x0a, 0x0d, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, - 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, - 0x65, 0x6c, 0x6c, 0x61, 0x48, 0x00, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x4b, 0x0a, 0x0b, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x5f, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, - 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, - 0x6e, 0x65, 0x62, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0xd9, 0x03, 0x0a, 0x29, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, - 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x12, 0x47, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x68, - 0x61, 0x73, 0x65, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x4d, 0x0a, 0x0c, 0x61, 0x6c, 0x74, - 0x61, 0x69, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x6c, 0x74, - 0x61, 0x69, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x5d, 0x0a, 0x0f, 0x62, 0x65, 0x6c, 0x6c, - 0x61, 0x74, 0x72, 0x69, 0x78, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, - 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, - 0x69, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x57, 0x0a, 0x0d, 0x63, 0x61, 0x70, 0x65, 0x6c, - 0x6c, 0x61, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, - 0x48, 0x00, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x12, 0x51, 0x0a, 0x0b, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, - 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x44, 0x65, 0x6e, 0x65, 0x62, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x7d, - 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x3c, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x83, 0x01, - 0x0a, 0x1a, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x3f, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, - 0x74, 0x72, 0x69, 0x78, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x22, 0x7f, 0x0a, 0x18, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, - 0x3d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, - 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x22, 0x7b, 0x0a, 0x16, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x3b, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, - 0x65, 0x62, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x22, 0x91, 0x01, 0x0a, 0x21, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, - 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, - 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x46, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, - 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, - 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x8d, 0x01, 0x0a, 0x1f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x44, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, - 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, - 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x42, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, - 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, - 0x65, 0x62, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x22, 0xf2, 0x02, 0x0a, 0x11, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, - 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, - 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xf8, 0x02, 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, - 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, - 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, - 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, - 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, - 0x6f, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, - 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x22, 0x86, 0x03, 0x0a, 0x1b, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, - 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, - 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x44, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, - 0x74, 0x72, 0x69, 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xf4, 0x02, 0x0a, 0x12, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, - 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, - 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, - 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x22, 0x82, 0x03, 0x0a, 0x19, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, - 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, - 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, - 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, - 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, - 0x6f, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xf0, 0x02, 0x0a, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x59, 0x0a, 0x04, 0x73, - 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, - 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, - 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, - 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, - 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x39, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, 0x65, - 0x6e, 0x65, 0x62, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xfe, 0x02, 0x0a, 0x17, 0x42, 0x6c, - 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, - 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, - 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, - 0x65, 0x6e, 0x65, 0x62, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xfa, 0x04, 0x0a, 0x15, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x41, 0x6c, - 0x74, 0x61, 0x69, 0x72, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, - 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, - 0x6c, 0x12, 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, - 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, - 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, - 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, - 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, - 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x49, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, - 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, - 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, - 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, - 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, - 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x22, 0xd0, 0x05, 0x0a, 0x18, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, - 0x74, 0x72, 0x69, 0x78, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, - 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, - 0x6c, 0x12, 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, - 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, - 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, - 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, - 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, - 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x49, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, - 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, - 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, - 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, - 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, - 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, - 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xea, 0x05, 0x0a, 0x1f, 0x42, - 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x2b, - 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, - 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x09, 0x65, - 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, - 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, - 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, - 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x0c, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, - 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, - 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, - 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, - 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, - 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x12, 0x64, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, - 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0xc3, 0x06, 0x0a, 0x16, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, 0x70, 0x65, 0x6c, - 0x6c, 0x61, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, - 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, - 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, - 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, - 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, - 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, 0x12, 0x70, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, - 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, - 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x49, - 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, - 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, - 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, - 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x45, - 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x10, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, - 0x6c, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, - 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0xdd, 0x06, - 0x0a, 0x1d, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, - 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, - 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x09, - 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, - 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, - 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, - 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, - 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, - 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x0c, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, - 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, - 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, - 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, - 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x73, - 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, - 0x6c, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, - 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x9d, 0x07, - 0x0a, 0x1b, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x2b, 0x0a, - 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, - 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x09, 0x65, 0x74, - 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, - 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, - 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x58, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, - 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, - 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x49, 0x0a, 0x0c, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, - 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, - 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, - 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, - 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, - 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, - 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x12, 0x69, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, - 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, - 0x6e, 0x65, 0x62, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x6c, 0x0a, 0x18, 0x62, - 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, - 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, - 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, - 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, - 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x83, 0x07, - 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, - 0x79, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, - 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, - 0x65, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, - 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, - 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, - 0x58, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, - 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, - 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x57, 0x0a, 0x12, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, - 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, - 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x49, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, - 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, - 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, - 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x0f, 0x76, - 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, - 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, - 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, - 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, - 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, - 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x12, 0x6c, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, - 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, - 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, - 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, - 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x1e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x4a, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, - 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, - 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, - 0xb0, 0x01, 0x0a, 0x18, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x37, 0x0a, 0x05, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x05, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, - 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, 0x6b, 0x7a, 0x67, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, 0x31, - 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, - 0x62, 0x73, 0x22, 0x4d, 0x0a, 0x0e, 0x42, 0x6c, 0x6f, 0x62, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, - 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, - 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x42, 0x83, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x12, 0x53, 0x79, 0x6e, 0x63, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, - 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, - 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_proto_eth_v2_beacon_block_proto_rawDescOnce sync.Once - file_proto_eth_v2_beacon_block_proto_rawDescData = file_proto_eth_v2_beacon_block_proto_rawDesc -) - -func file_proto_eth_v2_beacon_block_proto_rawDescGZIP() []byte { - file_proto_eth_v2_beacon_block_proto_rawDescOnce.Do(func() { - file_proto_eth_v2_beacon_block_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_beacon_block_proto_rawDescData) - }) - return file_proto_eth_v2_beacon_block_proto_rawDescData -} - -var file_proto_eth_v2_beacon_block_proto_msgTypes = make([]protoimpl.MessageInfo, 30) -var file_proto_eth_v2_beacon_block_proto_goTypes = []interface{}{ - (*BeaconBlockContainerV2)(nil), // 0: ethereum.eth.v2.BeaconBlockContainerV2 - (*SignedBeaconBlockContainer)(nil), // 1: ethereum.eth.v2.SignedBeaconBlockContainer - (*SignedBeaconBlockContentsContainer)(nil), // 2: ethereum.eth.v2.SignedBeaconBlockContentsContainer - (*BlindedBeaconBlockContainer)(nil), // 3: ethereum.eth.v2.BlindedBeaconBlockContainer - (*SignedBlindedBeaconBlockContainer)(nil), // 4: ethereum.eth.v2.SignedBlindedBeaconBlockContainer - (*SignedBlindedBeaconBlockContentsContainer)(nil), // 5: ethereum.eth.v2.SignedBlindedBeaconBlockContentsContainer - (*SignedBeaconBlockAltair)(nil), // 6: ethereum.eth.v2.SignedBeaconBlockAltair - (*SignedBeaconBlockBellatrix)(nil), // 7: ethereum.eth.v2.SignedBeaconBlockBellatrix - (*SignedBeaconBlockCapella)(nil), // 8: ethereum.eth.v2.SignedBeaconBlockCapella - (*SignedBeaconBlockDeneb)(nil), // 9: ethereum.eth.v2.SignedBeaconBlockDeneb - (*SignedBlindedBeaconBlockBellatrix)(nil), // 10: ethereum.eth.v2.SignedBlindedBeaconBlockBellatrix - (*SignedBlindedBeaconBlockCapella)(nil), // 11: ethereum.eth.v2.SignedBlindedBeaconBlockCapella - (*SignedBlindedBeaconBlockDeneb)(nil), // 12: ethereum.eth.v2.SignedBlindedBeaconBlockDeneb - (*BeaconBlockAltair)(nil), // 13: ethereum.eth.v2.BeaconBlockAltair - (*BeaconBlockBellatrix)(nil), // 14: ethereum.eth.v2.BeaconBlockBellatrix - (*BlindedBeaconBlockBellatrix)(nil), // 15: ethereum.eth.v2.BlindedBeaconBlockBellatrix - (*BeaconBlockCapella)(nil), // 16: ethereum.eth.v2.BeaconBlockCapella - (*BlindedBeaconBlockCapella)(nil), // 17: ethereum.eth.v2.BlindedBeaconBlockCapella - (*BeaconBlockDeneb)(nil), // 18: ethereum.eth.v2.BeaconBlockDeneb - (*BlindedBeaconBlockDeneb)(nil), // 19: ethereum.eth.v2.BlindedBeaconBlockDeneb - (*BeaconBlockBodyAltair)(nil), // 20: ethereum.eth.v2.BeaconBlockBodyAltair - (*BeaconBlockBodyBellatrix)(nil), // 21: ethereum.eth.v2.BeaconBlockBodyBellatrix - (*BlindedBeaconBlockBodyBellatrix)(nil), // 22: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix - (*BeaconBlockBodyCapella)(nil), // 23: ethereum.eth.v2.BeaconBlockBodyCapella - (*BlindedBeaconBlockBodyCapella)(nil), // 24: ethereum.eth.v2.BlindedBeaconBlockBodyCapella - (*BlindedBeaconBlockBodyDeneb)(nil), // 25: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb - (*BeaconBlockBodyDeneb)(nil), // 26: ethereum.eth.v2.BeaconBlockBodyDeneb - (*SignedBeaconBlockContentsDeneb)(nil), // 27: ethereum.eth.v2.SignedBeaconBlockContentsDeneb - (*BeaconBlockContentsDeneb)(nil), // 28: ethereum.eth.v2.BeaconBlockContentsDeneb - (*BlobIdentifier)(nil), // 29: ethereum.eth.v2.BlobIdentifier - (*v1.BeaconBlock)(nil), // 30: ethereum.eth.v1.BeaconBlock - (*v1.SignedBeaconBlock)(nil), // 31: ethereum.eth.v1.SignedBeaconBlock - (*v1.Eth1Data)(nil), // 32: ethereum.eth.v1.Eth1Data - (*v1.ProposerSlashing)(nil), // 33: ethereum.eth.v1.ProposerSlashing - (*v1.AttesterSlashing)(nil), // 34: ethereum.eth.v1.AttesterSlashing - (*v1.Attestation)(nil), // 35: ethereum.eth.v1.Attestation - (*v1.Deposit)(nil), // 36: ethereum.eth.v1.Deposit - (*v1.SignedVoluntaryExit)(nil), // 37: ethereum.eth.v1.SignedVoluntaryExit - (*v1.SyncAggregate)(nil), // 38: ethereum.eth.v1.SyncAggregate - (*v11.ExecutionPayload)(nil), // 39: ethereum.engine.v1.ExecutionPayload - (*v11.ExecutionPayloadHeader)(nil), // 40: ethereum.engine.v1.ExecutionPayloadHeader - (*v11.ExecutionPayloadCapella)(nil), // 41: ethereum.engine.v1.ExecutionPayloadCapella - (*SignedBLSToExecutionChange)(nil), // 42: ethereum.eth.v2.SignedBLSToExecutionChange - (*v11.ExecutionPayloadHeaderCapella)(nil), // 43: ethereum.engine.v1.ExecutionPayloadHeaderCapella - (*v11.ExecutionPayloadHeaderDeneb)(nil), // 44: ethereum.engine.v1.ExecutionPayloadHeaderDeneb - (*v11.ExecutionPayloadDeneb)(nil), // 45: ethereum.engine.v1.ExecutionPayloadDeneb -} -var file_proto_eth_v2_beacon_block_proto_depIdxs = []int32{ - 30, // 0: ethereum.eth.v2.BeaconBlockContainerV2.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock - 13, // 1: ethereum.eth.v2.BeaconBlockContainerV2.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair - 14, // 2: ethereum.eth.v2.BeaconBlockContainerV2.bellatrix_block:type_name -> ethereum.eth.v2.BeaconBlockBellatrix - 16, // 3: ethereum.eth.v2.BeaconBlockContainerV2.capella_block:type_name -> ethereum.eth.v2.BeaconBlockCapella - 28, // 4: ethereum.eth.v2.BeaconBlockContainerV2.deneb_contents:type_name -> ethereum.eth.v2.BeaconBlockContentsDeneb - 30, // 5: ethereum.eth.v2.SignedBeaconBlockContainer.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock - 13, // 6: ethereum.eth.v2.SignedBeaconBlockContainer.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair - 14, // 7: ethereum.eth.v2.SignedBeaconBlockContainer.bellatrix_block:type_name -> ethereum.eth.v2.BeaconBlockBellatrix - 16, // 8: ethereum.eth.v2.SignedBeaconBlockContainer.capella_block:type_name -> ethereum.eth.v2.BeaconBlockCapella - 18, // 9: ethereum.eth.v2.SignedBeaconBlockContainer.deneb_block:type_name -> ethereum.eth.v2.BeaconBlockDeneb - 31, // 10: ethereum.eth.v2.SignedBeaconBlockContentsContainer.phase0_block:type_name -> ethereum.eth.v1.SignedBeaconBlock - 6, // 11: ethereum.eth.v2.SignedBeaconBlockContentsContainer.altair_block:type_name -> ethereum.eth.v2.SignedBeaconBlockAltair - 7, // 12: ethereum.eth.v2.SignedBeaconBlockContentsContainer.bellatrix_block:type_name -> ethereum.eth.v2.SignedBeaconBlockBellatrix - 8, // 13: ethereum.eth.v2.SignedBeaconBlockContentsContainer.capella_block:type_name -> ethereum.eth.v2.SignedBeaconBlockCapella - 27, // 14: ethereum.eth.v2.SignedBeaconBlockContentsContainer.deneb_contents:type_name -> ethereum.eth.v2.SignedBeaconBlockContentsDeneb - 30, // 15: ethereum.eth.v2.BlindedBeaconBlockContainer.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock - 13, // 16: ethereum.eth.v2.BlindedBeaconBlockContainer.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair - 15, // 17: ethereum.eth.v2.BlindedBeaconBlockContainer.bellatrix_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix - 17, // 18: ethereum.eth.v2.BlindedBeaconBlockContainer.capella_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockCapella - 19, // 19: ethereum.eth.v2.BlindedBeaconBlockContainer.deneb_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockDeneb - 30, // 20: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.phase0_block:type_name -> ethereum.eth.v1.BeaconBlock - 13, // 21: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.altair_block:type_name -> ethereum.eth.v2.BeaconBlockAltair - 15, // 22: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.bellatrix_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix - 17, // 23: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.capella_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockCapella - 19, // 24: ethereum.eth.v2.SignedBlindedBeaconBlockContainer.deneb_block:type_name -> ethereum.eth.v2.BlindedBeaconBlockDeneb - 31, // 25: ethereum.eth.v2.SignedBlindedBeaconBlockContentsContainer.phase0_block:type_name -> ethereum.eth.v1.SignedBeaconBlock - 6, // 26: ethereum.eth.v2.SignedBlindedBeaconBlockContentsContainer.altair_block:type_name -> ethereum.eth.v2.SignedBeaconBlockAltair - 10, // 27: ethereum.eth.v2.SignedBlindedBeaconBlockContentsContainer.bellatrix_block:type_name -> ethereum.eth.v2.SignedBlindedBeaconBlockBellatrix - 11, // 28: ethereum.eth.v2.SignedBlindedBeaconBlockContentsContainer.capella_block:type_name -> ethereum.eth.v2.SignedBlindedBeaconBlockCapella - 12, // 29: ethereum.eth.v2.SignedBlindedBeaconBlockContentsContainer.deneb_block:type_name -> ethereum.eth.v2.SignedBlindedBeaconBlockDeneb - 13, // 30: ethereum.eth.v2.SignedBeaconBlockAltair.message:type_name -> ethereum.eth.v2.BeaconBlockAltair - 14, // 31: ethereum.eth.v2.SignedBeaconBlockBellatrix.message:type_name -> ethereum.eth.v2.BeaconBlockBellatrix - 16, // 32: ethereum.eth.v2.SignedBeaconBlockCapella.message:type_name -> ethereum.eth.v2.BeaconBlockCapella - 18, // 33: ethereum.eth.v2.SignedBeaconBlockDeneb.message:type_name -> ethereum.eth.v2.BeaconBlockDeneb - 15, // 34: ethereum.eth.v2.SignedBlindedBeaconBlockBellatrix.message:type_name -> ethereum.eth.v2.BlindedBeaconBlockBellatrix - 17, // 35: ethereum.eth.v2.SignedBlindedBeaconBlockCapella.message:type_name -> ethereum.eth.v2.BlindedBeaconBlockCapella - 19, // 36: ethereum.eth.v2.SignedBlindedBeaconBlockDeneb.message:type_name -> ethereum.eth.v2.BlindedBeaconBlockDeneb - 20, // 37: ethereum.eth.v2.BeaconBlockAltair.body:type_name -> ethereum.eth.v2.BeaconBlockBodyAltair - 21, // 38: ethereum.eth.v2.BeaconBlockBellatrix.body:type_name -> ethereum.eth.v2.BeaconBlockBodyBellatrix - 22, // 39: ethereum.eth.v2.BlindedBeaconBlockBellatrix.body:type_name -> ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix - 23, // 40: ethereum.eth.v2.BeaconBlockCapella.body:type_name -> ethereum.eth.v2.BeaconBlockBodyCapella - 24, // 41: ethereum.eth.v2.BlindedBeaconBlockCapella.body:type_name -> ethereum.eth.v2.BlindedBeaconBlockBodyCapella - 26, // 42: ethereum.eth.v2.BeaconBlockDeneb.body:type_name -> ethereum.eth.v2.BeaconBlockBodyDeneb - 25, // 43: ethereum.eth.v2.BlindedBeaconBlockDeneb.body:type_name -> ethereum.eth.v2.BlindedBeaconBlockBodyDeneb - 32, // 44: ethereum.eth.v2.BeaconBlockBodyAltair.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 33, // 45: ethereum.eth.v2.BeaconBlockBodyAltair.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 34, // 46: ethereum.eth.v2.BeaconBlockBodyAltair.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 35, // 47: ethereum.eth.v2.BeaconBlockBodyAltair.attestations:type_name -> ethereum.eth.v1.Attestation - 36, // 48: ethereum.eth.v2.BeaconBlockBodyAltair.deposits:type_name -> ethereum.eth.v1.Deposit - 37, // 49: ethereum.eth.v2.BeaconBlockBodyAltair.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 38, // 50: ethereum.eth.v2.BeaconBlockBodyAltair.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 32, // 51: ethereum.eth.v2.BeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 33, // 52: ethereum.eth.v2.BeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 34, // 53: ethereum.eth.v2.BeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 35, // 54: ethereum.eth.v2.BeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1.Attestation - 36, // 55: ethereum.eth.v2.BeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1.Deposit - 37, // 56: ethereum.eth.v2.BeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 38, // 57: ethereum.eth.v2.BeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 39, // 58: ethereum.eth.v2.BeaconBlockBodyBellatrix.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayload - 32, // 59: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 33, // 60: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 34, // 61: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 35, // 62: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1.Attestation - 36, // 63: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1.Deposit - 37, // 64: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 38, // 65: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 40, // 66: ethereum.eth.v2.BlindedBeaconBlockBodyBellatrix.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeader - 32, // 67: ethereum.eth.v2.BeaconBlockBodyCapella.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 33, // 68: ethereum.eth.v2.BeaconBlockBodyCapella.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 34, // 69: ethereum.eth.v2.BeaconBlockBodyCapella.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 35, // 70: ethereum.eth.v2.BeaconBlockBodyCapella.attestations:type_name -> ethereum.eth.v1.Attestation - 36, // 71: ethereum.eth.v2.BeaconBlockBodyCapella.deposits:type_name -> ethereum.eth.v1.Deposit - 37, // 72: ethereum.eth.v2.BeaconBlockBodyCapella.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 38, // 73: ethereum.eth.v2.BeaconBlockBodyCapella.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 41, // 74: ethereum.eth.v2.BeaconBlockBodyCapella.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayloadCapella - 42, // 75: ethereum.eth.v2.BeaconBlockBodyCapella.bls_to_execution_changes:type_name -> ethereum.eth.v2.SignedBLSToExecutionChange - 32, // 76: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 33, // 77: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 34, // 78: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 35, // 79: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.attestations:type_name -> ethereum.eth.v1.Attestation - 36, // 80: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.deposits:type_name -> ethereum.eth.v1.Deposit - 37, // 81: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 38, // 82: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 43, // 83: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderCapella - 42, // 84: ethereum.eth.v2.BlindedBeaconBlockBodyCapella.bls_to_execution_changes:type_name -> ethereum.eth.v2.SignedBLSToExecutionChange - 32, // 85: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 33, // 86: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 34, // 87: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 35, // 88: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.attestations:type_name -> ethereum.eth.v1.Attestation - 36, // 89: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.deposits:type_name -> ethereum.eth.v1.Deposit - 37, // 90: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 38, // 91: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 44, // 92: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb - 42, // 93: ethereum.eth.v2.BlindedBeaconBlockBodyDeneb.bls_to_execution_changes:type_name -> ethereum.eth.v2.SignedBLSToExecutionChange - 32, // 94: ethereum.eth.v2.BeaconBlockBodyDeneb.eth1_data:type_name -> ethereum.eth.v1.Eth1Data - 33, // 95: ethereum.eth.v2.BeaconBlockBodyDeneb.proposer_slashings:type_name -> ethereum.eth.v1.ProposerSlashing - 34, // 96: ethereum.eth.v2.BeaconBlockBodyDeneb.attester_slashings:type_name -> ethereum.eth.v1.AttesterSlashing - 35, // 97: ethereum.eth.v2.BeaconBlockBodyDeneb.attestations:type_name -> ethereum.eth.v1.Attestation - 36, // 98: ethereum.eth.v2.BeaconBlockBodyDeneb.deposits:type_name -> ethereum.eth.v1.Deposit - 37, // 99: ethereum.eth.v2.BeaconBlockBodyDeneb.voluntary_exits:type_name -> ethereum.eth.v1.SignedVoluntaryExit - 38, // 100: ethereum.eth.v2.BeaconBlockBodyDeneb.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 45, // 101: ethereum.eth.v2.BeaconBlockBodyDeneb.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayloadDeneb - 42, // 102: ethereum.eth.v2.BeaconBlockBodyDeneb.bls_to_execution_changes:type_name -> ethereum.eth.v2.SignedBLSToExecutionChange - 9, // 103: ethereum.eth.v2.SignedBeaconBlockContentsDeneb.signed_block:type_name -> ethereum.eth.v2.SignedBeaconBlockDeneb - 18, // 104: ethereum.eth.v2.BeaconBlockContentsDeneb.block:type_name -> ethereum.eth.v2.BeaconBlockDeneb - 105, // [105:105] is the sub-list for method output_type - 105, // [105:105] is the sub-list for method input_type - 105, // [105:105] is the sub-list for extension type_name - 105, // [105:105] is the sub-list for extension extendee - 0, // [0:105] is the sub-list for field type_name -} - -func init() { file_proto_eth_v2_beacon_block_proto_init() } -func file_proto_eth_v2_beacon_block_proto_init() { - if File_proto_eth_v2_beacon_block_proto != nil { - return - } - file_proto_eth_v2_withdrawals_proto_init() - if !protoimpl.UnsafeEnabled { - file_proto_eth_v2_beacon_block_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockContainerV2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockContainer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockContentsContainer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockContainer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockContainer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockContentsContainer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockAltair); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockBellatrix); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockCapella); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockDeneb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockBellatrix); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockCapella); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockDeneb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockAltair); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBellatrix); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBellatrix); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockCapella); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockCapella); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockDeneb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockDeneb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyAltair); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyBellatrix); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBodyBellatrix); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyCapella); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBodyCapella); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBodyDeneb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyDeneb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockContentsDeneb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockContentsDeneb); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlobIdentifier); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_proto_eth_v2_beacon_block_proto_msgTypes[0].OneofWrappers = []interface{}{ - (*BeaconBlockContainerV2_Phase0Block)(nil), - (*BeaconBlockContainerV2_AltairBlock)(nil), - (*BeaconBlockContainerV2_BellatrixBlock)(nil), - (*BeaconBlockContainerV2_CapellaBlock)(nil), - (*BeaconBlockContainerV2_DenebContents)(nil), - } - file_proto_eth_v2_beacon_block_proto_msgTypes[1].OneofWrappers = []interface{}{ - (*SignedBeaconBlockContainer_Phase0Block)(nil), - (*SignedBeaconBlockContainer_AltairBlock)(nil), - (*SignedBeaconBlockContainer_BellatrixBlock)(nil), - (*SignedBeaconBlockContainer_CapellaBlock)(nil), - (*SignedBeaconBlockContainer_DenebBlock)(nil), - } - file_proto_eth_v2_beacon_block_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*SignedBeaconBlockContentsContainer_Phase0Block)(nil), - (*SignedBeaconBlockContentsContainer_AltairBlock)(nil), - (*SignedBeaconBlockContentsContainer_BellatrixBlock)(nil), - (*SignedBeaconBlockContentsContainer_CapellaBlock)(nil), - (*SignedBeaconBlockContentsContainer_DenebContents)(nil), - } - file_proto_eth_v2_beacon_block_proto_msgTypes[3].OneofWrappers = []interface{}{ - (*BlindedBeaconBlockContainer_Phase0Block)(nil), - (*BlindedBeaconBlockContainer_AltairBlock)(nil), - (*BlindedBeaconBlockContainer_BellatrixBlock)(nil), - (*BlindedBeaconBlockContainer_CapellaBlock)(nil), - (*BlindedBeaconBlockContainer_DenebBlock)(nil), - } - file_proto_eth_v2_beacon_block_proto_msgTypes[4].OneofWrappers = []interface{}{ - (*SignedBlindedBeaconBlockContainer_Phase0Block)(nil), - (*SignedBlindedBeaconBlockContainer_AltairBlock)(nil), - (*SignedBlindedBeaconBlockContainer_BellatrixBlock)(nil), - (*SignedBlindedBeaconBlockContainer_CapellaBlock)(nil), - (*SignedBlindedBeaconBlockContainer_DenebBlock)(nil), - } - file_proto_eth_v2_beacon_block_proto_msgTypes[5].OneofWrappers = []interface{}{ - (*SignedBlindedBeaconBlockContentsContainer_Phase0Block)(nil), - (*SignedBlindedBeaconBlockContentsContainer_AltairBlock)(nil), - (*SignedBlindedBeaconBlockContentsContainer_BellatrixBlock)(nil), - (*SignedBlindedBeaconBlockContentsContainer_CapellaBlock)(nil), - (*SignedBlindedBeaconBlockContentsContainer_DenebBlock)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_eth_v2_beacon_block_proto_rawDesc, - NumEnums: 0, - NumMessages: 30, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_eth_v2_beacon_block_proto_goTypes, - DependencyIndexes: file_proto_eth_v2_beacon_block_proto_depIdxs, - MessageInfos: file_proto_eth_v2_beacon_block_proto_msgTypes, - }.Build() - File_proto_eth_v2_beacon_block_proto = out.File - file_proto_eth_v2_beacon_block_proto_rawDesc = nil - file_proto_eth_v2_beacon_block_proto_goTypes = nil - file_proto_eth_v2_beacon_block_proto_depIdxs = nil -} diff --git a/proto/eth/v2/beacon_block.pb.gw.go b/proto/eth/v2/beacon_block.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v2/beacon_block.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v2/beacon_block.proto b/proto/eth/v2/beacon_block.proto deleted file mode 100644 index 100bbec273f0..000000000000 --- a/proto/eth/v2/beacon_block.proto +++ /dev/null @@ -1,545 +0,0 @@ -// Copyright 2021 Prysmatic Labs. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -syntax = "proto3"; - -package ethereum.eth.v2; - -import "proto/eth/ext/options.proto"; -import "proto/eth/v1/attestation.proto"; -import "proto/eth/v1/beacon_block.proto"; -import "proto/eth/v2/withdrawals.proto"; -import "proto/engine/v1/execution_engine.proto"; - -option csharp_namespace = "Ethereum.Eth.V2"; -option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2;eth"; -option java_multiple_files = true; -option java_outer_classname = "SyncCommitteeProto"; -option java_package = "org.ethereum.eth.v2"; -option php_namespace = "Ethereum\\Eth\\v2"; - -message BeaconBlockContainerV2 { - oneof block { - v1.BeaconBlock phase0_block = 1; - BeaconBlockAltair altair_block = 2; - BeaconBlockBellatrix bellatrix_block = 3; - BeaconBlockCapella capella_block = 4; - BeaconBlockContentsDeneb deneb_contents = 5; - } -} - -message SignedBeaconBlockContainer { - oneof message { - v1.BeaconBlock phase0_block = 1; - BeaconBlockAltair altair_block = 2; - BeaconBlockBellatrix bellatrix_block = 3; - BeaconBlockCapella capella_block = 4; - BeaconBlockDeneb deneb_block = 5; - } - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 6 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message SignedBeaconBlockContentsContainer { - oneof message { - v1.SignedBeaconBlock phase0_block = 1; - SignedBeaconBlockAltair altair_block = 2; - SignedBeaconBlockBellatrix bellatrix_block = 3; - SignedBeaconBlockCapella capella_block = 4; - SignedBeaconBlockContentsDeneb deneb_contents = 5; - } -} - -// used in produce block -message BlindedBeaconBlockContainer { - oneof block { - v1.BeaconBlock phase0_block = 1; - BeaconBlockAltair altair_block = 2; - BlindedBeaconBlockBellatrix bellatrix_block = 3; - BlindedBeaconBlockCapella capella_block = 4; - BlindedBeaconBlockDeneb deneb_block = 5; - } -} - -// used in get block -message SignedBlindedBeaconBlockContainer { - oneof message { - v1.BeaconBlock phase0_block = 1; - BeaconBlockAltair altair_block = 2; - BlindedBeaconBlockBellatrix bellatrix_block = 3; - BlindedBeaconBlockCapella capella_block = 4; - BlindedBeaconBlockDeneb deneb_block = 5; - } - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 6 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message SignedBlindedBeaconBlockContentsContainer { - oneof message { - v1.SignedBeaconBlock phase0_block = 1; - SignedBeaconBlockAltair altair_block = 2; - SignedBlindedBeaconBlockBellatrix bellatrix_block = 3; - SignedBlindedBeaconBlockCapella capella_block = 4; - SignedBlindedBeaconBlockDeneb deneb_block = 5; - } -} - -message SignedBeaconBlockAltair { - BeaconBlockAltair message = 1; - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message SignedBeaconBlockBellatrix { - BeaconBlockBellatrix message = 1; - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message SignedBeaconBlockCapella { - BeaconBlockCapella message = 1; - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message SignedBeaconBlockDeneb { - BeaconBlockDeneb message = 1; - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message SignedBlindedBeaconBlockBellatrix { - BlindedBeaconBlockBellatrix message = 1; - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message SignedBlindedBeaconBlockCapella { - BlindedBeaconBlockCapella message = 1; - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message SignedBlindedBeaconBlockDeneb { - BlindedBeaconBlockDeneb message = 1; - - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -// The Ethereum consensus beacon block. The message does not contain a validator signature. -message BeaconBlockAltair { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The block body itself. - BeaconBlockBodyAltair body = 5; -} - -// The Ethereum consensus beacon block. The message does not contain a validator signature. -message BeaconBlockBellatrix { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The block body itself. - BeaconBlockBodyBellatrix body = 5; -} - -// The Ethereum consensus beacon block. The message does not contain a validator signature. -message BlindedBeaconBlockBellatrix { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The block body itself. - BlindedBeaconBlockBodyBellatrix body = 5; -} - -// The Ethereum consensus beacon block. The message does not contain a validator signature. -message BeaconBlockCapella { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The block body itself. - BeaconBlockBodyCapella body = 5; -} - -// The Ethereum consensus beacon block. The message does not contain a validator signature. -message BlindedBeaconBlockCapella { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The block body itself. - BlindedBeaconBlockBodyCapella body = 5; -} - -// The Ethereum consensus beacon block. The message does not contain a validator signature. -message BeaconBlockDeneb { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The beacon block body. - BeaconBlockBodyDeneb body = 5; -} - -// The Ethereum consensus beacon block. The message does not contain a validator signature. -message BlindedBeaconBlockDeneb { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The block body itself. - BlindedBeaconBlockBodyDeneb body = 5; -} - -message BeaconBlockBodyAltair { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - v1.Eth1Data eth1_data = 2; - - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - - // At most MAX_PROPOSER_SLASHINGS. - repeated v1.ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_ATTESTER_SLASHINGS. - repeated v1.AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; - - // At most MAX_ATTESTATIONS. - repeated v1.Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; - - // At most MAX_DEPOSITS. - repeated v1.Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_VOLUNTARY_EXITS. - repeated v1.SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; - - // Sync aggregate object to track sync committee votes for light client support. [New in ] - v1.SyncAggregate sync_aggregate = 9; -} - -message BeaconBlockBodyBellatrix { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - v1.Eth1Data eth1_data = 2; - - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - - // At most MAX_PROPOSER_SLASHINGS. - repeated v1.ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_ATTESTER_SLASHINGS. - repeated v1.AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; - - // At most MAX_ATTESTATIONS. - repeated v1.Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; - - // At most MAX_DEPOSITS. - repeated v1.Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_VOLUNTARY_EXITS. - repeated v1.SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; - - // Sync aggregate object to track sync committee votes for light client support. - v1.SyncAggregate sync_aggregate = 9; - - // Execution payload: the embedded execution payload of the block [New in Bellatrix] - ethereum.engine.v1.ExecutionPayload execution_payload = 10; -} - -message BlindedBeaconBlockBodyBellatrix { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - v1.Eth1Data eth1_data = 2; - - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - - // At most MAX_PROPOSER_SLASHINGS. - repeated v1.ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_ATTESTER_SLASHINGS. - repeated v1.AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; - - // At most MAX_ATTESTATIONS. - repeated v1.Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; - - // At most MAX_DEPOSITS. - repeated v1.Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_VOLUNTARY_EXITS. - repeated v1.SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; - - // Sync aggregate object to track sync committee votes for light client support. - v1.SyncAggregate sync_aggregate = 9; - - // Execution payload header: the embedded execution payload of the block [New in Bellatrix] - ethereum.engine.v1.ExecutionPayloadHeader execution_payload_header = 10; -} - -message BeaconBlockBodyCapella { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - v1.Eth1Data eth1_data = 2; - - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - - // At most MAX_PROPOSER_SLASHINGS. - repeated v1.ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_ATTESTER_SLASHINGS. - repeated v1.AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; - - // At most MAX_ATTESTATIONS. - repeated v1.Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; - - // At most MAX_DEPOSITS. - repeated v1.Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_VOLUNTARY_EXITS. - repeated v1.SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; - - // Sync aggregate object to track sync committee votes for light client support. - v1.SyncAggregate sync_aggregate = 9; - - // Execution payload: the embedded execution payload of the block [Modified in Capella] - ethereum.engine.v1.ExecutionPayloadCapella execution_payload = 10; - - // BLS To Execution Changes: signed messages to change withdrawal credentials [New in Capella] - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; -} - -message BlindedBeaconBlockBodyCapella { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - v1.Eth1Data eth1_data = 2; - - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - - // At most MAX_PROPOSER_SLASHINGS. - repeated v1.ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_ATTESTER_SLASHINGS. - repeated v1.AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; - - // At most MAX_ATTESTATIONS. - repeated v1.Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; - - // At most MAX_DEPOSITS. - repeated v1.Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_VOLUNTARY_EXITS. - repeated v1.SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; - - // Sync aggregate object to track sync committee votes for light client support. - v1.SyncAggregate sync_aggregate = 9; - - // Execution payload header: the embedded execution payload of the block [Modified in Capella] - ethereum.engine.v1.ExecutionPayloadHeaderCapella execution_payload_header = 10; - - // BLS To Execution Changes: signed messages to change withdrawal credentials [New in Capella] - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; -} - -message BlindedBeaconBlockBodyDeneb { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - v1.Eth1Data eth1_data = 2; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#max-operations-per-block - // At most MAX_PROPOSER_SLASHINGS. - repeated v1.ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; - // At most MAX_ATTESTER_SLASHINGS. - repeated v1.AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; - // At most MAX_ATTESTATIONS. - repeated v1.Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; - // At most MAX_DEPOSITS. - repeated v1.Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; - // At most MAX_VOLUNTARY_EXITS. - repeated v1.SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; - // Sync aggregate object to track sync committee votes for light client support. - v1.SyncAggregate sync_aggregate = 9; - - // Execution payload header: the embedded execution payload of the block [Modified in Deneb] - ethereum.engine.v1.ExecutionPayloadHeaderDeneb execution_payload_header = 10; - - // BLS To Execution Changes: signed messages to change withdrawal credentials [New in Capella] - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; - - repeated bytes blob_kzg_commitments = 12 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; -} - -message BeaconBlockBodyDeneb { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - v1.Eth1Data eth1_data = 2; - - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - - // At most MAX_PROPOSER_SLASHINGS. - repeated v1.ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_ATTESTER_SLASHINGS. - repeated v1.AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; - - // At most MAX_ATTESTATIONS. - repeated v1.Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; - - // At most MAX_DEPOSITS. - repeated v1.Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_VOLUNTARY_EXITS. - repeated v1.SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; - - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - v1.SyncAggregate sync_aggregate = 9; - - // Execution payload from the execution chain. New in Bellatrix network upgrade. - ethereum.engine.v1.ExecutionPayloadDeneb execution_payload = 10; - - // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_BLOB_COMMITMENTS_PER_BLOCK. New in Deneb network upgrade. - repeated bytes blob_kzg_commitments = 12 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; -} - -message SignedBeaconBlockContentsDeneb { - SignedBeaconBlockDeneb signed_block = 1; - repeated bytes kzg_proofs = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "4096"]; - repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,blob.size", (ethereum.eth.ext.ssz_max) = "4096"]; -} - -message BeaconBlockContentsDeneb { - BeaconBlockDeneb block = 1; - repeated bytes kzg_proofs = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "4096"]; - repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,blob.size", (ethereum.eth.ext.ssz_max) = "4096"]; -} - -message BlobIdentifier { - bytes block_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 index = 2; -} \ No newline at end of file diff --git a/proto/eth/v2/beacon_chain.pb.gw.go b/proto/eth/v2/beacon_chain.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v2/beacon_chain.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v2/beacon_lightclient.pb.go b/proto/eth/v2/beacon_lightclient.pb.go deleted file mode 100755 index 812355cdbd11..000000000000 --- a/proto/eth/v2/beacon_lightclient.pb.go +++ /dev/null @@ -1,722 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 -// source: proto/eth/v2/beacon_lightclient.proto - -package eth - -import ( - reflect "reflect" - sync "sync" - - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - _ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext" - v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type LightClientBootstrap struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Header *v1.BeaconBlockHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` - CurrentSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=current_sync_committee_branch,json=currentSyncCommitteeBranch,proto3" json:"current_sync_committee_branch,omitempty"` -} - -func (x *LightClientBootstrap) Reset() { - *x = LightClientBootstrap{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LightClientBootstrap) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LightClientBootstrap) ProtoMessage() {} - -func (x *LightClientBootstrap) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LightClientBootstrap.ProtoReflect.Descriptor instead. -func (*LightClientBootstrap) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{0} -} - -func (x *LightClientBootstrap) GetHeader() *v1.BeaconBlockHeader { - if x != nil { - return x.Header - } - return nil -} - -func (x *LightClientBootstrap) GetCurrentSyncCommittee() *SyncCommittee { - if x != nil { - return x.CurrentSyncCommittee - } - return nil -} - -func (x *LightClientBootstrap) GetCurrentSyncCommitteeBranch() [][]byte { - if x != nil { - return x.CurrentSyncCommitteeBranch - } - return nil -} - -type LightClientUpdate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AttestedHeader *v1.BeaconBlockHeader `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` - NextSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` - NextSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=next_sync_committee_branch,json=nextSyncCommitteeBranch,proto3" json:"next_sync_committee_branch,omitempty"` - FinalizedHeader *v1.BeaconBlockHeader `protobuf:"bytes,4,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` - FinalityBranch [][]byte `protobuf:"bytes,5,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,6,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,7,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` -} - -func (x *LightClientUpdate) Reset() { - *x = LightClientUpdate{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LightClientUpdate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LightClientUpdate) ProtoMessage() {} - -func (x *LightClientUpdate) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LightClientUpdate.ProtoReflect.Descriptor instead. -func (*LightClientUpdate) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{1} -} - -func (x *LightClientUpdate) GetAttestedHeader() *v1.BeaconBlockHeader { - if x != nil { - return x.AttestedHeader - } - return nil -} - -func (x *LightClientUpdate) GetNextSyncCommittee() *SyncCommittee { - if x != nil { - return x.NextSyncCommittee - } - return nil -} - -func (x *LightClientUpdate) GetNextSyncCommitteeBranch() [][]byte { - if x != nil { - return x.NextSyncCommitteeBranch - } - return nil -} - -func (x *LightClientUpdate) GetFinalizedHeader() *v1.BeaconBlockHeader { - if x != nil { - return x.FinalizedHeader - } - return nil -} - -func (x *LightClientUpdate) GetFinalityBranch() [][]byte { - if x != nil { - return x.FinalityBranch - } - return nil -} - -func (x *LightClientUpdate) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *LightClientUpdate) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.SignatureSlot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -type LightClientFinalityUpdateWithVersion struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=ethereum.eth.v2.Version" json:"version,omitempty"` - Data *LightClientFinalityUpdate `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` -} - -func (x *LightClientFinalityUpdateWithVersion) Reset() { - *x = LightClientFinalityUpdateWithVersion{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LightClientFinalityUpdateWithVersion) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LightClientFinalityUpdateWithVersion) ProtoMessage() {} - -func (x *LightClientFinalityUpdateWithVersion) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LightClientFinalityUpdateWithVersion.ProtoReflect.Descriptor instead. -func (*LightClientFinalityUpdateWithVersion) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{2} -} - -func (x *LightClientFinalityUpdateWithVersion) GetVersion() Version { - if x != nil { - return x.Version - } - return Version_PHASE0 -} - -func (x *LightClientFinalityUpdateWithVersion) GetData() *LightClientFinalityUpdate { - if x != nil { - return x.Data - } - return nil -} - -type LightClientFinalityUpdate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AttestedHeader *v1.BeaconBlockHeader `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` - FinalizedHeader *v1.BeaconBlockHeader `protobuf:"bytes,2,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` - FinalityBranch [][]byte `protobuf:"bytes,3,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,4,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,5,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` -} - -func (x *LightClientFinalityUpdate) Reset() { - *x = LightClientFinalityUpdate{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LightClientFinalityUpdate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LightClientFinalityUpdate) ProtoMessage() {} - -func (x *LightClientFinalityUpdate) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LightClientFinalityUpdate.ProtoReflect.Descriptor instead. -func (*LightClientFinalityUpdate) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{3} -} - -func (x *LightClientFinalityUpdate) GetAttestedHeader() *v1.BeaconBlockHeader { - if x != nil { - return x.AttestedHeader - } - return nil -} - -func (x *LightClientFinalityUpdate) GetFinalizedHeader() *v1.BeaconBlockHeader { - if x != nil { - return x.FinalizedHeader - } - return nil -} - -func (x *LightClientFinalityUpdate) GetFinalityBranch() [][]byte { - if x != nil { - return x.FinalityBranch - } - return nil -} - -func (x *LightClientFinalityUpdate) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *LightClientFinalityUpdate) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.SignatureSlot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -type LightClientOptimisticUpdateWithVersion struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=ethereum.eth.v2.Version" json:"version,omitempty"` - Data *LightClientOptimisticUpdate `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` -} - -func (x *LightClientOptimisticUpdateWithVersion) Reset() { - *x = LightClientOptimisticUpdateWithVersion{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LightClientOptimisticUpdateWithVersion) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LightClientOptimisticUpdateWithVersion) ProtoMessage() {} - -func (x *LightClientOptimisticUpdateWithVersion) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LightClientOptimisticUpdateWithVersion.ProtoReflect.Descriptor instead. -func (*LightClientOptimisticUpdateWithVersion) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{4} -} - -func (x *LightClientOptimisticUpdateWithVersion) GetVersion() Version { - if x != nil { - return x.Version - } - return Version_PHASE0 -} - -func (x *LightClientOptimisticUpdateWithVersion) GetData() *LightClientOptimisticUpdate { - if x != nil { - return x.Data - } - return nil -} - -type LightClientOptimisticUpdate struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AttestedHeader *v1.BeaconBlockHeader `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` - SyncAggregate *v1.SyncAggregate `protobuf:"bytes,2,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,3,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` -} - -func (x *LightClientOptimisticUpdate) Reset() { - *x = LightClientOptimisticUpdate{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LightClientOptimisticUpdate) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LightClientOptimisticUpdate) ProtoMessage() {} - -func (x *LightClientOptimisticUpdate) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_beacon_lightclient_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LightClientOptimisticUpdate.ProtoReflect.Descriptor instead. -func (*LightClientOptimisticUpdate) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP(), []int{5} -} - -func (x *LightClientOptimisticUpdate) GetAttestedHeader() *v1.BeaconBlockHeader { - if x != nil { - return x.AttestedHeader - } - return nil -} - -func (x *LightClientOptimisticUpdate) GetSyncAggregate() *v1.SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *LightClientOptimisticUpdate) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.SignatureSlot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -var File_proto_eth_v2_beacon_lightclient_proto protoreflect.FileDescriptor - -var file_proto_eth_v2_beacon_lightclient_proto_rawDesc = []byte{ - 0x0a, 0x25, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, - 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, - 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xeb, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x12, 0x3a, - 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x16, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x12, 0x41, 0x0a, 0x1d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, - 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, - 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, 0x72, 0x61, - 0x6e, 0x63, 0x68, 0x22, 0x9a, 0x04, 0x0a, 0x11, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, - 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x52, 0x11, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x3b, 0x0a, 0x1a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, - 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, - 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x17, 0x6e, 0x65, 0x78, 0x74, - 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, 0x72, 0x61, - 0x6e, 0x63, 0x68, 0x12, 0x4d, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, - 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x62, - 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, 0x66, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x45, 0x0a, 0x0e, 0x73, - 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, - 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, - 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, - 0x22, 0x9a, 0x01, 0x0a, 0x24, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, - 0x74, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, - 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, - 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x95, 0x03, - 0x0a, 0x19, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x46, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4d, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, - 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x22, 0x9e, 0x01, 0x0a, 0x26, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x32, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x9f, 0x02, 0x0a, 0x1b, 0x4c, 0x69, 0x67, 0x68, 0x74, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, - 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, - 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, - 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x42, 0x83, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, - 0x42, 0x12, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_proto_eth_v2_beacon_lightclient_proto_rawDescOnce sync.Once - file_proto_eth_v2_beacon_lightclient_proto_rawDescData = file_proto_eth_v2_beacon_lightclient_proto_rawDesc -) - -func file_proto_eth_v2_beacon_lightclient_proto_rawDescGZIP() []byte { - file_proto_eth_v2_beacon_lightclient_proto_rawDescOnce.Do(func() { - file_proto_eth_v2_beacon_lightclient_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_beacon_lightclient_proto_rawDescData) - }) - return file_proto_eth_v2_beacon_lightclient_proto_rawDescData -} - -var file_proto_eth_v2_beacon_lightclient_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_proto_eth_v2_beacon_lightclient_proto_goTypes = []interface{}{ - (*LightClientBootstrap)(nil), // 0: ethereum.eth.v2.LightClientBootstrap - (*LightClientUpdate)(nil), // 1: ethereum.eth.v2.LightClientUpdate - (*LightClientFinalityUpdateWithVersion)(nil), // 2: ethereum.eth.v2.LightClientFinalityUpdateWithVersion - (*LightClientFinalityUpdate)(nil), // 3: ethereum.eth.v2.LightClientFinalityUpdate - (*LightClientOptimisticUpdateWithVersion)(nil), // 4: ethereum.eth.v2.LightClientOptimisticUpdateWithVersion - (*LightClientOptimisticUpdate)(nil), // 5: ethereum.eth.v2.LightClientOptimisticUpdate - (*v1.BeaconBlockHeader)(nil), // 6: ethereum.eth.v1.BeaconBlockHeader - (*SyncCommittee)(nil), // 7: ethereum.eth.v2.SyncCommittee - (*v1.SyncAggregate)(nil), // 8: ethereum.eth.v1.SyncAggregate - (Version)(0), // 9: ethereum.eth.v2.Version -} -var file_proto_eth_v2_beacon_lightclient_proto_depIdxs = []int32{ - 6, // 0: ethereum.eth.v2.LightClientBootstrap.header:type_name -> ethereum.eth.v1.BeaconBlockHeader - 7, // 1: ethereum.eth.v2.LightClientBootstrap.current_sync_committee:type_name -> ethereum.eth.v2.SyncCommittee - 6, // 2: ethereum.eth.v2.LightClientUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader - 7, // 3: ethereum.eth.v2.LightClientUpdate.next_sync_committee:type_name -> ethereum.eth.v2.SyncCommittee - 6, // 4: ethereum.eth.v2.LightClientUpdate.finalized_header:type_name -> ethereum.eth.v1.BeaconBlockHeader - 8, // 5: ethereum.eth.v2.LightClientUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 9, // 6: ethereum.eth.v2.LightClientFinalityUpdateWithVersion.version:type_name -> ethereum.eth.v2.Version - 3, // 7: ethereum.eth.v2.LightClientFinalityUpdateWithVersion.data:type_name -> ethereum.eth.v2.LightClientFinalityUpdate - 6, // 8: ethereum.eth.v2.LightClientFinalityUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader - 6, // 9: ethereum.eth.v2.LightClientFinalityUpdate.finalized_header:type_name -> ethereum.eth.v1.BeaconBlockHeader - 8, // 10: ethereum.eth.v2.LightClientFinalityUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 9, // 11: ethereum.eth.v2.LightClientOptimisticUpdateWithVersion.version:type_name -> ethereum.eth.v2.Version - 5, // 12: ethereum.eth.v2.LightClientOptimisticUpdateWithVersion.data:type_name -> ethereum.eth.v2.LightClientOptimisticUpdate - 6, // 13: ethereum.eth.v2.LightClientOptimisticUpdate.attested_header:type_name -> ethereum.eth.v1.BeaconBlockHeader - 8, // 14: ethereum.eth.v2.LightClientOptimisticUpdate.sync_aggregate:type_name -> ethereum.eth.v1.SyncAggregate - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name -} - -func init() { file_proto_eth_v2_beacon_lightclient_proto_init() } -func file_proto_eth_v2_beacon_lightclient_proto_init() { - if File_proto_eth_v2_beacon_lightclient_proto != nil { - return - } - file_proto_eth_v2_version_proto_init() - file_proto_eth_v2_sync_committee_proto_init() - if !protoimpl.UnsafeEnabled { - file_proto_eth_v2_beacon_lightclient_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LightClientBootstrap); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_lightclient_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LightClientUpdate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_lightclient_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LightClientFinalityUpdateWithVersion); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_lightclient_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LightClientFinalityUpdate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_lightclient_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LightClientOptimisticUpdateWithVersion); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_beacon_lightclient_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LightClientOptimisticUpdate); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_eth_v2_beacon_lightclient_proto_rawDesc, - NumEnums: 0, - NumMessages: 6, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_eth_v2_beacon_lightclient_proto_goTypes, - DependencyIndexes: file_proto_eth_v2_beacon_lightclient_proto_depIdxs, - MessageInfos: file_proto_eth_v2_beacon_lightclient_proto_msgTypes, - }.Build() - File_proto_eth_v2_beacon_lightclient_proto = out.File - file_proto_eth_v2_beacon_lightclient_proto_rawDesc = nil - file_proto_eth_v2_beacon_lightclient_proto_goTypes = nil - file_proto_eth_v2_beacon_lightclient_proto_depIdxs = nil -} diff --git a/proto/eth/v2/beacon_lightclient.pb.gw.go b/proto/eth/v2/beacon_lightclient.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v2/beacon_lightclient.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v2/beacon_lightclient.proto b/proto/eth/v2/beacon_lightclient.proto deleted file mode 100644 index 6f3bcd62f745..000000000000 --- a/proto/eth/v2/beacon_lightclient.proto +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2023 Prysmatic Labs. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -syntax = "proto3"; - -package ethereum.eth.v2; - -import "proto/eth/ext/options.proto"; -import "proto/eth/v1/beacon_block.proto"; -import "proto/eth/v2/version.proto"; -import "proto/eth/v2/sync_committee.proto"; - -option csharp_namespace = "Ethereum.Eth.V2"; -option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2;eth"; -option java_multiple_files = true; -option java_outer_classname = "SyncCommitteeProto"; -option java_package = "org.ethereum.eth.v2"; -option php_namespace = "Ethereum\\Eth\\v2"; - -// Beacon LightClient API related messages. - -message LightClientBootstrap { - v1.BeaconBlockHeader header = 1; - SyncCommittee current_sync_committee = 2; - repeated bytes current_sync_committee_branch = 3; -} - -message LightClientUpdate { - v1.BeaconBlockHeader attested_header = 1; - SyncCommittee next_sync_committee = 2; - repeated bytes next_sync_committee_branch = 3; - v1.BeaconBlockHeader finalized_header = 4; - repeated bytes finality_branch = 5; - v1.SyncAggregate sync_aggregate = 6; - uint64 signature_slot = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; -} - -message LightClientFinalityUpdateWithVersion { - v2.Version version = 1; - LightClientFinalityUpdate data = 2; -} - -message LightClientFinalityUpdate { - v1.BeaconBlockHeader attested_header = 1; - v1.BeaconBlockHeader finalized_header = 2; - repeated bytes finality_branch = 3; - v1.SyncAggregate sync_aggregate = 4; - uint64 signature_slot = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; -} - -message LightClientOptimisticUpdateWithVersion { - v2.Version version = 1; - LightClientOptimisticUpdate data = 2; -} - -message LightClientOptimisticUpdate { - v1.BeaconBlockHeader attested_header = 1; - v1.SyncAggregate sync_aggregate = 2; - uint64 signature_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; -} diff --git a/proto/eth/v2/custom.go b/proto/eth/v2/custom.go deleted file mode 100644 index 9e7d97493fbc..000000000000 --- a/proto/eth/v2/custom.go +++ /dev/null @@ -1,51 +0,0 @@ -package eth - -import ( - "bytes" - "math/bits" -) - -const ( - NextSyncCommitteeIndex = uint64(55) - FinalizedRootIndex = uint64(105) -) - -func (x *SyncCommittee) Equals(other *SyncCommittee) bool { - if len(x.Pubkeys) != len(other.Pubkeys) { - return false - } - for i := range x.Pubkeys { - if !bytes.Equal(x.Pubkeys[i], other.Pubkeys[i]) { - return false - } - } - return bytes.Equal(x.AggregatePubkey, other.AggregatePubkey) -} - -func FloorLog2(x uint64) int { - return bits.Len64(x - 1) -} - -func isEmptyWithLength(bb [][]byte, length uint64) bool { - if len(bb) == 0 { - return true - } - l := FloorLog2(length) - if len(bb) != l { - return false - } - for _, b := range bb { - if !bytes.Equal(b, []byte{}) { - return false - } - } - return true -} - -func (x *LightClientUpdate) IsSyncCommiteeUpdate() bool { - return !isEmptyWithLength(x.GetNextSyncCommitteeBranch(), NextSyncCommitteeIndex) -} - -func (x *LightClientUpdate) IsFinalityUpdate() bool { - return !isEmptyWithLength(x.GetFinalityBranch(), FinalizedRootIndex) -} diff --git a/proto/eth/v2/grpc.ssz.go b/proto/eth/v2/grpc.ssz.go deleted file mode 100644 index af4fd70ce818..000000000000 --- a/proto/eth/v2/grpc.ssz.go +++ /dev/null @@ -1,6305 +0,0 @@ -// Code generated by fastssz. DO NOT EDIT. -// Hash: e1b3713d854395a4c86aa7a0bf0249d9f2764183a636fcc53badddeaf38990f2 -package eth - -import ( - ssz "github.com/prysmaticlabs/fastssz" - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" - v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" -) - -// MarshalSSZ ssz marshals the SignedBeaconBlockAltair object -func (s *SignedBeaconBlockAltair) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBeaconBlockAltair object to a target array -func (s *SignedBeaconBlockAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Message' - dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(BeaconBlockAltair) - } - offset += s.Message.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockAltair object -func (s *SignedBeaconBlockAltair) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Message' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Message' - { - buf = tail[o0:] - if s.Message == nil { - s.Message = new(BeaconBlockAltair) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockAltair object -func (s *SignedBeaconBlockAltair) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BeaconBlockAltair) - } - size += s.Message.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBeaconBlockAltair object -func (s *SignedBeaconBlockAltair) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBeaconBlockAltair object with a hasher -func (s *SignedBeaconBlockAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBeaconBlockBellatrix object -func (s *SignedBeaconBlockBellatrix) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBeaconBlockBellatrix object to a target array -func (s *SignedBeaconBlockBellatrix) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Message' - dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(BeaconBlockBellatrix) - } - offset += s.Message.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockBellatrix object -func (s *SignedBeaconBlockBellatrix) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Message' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Message' - { - buf = tail[o0:] - if s.Message == nil { - s.Message = new(BeaconBlockBellatrix) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockBellatrix object -func (s *SignedBeaconBlockBellatrix) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BeaconBlockBellatrix) - } - size += s.Message.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBeaconBlockBellatrix object -func (s *SignedBeaconBlockBellatrix) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBeaconBlockBellatrix object with a hasher -func (s *SignedBeaconBlockBellatrix) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBeaconBlockCapella object -func (s *SignedBeaconBlockCapella) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBeaconBlockCapella object to a target array -func (s *SignedBeaconBlockCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Message' - dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(BeaconBlockCapella) - } - offset += s.Message.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockCapella object -func (s *SignedBeaconBlockCapella) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Message' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Message' - { - buf = tail[o0:] - if s.Message == nil { - s.Message = new(BeaconBlockCapella) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockCapella object -func (s *SignedBeaconBlockCapella) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BeaconBlockCapella) - } - size += s.Message.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBeaconBlockCapella object -func (s *SignedBeaconBlockCapella) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBeaconBlockCapella object with a hasher -func (s *SignedBeaconBlockCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBeaconBlockDeneb object -func (s *SignedBeaconBlockDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBeaconBlockDeneb object to a target array -func (s *SignedBeaconBlockDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Message' - dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(BeaconBlockDeneb) - } - offset += s.Message.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockDeneb object -func (s *SignedBeaconBlockDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Message' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Message' - { - buf = tail[o0:] - if s.Message == nil { - s.Message = new(BeaconBlockDeneb) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockDeneb object -func (s *SignedBeaconBlockDeneb) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BeaconBlockDeneb) - } - size += s.Message.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBeaconBlockDeneb object -func (s *SignedBeaconBlockDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBeaconBlockDeneb object with a hasher -func (s *SignedBeaconBlockDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBlindedBeaconBlockBellatrix object -func (s *SignedBlindedBeaconBlockBellatrix) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBlindedBeaconBlockBellatrix object to a target array -func (s *SignedBlindedBeaconBlockBellatrix) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Message' - dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(BlindedBeaconBlockBellatrix) - } - offset += s.Message.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBlindedBeaconBlockBellatrix object -func (s *SignedBlindedBeaconBlockBellatrix) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Message' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Message' - { - buf = tail[o0:] - if s.Message == nil { - s.Message = new(BlindedBeaconBlockBellatrix) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBlindedBeaconBlockBellatrix object -func (s *SignedBlindedBeaconBlockBellatrix) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BlindedBeaconBlockBellatrix) - } - size += s.Message.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBlindedBeaconBlockBellatrix object -func (s *SignedBlindedBeaconBlockBellatrix) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBlindedBeaconBlockBellatrix object with a hasher -func (s *SignedBlindedBeaconBlockBellatrix) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBlindedBeaconBlockCapella object -func (s *SignedBlindedBeaconBlockCapella) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBlindedBeaconBlockCapella object to a target array -func (s *SignedBlindedBeaconBlockCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Message' - dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(BlindedBeaconBlockCapella) - } - offset += s.Message.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBlindedBeaconBlockCapella object -func (s *SignedBlindedBeaconBlockCapella) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Message' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Message' - { - buf = tail[o0:] - if s.Message == nil { - s.Message = new(BlindedBeaconBlockCapella) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBlindedBeaconBlockCapella object -func (s *SignedBlindedBeaconBlockCapella) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BlindedBeaconBlockCapella) - } - size += s.Message.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBlindedBeaconBlockCapella object -func (s *SignedBlindedBeaconBlockCapella) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBlindedBeaconBlockCapella object with a hasher -func (s *SignedBlindedBeaconBlockCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBlindedBeaconBlockDeneb object -func (s *SignedBlindedBeaconBlockDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBlindedBeaconBlockDeneb object to a target array -func (s *SignedBlindedBeaconBlockDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Message' - dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(BlindedBeaconBlockDeneb) - } - offset += s.Message.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBlindedBeaconBlockDeneb object -func (s *SignedBlindedBeaconBlockDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Message' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Message' - { - buf = tail[o0:] - if s.Message == nil { - s.Message = new(BlindedBeaconBlockDeneb) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBlindedBeaconBlockDeneb object -func (s *SignedBlindedBeaconBlockDeneb) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BlindedBeaconBlockDeneb) - } - size += s.Message.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBlindedBeaconBlockDeneb object -func (s *SignedBlindedBeaconBlockDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBlindedBeaconBlockDeneb object with a hasher -func (s *SignedBlindedBeaconBlockDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockAltair object -func (b *BeaconBlockAltair) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockAltair object to a target array -func (b *BeaconBlockAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(84) - - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - dst = append(dst, b.ParentRoot...) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - dst = append(dst, b.StateRoot...) - - // Offset (4) 'Body' - dst = ssz.WriteOffset(dst, offset) - if b.Body == nil { - b.Body = new(BeaconBlockBodyAltair) - } - offset += b.Body.SizeSSZ() - - // Field (4) 'Body' - if dst, err = b.Body.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockAltair object -func (b *BeaconBlockAltair) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 84 { - return ssz.ErrSize - } - - tail := buf - var o4 uint64 - - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) - } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) - } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - - // Offset (4) 'Body' - if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { - return ssz.ErrOffset - } - - if o4 != 84 { - return ssz.ErrInvalidVariableOffset - } - - // Field (4) 'Body' - { - buf = tail[o4:] - if b.Body == nil { - b.Body = new(BeaconBlockBodyAltair) - } - if err = b.Body.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockAltair object -func (b *BeaconBlockAltair) SizeSSZ() (size int) { - size = 84 - - // Field (4) 'Body' - if b.Body == nil { - b.Body = new(BeaconBlockBodyAltair) - } - size += b.Body.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockAltair object -func (b *BeaconBlockAltair) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockAltair object with a hasher -func (b *BeaconBlockAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - hh.PutBytes(b.ParentRoot) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - hh.PutBytes(b.StateRoot) - - // Field (4) 'Body' - if err = b.Body.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockBellatrix object -func (b *BeaconBlockBellatrix) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockBellatrix object to a target array -func (b *BeaconBlockBellatrix) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(84) - - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - dst = append(dst, b.ParentRoot...) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - dst = append(dst, b.StateRoot...) - - // Offset (4) 'Body' - dst = ssz.WriteOffset(dst, offset) - if b.Body == nil { - b.Body = new(BeaconBlockBodyBellatrix) - } - offset += b.Body.SizeSSZ() - - // Field (4) 'Body' - if dst, err = b.Body.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockBellatrix object -func (b *BeaconBlockBellatrix) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 84 { - return ssz.ErrSize - } - - tail := buf - var o4 uint64 - - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) - } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) - } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - - // Offset (4) 'Body' - if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { - return ssz.ErrOffset - } - - if o4 != 84 { - return ssz.ErrInvalidVariableOffset - } - - // Field (4) 'Body' - { - buf = tail[o4:] - if b.Body == nil { - b.Body = new(BeaconBlockBodyBellatrix) - } - if err = b.Body.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBellatrix object -func (b *BeaconBlockBellatrix) SizeSSZ() (size int) { - size = 84 - - // Field (4) 'Body' - if b.Body == nil { - b.Body = new(BeaconBlockBodyBellatrix) - } - size += b.Body.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockBellatrix object -func (b *BeaconBlockBellatrix) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockBellatrix object with a hasher -func (b *BeaconBlockBellatrix) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - hh.PutBytes(b.ParentRoot) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - hh.PutBytes(b.StateRoot) - - // Field (4) 'Body' - if err = b.Body.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BlindedBeaconBlockBellatrix object -func (b *BlindedBeaconBlockBellatrix) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlindedBeaconBlockBellatrix object to a target array -func (b *BlindedBeaconBlockBellatrix) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(84) - - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - dst = append(dst, b.ParentRoot...) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - dst = append(dst, b.StateRoot...) - - // Offset (4) 'Body' - dst = ssz.WriteOffset(dst, offset) - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyBellatrix) - } - offset += b.Body.SizeSSZ() - - // Field (4) 'Body' - if dst, err = b.Body.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockBellatrix object -func (b *BlindedBeaconBlockBellatrix) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 84 { - return ssz.ErrSize - } - - tail := buf - var o4 uint64 - - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) - } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) - } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - - // Offset (4) 'Body' - if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { - return ssz.ErrOffset - } - - if o4 != 84 { - return ssz.ErrInvalidVariableOffset - } - - // Field (4) 'Body' - { - buf = tail[o4:] - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyBellatrix) - } - if err = b.Body.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockBellatrix object -func (b *BlindedBeaconBlockBellatrix) SizeSSZ() (size int) { - size = 84 - - // Field (4) 'Body' - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyBellatrix) - } - size += b.Body.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BlindedBeaconBlockBellatrix object -func (b *BlindedBeaconBlockBellatrix) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlindedBeaconBlockBellatrix object with a hasher -func (b *BlindedBeaconBlockBellatrix) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - hh.PutBytes(b.ParentRoot) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - hh.PutBytes(b.StateRoot) - - // Field (4) 'Body' - if err = b.Body.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockCapella object -func (b *BeaconBlockCapella) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockCapella object to a target array -func (b *BeaconBlockCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(84) - - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - dst = append(dst, b.ParentRoot...) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - dst = append(dst, b.StateRoot...) - - // Offset (4) 'Body' - dst = ssz.WriteOffset(dst, offset) - if b.Body == nil { - b.Body = new(BeaconBlockBodyCapella) - } - offset += b.Body.SizeSSZ() - - // Field (4) 'Body' - if dst, err = b.Body.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockCapella object -func (b *BeaconBlockCapella) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 84 { - return ssz.ErrSize - } - - tail := buf - var o4 uint64 - - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) - } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) - } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - - // Offset (4) 'Body' - if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { - return ssz.ErrOffset - } - - if o4 != 84 { - return ssz.ErrInvalidVariableOffset - } - - // Field (4) 'Body' - { - buf = tail[o4:] - if b.Body == nil { - b.Body = new(BeaconBlockBodyCapella) - } - if err = b.Body.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockCapella object -func (b *BeaconBlockCapella) SizeSSZ() (size int) { - size = 84 - - // Field (4) 'Body' - if b.Body == nil { - b.Body = new(BeaconBlockBodyCapella) - } - size += b.Body.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockCapella object -func (b *BeaconBlockCapella) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockCapella object with a hasher -func (b *BeaconBlockCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - hh.PutBytes(b.ParentRoot) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - hh.PutBytes(b.StateRoot) - - // Field (4) 'Body' - if err = b.Body.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BlindedBeaconBlockCapella object -func (b *BlindedBeaconBlockCapella) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlindedBeaconBlockCapella object to a target array -func (b *BlindedBeaconBlockCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(84) - - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - dst = append(dst, b.ParentRoot...) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - dst = append(dst, b.StateRoot...) - - // Offset (4) 'Body' - dst = ssz.WriteOffset(dst, offset) - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyCapella) - } - offset += b.Body.SizeSSZ() - - // Field (4) 'Body' - if dst, err = b.Body.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockCapella object -func (b *BlindedBeaconBlockCapella) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 84 { - return ssz.ErrSize - } - - tail := buf - var o4 uint64 - - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) - } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) - } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - - // Offset (4) 'Body' - if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { - return ssz.ErrOffset - } - - if o4 != 84 { - return ssz.ErrInvalidVariableOffset - } - - // Field (4) 'Body' - { - buf = tail[o4:] - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyCapella) - } - if err = b.Body.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockCapella object -func (b *BlindedBeaconBlockCapella) SizeSSZ() (size int) { - size = 84 - - // Field (4) 'Body' - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyCapella) - } - size += b.Body.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BlindedBeaconBlockCapella object -func (b *BlindedBeaconBlockCapella) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlindedBeaconBlockCapella object with a hasher -func (b *BlindedBeaconBlockCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - hh.PutBytes(b.ParentRoot) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - hh.PutBytes(b.StateRoot) - - // Field (4) 'Body' - if err = b.Body.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockDeneb object -func (b *BeaconBlockDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockDeneb object to a target array -func (b *BeaconBlockDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(84) - - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - dst = append(dst, b.ParentRoot...) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - dst = append(dst, b.StateRoot...) - - // Offset (4) 'Body' - dst = ssz.WriteOffset(dst, offset) - if b.Body == nil { - b.Body = new(BeaconBlockBodyDeneb) - } - offset += b.Body.SizeSSZ() - - // Field (4) 'Body' - if dst, err = b.Body.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockDeneb object -func (b *BeaconBlockDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 84 { - return ssz.ErrSize - } - - tail := buf - var o4 uint64 - - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) - } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) - } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - - // Offset (4) 'Body' - if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { - return ssz.ErrOffset - } - - if o4 != 84 { - return ssz.ErrInvalidVariableOffset - } - - // Field (4) 'Body' - { - buf = tail[o4:] - if b.Body == nil { - b.Body = new(BeaconBlockBodyDeneb) - } - if err = b.Body.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockDeneb object -func (b *BeaconBlockDeneb) SizeSSZ() (size int) { - size = 84 - - // Field (4) 'Body' - if b.Body == nil { - b.Body = new(BeaconBlockBodyDeneb) - } - size += b.Body.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockDeneb object -func (b *BeaconBlockDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockDeneb object with a hasher -func (b *BeaconBlockDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - hh.PutBytes(b.ParentRoot) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - hh.PutBytes(b.StateRoot) - - // Field (4) 'Body' - if err = b.Body.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BlindedBeaconBlockDeneb object -func (b *BlindedBeaconBlockDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlindedBeaconBlockDeneb object to a target array -func (b *BlindedBeaconBlockDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(84) - - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - dst = append(dst, b.ParentRoot...) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - dst = append(dst, b.StateRoot...) - - // Offset (4) 'Body' - dst = ssz.WriteOffset(dst, offset) - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyDeneb) - } - offset += b.Body.SizeSSZ() - - // Field (4) 'Body' - if dst, err = b.Body.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockDeneb object -func (b *BlindedBeaconBlockDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 84 { - return ssz.ErrSize - } - - tail := buf - var o4 uint64 - - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) - } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) - } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - - // Offset (4) 'Body' - if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { - return ssz.ErrOffset - } - - if o4 != 84 { - return ssz.ErrInvalidVariableOffset - } - - // Field (4) 'Body' - { - buf = tail[o4:] - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyDeneb) - } - if err = b.Body.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockDeneb object -func (b *BlindedBeaconBlockDeneb) SizeSSZ() (size int) { - size = 84 - - // Field (4) 'Body' - if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyDeneb) - } - size += b.Body.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BlindedBeaconBlockDeneb object -func (b *BlindedBeaconBlockDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlindedBeaconBlockDeneb object with a hasher -func (b *BlindedBeaconBlockDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - hh.PutBytes(b.ParentRoot) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) - return - } - hh.PutBytes(b.StateRoot) - - // Field (4) 'Body' - if err = b.Body.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockBodyAltair object -func (b *BeaconBlockBodyAltair) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockBodyAltair object to a target array -func (b *BeaconBlockBodyAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(380) - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - dst = append(dst, b.RandaoReveal...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - dst = append(dst, b.Graffiti...) - - // Offset (3) 'ProposerSlashings' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.ProposerSlashings) * 416 - - // Offset (4) 'AttesterSlashings' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - offset += 4 - offset += b.AttesterSlashings[ii].SizeSSZ() - } - - // Offset (5) 'Attestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.Attestations); ii++ { - offset += 4 - offset += b.Attestations[ii].SizeSSZ() - } - - // Offset (6) 'Deposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Deposits) * 1240 - - // Offset (7) 'VoluntaryExits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.VoluntaryExits) * 112 - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { - return - } - - // Field (3) 'ProposerSlashings' - if size := len(b.ProposerSlashings); size > 16 { - err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) - return - } - for ii := 0; ii < len(b.ProposerSlashings); ii++ { - if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (4) 'AttesterSlashings' - if size := len(b.AttesterSlashings); size > 2 { - err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 2) - return - } - { - offset = 4 * len(b.AttesterSlashings) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.AttesterSlashings[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (5) 'Attestations' - if size := len(b.Attestations); size > 128 { - err = ssz.ErrListTooBigFn("--.Attestations", size, 128) - return - } - { - offset = 4 * len(b.Attestations) - for ii := 0; ii < len(b.Attestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.Attestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.Attestations); ii++ { - if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (6) 'Deposits' - if size := len(b.Deposits); size > 16 { - err = ssz.ErrListTooBigFn("--.Deposits", size, 16) - return - } - for ii := 0; ii < len(b.Deposits); ii++ { - if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (7) 'VoluntaryExits' - if size := len(b.VoluntaryExits); size > 16 { - err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) - return - } - for ii := 0; ii < len(b.VoluntaryExits); ii++ { - if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockBodyAltair object -func (b *BeaconBlockBodyAltair) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 380 { - return ssz.ErrSize - } - - tail := buf - var o3, o4, o5, o6, o7 uint64 - - // Field (0) 'RandaoReveal' - if cap(b.RandaoReveal) == 0 { - b.RandaoReveal = make([]byte, 0, len(buf[0:96])) - } - b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { - return err - } - - // Field (2) 'Graffiti' - if cap(b.Graffiti) == 0 { - b.Graffiti = make([]byte, 0, len(buf[168:200])) - } - b.Graffiti = append(b.Graffiti, buf[168:200]...) - - // Offset (3) 'ProposerSlashings' - if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { - return ssz.ErrOffset - } - - if o3 != 380 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (4) 'AttesterSlashings' - if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { - return ssz.ErrOffset - } - - // Offset (5) 'Attestations' - if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } - - // Offset (6) 'Deposits' - if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { - return ssz.ErrOffset - } - - // Offset (7) 'VoluntaryExits' - if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { - return ssz.ErrOffset - } - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { - return err - } - - // Field (3) 'ProposerSlashings' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 416, 16) - if err != nil { - return err - } - b.ProposerSlashings = make([]*v1.ProposerSlashing, num) - for ii := 0; ii < num; ii++ { - if b.ProposerSlashings[ii] == nil { - b.ProposerSlashings[ii] = new(v1.ProposerSlashing) - } - if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { - return err - } - } - } - - // Field (4) 'AttesterSlashings' - { - buf = tail[o4:o5] - num, err := ssz.DecodeDynamicLength(buf, 2) - if err != nil { - return err - } - b.AttesterSlashings = make([]*v1.AttesterSlashing, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.AttesterSlashings[indx] == nil { - b.AttesterSlashings[indx] = new(v1.AttesterSlashing) - } - if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (5) 'Attestations' - { - buf = tail[o5:o6] - num, err := ssz.DecodeDynamicLength(buf, 128) - if err != nil { - return err - } - b.Attestations = make([]*v1.Attestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.Attestations[indx] == nil { - b.Attestations[indx] = new(v1.Attestation) - } - if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (6) 'Deposits' - { - buf = tail[o6:o7] - num, err := ssz.DivideInt2(len(buf), 1240, 16) - if err != nil { - return err - } - b.Deposits = make([]*v1.Deposit, num) - for ii := 0; ii < num; ii++ { - if b.Deposits[ii] == nil { - b.Deposits[ii] = new(v1.Deposit) - } - if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { - return err - } - } - } - - // Field (7) 'VoluntaryExits' - { - buf = tail[o7:] - num, err := ssz.DivideInt2(len(buf), 112, 16) - if err != nil { - return err - } - b.VoluntaryExits = make([]*v1.SignedVoluntaryExit, num) - for ii := 0; ii < num; ii++ { - if b.VoluntaryExits[ii] == nil { - b.VoluntaryExits[ii] = new(v1.SignedVoluntaryExit) - } - if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { - return err - } - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyAltair object -func (b *BeaconBlockBodyAltair) SizeSSZ() (size int) { - size = 380 - - // Field (3) 'ProposerSlashings' - size += len(b.ProposerSlashings) * 416 - - // Field (4) 'AttesterSlashings' - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - size += 4 - size += b.AttesterSlashings[ii].SizeSSZ() - } - - // Field (5) 'Attestations' - for ii := 0; ii < len(b.Attestations); ii++ { - size += 4 - size += b.Attestations[ii].SizeSSZ() - } - - // Field (6) 'Deposits' - size += len(b.Deposits) * 1240 - - // Field (7) 'VoluntaryExits' - size += len(b.VoluntaryExits) * 112 - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockBodyAltair object -func (b *BeaconBlockBodyAltair) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockBodyAltair object with a hasher -func (b *BeaconBlockBodyAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - hh.PutBytes(b.RandaoReveal) - - // Field (1) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - hh.PutBytes(b.Graffiti) - - // Field (3) 'ProposerSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.ProposerSlashings)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.ProposerSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (4) 'AttesterSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.AttesterSlashings)) - if num > 2 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.AttesterSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 2) - } - - // Field (5) 'Attestations' - { - subIndx := hh.Index() - num := uint64(len(b.Attestations)) - if num > 128 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Attestations { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 128) - } - - // Field (6) 'Deposits' - { - subIndx := hh.Index() - num := uint64(len(b.Deposits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Deposits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (7) 'VoluntaryExits' - { - subIndx := hh.Index() - num := uint64(len(b.VoluntaryExits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.VoluntaryExits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (8) 'SyncAggregate' - if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockBodyBellatrix object -func (b *BeaconBlockBodyBellatrix) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockBodyBellatrix object to a target array -func (b *BeaconBlockBodyBellatrix) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(384) - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - dst = append(dst, b.RandaoReveal...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - dst = append(dst, b.Graffiti...) - - // Offset (3) 'ProposerSlashings' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.ProposerSlashings) * 416 - - // Offset (4) 'AttesterSlashings' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - offset += 4 - offset += b.AttesterSlashings[ii].SizeSSZ() - } - - // Offset (5) 'Attestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.Attestations); ii++ { - offset += 4 - offset += b.Attestations[ii].SizeSSZ() - } - - // Offset (6) 'Deposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Deposits) * 1240 - - // Offset (7) 'VoluntaryExits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.VoluntaryExits) * 112 - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'ExecutionPayload' - dst = ssz.WriteOffset(dst, offset) - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayload) - } - offset += b.ExecutionPayload.SizeSSZ() - - // Field (3) 'ProposerSlashings' - if size := len(b.ProposerSlashings); size > 16 { - err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) - return - } - for ii := 0; ii < len(b.ProposerSlashings); ii++ { - if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (4) 'AttesterSlashings' - if size := len(b.AttesterSlashings); size > 2 { - err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 2) - return - } - { - offset = 4 * len(b.AttesterSlashings) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.AttesterSlashings[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (5) 'Attestations' - if size := len(b.Attestations); size > 128 { - err = ssz.ErrListTooBigFn("--.Attestations", size, 128) - return - } - { - offset = 4 * len(b.Attestations) - for ii := 0; ii < len(b.Attestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.Attestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.Attestations); ii++ { - if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (6) 'Deposits' - if size := len(b.Deposits); size > 16 { - err = ssz.ErrListTooBigFn("--.Deposits", size, 16) - return - } - for ii := 0; ii < len(b.Deposits); ii++ { - if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (7) 'VoluntaryExits' - if size := len(b.VoluntaryExits); size > 16 { - err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) - return - } - for ii := 0; ii < len(b.VoluntaryExits); ii++ { - if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (9) 'ExecutionPayload' - if dst, err = b.ExecutionPayload.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockBodyBellatrix object -func (b *BeaconBlockBodyBellatrix) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 384 { - return ssz.ErrSize - } - - tail := buf - var o3, o4, o5, o6, o7, o9 uint64 - - // Field (0) 'RandaoReveal' - if cap(b.RandaoReveal) == 0 { - b.RandaoReveal = make([]byte, 0, len(buf[0:96])) - } - b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { - return err - } - - // Field (2) 'Graffiti' - if cap(b.Graffiti) == 0 { - b.Graffiti = make([]byte, 0, len(buf[168:200])) - } - b.Graffiti = append(b.Graffiti, buf[168:200]...) - - // Offset (3) 'ProposerSlashings' - if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { - return ssz.ErrOffset - } - - if o3 != 384 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (4) 'AttesterSlashings' - if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { - return ssz.ErrOffset - } - - // Offset (5) 'Attestations' - if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } - - // Offset (6) 'Deposits' - if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { - return ssz.ErrOffset - } - - // Offset (7) 'VoluntaryExits' - if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { - return ssz.ErrOffset - } - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { - return err - } - - // Offset (9) 'ExecutionPayload' - if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Field (3) 'ProposerSlashings' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 416, 16) - if err != nil { - return err - } - b.ProposerSlashings = make([]*v1.ProposerSlashing, num) - for ii := 0; ii < num; ii++ { - if b.ProposerSlashings[ii] == nil { - b.ProposerSlashings[ii] = new(v1.ProposerSlashing) - } - if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { - return err - } - } - } - - // Field (4) 'AttesterSlashings' - { - buf = tail[o4:o5] - num, err := ssz.DecodeDynamicLength(buf, 2) - if err != nil { - return err - } - b.AttesterSlashings = make([]*v1.AttesterSlashing, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.AttesterSlashings[indx] == nil { - b.AttesterSlashings[indx] = new(v1.AttesterSlashing) - } - if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (5) 'Attestations' - { - buf = tail[o5:o6] - num, err := ssz.DecodeDynamicLength(buf, 128) - if err != nil { - return err - } - b.Attestations = make([]*v1.Attestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.Attestations[indx] == nil { - b.Attestations[indx] = new(v1.Attestation) - } - if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (6) 'Deposits' - { - buf = tail[o6:o7] - num, err := ssz.DivideInt2(len(buf), 1240, 16) - if err != nil { - return err - } - b.Deposits = make([]*v1.Deposit, num) - for ii := 0; ii < num; ii++ { - if b.Deposits[ii] == nil { - b.Deposits[ii] = new(v1.Deposit) - } - if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { - return err - } - } - } - - // Field (7) 'VoluntaryExits' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 112, 16) - if err != nil { - return err - } - b.VoluntaryExits = make([]*v1.SignedVoluntaryExit, num) - for ii := 0; ii < num; ii++ { - if b.VoluntaryExits[ii] == nil { - b.VoluntaryExits[ii] = new(v1.SignedVoluntaryExit) - } - if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { - return err - } - } - } - - // Field (9) 'ExecutionPayload' - { - buf = tail[o9:] - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayload) - } - if err = b.ExecutionPayload.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyBellatrix object -func (b *BeaconBlockBodyBellatrix) SizeSSZ() (size int) { - size = 384 - - // Field (3) 'ProposerSlashings' - size += len(b.ProposerSlashings) * 416 - - // Field (4) 'AttesterSlashings' - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - size += 4 - size += b.AttesterSlashings[ii].SizeSSZ() - } - - // Field (5) 'Attestations' - for ii := 0; ii < len(b.Attestations); ii++ { - size += 4 - size += b.Attestations[ii].SizeSSZ() - } - - // Field (6) 'Deposits' - size += len(b.Deposits) * 1240 - - // Field (7) 'VoluntaryExits' - size += len(b.VoluntaryExits) * 112 - - // Field (9) 'ExecutionPayload' - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayload) - } - size += b.ExecutionPayload.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockBodyBellatrix object -func (b *BeaconBlockBodyBellatrix) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockBodyBellatrix object with a hasher -func (b *BeaconBlockBodyBellatrix) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - hh.PutBytes(b.RandaoReveal) - - // Field (1) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - hh.PutBytes(b.Graffiti) - - // Field (3) 'ProposerSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.ProposerSlashings)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.ProposerSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (4) 'AttesterSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.AttesterSlashings)) - if num > 2 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.AttesterSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 2) - } - - // Field (5) 'Attestations' - { - subIndx := hh.Index() - num := uint64(len(b.Attestations)) - if num > 128 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Attestations { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 128) - } - - // Field (6) 'Deposits' - { - subIndx := hh.Index() - num := uint64(len(b.Deposits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Deposits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (7) 'VoluntaryExits' - { - subIndx := hh.Index() - num := uint64(len(b.VoluntaryExits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.VoluntaryExits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (8) 'SyncAggregate' - if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { - return - } - - // Field (9) 'ExecutionPayload' - if err = b.ExecutionPayload.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BlindedBeaconBlockBodyBellatrix object -func (b *BlindedBeaconBlockBodyBellatrix) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlindedBeaconBlockBodyBellatrix object to a target array -func (b *BlindedBeaconBlockBodyBellatrix) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(384) - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - dst = append(dst, b.RandaoReveal...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - dst = append(dst, b.Graffiti...) - - // Offset (3) 'ProposerSlashings' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.ProposerSlashings) * 416 - - // Offset (4) 'AttesterSlashings' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - offset += 4 - offset += b.AttesterSlashings[ii].SizeSSZ() - } - - // Offset (5) 'Attestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.Attestations); ii++ { - offset += 4 - offset += b.Attestations[ii].SizeSSZ() - } - - // Offset (6) 'Deposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Deposits) * 1240 - - // Offset (7) 'VoluntaryExits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.VoluntaryExits) * 112 - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'ExecutionPayloadHeader' - dst = ssz.WriteOffset(dst, offset) - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeader) - } - offset += b.ExecutionPayloadHeader.SizeSSZ() - - // Field (3) 'ProposerSlashings' - if size := len(b.ProposerSlashings); size > 16 { - err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) - return - } - for ii := 0; ii < len(b.ProposerSlashings); ii++ { - if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (4) 'AttesterSlashings' - if size := len(b.AttesterSlashings); size > 2 { - err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 2) - return - } - { - offset = 4 * len(b.AttesterSlashings) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.AttesterSlashings[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (5) 'Attestations' - if size := len(b.Attestations); size > 128 { - err = ssz.ErrListTooBigFn("--.Attestations", size, 128) - return - } - { - offset = 4 * len(b.Attestations) - for ii := 0; ii < len(b.Attestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.Attestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.Attestations); ii++ { - if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (6) 'Deposits' - if size := len(b.Deposits); size > 16 { - err = ssz.ErrListTooBigFn("--.Deposits", size, 16) - return - } - for ii := 0; ii < len(b.Deposits); ii++ { - if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (7) 'VoluntaryExits' - if size := len(b.VoluntaryExits); size > 16 { - err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) - return - } - for ii := 0; ii < len(b.VoluntaryExits); ii++ { - if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (9) 'ExecutionPayloadHeader' - if dst, err = b.ExecutionPayloadHeader.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockBodyBellatrix object -func (b *BlindedBeaconBlockBodyBellatrix) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 384 { - return ssz.ErrSize - } - - tail := buf - var o3, o4, o5, o6, o7, o9 uint64 - - // Field (0) 'RandaoReveal' - if cap(b.RandaoReveal) == 0 { - b.RandaoReveal = make([]byte, 0, len(buf[0:96])) - } - b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { - return err - } - - // Field (2) 'Graffiti' - if cap(b.Graffiti) == 0 { - b.Graffiti = make([]byte, 0, len(buf[168:200])) - } - b.Graffiti = append(b.Graffiti, buf[168:200]...) - - // Offset (3) 'ProposerSlashings' - if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { - return ssz.ErrOffset - } - - if o3 != 384 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (4) 'AttesterSlashings' - if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { - return ssz.ErrOffset - } - - // Offset (5) 'Attestations' - if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } - - // Offset (6) 'Deposits' - if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { - return ssz.ErrOffset - } - - // Offset (7) 'VoluntaryExits' - if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { - return ssz.ErrOffset - } - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { - return err - } - - // Offset (9) 'ExecutionPayloadHeader' - if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Field (3) 'ProposerSlashings' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 416, 16) - if err != nil { - return err - } - b.ProposerSlashings = make([]*v1.ProposerSlashing, num) - for ii := 0; ii < num; ii++ { - if b.ProposerSlashings[ii] == nil { - b.ProposerSlashings[ii] = new(v1.ProposerSlashing) - } - if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { - return err - } - } - } - - // Field (4) 'AttesterSlashings' - { - buf = tail[o4:o5] - num, err := ssz.DecodeDynamicLength(buf, 2) - if err != nil { - return err - } - b.AttesterSlashings = make([]*v1.AttesterSlashing, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.AttesterSlashings[indx] == nil { - b.AttesterSlashings[indx] = new(v1.AttesterSlashing) - } - if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (5) 'Attestations' - { - buf = tail[o5:o6] - num, err := ssz.DecodeDynamicLength(buf, 128) - if err != nil { - return err - } - b.Attestations = make([]*v1.Attestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.Attestations[indx] == nil { - b.Attestations[indx] = new(v1.Attestation) - } - if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (6) 'Deposits' - { - buf = tail[o6:o7] - num, err := ssz.DivideInt2(len(buf), 1240, 16) - if err != nil { - return err - } - b.Deposits = make([]*v1.Deposit, num) - for ii := 0; ii < num; ii++ { - if b.Deposits[ii] == nil { - b.Deposits[ii] = new(v1.Deposit) - } - if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { - return err - } - } - } - - // Field (7) 'VoluntaryExits' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 112, 16) - if err != nil { - return err - } - b.VoluntaryExits = make([]*v1.SignedVoluntaryExit, num) - for ii := 0; ii < num; ii++ { - if b.VoluntaryExits[ii] == nil { - b.VoluntaryExits[ii] = new(v1.SignedVoluntaryExit) - } - if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { - return err - } - } - } - - // Field (9) 'ExecutionPayloadHeader' - { - buf = tail[o9:] - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeader) - } - if err = b.ExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockBodyBellatrix object -func (b *BlindedBeaconBlockBodyBellatrix) SizeSSZ() (size int) { - size = 384 - - // Field (3) 'ProposerSlashings' - size += len(b.ProposerSlashings) * 416 - - // Field (4) 'AttesterSlashings' - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - size += 4 - size += b.AttesterSlashings[ii].SizeSSZ() - } - - // Field (5) 'Attestations' - for ii := 0; ii < len(b.Attestations); ii++ { - size += 4 - size += b.Attestations[ii].SizeSSZ() - } - - // Field (6) 'Deposits' - size += len(b.Deposits) * 1240 - - // Field (7) 'VoluntaryExits' - size += len(b.VoluntaryExits) * 112 - - // Field (9) 'ExecutionPayloadHeader' - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeader) - } - size += b.ExecutionPayloadHeader.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the BlindedBeaconBlockBodyBellatrix object -func (b *BlindedBeaconBlockBodyBellatrix) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlindedBeaconBlockBodyBellatrix object with a hasher -func (b *BlindedBeaconBlockBodyBellatrix) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - hh.PutBytes(b.RandaoReveal) - - // Field (1) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - hh.PutBytes(b.Graffiti) - - // Field (3) 'ProposerSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.ProposerSlashings)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.ProposerSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (4) 'AttesterSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.AttesterSlashings)) - if num > 2 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.AttesterSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 2) - } - - // Field (5) 'Attestations' - { - subIndx := hh.Index() - num := uint64(len(b.Attestations)) - if num > 128 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Attestations { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 128) - } - - // Field (6) 'Deposits' - { - subIndx := hh.Index() - num := uint64(len(b.Deposits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Deposits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (7) 'VoluntaryExits' - { - subIndx := hh.Index() - num := uint64(len(b.VoluntaryExits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.VoluntaryExits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (8) 'SyncAggregate' - if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { - return - } - - // Field (9) 'ExecutionPayloadHeader' - if err = b.ExecutionPayloadHeader.HashTreeRootWith(hh); err != nil { - return - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockBodyCapella object -func (b *BeaconBlockBodyCapella) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockBodyCapella object to a target array -func (b *BeaconBlockBodyCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(388) - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - dst = append(dst, b.RandaoReveal...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - dst = append(dst, b.Graffiti...) - - // Offset (3) 'ProposerSlashings' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.ProposerSlashings) * 416 - - // Offset (4) 'AttesterSlashings' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - offset += 4 - offset += b.AttesterSlashings[ii].SizeSSZ() - } - - // Offset (5) 'Attestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.Attestations); ii++ { - offset += 4 - offset += b.Attestations[ii].SizeSSZ() - } - - // Offset (6) 'Deposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Deposits) * 1240 - - // Offset (7) 'VoluntaryExits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.VoluntaryExits) * 112 - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'ExecutionPayload' - dst = ssz.WriteOffset(dst, offset) - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayloadCapella) - } - offset += b.ExecutionPayload.SizeSSZ() - - // Offset (10) 'BlsToExecutionChanges' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.BlsToExecutionChanges) * 172 - - // Field (3) 'ProposerSlashings' - if size := len(b.ProposerSlashings); size > 16 { - err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) - return - } - for ii := 0; ii < len(b.ProposerSlashings); ii++ { - if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (4) 'AttesterSlashings' - if size := len(b.AttesterSlashings); size > 2 { - err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 2) - return - } - { - offset = 4 * len(b.AttesterSlashings) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.AttesterSlashings[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (5) 'Attestations' - if size := len(b.Attestations); size > 128 { - err = ssz.ErrListTooBigFn("--.Attestations", size, 128) - return - } - { - offset = 4 * len(b.Attestations) - for ii := 0; ii < len(b.Attestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.Attestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.Attestations); ii++ { - if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (6) 'Deposits' - if size := len(b.Deposits); size > 16 { - err = ssz.ErrListTooBigFn("--.Deposits", size, 16) - return - } - for ii := 0; ii < len(b.Deposits); ii++ { - if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (7) 'VoluntaryExits' - if size := len(b.VoluntaryExits); size > 16 { - err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) - return - } - for ii := 0; ii < len(b.VoluntaryExits); ii++ { - if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (9) 'ExecutionPayload' - if dst, err = b.ExecutionPayload.MarshalSSZTo(dst); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - if size := len(b.BlsToExecutionChanges); size > 16 { - err = ssz.ErrListTooBigFn("--.BlsToExecutionChanges", size, 16) - return - } - for ii := 0; ii < len(b.BlsToExecutionChanges); ii++ { - if dst, err = b.BlsToExecutionChanges[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockBodyCapella object -func (b *BeaconBlockBodyCapella) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 388 { - return ssz.ErrSize - } - - tail := buf - var o3, o4, o5, o6, o7, o9, o10 uint64 - - // Field (0) 'RandaoReveal' - if cap(b.RandaoReveal) == 0 { - b.RandaoReveal = make([]byte, 0, len(buf[0:96])) - } - b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { - return err - } - - // Field (2) 'Graffiti' - if cap(b.Graffiti) == 0 { - b.Graffiti = make([]byte, 0, len(buf[168:200])) - } - b.Graffiti = append(b.Graffiti, buf[168:200]...) - - // Offset (3) 'ProposerSlashings' - if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { - return ssz.ErrOffset - } - - if o3 != 388 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (4) 'AttesterSlashings' - if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { - return ssz.ErrOffset - } - - // Offset (5) 'Attestations' - if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } - - // Offset (6) 'Deposits' - if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { - return ssz.ErrOffset - } - - // Offset (7) 'VoluntaryExits' - if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { - return ssz.ErrOffset - } - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { - return err - } - - // Offset (9) 'ExecutionPayload' - if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Offset (10) 'BlsToExecutionChanges' - if o10 = ssz.ReadOffset(buf[384:388]); o10 > size || o9 > o10 { - return ssz.ErrOffset - } - - // Field (3) 'ProposerSlashings' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 416, 16) - if err != nil { - return err - } - b.ProposerSlashings = make([]*v1.ProposerSlashing, num) - for ii := 0; ii < num; ii++ { - if b.ProposerSlashings[ii] == nil { - b.ProposerSlashings[ii] = new(v1.ProposerSlashing) - } - if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { - return err - } - } - } - - // Field (4) 'AttesterSlashings' - { - buf = tail[o4:o5] - num, err := ssz.DecodeDynamicLength(buf, 2) - if err != nil { - return err - } - b.AttesterSlashings = make([]*v1.AttesterSlashing, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.AttesterSlashings[indx] == nil { - b.AttesterSlashings[indx] = new(v1.AttesterSlashing) - } - if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (5) 'Attestations' - { - buf = tail[o5:o6] - num, err := ssz.DecodeDynamicLength(buf, 128) - if err != nil { - return err - } - b.Attestations = make([]*v1.Attestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.Attestations[indx] == nil { - b.Attestations[indx] = new(v1.Attestation) - } - if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (6) 'Deposits' - { - buf = tail[o6:o7] - num, err := ssz.DivideInt2(len(buf), 1240, 16) - if err != nil { - return err - } - b.Deposits = make([]*v1.Deposit, num) - for ii := 0; ii < num; ii++ { - if b.Deposits[ii] == nil { - b.Deposits[ii] = new(v1.Deposit) - } - if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { - return err - } - } - } - - // Field (7) 'VoluntaryExits' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 112, 16) - if err != nil { - return err - } - b.VoluntaryExits = make([]*v1.SignedVoluntaryExit, num) - for ii := 0; ii < num; ii++ { - if b.VoluntaryExits[ii] == nil { - b.VoluntaryExits[ii] = new(v1.SignedVoluntaryExit) - } - if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { - return err - } - } - } - - // Field (9) 'ExecutionPayload' - { - buf = tail[o9:o10] - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayloadCapella) - } - if err = b.ExecutionPayload.UnmarshalSSZ(buf); err != nil { - return err - } - } - - // Field (10) 'BlsToExecutionChanges' - { - buf = tail[o10:] - num, err := ssz.DivideInt2(len(buf), 172, 16) - if err != nil { - return err - } - b.BlsToExecutionChanges = make([]*SignedBLSToExecutionChange, num) - for ii := 0; ii < num; ii++ { - if b.BlsToExecutionChanges[ii] == nil { - b.BlsToExecutionChanges[ii] = new(SignedBLSToExecutionChange) - } - if err = b.BlsToExecutionChanges[ii].UnmarshalSSZ(buf[ii*172 : (ii+1)*172]); err != nil { - return err - } - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyCapella object -func (b *BeaconBlockBodyCapella) SizeSSZ() (size int) { - size = 388 - - // Field (3) 'ProposerSlashings' - size += len(b.ProposerSlashings) * 416 - - // Field (4) 'AttesterSlashings' - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - size += 4 - size += b.AttesterSlashings[ii].SizeSSZ() - } - - // Field (5) 'Attestations' - for ii := 0; ii < len(b.Attestations); ii++ { - size += 4 - size += b.Attestations[ii].SizeSSZ() - } - - // Field (6) 'Deposits' - size += len(b.Deposits) * 1240 - - // Field (7) 'VoluntaryExits' - size += len(b.VoluntaryExits) * 112 - - // Field (9) 'ExecutionPayload' - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayloadCapella) - } - size += b.ExecutionPayload.SizeSSZ() - - // Field (10) 'BlsToExecutionChanges' - size += len(b.BlsToExecutionChanges) * 172 - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockBodyCapella object -func (b *BeaconBlockBodyCapella) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockBodyCapella object with a hasher -func (b *BeaconBlockBodyCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - hh.PutBytes(b.RandaoReveal) - - // Field (1) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - hh.PutBytes(b.Graffiti) - - // Field (3) 'ProposerSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.ProposerSlashings)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.ProposerSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (4) 'AttesterSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.AttesterSlashings)) - if num > 2 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.AttesterSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 2) - } - - // Field (5) 'Attestations' - { - subIndx := hh.Index() - num := uint64(len(b.Attestations)) - if num > 128 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Attestations { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 128) - } - - // Field (6) 'Deposits' - { - subIndx := hh.Index() - num := uint64(len(b.Deposits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Deposits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (7) 'VoluntaryExits' - { - subIndx := hh.Index() - num := uint64(len(b.VoluntaryExits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.VoluntaryExits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (8) 'SyncAggregate' - if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { - return - } - - // Field (9) 'ExecutionPayload' - if err = b.ExecutionPayload.HashTreeRootWith(hh); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - { - subIndx := hh.Index() - num := uint64(len(b.BlsToExecutionChanges)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.BlsToExecutionChanges { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BlindedBeaconBlockBodyCapella object -func (b *BlindedBeaconBlockBodyCapella) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlindedBeaconBlockBodyCapella object to a target array -func (b *BlindedBeaconBlockBodyCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(388) - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - dst = append(dst, b.RandaoReveal...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - dst = append(dst, b.Graffiti...) - - // Offset (3) 'ProposerSlashings' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.ProposerSlashings) * 416 - - // Offset (4) 'AttesterSlashings' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - offset += 4 - offset += b.AttesterSlashings[ii].SizeSSZ() - } - - // Offset (5) 'Attestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.Attestations); ii++ { - offset += 4 - offset += b.Attestations[ii].SizeSSZ() - } - - // Offset (6) 'Deposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Deposits) * 1240 - - // Offset (7) 'VoluntaryExits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.VoluntaryExits) * 112 - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'ExecutionPayloadHeader' - dst = ssz.WriteOffset(dst, offset) - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeaderCapella) - } - offset += b.ExecutionPayloadHeader.SizeSSZ() - - // Offset (10) 'BlsToExecutionChanges' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.BlsToExecutionChanges) * 172 - - // Field (3) 'ProposerSlashings' - if size := len(b.ProposerSlashings); size > 16 { - err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) - return - } - for ii := 0; ii < len(b.ProposerSlashings); ii++ { - if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (4) 'AttesterSlashings' - if size := len(b.AttesterSlashings); size > 2 { - err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 2) - return - } - { - offset = 4 * len(b.AttesterSlashings) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.AttesterSlashings[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (5) 'Attestations' - if size := len(b.Attestations); size > 128 { - err = ssz.ErrListTooBigFn("--.Attestations", size, 128) - return - } - { - offset = 4 * len(b.Attestations) - for ii := 0; ii < len(b.Attestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.Attestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.Attestations); ii++ { - if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (6) 'Deposits' - if size := len(b.Deposits); size > 16 { - err = ssz.ErrListTooBigFn("--.Deposits", size, 16) - return - } - for ii := 0; ii < len(b.Deposits); ii++ { - if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (7) 'VoluntaryExits' - if size := len(b.VoluntaryExits); size > 16 { - err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) - return - } - for ii := 0; ii < len(b.VoluntaryExits); ii++ { - if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (9) 'ExecutionPayloadHeader' - if dst, err = b.ExecutionPayloadHeader.MarshalSSZTo(dst); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - if size := len(b.BlsToExecutionChanges); size > 16 { - err = ssz.ErrListTooBigFn("--.BlsToExecutionChanges", size, 16) - return - } - for ii := 0; ii < len(b.BlsToExecutionChanges); ii++ { - if dst, err = b.BlsToExecutionChanges[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockBodyCapella object -func (b *BlindedBeaconBlockBodyCapella) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 388 { - return ssz.ErrSize - } - - tail := buf - var o3, o4, o5, o6, o7, o9, o10 uint64 - - // Field (0) 'RandaoReveal' - if cap(b.RandaoReveal) == 0 { - b.RandaoReveal = make([]byte, 0, len(buf[0:96])) - } - b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { - return err - } - - // Field (2) 'Graffiti' - if cap(b.Graffiti) == 0 { - b.Graffiti = make([]byte, 0, len(buf[168:200])) - } - b.Graffiti = append(b.Graffiti, buf[168:200]...) - - // Offset (3) 'ProposerSlashings' - if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { - return ssz.ErrOffset - } - - if o3 != 388 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (4) 'AttesterSlashings' - if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { - return ssz.ErrOffset - } - - // Offset (5) 'Attestations' - if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } - - // Offset (6) 'Deposits' - if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { - return ssz.ErrOffset - } - - // Offset (7) 'VoluntaryExits' - if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { - return ssz.ErrOffset - } - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { - return err - } - - // Offset (9) 'ExecutionPayloadHeader' - if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Offset (10) 'BlsToExecutionChanges' - if o10 = ssz.ReadOffset(buf[384:388]); o10 > size || o9 > o10 { - return ssz.ErrOffset - } - - // Field (3) 'ProposerSlashings' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 416, 16) - if err != nil { - return err - } - b.ProposerSlashings = make([]*v1.ProposerSlashing, num) - for ii := 0; ii < num; ii++ { - if b.ProposerSlashings[ii] == nil { - b.ProposerSlashings[ii] = new(v1.ProposerSlashing) - } - if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { - return err - } - } - } - - // Field (4) 'AttesterSlashings' - { - buf = tail[o4:o5] - num, err := ssz.DecodeDynamicLength(buf, 2) - if err != nil { - return err - } - b.AttesterSlashings = make([]*v1.AttesterSlashing, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.AttesterSlashings[indx] == nil { - b.AttesterSlashings[indx] = new(v1.AttesterSlashing) - } - if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (5) 'Attestations' - { - buf = tail[o5:o6] - num, err := ssz.DecodeDynamicLength(buf, 128) - if err != nil { - return err - } - b.Attestations = make([]*v1.Attestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.Attestations[indx] == nil { - b.Attestations[indx] = new(v1.Attestation) - } - if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (6) 'Deposits' - { - buf = tail[o6:o7] - num, err := ssz.DivideInt2(len(buf), 1240, 16) - if err != nil { - return err - } - b.Deposits = make([]*v1.Deposit, num) - for ii := 0; ii < num; ii++ { - if b.Deposits[ii] == nil { - b.Deposits[ii] = new(v1.Deposit) - } - if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { - return err - } - } - } - - // Field (7) 'VoluntaryExits' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 112, 16) - if err != nil { - return err - } - b.VoluntaryExits = make([]*v1.SignedVoluntaryExit, num) - for ii := 0; ii < num; ii++ { - if b.VoluntaryExits[ii] == nil { - b.VoluntaryExits[ii] = new(v1.SignedVoluntaryExit) - } - if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { - return err - } - } - } - - // Field (9) 'ExecutionPayloadHeader' - { - buf = tail[o9:o10] - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeaderCapella) - } - if err = b.ExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { - return err - } - } - - // Field (10) 'BlsToExecutionChanges' - { - buf = tail[o10:] - num, err := ssz.DivideInt2(len(buf), 172, 16) - if err != nil { - return err - } - b.BlsToExecutionChanges = make([]*SignedBLSToExecutionChange, num) - for ii := 0; ii < num; ii++ { - if b.BlsToExecutionChanges[ii] == nil { - b.BlsToExecutionChanges[ii] = new(SignedBLSToExecutionChange) - } - if err = b.BlsToExecutionChanges[ii].UnmarshalSSZ(buf[ii*172 : (ii+1)*172]); err != nil { - return err - } - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockBodyCapella object -func (b *BlindedBeaconBlockBodyCapella) SizeSSZ() (size int) { - size = 388 - - // Field (3) 'ProposerSlashings' - size += len(b.ProposerSlashings) * 416 - - // Field (4) 'AttesterSlashings' - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - size += 4 - size += b.AttesterSlashings[ii].SizeSSZ() - } - - // Field (5) 'Attestations' - for ii := 0; ii < len(b.Attestations); ii++ { - size += 4 - size += b.Attestations[ii].SizeSSZ() - } - - // Field (6) 'Deposits' - size += len(b.Deposits) * 1240 - - // Field (7) 'VoluntaryExits' - size += len(b.VoluntaryExits) * 112 - - // Field (9) 'ExecutionPayloadHeader' - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeaderCapella) - } - size += b.ExecutionPayloadHeader.SizeSSZ() - - // Field (10) 'BlsToExecutionChanges' - size += len(b.BlsToExecutionChanges) * 172 - - return -} - -// HashTreeRoot ssz hashes the BlindedBeaconBlockBodyCapella object -func (b *BlindedBeaconBlockBodyCapella) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlindedBeaconBlockBodyCapella object with a hasher -func (b *BlindedBeaconBlockBodyCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - hh.PutBytes(b.RandaoReveal) - - // Field (1) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - hh.PutBytes(b.Graffiti) - - // Field (3) 'ProposerSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.ProposerSlashings)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.ProposerSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (4) 'AttesterSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.AttesterSlashings)) - if num > 2 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.AttesterSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 2) - } - - // Field (5) 'Attestations' - { - subIndx := hh.Index() - num := uint64(len(b.Attestations)) - if num > 128 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Attestations { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 128) - } - - // Field (6) 'Deposits' - { - subIndx := hh.Index() - num := uint64(len(b.Deposits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Deposits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (7) 'VoluntaryExits' - { - subIndx := hh.Index() - num := uint64(len(b.VoluntaryExits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.VoluntaryExits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (8) 'SyncAggregate' - if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { - return - } - - // Field (9) 'ExecutionPayloadHeader' - if err = b.ExecutionPayloadHeader.HashTreeRootWith(hh); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - { - subIndx := hh.Index() - num := uint64(len(b.BlsToExecutionChanges)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.BlsToExecutionChanges { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BlindedBeaconBlockBodyDeneb object -func (b *BlindedBeaconBlockBodyDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlindedBeaconBlockBodyDeneb object to a target array -func (b *BlindedBeaconBlockBodyDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(392) - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - dst = append(dst, b.RandaoReveal...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - dst = append(dst, b.Graffiti...) - - // Offset (3) 'ProposerSlashings' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.ProposerSlashings) * 416 - - // Offset (4) 'AttesterSlashings' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - offset += 4 - offset += b.AttesterSlashings[ii].SizeSSZ() - } - - // Offset (5) 'Attestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.Attestations); ii++ { - offset += 4 - offset += b.Attestations[ii].SizeSSZ() - } - - // Offset (6) 'Deposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Deposits) * 1240 - - // Offset (7) 'VoluntaryExits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.VoluntaryExits) * 112 - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'ExecutionPayloadHeader' - dst = ssz.WriteOffset(dst, offset) - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeaderDeneb) - } - offset += b.ExecutionPayloadHeader.SizeSSZ() - - // Offset (10) 'BlsToExecutionChanges' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.BlsToExecutionChanges) * 172 - - // Offset (11) 'BlobKzgCommitments' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.BlobKzgCommitments) * 48 - - // Field (3) 'ProposerSlashings' - if size := len(b.ProposerSlashings); size > 16 { - err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) - return - } - for ii := 0; ii < len(b.ProposerSlashings); ii++ { - if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (4) 'AttesterSlashings' - if size := len(b.AttesterSlashings); size > 2 { - err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 2) - return - } - { - offset = 4 * len(b.AttesterSlashings) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.AttesterSlashings[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (5) 'Attestations' - if size := len(b.Attestations); size > 128 { - err = ssz.ErrListTooBigFn("--.Attestations", size, 128) - return - } - { - offset = 4 * len(b.Attestations) - for ii := 0; ii < len(b.Attestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.Attestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.Attestations); ii++ { - if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (6) 'Deposits' - if size := len(b.Deposits); size > 16 { - err = ssz.ErrListTooBigFn("--.Deposits", size, 16) - return - } - for ii := 0; ii < len(b.Deposits); ii++ { - if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (7) 'VoluntaryExits' - if size := len(b.VoluntaryExits); size > 16 { - err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) - return - } - for ii := 0; ii < len(b.VoluntaryExits); ii++ { - if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (9) 'ExecutionPayloadHeader' - if dst, err = b.ExecutionPayloadHeader.MarshalSSZTo(dst); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - if size := len(b.BlsToExecutionChanges); size > 16 { - err = ssz.ErrListTooBigFn("--.BlsToExecutionChanges", size, 16) - return - } - for ii := 0; ii < len(b.BlsToExecutionChanges); ii++ { - if dst, err = b.BlsToExecutionChanges[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (11) 'BlobKzgCommitments' - if size := len(b.BlobKzgCommitments); size > 4096 { - err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) - return - } - for ii := 0; ii < len(b.BlobKzgCommitments); ii++ { - if size := len(b.BlobKzgCommitments[ii]); size != 48 { - err = ssz.ErrBytesLengthFn("--.BlobKzgCommitments[ii]", size, 48) - return - } - dst = append(dst, b.BlobKzgCommitments[ii]...) - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockBodyDeneb object -func (b *BlindedBeaconBlockBodyDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 392 { - return ssz.ErrSize - } - - tail := buf - var o3, o4, o5, o6, o7, o9, o10, o11 uint64 - - // Field (0) 'RandaoReveal' - if cap(b.RandaoReveal) == 0 { - b.RandaoReveal = make([]byte, 0, len(buf[0:96])) - } - b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { - return err - } - - // Field (2) 'Graffiti' - if cap(b.Graffiti) == 0 { - b.Graffiti = make([]byte, 0, len(buf[168:200])) - } - b.Graffiti = append(b.Graffiti, buf[168:200]...) - - // Offset (3) 'ProposerSlashings' - if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { - return ssz.ErrOffset - } - - if o3 != 392 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (4) 'AttesterSlashings' - if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { - return ssz.ErrOffset - } - - // Offset (5) 'Attestations' - if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } - - // Offset (6) 'Deposits' - if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { - return ssz.ErrOffset - } - - // Offset (7) 'VoluntaryExits' - if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { - return ssz.ErrOffset - } - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { - return err - } - - // Offset (9) 'ExecutionPayloadHeader' - if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Offset (10) 'BlsToExecutionChanges' - if o10 = ssz.ReadOffset(buf[384:388]); o10 > size || o9 > o10 { - return ssz.ErrOffset - } - - // Offset (11) 'BlobKzgCommitments' - if o11 = ssz.ReadOffset(buf[388:392]); o11 > size || o10 > o11 { - return ssz.ErrOffset - } - - // Field (3) 'ProposerSlashings' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 416, 16) - if err != nil { - return err - } - b.ProposerSlashings = make([]*v1.ProposerSlashing, num) - for ii := 0; ii < num; ii++ { - if b.ProposerSlashings[ii] == nil { - b.ProposerSlashings[ii] = new(v1.ProposerSlashing) - } - if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { - return err - } - } - } - - // Field (4) 'AttesterSlashings' - { - buf = tail[o4:o5] - num, err := ssz.DecodeDynamicLength(buf, 2) - if err != nil { - return err - } - b.AttesterSlashings = make([]*v1.AttesterSlashing, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.AttesterSlashings[indx] == nil { - b.AttesterSlashings[indx] = new(v1.AttesterSlashing) - } - if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (5) 'Attestations' - { - buf = tail[o5:o6] - num, err := ssz.DecodeDynamicLength(buf, 128) - if err != nil { - return err - } - b.Attestations = make([]*v1.Attestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.Attestations[indx] == nil { - b.Attestations[indx] = new(v1.Attestation) - } - if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (6) 'Deposits' - { - buf = tail[o6:o7] - num, err := ssz.DivideInt2(len(buf), 1240, 16) - if err != nil { - return err - } - b.Deposits = make([]*v1.Deposit, num) - for ii := 0; ii < num; ii++ { - if b.Deposits[ii] == nil { - b.Deposits[ii] = new(v1.Deposit) - } - if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { - return err - } - } - } - - // Field (7) 'VoluntaryExits' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 112, 16) - if err != nil { - return err - } - b.VoluntaryExits = make([]*v1.SignedVoluntaryExit, num) - for ii := 0; ii < num; ii++ { - if b.VoluntaryExits[ii] == nil { - b.VoluntaryExits[ii] = new(v1.SignedVoluntaryExit) - } - if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { - return err - } - } - } - - // Field (9) 'ExecutionPayloadHeader' - { - buf = tail[o9:o10] - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeaderDeneb) - } - if err = b.ExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { - return err - } - } - - // Field (10) 'BlsToExecutionChanges' - { - buf = tail[o10:o11] - num, err := ssz.DivideInt2(len(buf), 172, 16) - if err != nil { - return err - } - b.BlsToExecutionChanges = make([]*SignedBLSToExecutionChange, num) - for ii := 0; ii < num; ii++ { - if b.BlsToExecutionChanges[ii] == nil { - b.BlsToExecutionChanges[ii] = new(SignedBLSToExecutionChange) - } - if err = b.BlsToExecutionChanges[ii].UnmarshalSSZ(buf[ii*172 : (ii+1)*172]); err != nil { - return err - } - } - } - - // Field (11) 'BlobKzgCommitments' - { - buf = tail[o11:] - num, err := ssz.DivideInt2(len(buf), 48, 4096) - if err != nil { - return err - } - b.BlobKzgCommitments = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(b.BlobKzgCommitments[ii]) == 0 { - b.BlobKzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) - } - b.BlobKzgCommitments[ii] = append(b.BlobKzgCommitments[ii], buf[ii*48:(ii+1)*48]...) - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockBodyDeneb object -func (b *BlindedBeaconBlockBodyDeneb) SizeSSZ() (size int) { - size = 392 - - // Field (3) 'ProposerSlashings' - size += len(b.ProposerSlashings) * 416 - - // Field (4) 'AttesterSlashings' - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - size += 4 - size += b.AttesterSlashings[ii].SizeSSZ() - } - - // Field (5) 'Attestations' - for ii := 0; ii < len(b.Attestations); ii++ { - size += 4 - size += b.Attestations[ii].SizeSSZ() - } - - // Field (6) 'Deposits' - size += len(b.Deposits) * 1240 - - // Field (7) 'VoluntaryExits' - size += len(b.VoluntaryExits) * 112 - - // Field (9) 'ExecutionPayloadHeader' - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v11.ExecutionPayloadHeaderDeneb) - } - size += b.ExecutionPayloadHeader.SizeSSZ() - - // Field (10) 'BlsToExecutionChanges' - size += len(b.BlsToExecutionChanges) * 172 - - // Field (11) 'BlobKzgCommitments' - size += len(b.BlobKzgCommitments) * 48 - - return -} - -// HashTreeRoot ssz hashes the BlindedBeaconBlockBodyDeneb object -func (b *BlindedBeaconBlockBodyDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlindedBeaconBlockBodyDeneb object with a hasher -func (b *BlindedBeaconBlockBodyDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - hh.PutBytes(b.RandaoReveal) - - // Field (1) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - hh.PutBytes(b.Graffiti) - - // Field (3) 'ProposerSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.ProposerSlashings)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.ProposerSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (4) 'AttesterSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.AttesterSlashings)) - if num > 2 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.AttesterSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 2) - } - - // Field (5) 'Attestations' - { - subIndx := hh.Index() - num := uint64(len(b.Attestations)) - if num > 128 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Attestations { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 128) - } - - // Field (6) 'Deposits' - { - subIndx := hh.Index() - num := uint64(len(b.Deposits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Deposits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (7) 'VoluntaryExits' - { - subIndx := hh.Index() - num := uint64(len(b.VoluntaryExits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.VoluntaryExits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (8) 'SyncAggregate' - if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { - return - } - - // Field (9) 'ExecutionPayloadHeader' - if err = b.ExecutionPayloadHeader.HashTreeRootWith(hh); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - { - subIndx := hh.Index() - num := uint64(len(b.BlsToExecutionChanges)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.BlsToExecutionChanges { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (11) 'BlobKzgCommitments' - { - if size := len(b.BlobKzgCommitments); size > 4096 { - err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range b.BlobKzgCommitments { - if len(i) != 48 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(b.BlobKzgCommitments)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockBodyDeneb object -func (b *BeaconBlockBodyDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockBodyDeneb object to a target array -func (b *BeaconBlockBodyDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(392) - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - dst = append(dst, b.RandaoReveal...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - dst = append(dst, b.Graffiti...) - - // Offset (3) 'ProposerSlashings' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.ProposerSlashings) * 416 - - // Offset (4) 'AttesterSlashings' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - offset += 4 - offset += b.AttesterSlashings[ii].SizeSSZ() - } - - // Offset (5) 'Attestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.Attestations); ii++ { - offset += 4 - offset += b.Attestations[ii].SizeSSZ() - } - - // Offset (6) 'Deposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Deposits) * 1240 - - // Offset (7) 'VoluntaryExits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.VoluntaryExits) * 112 - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { - return - } - - // Offset (9) 'ExecutionPayload' - dst = ssz.WriteOffset(dst, offset) - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayloadDeneb) - } - offset += b.ExecutionPayload.SizeSSZ() - - // Offset (10) 'BlsToExecutionChanges' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.BlsToExecutionChanges) * 172 - - // Offset (11) 'BlobKzgCommitments' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.BlobKzgCommitments) * 48 - - // Field (3) 'ProposerSlashings' - if size := len(b.ProposerSlashings); size > 16 { - err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) - return - } - for ii := 0; ii < len(b.ProposerSlashings); ii++ { - if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (4) 'AttesterSlashings' - if size := len(b.AttesterSlashings); size > 2 { - err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 2) - return - } - { - offset = 4 * len(b.AttesterSlashings) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.AttesterSlashings[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (5) 'Attestations' - if size := len(b.Attestations); size > 128 { - err = ssz.ErrListTooBigFn("--.Attestations", size, 128) - return - } - { - offset = 4 * len(b.Attestations) - for ii := 0; ii < len(b.Attestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.Attestations[ii].SizeSSZ() - } - } - for ii := 0; ii < len(b.Attestations); ii++ { - if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (6) 'Deposits' - if size := len(b.Deposits); size > 16 { - err = ssz.ErrListTooBigFn("--.Deposits", size, 16) - return - } - for ii := 0; ii < len(b.Deposits); ii++ { - if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (7) 'VoluntaryExits' - if size := len(b.VoluntaryExits); size > 16 { - err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) - return - } - for ii := 0; ii < len(b.VoluntaryExits); ii++ { - if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (9) 'ExecutionPayload' - if dst, err = b.ExecutionPayload.MarshalSSZTo(dst); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - if size := len(b.BlsToExecutionChanges); size > 16 { - err = ssz.ErrListTooBigFn("--.BlsToExecutionChanges", size, 16) - return - } - for ii := 0; ii < len(b.BlsToExecutionChanges); ii++ { - if dst, err = b.BlsToExecutionChanges[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (11) 'BlobKzgCommitments' - if size := len(b.BlobKzgCommitments); size > 4096 { - err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) - return - } - for ii := 0; ii < len(b.BlobKzgCommitments); ii++ { - if size := len(b.BlobKzgCommitments[ii]); size != 48 { - err = ssz.ErrBytesLengthFn("--.BlobKzgCommitments[ii]", size, 48) - return - } - dst = append(dst, b.BlobKzgCommitments[ii]...) - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockBodyDeneb object -func (b *BeaconBlockBodyDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 392 { - return ssz.ErrSize - } - - tail := buf - var o3, o4, o5, o6, o7, o9, o10, o11 uint64 - - // Field (0) 'RandaoReveal' - if cap(b.RandaoReveal) == 0 { - b.RandaoReveal = make([]byte, 0, len(buf[0:96])) - } - b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) - - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(v1.Eth1Data) - } - if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { - return err - } - - // Field (2) 'Graffiti' - if cap(b.Graffiti) == 0 { - b.Graffiti = make([]byte, 0, len(buf[168:200])) - } - b.Graffiti = append(b.Graffiti, buf[168:200]...) - - // Offset (3) 'ProposerSlashings' - if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { - return ssz.ErrOffset - } - - if o3 != 392 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (4) 'AttesterSlashings' - if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { - return ssz.ErrOffset - } - - // Offset (5) 'Attestations' - if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } - - // Offset (6) 'Deposits' - if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { - return ssz.ErrOffset - } - - // Offset (7) 'VoluntaryExits' - if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { - return ssz.ErrOffset - } - - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(v1.SyncAggregate) - } - if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { - return err - } - - // Offset (9) 'ExecutionPayload' - if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Offset (10) 'BlsToExecutionChanges' - if o10 = ssz.ReadOffset(buf[384:388]); o10 > size || o9 > o10 { - return ssz.ErrOffset - } - - // Offset (11) 'BlobKzgCommitments' - if o11 = ssz.ReadOffset(buf[388:392]); o11 > size || o10 > o11 { - return ssz.ErrOffset - } - - // Field (3) 'ProposerSlashings' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 416, 16) - if err != nil { - return err - } - b.ProposerSlashings = make([]*v1.ProposerSlashing, num) - for ii := 0; ii < num; ii++ { - if b.ProposerSlashings[ii] == nil { - b.ProposerSlashings[ii] = new(v1.ProposerSlashing) - } - if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { - return err - } - } - } - - // Field (4) 'AttesterSlashings' - { - buf = tail[o4:o5] - num, err := ssz.DecodeDynamicLength(buf, 2) - if err != nil { - return err - } - b.AttesterSlashings = make([]*v1.AttesterSlashing, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.AttesterSlashings[indx] == nil { - b.AttesterSlashings[indx] = new(v1.AttesterSlashing) - } - if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (5) 'Attestations' - { - buf = tail[o5:o6] - num, err := ssz.DecodeDynamicLength(buf, 128) - if err != nil { - return err - } - b.Attestations = make([]*v1.Attestation, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.Attestations[indx] == nil { - b.Attestations[indx] = new(v1.Attestation) - } - if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } - } - - // Field (6) 'Deposits' - { - buf = tail[o6:o7] - num, err := ssz.DivideInt2(len(buf), 1240, 16) - if err != nil { - return err - } - b.Deposits = make([]*v1.Deposit, num) - for ii := 0; ii < num; ii++ { - if b.Deposits[ii] == nil { - b.Deposits[ii] = new(v1.Deposit) - } - if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { - return err - } - } - } - - // Field (7) 'VoluntaryExits' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 112, 16) - if err != nil { - return err - } - b.VoluntaryExits = make([]*v1.SignedVoluntaryExit, num) - for ii := 0; ii < num; ii++ { - if b.VoluntaryExits[ii] == nil { - b.VoluntaryExits[ii] = new(v1.SignedVoluntaryExit) - } - if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { - return err - } - } - } - - // Field (9) 'ExecutionPayload' - { - buf = tail[o9:o10] - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayloadDeneb) - } - if err = b.ExecutionPayload.UnmarshalSSZ(buf); err != nil { - return err - } - } - - // Field (10) 'BlsToExecutionChanges' - { - buf = tail[o10:o11] - num, err := ssz.DivideInt2(len(buf), 172, 16) - if err != nil { - return err - } - b.BlsToExecutionChanges = make([]*SignedBLSToExecutionChange, num) - for ii := 0; ii < num; ii++ { - if b.BlsToExecutionChanges[ii] == nil { - b.BlsToExecutionChanges[ii] = new(SignedBLSToExecutionChange) - } - if err = b.BlsToExecutionChanges[ii].UnmarshalSSZ(buf[ii*172 : (ii+1)*172]); err != nil { - return err - } - } - } - - // Field (11) 'BlobKzgCommitments' - { - buf = tail[o11:] - num, err := ssz.DivideInt2(len(buf), 48, 4096) - if err != nil { - return err - } - b.BlobKzgCommitments = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(b.BlobKzgCommitments[ii]) == 0 { - b.BlobKzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) - } - b.BlobKzgCommitments[ii] = append(b.BlobKzgCommitments[ii], buf[ii*48:(ii+1)*48]...) - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyDeneb object -func (b *BeaconBlockBodyDeneb) SizeSSZ() (size int) { - size = 392 - - // Field (3) 'ProposerSlashings' - size += len(b.ProposerSlashings) * 416 - - // Field (4) 'AttesterSlashings' - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - size += 4 - size += b.AttesterSlashings[ii].SizeSSZ() - } - - // Field (5) 'Attestations' - for ii := 0; ii < len(b.Attestations); ii++ { - size += 4 - size += b.Attestations[ii].SizeSSZ() - } - - // Field (6) 'Deposits' - size += len(b.Deposits) * 1240 - - // Field (7) 'VoluntaryExits' - size += len(b.VoluntaryExits) * 112 - - // Field (9) 'ExecutionPayload' - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v11.ExecutionPayloadDeneb) - } - size += b.ExecutionPayload.SizeSSZ() - - // Field (10) 'BlsToExecutionChanges' - size += len(b.BlsToExecutionChanges) * 172 - - // Field (11) 'BlobKzgCommitments' - size += len(b.BlobKzgCommitments) * 48 - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockBodyDeneb object -func (b *BeaconBlockBodyDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockBodyDeneb object with a hasher -func (b *BeaconBlockBodyDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - hh.PutBytes(b.RandaoReveal) - - // Field (1) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) - return - } - hh.PutBytes(b.Graffiti) - - // Field (3) 'ProposerSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.ProposerSlashings)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.ProposerSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (4) 'AttesterSlashings' - { - subIndx := hh.Index() - num := uint64(len(b.AttesterSlashings)) - if num > 2 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.AttesterSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 2) - } - - // Field (5) 'Attestations' - { - subIndx := hh.Index() - num := uint64(len(b.Attestations)) - if num > 128 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Attestations { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 128) - } - - // Field (6) 'Deposits' - { - subIndx := hh.Index() - num := uint64(len(b.Deposits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Deposits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (7) 'VoluntaryExits' - { - subIndx := hh.Index() - num := uint64(len(b.VoluntaryExits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.VoluntaryExits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (8) 'SyncAggregate' - if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { - return - } - - // Field (9) 'ExecutionPayload' - if err = b.ExecutionPayload.HashTreeRootWith(hh); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - { - subIndx := hh.Index() - num := uint64(len(b.BlsToExecutionChanges)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.BlsToExecutionChanges { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (11) 'BlobKzgCommitments' - { - if size := len(b.BlobKzgCommitments); size > 4096 { - err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range b.BlobKzgCommitments { - if len(i) != 48 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(b.BlobKzgCommitments)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBeaconBlockContentsDeneb object -func (s *SignedBeaconBlockContentsDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBeaconBlockContentsDeneb object to a target array -func (s *SignedBeaconBlockContentsDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(12) - - // Offset (0) 'SignedBlock' - dst = ssz.WriteOffset(dst, offset) - if s.SignedBlock == nil { - s.SignedBlock = new(SignedBeaconBlockDeneb) - } - offset += s.SignedBlock.SizeSSZ() - - // Offset (1) 'KzgProofs' - dst = ssz.WriteOffset(dst, offset) - offset += len(s.KzgProofs) * 48 - - // Offset (2) 'Blobs' - dst = ssz.WriteOffset(dst, offset) - offset += len(s.Blobs) * 131072 - - // Field (0) 'SignedBlock' - if dst, err = s.SignedBlock.MarshalSSZTo(dst); err != nil { - return - } - - // Field (1) 'KzgProofs' - if size := len(s.KzgProofs); size > 4096 { - err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) - return - } - for ii := 0; ii < len(s.KzgProofs); ii++ { - if size := len(s.KzgProofs[ii]); size != 48 { - err = ssz.ErrBytesLengthFn("--.KzgProofs[ii]", size, 48) - return - } - dst = append(dst, s.KzgProofs[ii]...) - } - - // Field (2) 'Blobs' - if size := len(s.Blobs); size > 4096 { - err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) - return - } - for ii := 0; ii < len(s.Blobs); ii++ { - if size := len(s.Blobs[ii]); size != 131072 { - err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072) - return - } - dst = append(dst, s.Blobs[ii]...) - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockContentsDeneb object -func (s *SignedBeaconBlockContentsDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 12 { - return ssz.ErrSize - } - - tail := buf - var o0, o1, o2 uint64 - - // Offset (0) 'SignedBlock' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 12 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (1) 'KzgProofs' - if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { - return ssz.ErrOffset - } - - // Offset (2) 'Blobs' - if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { - return ssz.ErrOffset - } - - // Field (0) 'SignedBlock' - { - buf = tail[o0:o1] - if s.SignedBlock == nil { - s.SignedBlock = new(SignedBeaconBlockDeneb) - } - if err = s.SignedBlock.UnmarshalSSZ(buf); err != nil { - return err - } - } - - // Field (1) 'KzgProofs' - { - buf = tail[o1:o2] - num, err := ssz.DivideInt2(len(buf), 48, 4096) - if err != nil { - return err - } - s.KzgProofs = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(s.KzgProofs[ii]) == 0 { - s.KzgProofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) - } - s.KzgProofs[ii] = append(s.KzgProofs[ii], buf[ii*48:(ii+1)*48]...) - } - } - - // Field (2) 'Blobs' - { - buf = tail[o2:] - num, err := ssz.DivideInt2(len(buf), 131072, 4096) - if err != nil { - return err - } - s.Blobs = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(s.Blobs[ii]) == 0 { - s.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072])) - } - s.Blobs[ii] = append(s.Blobs[ii], buf[ii*131072:(ii+1)*131072]...) - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockContentsDeneb object -func (s *SignedBeaconBlockContentsDeneb) SizeSSZ() (size int) { - size = 12 - - // Field (0) 'SignedBlock' - if s.SignedBlock == nil { - s.SignedBlock = new(SignedBeaconBlockDeneb) - } - size += s.SignedBlock.SizeSSZ() - - // Field (1) 'KzgProofs' - size += len(s.KzgProofs) * 48 - - // Field (2) 'Blobs' - size += len(s.Blobs) * 131072 - - return -} - -// HashTreeRoot ssz hashes the SignedBeaconBlockContentsDeneb object -func (s *SignedBeaconBlockContentsDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBeaconBlockContentsDeneb object with a hasher -func (s *SignedBeaconBlockContentsDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'SignedBlock' - if err = s.SignedBlock.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'KzgProofs' - { - if size := len(s.KzgProofs); size > 4096 { - err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range s.KzgProofs { - if len(i) != 48 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(s.KzgProofs)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - // Field (2) 'Blobs' - { - if size := len(s.Blobs); size > 4096 { - err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range s.Blobs { - if len(i) != 131072 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(s.Blobs)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BeaconBlockContentsDeneb object -func (b *BeaconBlockContentsDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BeaconBlockContentsDeneb object to a target array -func (b *BeaconBlockContentsDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(12) - - // Offset (0) 'Block' - dst = ssz.WriteOffset(dst, offset) - if b.Block == nil { - b.Block = new(BeaconBlockDeneb) - } - offset += b.Block.SizeSSZ() - - // Offset (1) 'KzgProofs' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.KzgProofs) * 48 - - // Offset (2) 'Blobs' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Blobs) * 131072 - - // Field (0) 'Block' - if dst, err = b.Block.MarshalSSZTo(dst); err != nil { - return - } - - // Field (1) 'KzgProofs' - if size := len(b.KzgProofs); size > 4096 { - err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) - return - } - for ii := 0; ii < len(b.KzgProofs); ii++ { - if size := len(b.KzgProofs[ii]); size != 48 { - err = ssz.ErrBytesLengthFn("--.KzgProofs[ii]", size, 48) - return - } - dst = append(dst, b.KzgProofs[ii]...) - } - - // Field (2) 'Blobs' - if size := len(b.Blobs); size > 4096 { - err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) - return - } - for ii := 0; ii < len(b.Blobs); ii++ { - if size := len(b.Blobs[ii]); size != 131072 { - err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072) - return - } - dst = append(dst, b.Blobs[ii]...) - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconBlockContentsDeneb object -func (b *BeaconBlockContentsDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 12 { - return ssz.ErrSize - } - - tail := buf - var o0, o1, o2 uint64 - - // Offset (0) 'Block' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 12 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (1) 'KzgProofs' - if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { - return ssz.ErrOffset - } - - // Offset (2) 'Blobs' - if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { - return ssz.ErrOffset - } - - // Field (0) 'Block' - { - buf = tail[o0:o1] - if b.Block == nil { - b.Block = new(BeaconBlockDeneb) - } - if err = b.Block.UnmarshalSSZ(buf); err != nil { - return err - } - } - - // Field (1) 'KzgProofs' - { - buf = tail[o1:o2] - num, err := ssz.DivideInt2(len(buf), 48, 4096) - if err != nil { - return err - } - b.KzgProofs = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(b.KzgProofs[ii]) == 0 { - b.KzgProofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) - } - b.KzgProofs[ii] = append(b.KzgProofs[ii], buf[ii*48:(ii+1)*48]...) - } - } - - // Field (2) 'Blobs' - { - buf = tail[o2:] - num, err := ssz.DivideInt2(len(buf), 131072, 4096) - if err != nil { - return err - } - b.Blobs = make([][]byte, num) - for ii := 0; ii < num; ii++ { - if cap(b.Blobs[ii]) == 0 { - b.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072])) - } - b.Blobs[ii] = append(b.Blobs[ii], buf[ii*131072:(ii+1)*131072]...) - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockContentsDeneb object -func (b *BeaconBlockContentsDeneb) SizeSSZ() (size int) { - size = 12 - - // Field (0) 'Block' - if b.Block == nil { - b.Block = new(BeaconBlockDeneb) - } - size += b.Block.SizeSSZ() - - // Field (1) 'KzgProofs' - size += len(b.KzgProofs) * 48 - - // Field (2) 'Blobs' - size += len(b.Blobs) * 131072 - - return -} - -// HashTreeRoot ssz hashes the BeaconBlockContentsDeneb object -func (b *BeaconBlockContentsDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BeaconBlockContentsDeneb object with a hasher -func (b *BeaconBlockContentsDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Block' - if err = b.Block.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'KzgProofs' - { - if size := len(b.KzgProofs); size > 4096 { - err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range b.KzgProofs { - if len(i) != 48 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(b.KzgProofs)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - // Field (2) 'Blobs' - { - if size := len(b.Blobs); size > 4096 { - err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range b.Blobs { - if len(i) != 131072 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(b.Blobs)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BlobIdentifier object -func (b *BlobIdentifier) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlobIdentifier object to a target array -func (b *BlobIdentifier) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'BlockRoot' - if size := len(b.BlockRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) - return - } - dst = append(dst, b.BlockRoot...) - - // Field (1) 'Index' - dst = ssz.MarshalUint64(dst, b.Index) - - return -} - -// UnmarshalSSZ ssz unmarshals the BlobIdentifier object -func (b *BlobIdentifier) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 40 { - return ssz.ErrSize - } - - // Field (0) 'BlockRoot' - if cap(b.BlockRoot) == 0 { - b.BlockRoot = make([]byte, 0, len(buf[0:32])) - } - b.BlockRoot = append(b.BlockRoot, buf[0:32]...) - - // Field (1) 'Index' - b.Index = ssz.UnmarshallUint64(buf[32:40]) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlobIdentifier object -func (b *BlobIdentifier) SizeSSZ() (size int) { - size = 40 - return -} - -// HashTreeRoot ssz hashes the BlobIdentifier object -func (b *BlobIdentifier) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlobIdentifier object with a hasher -func (b *BlobIdentifier) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'BlockRoot' - if size := len(b.BlockRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) - return - } - hh.PutBytes(b.BlockRoot) - - // Field (1) 'Index' - hh.PutUint64(b.Index) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SyncCommittee object -func (s *SyncCommittee) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SyncCommittee object to a target array -func (s *SyncCommittee) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Pubkeys' - if size := len(s.Pubkeys); size != 512 { - err = ssz.ErrVectorLengthFn("--.Pubkeys", size, 512) - return - } - for ii := 0; ii < 512; ii++ { - if size := len(s.Pubkeys[ii]); size != 48 { - err = ssz.ErrBytesLengthFn("--.Pubkeys[ii]", size, 48) - return - } - dst = append(dst, s.Pubkeys[ii]...) - } - - // Field (1) 'AggregatePubkey' - if size := len(s.AggregatePubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.AggregatePubkey", size, 48) - return - } - dst = append(dst, s.AggregatePubkey...) - - return -} - -// UnmarshalSSZ ssz unmarshals the SyncCommittee object -func (s *SyncCommittee) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 24624 { - return ssz.ErrSize - } - - // Field (0) 'Pubkeys' - s.Pubkeys = make([][]byte, 512) - for ii := 0; ii < 512; ii++ { - if cap(s.Pubkeys[ii]) == 0 { - s.Pubkeys[ii] = make([]byte, 0, len(buf[0:24576][ii*48:(ii+1)*48])) - } - s.Pubkeys[ii] = append(s.Pubkeys[ii], buf[0:24576][ii*48:(ii+1)*48]...) - } - - // Field (1) 'AggregatePubkey' - if cap(s.AggregatePubkey) == 0 { - s.AggregatePubkey = make([]byte, 0, len(buf[24576:24624])) - } - s.AggregatePubkey = append(s.AggregatePubkey, buf[24576:24624]...) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SyncCommittee object -func (s *SyncCommittee) SizeSSZ() (size int) { - size = 24624 - return -} - -// HashTreeRoot ssz hashes the SyncCommittee object -func (s *SyncCommittee) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SyncCommittee object with a hasher -func (s *SyncCommittee) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Pubkeys' - { - if size := len(s.Pubkeys); size != 512 { - err = ssz.ErrVectorLengthFn("--.Pubkeys", size, 512) - return - } - subIndx := hh.Index() - for _, i := range s.Pubkeys { - if len(i) != 48 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - hh.Merkleize(subIndx) - } - - // Field (1) 'AggregatePubkey' - if size := len(s.AggregatePubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.AggregatePubkey", size, 48) - return - } - hh.PutBytes(s.AggregatePubkey) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the BLSToExecutionChange object -func (b *BLSToExecutionChange) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BLSToExecutionChange object to a target array -func (b *BLSToExecutionChange) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'ValidatorIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ValidatorIndex)) - - // Field (1) 'FromBlsPubkey' - if size := len(b.FromBlsPubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.FromBlsPubkey", size, 48) - return - } - dst = append(dst, b.FromBlsPubkey...) - - // Field (2) 'ToExecutionAddress' - if size := len(b.ToExecutionAddress); size != 20 { - err = ssz.ErrBytesLengthFn("--.ToExecutionAddress", size, 20) - return - } - dst = append(dst, b.ToExecutionAddress...) - - return -} - -// UnmarshalSSZ ssz unmarshals the BLSToExecutionChange object -func (b *BLSToExecutionChange) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 76 { - return ssz.ErrSize - } - - // Field (0) 'ValidatorIndex' - b.ValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'FromBlsPubkey' - if cap(b.FromBlsPubkey) == 0 { - b.FromBlsPubkey = make([]byte, 0, len(buf[8:56])) - } - b.FromBlsPubkey = append(b.FromBlsPubkey, buf[8:56]...) - - // Field (2) 'ToExecutionAddress' - if cap(b.ToExecutionAddress) == 0 { - b.ToExecutionAddress = make([]byte, 0, len(buf[56:76])) - } - b.ToExecutionAddress = append(b.ToExecutionAddress, buf[56:76]...) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BLSToExecutionChange object -func (b *BLSToExecutionChange) SizeSSZ() (size int) { - size = 76 - return -} - -// HashTreeRoot ssz hashes the BLSToExecutionChange object -func (b *BLSToExecutionChange) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BLSToExecutionChange object with a hasher -func (b *BLSToExecutionChange) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'ValidatorIndex' - hh.PutUint64(uint64(b.ValidatorIndex)) - - // Field (1) 'FromBlsPubkey' - if size := len(b.FromBlsPubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.FromBlsPubkey", size, 48) - return - } - hh.PutBytes(b.FromBlsPubkey) - - // Field (2) 'ToExecutionAddress' - if size := len(b.ToExecutionAddress); size != 20 { - err = ssz.ErrBytesLengthFn("--.ToExecutionAddress", size, 20) - return - } - hh.PutBytes(b.ToExecutionAddress) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBLSToExecutionChange object -func (s *SignedBLSToExecutionChange) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBLSToExecutionChange object to a target array -func (s *SignedBLSToExecutionChange) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BLSToExecutionChange) - } - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBLSToExecutionChange object -func (s *SignedBLSToExecutionChange) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 172 { - return ssz.ErrSize - } - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BLSToExecutionChange) - } - if err = s.Message.UnmarshalSSZ(buf[0:76]); err != nil { - return err - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[76:172])) - } - s.Signature = append(s.Signature, buf[76:172]...) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBLSToExecutionChange object -func (s *SignedBLSToExecutionChange) SizeSSZ() (size int) { - size = 172 - return -} - -// HashTreeRoot ssz hashes the SignedBLSToExecutionChange object -func (s *SignedBLSToExecutionChange) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBLSToExecutionChange object with a hasher -func (s *SignedBLSToExecutionChange) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} diff --git a/proto/eth/v2/ssz.pb.go b/proto/eth/v2/ssz.pb.go deleted file mode 100755 index 7e90a34fb9c3..000000000000 --- a/proto/eth/v2/ssz.pb.go +++ /dev/null @@ -1,188 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 -// source: proto/eth/v2/ssz.proto - -package eth - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type SSZContainer struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=ethereum.eth.v2.Version" json:"version,omitempty"` - ExecutionOptimistic bool `protobuf:"varint,2,opt,name=execution_optimistic,json=executionOptimistic,proto3" json:"execution_optimistic,omitempty"` - Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` - Finalized bool `protobuf:"varint,4,opt,name=finalized,proto3" json:"finalized,omitempty"` -} - -func (x *SSZContainer) Reset() { - *x = SSZContainer{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_ssz_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SSZContainer) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SSZContainer) ProtoMessage() {} - -func (x *SSZContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_ssz_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SSZContainer.ProtoReflect.Descriptor instead. -func (*SSZContainer) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_ssz_proto_rawDescGZIP(), []int{0} -} - -func (x *SSZContainer) GetVersion() Version { - if x != nil { - return x.Version - } - return Version_PHASE0 -} - -func (x *SSZContainer) GetExecutionOptimistic() bool { - if x != nil { - return x.ExecutionOptimistic - } - return false -} - -func (x *SSZContainer) GetData() []byte { - if x != nil { - return x.Data - } - return nil -} - -func (x *SSZContainer) GetFinalized() bool { - if x != nil { - return x.Finalized - } - return false -} - -var File_proto_eth_v2_ssz_proto protoreflect.FileDescriptor - -var file_proto_eth_v2_ssz_proto_rawDesc = []byte{ - 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x73, - 0x73, 0x7a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x1a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x01, 0x0a, 0x0c, 0x53, 0x53, 0x5a, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x14, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, - 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x12, 0x12, 0x0a, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, - 0x79, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x08, 0x53, 0x73, 0x7a, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_proto_eth_v2_ssz_proto_rawDescOnce sync.Once - file_proto_eth_v2_ssz_proto_rawDescData = file_proto_eth_v2_ssz_proto_rawDesc -) - -func file_proto_eth_v2_ssz_proto_rawDescGZIP() []byte { - file_proto_eth_v2_ssz_proto_rawDescOnce.Do(func() { - file_proto_eth_v2_ssz_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_ssz_proto_rawDescData) - }) - return file_proto_eth_v2_ssz_proto_rawDescData -} - -var file_proto_eth_v2_ssz_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_proto_eth_v2_ssz_proto_goTypes = []interface{}{ - (*SSZContainer)(nil), // 0: ethereum.eth.v2.SSZContainer - (Version)(0), // 1: ethereum.eth.v2.Version -} -var file_proto_eth_v2_ssz_proto_depIdxs = []int32{ - 1, // 0: ethereum.eth.v2.SSZContainer.version:type_name -> ethereum.eth.v2.Version - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_proto_eth_v2_ssz_proto_init() } -func file_proto_eth_v2_ssz_proto_init() { - if File_proto_eth_v2_ssz_proto != nil { - return - } - file_proto_eth_v2_version_proto_init() - if !protoimpl.UnsafeEnabled { - file_proto_eth_v2_ssz_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SSZContainer); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_eth_v2_ssz_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_eth_v2_ssz_proto_goTypes, - DependencyIndexes: file_proto_eth_v2_ssz_proto_depIdxs, - MessageInfos: file_proto_eth_v2_ssz_proto_msgTypes, - }.Build() - File_proto_eth_v2_ssz_proto = out.File - file_proto_eth_v2_ssz_proto_rawDesc = nil - file_proto_eth_v2_ssz_proto_goTypes = nil - file_proto_eth_v2_ssz_proto_depIdxs = nil -} diff --git a/proto/eth/v2/ssz.pb.gw.go b/proto/eth/v2/ssz.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v2/ssz.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v2/ssz.proto b/proto/eth/v2/ssz.proto deleted file mode 100644 index 4ba494ce1a1e..000000000000 --- a/proto/eth/v2/ssz.proto +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 Prysmatic Labs. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -syntax = "proto3"; - -package ethereum.eth.v2; - -option csharp_namespace = "Ethereum.Eth.V2"; -option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2;eth"; -option java_multiple_files = true; -option java_outer_classname = "SszProto"; -option java_package = "org.ethereum.eth.v2"; -option php_namespace = "Ethereum\\Eth\\v2"; - -import "proto/eth/v2/version.proto"; - -message SSZContainer { - Version version = 1; - bool execution_optimistic = 2; - bytes data = 3; - bool finalized = 4; -} \ No newline at end of file diff --git a/proto/eth/v2/sync_committee.pb.go b/proto/eth/v2/sync_committee.pb.go deleted file mode 100755 index 6311707f0a82..000000000000 --- a/proto/eth/v2/sync_committee.pb.go +++ /dev/null @@ -1,340 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 -// source: proto/eth/v2/sync_committee.proto - -package eth - -import ( - reflect "reflect" - sync "sync" - - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - _ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type SubmitSyncCommitteeSignaturesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Data []*SyncCommitteeMessage `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` -} - -func (x *SubmitSyncCommitteeSignaturesRequest) Reset() { - *x = SubmitSyncCommitteeSignaturesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_sync_committee_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SubmitSyncCommitteeSignaturesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubmitSyncCommitteeSignaturesRequest) ProtoMessage() {} - -func (x *SubmitSyncCommitteeSignaturesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_sync_committee_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SubmitSyncCommitteeSignaturesRequest.ProtoReflect.Descriptor instead. -func (*SubmitSyncCommitteeSignaturesRequest) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_sync_committee_proto_rawDescGZIP(), []int{0} -} - -func (x *SubmitSyncCommitteeSignaturesRequest) GetData() []*SyncCommitteeMessage { - if x != nil { - return x.Data - } - return nil -} - -type SyncCommittee struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Pubkeys [][]byte `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty" ssz-size:"512,48"` - AggregatePubkey []byte `protobuf:"bytes,2,opt,name=aggregate_pubkey,json=aggregatePubkey,proto3" json:"aggregate_pubkey,omitempty" ssz-size:"48"` -} - -func (x *SyncCommittee) Reset() { - *x = SyncCommittee{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_sync_committee_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SyncCommittee) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncCommittee) ProtoMessage() {} - -func (x *SyncCommittee) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_sync_committee_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncCommittee.ProtoReflect.Descriptor instead. -func (*SyncCommittee) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_sync_committee_proto_rawDescGZIP(), []int{1} -} - -func (x *SyncCommittee) GetPubkeys() [][]byte { - if x != nil { - return x.Pubkeys - } - return nil -} - -func (x *SyncCommittee) GetAggregatePubkey() []byte { - if x != nil { - return x.AggregatePubkey - } - return nil -} - -type SyncCommitteeMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - BeaconBlockRoot []byte `protobuf:"bytes,2,opt,name=beacon_block_root,json=beaconBlockRoot,proto3" json:"beacon_block_root,omitempty" ssz-size:"32"` - ValidatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,3,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SyncCommitteeMessage) Reset() { - *x = SyncCommitteeMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_sync_committee_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SyncCommitteeMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncCommitteeMessage) ProtoMessage() {} - -func (x *SyncCommitteeMessage) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_sync_committee_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncCommitteeMessage.ProtoReflect.Descriptor instead. -func (*SyncCommitteeMessage) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_sync_committee_proto_rawDescGZIP(), []int{2} -} - -func (x *SyncCommitteeMessage) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *SyncCommitteeMessage) GetBeaconBlockRoot() []byte { - if x != nil { - return x.BeaconBlockRoot - } - return nil -} - -func (x *SyncCommitteeMessage) GetValidatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ValidatorIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *SyncCommitteeMessage) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -var File_proto_eth_v2_sync_committee_proto protoreflect.FileDescriptor - -var file_proto_eth_v2_sync_committee_proto_rawDesc = []byte{ - 0x0a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x73, - 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x32, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x61, 0x0a, 0x24, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x22, 0x68, 0x0a, 0x0d, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x24, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x06, 0x35, 0x31, 0x32, 0x2c, - 0x34, 0x38, 0x52, 0x07, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x31, 0x0a, 0x10, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0f, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0xc5, - 0x02, 0x0a, 0x14, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, - 0x6f, 0x74, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x83, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x12, - 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_proto_eth_v2_sync_committee_proto_rawDescOnce sync.Once - file_proto_eth_v2_sync_committee_proto_rawDescData = file_proto_eth_v2_sync_committee_proto_rawDesc -) - -func file_proto_eth_v2_sync_committee_proto_rawDescGZIP() []byte { - file_proto_eth_v2_sync_committee_proto_rawDescOnce.Do(func() { - file_proto_eth_v2_sync_committee_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_sync_committee_proto_rawDescData) - }) - return file_proto_eth_v2_sync_committee_proto_rawDescData -} - -var file_proto_eth_v2_sync_committee_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_proto_eth_v2_sync_committee_proto_goTypes = []interface{}{ - (*SubmitSyncCommitteeSignaturesRequest)(nil), // 0: ethereum.eth.v2.SubmitSyncCommitteeSignaturesRequest - (*SyncCommittee)(nil), // 1: ethereum.eth.v2.SyncCommittee - (*SyncCommitteeMessage)(nil), // 2: ethereum.eth.v2.SyncCommitteeMessage -} -var file_proto_eth_v2_sync_committee_proto_depIdxs = []int32{ - 2, // 0: ethereum.eth.v2.SubmitSyncCommitteeSignaturesRequest.data:type_name -> ethereum.eth.v2.SyncCommitteeMessage - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_proto_eth_v2_sync_committee_proto_init() } -func file_proto_eth_v2_sync_committee_proto_init() { - if File_proto_eth_v2_sync_committee_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_proto_eth_v2_sync_committee_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SubmitSyncCommitteeSignaturesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_sync_committee_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncCommittee); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_sync_committee_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncCommitteeMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_eth_v2_sync_committee_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_eth_v2_sync_committee_proto_goTypes, - DependencyIndexes: file_proto_eth_v2_sync_committee_proto_depIdxs, - MessageInfos: file_proto_eth_v2_sync_committee_proto_msgTypes, - }.Build() - File_proto_eth_v2_sync_committee_proto = out.File - file_proto_eth_v2_sync_committee_proto_rawDesc = nil - file_proto_eth_v2_sync_committee_proto_goTypes = nil - file_proto_eth_v2_sync_committee_proto_depIdxs = nil -} diff --git a/proto/eth/v2/sync_committee.pb.gw.go b/proto/eth/v2/sync_committee.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v2/sync_committee.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v2/sync_committee.proto b/proto/eth/v2/sync_committee.proto deleted file mode 100644 index e5aa96141378..000000000000 --- a/proto/eth/v2/sync_committee.proto +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 Prysmatic Labs. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -syntax = "proto3"; - -package ethereum.eth.v2; - -import "proto/eth/ext/options.proto"; - -option csharp_namespace = "Ethereum.Eth.V2"; -option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2;eth"; -option java_multiple_files = true; -option java_outer_classname = "SyncCommitteeProto"; -option java_package = "org.ethereum.eth.v2"; -option php_namespace = "Ethereum\\Eth\\v2"; - -message SubmitSyncCommitteeSignaturesRequest { - repeated SyncCommitteeMessage data = 1; -} - -// SyncCommittee serves as committees to facilitate light client syncing to beacon chain. -message SyncCommittee { - repeated bytes pubkeys = 1 [(ethereum.eth.ext.ssz_size) = "sync_committee_bits.size,48"]; - bytes aggregate_pubkey = 2 [(ethereum.eth.ext.ssz_size) = "48"]; -} - -// Sync committee object to support light client. -message SyncCommitteeMessage { - // Slot to which this contribution pertains. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // 32 byte block root for this signature. - bytes beacon_block_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Index of the validator that produced this signature. - uint64 validator_index = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // Signature by the validator over the block root of `slot`. - bytes signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; -} diff --git a/proto/eth/v2/validator.pb.go b/proto/eth/v2/validator.pb.go deleted file mode 100755 index 0377ae2c73b5..000000000000 --- a/proto/eth/v2/validator.pb.go +++ /dev/null @@ -1,547 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 -// source: proto/eth/v2/validator.proto - -package eth - -import ( - reflect "reflect" - sync "sync" - - github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield" - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - _ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ProduceBlockResponseV2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=ethereum.eth.v2.Version" json:"version,omitempty"` - Data *BeaconBlockContainerV2 `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` -} - -func (x *ProduceBlockResponseV2) Reset() { - *x = ProduceBlockResponseV2{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_validator_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProduceBlockResponseV2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProduceBlockResponseV2) ProtoMessage() {} - -func (x *ProduceBlockResponseV2) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_validator_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProduceBlockResponseV2.ProtoReflect.Descriptor instead. -func (*ProduceBlockResponseV2) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_validator_proto_rawDescGZIP(), []int{0} -} - -func (x *ProduceBlockResponseV2) GetVersion() Version { - if x != nil { - return x.Version - } - return Version_PHASE0 -} - -func (x *ProduceBlockResponseV2) GetData() *BeaconBlockContainerV2 { - if x != nil { - return x.Data - } - return nil -} - -type ProduceBlindedBlockResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Version Version `protobuf:"varint,1,opt,name=version,proto3,enum=ethereum.eth.v2.Version" json:"version,omitempty"` - Data *BlindedBeaconBlockContainer `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` -} - -func (x *ProduceBlindedBlockResponse) Reset() { - *x = ProduceBlindedBlockResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_validator_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProduceBlindedBlockResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProduceBlindedBlockResponse) ProtoMessage() {} - -func (x *ProduceBlindedBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_validator_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProduceBlindedBlockResponse.ProtoReflect.Descriptor instead. -func (*ProduceBlindedBlockResponse) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_validator_proto_rawDescGZIP(), []int{1} -} - -func (x *ProduceBlindedBlockResponse) GetVersion() Version { - if x != nil { - return x.Version - } - return Version_PHASE0 -} - -func (x *ProduceBlindedBlockResponse) GetData() *BlindedBeaconBlockContainer { - if x != nil { - return x.Data - } - return nil -} - -type SyncCommitteeContribution struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - BeaconBlockRoot []byte `protobuf:"bytes,2,opt,name=beacon_block_root,json=beaconBlockRoot,proto3" json:"beacon_block_root,omitempty" ssz-size:"32"` - SubcommitteeIndex uint64 `protobuf:"varint,3,opt,name=subcommittee_index,json=subcommitteeIndex,proto3" json:"subcommittee_index,omitempty"` - AggregationBits github_com_prysmaticlabs_go_bitfield.Bitvector128 `protobuf:"bytes,4,opt,name=aggregation_bits,json=aggregationBits,proto3" json:"aggregation_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector128" ssz-size:"16"` - Signature []byte `protobuf:"bytes,5,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SyncCommitteeContribution) Reset() { - *x = SyncCommitteeContribution{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_validator_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SyncCommitteeContribution) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncCommitteeContribution) ProtoMessage() {} - -func (x *SyncCommitteeContribution) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_validator_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SyncCommitteeContribution.ProtoReflect.Descriptor instead. -func (*SyncCommitteeContribution) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_validator_proto_rawDescGZIP(), []int{2} -} - -func (x *SyncCommitteeContribution) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *SyncCommitteeContribution) GetBeaconBlockRoot() []byte { - if x != nil { - return x.BeaconBlockRoot - } - return nil -} - -func (x *SyncCommitteeContribution) GetSubcommitteeIndex() uint64 { - if x != nil { - return x.SubcommitteeIndex - } - return 0 -} - -func (x *SyncCommitteeContribution) GetAggregationBits() github_com_prysmaticlabs_go_bitfield.Bitvector128 { - if x != nil { - return x.AggregationBits - } - return github_com_prysmaticlabs_go_bitfield.Bitvector128(nil) -} - -func (x *SyncCommitteeContribution) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type ContributionAndProof struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - AggregatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=aggregator_index,json=aggregatorIndex,proto3" json:"aggregator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - Contribution *SyncCommitteeContribution `protobuf:"bytes,2,opt,name=contribution,proto3" json:"contribution,omitempty"` - SelectionProof []byte `protobuf:"bytes,3,opt,name=selection_proof,json=selectionProof,proto3" json:"selection_proof,omitempty" ssz-size:"96"` -} - -func (x *ContributionAndProof) Reset() { - *x = ContributionAndProof{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_validator_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ContributionAndProof) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ContributionAndProof) ProtoMessage() {} - -func (x *ContributionAndProof) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_validator_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ContributionAndProof.ProtoReflect.Descriptor instead. -func (*ContributionAndProof) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_validator_proto_rawDescGZIP(), []int{3} -} - -func (x *ContributionAndProof) GetAggregatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.AggregatorIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *ContributionAndProof) GetContribution() *SyncCommitteeContribution { - if x != nil { - return x.Contribution - } - return nil -} - -func (x *ContributionAndProof) GetSelectionProof() []byte { - if x != nil { - return x.SelectionProof - } - return nil -} - -type SignedContributionAndProof struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *ContributionAndProof `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedContributionAndProof) Reset() { - *x = SignedContributionAndProof{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_validator_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedContributionAndProof) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedContributionAndProof) ProtoMessage() {} - -func (x *SignedContributionAndProof) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_validator_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedContributionAndProof.ProtoReflect.Descriptor instead. -func (*SignedContributionAndProof) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_validator_proto_rawDescGZIP(), []int{4} -} - -func (x *SignedContributionAndProof) GetMessage() *ContributionAndProof { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedContributionAndProof) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -var File_proto_eth_v2_validator_proto protoreflect.FileDescriptor - -var file_proto_eth_v2_validator_proto_rawDesc = []byte{ - 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x1a, - 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x89, 0x01, 0x0a, 0x16, 0x50, 0x72, - 0x6f, 0x64, 0x75, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x56, 0x32, 0x12, 0x32, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x56, 0x32, 0x52, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x93, 0x01, 0x0a, 0x1b, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, - 0x65, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xe7, 0x02, 0x0a, 0x19, - 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, - 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, - 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x75, 0x62, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x66, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x3b, 0x82, 0xb5, 0x18, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x31, 0x32, 0x38, 0x8a, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0f, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, - 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x93, 0x02, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x7a, - 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4e, 0x0a, 0x0c, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x32, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x83, 0x01, 0x0a, 0x1a, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x3f, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x42, 0x7f, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, - 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x32, - 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, - 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_proto_eth_v2_validator_proto_rawDescOnce sync.Once - file_proto_eth_v2_validator_proto_rawDescData = file_proto_eth_v2_validator_proto_rawDesc -) - -func file_proto_eth_v2_validator_proto_rawDescGZIP() []byte { - file_proto_eth_v2_validator_proto_rawDescOnce.Do(func() { - file_proto_eth_v2_validator_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_validator_proto_rawDescData) - }) - return file_proto_eth_v2_validator_proto_rawDescData -} - -var file_proto_eth_v2_validator_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_proto_eth_v2_validator_proto_goTypes = []interface{}{ - (*ProduceBlockResponseV2)(nil), // 0: ethereum.eth.v2.ProduceBlockResponseV2 - (*ProduceBlindedBlockResponse)(nil), // 1: ethereum.eth.v2.ProduceBlindedBlockResponse - (*SyncCommitteeContribution)(nil), // 2: ethereum.eth.v2.SyncCommitteeContribution - (*ContributionAndProof)(nil), // 3: ethereum.eth.v2.ContributionAndProof - (*SignedContributionAndProof)(nil), // 4: ethereum.eth.v2.SignedContributionAndProof - (Version)(0), // 5: ethereum.eth.v2.Version - (*BeaconBlockContainerV2)(nil), // 6: ethereum.eth.v2.BeaconBlockContainerV2 - (*BlindedBeaconBlockContainer)(nil), // 7: ethereum.eth.v2.BlindedBeaconBlockContainer -} -var file_proto_eth_v2_validator_proto_depIdxs = []int32{ - 5, // 0: ethereum.eth.v2.ProduceBlockResponseV2.version:type_name -> ethereum.eth.v2.Version - 6, // 1: ethereum.eth.v2.ProduceBlockResponseV2.data:type_name -> ethereum.eth.v2.BeaconBlockContainerV2 - 5, // 2: ethereum.eth.v2.ProduceBlindedBlockResponse.version:type_name -> ethereum.eth.v2.Version - 7, // 3: ethereum.eth.v2.ProduceBlindedBlockResponse.data:type_name -> ethereum.eth.v2.BlindedBeaconBlockContainer - 2, // 4: ethereum.eth.v2.ContributionAndProof.contribution:type_name -> ethereum.eth.v2.SyncCommitteeContribution - 3, // 5: ethereum.eth.v2.SignedContributionAndProof.message:type_name -> ethereum.eth.v2.ContributionAndProof - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name -} - -func init() { file_proto_eth_v2_validator_proto_init() } -func file_proto_eth_v2_validator_proto_init() { - if File_proto_eth_v2_validator_proto != nil { - return - } - file_proto_eth_v2_beacon_block_proto_init() - file_proto_eth_v2_version_proto_init() - if !protoimpl.UnsafeEnabled { - file_proto_eth_v2_validator_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProduceBlockResponseV2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_validator_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProduceBlindedBlockResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_validator_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncCommitteeContribution); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_validator_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ContributionAndProof); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_validator_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedContributionAndProof); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_eth_v2_validator_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_eth_v2_validator_proto_goTypes, - DependencyIndexes: file_proto_eth_v2_validator_proto_depIdxs, - MessageInfos: file_proto_eth_v2_validator_proto_msgTypes, - }.Build() - File_proto_eth_v2_validator_proto = out.File - file_proto_eth_v2_validator_proto_rawDesc = nil - file_proto_eth_v2_validator_proto_goTypes = nil - file_proto_eth_v2_validator_proto_depIdxs = nil -} diff --git a/proto/eth/v2/validator.pb.gw.go b/proto/eth/v2/validator.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v2/validator.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v2/validator.proto b/proto/eth/v2/validator.proto deleted file mode 100644 index 71bb0bdbf382..000000000000 --- a/proto/eth/v2/validator.proto +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2021 Prysmatic Labs. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -syntax = "proto3"; - -package ethereum.eth.v2; - -import "proto/eth/ext/options.proto"; -import "proto/eth/v2/beacon_block.proto"; -import "proto/eth/v2/version.proto"; - -option csharp_namespace = "Ethereum.Eth.V2"; -option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2;eth"; -option java_multiple_files = true; -option java_outer_classname = "ValidatorProto"; -option java_package = "org.ethereum.eth.v2"; -option php_namespace = "Ethereum\\Eth\\v2"; - -message ProduceBlockResponseV2 { - Version version = 1; - BeaconBlockContainerV2 data = 2; -} - -message ProduceBlindedBlockResponse { - Version version = 1; - BlindedBeaconBlockContainer data = 2; -} - -// Aggregated sync committee object to support light client. -message SyncCommitteeContribution { - // Slot to which this contribution pertains. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // 32 byte block root for this signature. - bytes beacon_block_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The subcommittee this contribution pertains to out of the broader sync committee. - uint64 subcommittee_index = 3; - - // A bit is set if a signature from the validator at the corresponding - // index in the subcommittee is present in the aggregate `signature`. - bytes aggregation_bits = 4 [(ethereum.eth.ext.ssz_size) = "sync_committee_aggregate_bytes.size", (ethereum.eth.ext.cast_type) = "sync_committee_aggregate_bits.type"]; - - // Signature by the validator(s) over the block root of `slot`. - bytes signature = 5 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -// Aggregated sync committee signature object with selection proof to support light client. -message ContributionAndProof { - // Index of the aggregator that produced this proof. - uint64 aggregator_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - SyncCommitteeContribution contribution = 2; - - // The selection proof itself. - bytes selection_proof = 3 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -// Signed aggregated sync committee signature object with selection proof to support light client. -message SignedContributionAndProof { - ContributionAndProof message = 1; - - // Signature of the aggregator that produced `message`. - bytes signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; -} diff --git a/proto/eth/v2/version.pb.go b/proto/eth/v2/version.pb.go deleted file mode 100755 index ca119f18a05e..000000000000 --- a/proto/eth/v2/version.pb.go +++ /dev/null @@ -1,147 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 -// source: proto/eth/v2/version.proto - -package eth - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Version int32 - -const ( - Version_PHASE0 Version = 0 - Version_ALTAIR Version = 1 - Version_BELLATRIX Version = 2 - Version_CAPELLA Version = 3 - Version_DENEB Version = 4 -) - -// Enum value maps for Version. -var ( - Version_name = map[int32]string{ - 0: "PHASE0", - 1: "ALTAIR", - 2: "BELLATRIX", - 3: "CAPELLA", - 4: "DENEB", - } - Version_value = map[string]int32{ - "PHASE0": 0, - "ALTAIR": 1, - "BELLATRIX": 2, - "CAPELLA": 3, - "DENEB": 4, - } -) - -func (x Version) Enum() *Version { - p := new(Version) - *p = x - return p -} - -func (x Version) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Version) Descriptor() protoreflect.EnumDescriptor { - return file_proto_eth_v2_version_proto_enumTypes[0].Descriptor() -} - -func (Version) Type() protoreflect.EnumType { - return &file_proto_eth_v2_version_proto_enumTypes[0] -} - -func (x Version) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Version.Descriptor instead. -func (Version) EnumDescriptor() ([]byte, []int) { - return file_proto_eth_v2_version_proto_rawDescGZIP(), []int{0} -} - -var File_proto_eth_v2_version_proto protoreflect.FileDescriptor - -var file_proto_eth_v2_version_proto_rawDesc = []byte{ - 0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2a, 0x48, 0x0a, - 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x48, 0x41, 0x53, - 0x45, 0x30, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4c, 0x54, 0x41, 0x49, 0x52, 0x10, 0x01, - 0x12, 0x0d, 0x0a, 0x09, 0x42, 0x45, 0x4c, 0x4c, 0x41, 0x54, 0x52, 0x49, 0x58, 0x10, 0x02, 0x12, - 0x0b, 0x0a, 0x07, 0x43, 0x41, 0x50, 0x45, 0x4c, 0x4c, 0x41, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, - 0x44, 0x45, 0x4e, 0x45, 0x42, 0x10, 0x04, 0x42, 0x7d, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x0c, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, - 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, - 0x68, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, - 0x45, 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_proto_eth_v2_version_proto_rawDescOnce sync.Once - file_proto_eth_v2_version_proto_rawDescData = file_proto_eth_v2_version_proto_rawDesc -) - -func file_proto_eth_v2_version_proto_rawDescGZIP() []byte { - file_proto_eth_v2_version_proto_rawDescOnce.Do(func() { - file_proto_eth_v2_version_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_version_proto_rawDescData) - }) - return file_proto_eth_v2_version_proto_rawDescData -} - -var file_proto_eth_v2_version_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_eth_v2_version_proto_goTypes = []interface{}{ - (Version)(0), // 0: ethereum.eth.v2.Version -} -var file_proto_eth_v2_version_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_proto_eth_v2_version_proto_init() } -func file_proto_eth_v2_version_proto_init() { - if File_proto_eth_v2_version_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_eth_v2_version_proto_rawDesc, - NumEnums: 1, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_eth_v2_version_proto_goTypes, - DependencyIndexes: file_proto_eth_v2_version_proto_depIdxs, - EnumInfos: file_proto_eth_v2_version_proto_enumTypes, - }.Build() - File_proto_eth_v2_version_proto = out.File - file_proto_eth_v2_version_proto_rawDesc = nil - file_proto_eth_v2_version_proto_goTypes = nil - file_proto_eth_v2_version_proto_depIdxs = nil -} diff --git a/proto/eth/v2/version.pb.gw.go b/proto/eth/v2/version.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v2/version.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v2/version.proto b/proto/eth/v2/version.proto deleted file mode 100644 index 4489a15fc43c..000000000000 --- a/proto/eth/v2/version.proto +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2021 Prysmatic Labs. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -syntax = "proto3"; - -package ethereum.eth.v2; - -option csharp_namespace = "Ethereum.Eth.V2"; -option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2;eth"; -option java_multiple_files = true; -option java_outer_classname = "VersionProto"; -option java_package = "org.ethereum.eth.v2"; -option php_namespace = "Ethereum\\Eth\\v2"; - -// Version states the version of the returned accompanying message. -enum Version { - PHASE0 = 0; - ALTAIR = 1; - BELLATRIX = 2; - CAPELLA = 3; - DENEB = 4; -} diff --git a/proto/eth/v2/withdrawals.pb.go b/proto/eth/v2/withdrawals.pb.go deleted file mode 100755 index a639b8a55d82..000000000000 --- a/proto/eth/v2/withdrawals.pb.go +++ /dev/null @@ -1,262 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 -// source: proto/eth/v2/withdrawals.proto - -package eth - -import ( - reflect "reflect" - sync "sync" - - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - _ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type BLSToExecutionChange struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ValidatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - FromBlsPubkey []byte `protobuf:"bytes,2,opt,name=from_bls_pubkey,json=fromBlsPubkey,proto3" json:"from_bls_pubkey,omitempty" ssz-size:"48"` - ToExecutionAddress []byte `protobuf:"bytes,3,opt,name=to_execution_address,json=toExecutionAddress,proto3" json:"to_execution_address,omitempty" ssz-size:"20"` -} - -func (x *BLSToExecutionChange) Reset() { - *x = BLSToExecutionChange{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_withdrawals_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BLSToExecutionChange) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BLSToExecutionChange) ProtoMessage() {} - -func (x *BLSToExecutionChange) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_withdrawals_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BLSToExecutionChange.ProtoReflect.Descriptor instead. -func (*BLSToExecutionChange) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_withdrawals_proto_rawDescGZIP(), []int{0} -} - -func (x *BLSToExecutionChange) GetValidatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ValidatorIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BLSToExecutionChange) GetFromBlsPubkey() []byte { - if x != nil { - return x.FromBlsPubkey - } - return nil -} - -func (x *BLSToExecutionChange) GetToExecutionAddress() []byte { - if x != nil { - return x.ToExecutionAddress - } - return nil -} - -type SignedBLSToExecutionChange struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BLSToExecutionChange `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBLSToExecutionChange) Reset() { - *x = SignedBLSToExecutionChange{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_eth_v2_withdrawals_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBLSToExecutionChange) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBLSToExecutionChange) ProtoMessage() {} - -func (x *SignedBLSToExecutionChange) ProtoReflect() protoreflect.Message { - mi := &file_proto_eth_v2_withdrawals_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBLSToExecutionChange.ProtoReflect.Descriptor instead. -func (*SignedBLSToExecutionChange) Descriptor() ([]byte, []int) { - return file_proto_eth_v2_withdrawals_proto_rawDescGZIP(), []int{1} -} - -func (x *SignedBLSToExecutionChange) GetMessage() *BLSToExecutionChange { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBLSToExecutionChange) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -var File_proto_eth_v2_withdrawals_proto protoreflect.FileDescriptor - -var file_proto_eth_v2_withdrawals_proto_rawDesc = []byte{ - 0x0a, 0x1e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x2f, 0x77, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x0f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x32, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, - 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfa, - 0x01, 0x0a, 0x14, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, - 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x12, 0x2e, 0x0a, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x62, 0x6c, 0x73, 0x5f, 0x70, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x34, 0x38, 0x52, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x42, 0x6c, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, - 0x79, 0x12, 0x38, 0x0a, 0x14, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x12, 0x74, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x1a, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x4c, - 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x42, 0x81, 0x01, 0x0a, 0x13, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x32, 0x42, 0x10, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x74, - 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, - 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, - 0x74, 0x68, 0x5c, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_proto_eth_v2_withdrawals_proto_rawDescOnce sync.Once - file_proto_eth_v2_withdrawals_proto_rawDescData = file_proto_eth_v2_withdrawals_proto_rawDesc -) - -func file_proto_eth_v2_withdrawals_proto_rawDescGZIP() []byte { - file_proto_eth_v2_withdrawals_proto_rawDescOnce.Do(func() { - file_proto_eth_v2_withdrawals_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_eth_v2_withdrawals_proto_rawDescData) - }) - return file_proto_eth_v2_withdrawals_proto_rawDescData -} - -var file_proto_eth_v2_withdrawals_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_proto_eth_v2_withdrawals_proto_goTypes = []interface{}{ - (*BLSToExecutionChange)(nil), // 0: ethereum.eth.v2.BLSToExecutionChange - (*SignedBLSToExecutionChange)(nil), // 1: ethereum.eth.v2.SignedBLSToExecutionChange -} -var file_proto_eth_v2_withdrawals_proto_depIdxs = []int32{ - 0, // 0: ethereum.eth.v2.SignedBLSToExecutionChange.message:type_name -> ethereum.eth.v2.BLSToExecutionChange - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_proto_eth_v2_withdrawals_proto_init() } -func file_proto_eth_v2_withdrawals_proto_init() { - if File_proto_eth_v2_withdrawals_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_proto_eth_v2_withdrawals_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BLSToExecutionChange); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_eth_v2_withdrawals_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBLSToExecutionChange); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_eth_v2_withdrawals_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_proto_eth_v2_withdrawals_proto_goTypes, - DependencyIndexes: file_proto_eth_v2_withdrawals_proto_depIdxs, - MessageInfos: file_proto_eth_v2_withdrawals_proto_msgTypes, - }.Build() - File_proto_eth_v2_withdrawals_proto = out.File - file_proto_eth_v2_withdrawals_proto_rawDesc = nil - file_proto_eth_v2_withdrawals_proto_goTypes = nil - file_proto_eth_v2_withdrawals_proto_depIdxs = nil -} diff --git a/proto/eth/v2/withdrawals.pb.gw.go b/proto/eth/v2/withdrawals.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/eth/v2/withdrawals.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/eth/v2/withdrawals.proto b/proto/eth/v2/withdrawals.proto deleted file mode 100644 index e4a5f026c18e..000000000000 --- a/proto/eth/v2/withdrawals.proto +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2022 Prysmatic Labs. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -syntax = "proto3"; - -package ethereum.eth.v2; - -import "proto/eth/ext/options.proto"; - -option csharp_namespace = "Ethereum.Eth.V2"; -option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v2;eth"; -option java_multiple_files = true; -option java_outer_classname = "WithdrawalsProto"; -option java_package = "org.ethereum.eth.v2"; -option php_namespace = "Ethereum\\Eth\\v2"; - -// The message requesting a BLS to execution withdrawal credentials change -message BLSToExecutionChange { - // The validator index requesting the change - uint64 validator_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // The public key of the BLS address requesting the change - bytes from_bls_pubkey = 2 [(ethereum.eth.ext.ssz_size) = "48"]; - - // The new execution address to be the withdrawal credentials - bytes to_execution_address = 3 [(ethereum.eth.ext.ssz_size) = "20"]; -} - -// The signed version of a BLSToExecutionChange -message SignedBLSToExecutionChange { - // The BLSToExecutionChange message itself - BLSToExecutionChange message = 1; - - // The 96 byte BLS signature from the withdrawal address requesting the change - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} diff --git a/proto/migration/BUILD.bazel b/proto/migration/BUILD.bazel index 154b51281fe3..3ceb9c6913e3 100644 --- a/proto/migration/BUILD.bazel +++ b/proto/migration/BUILD.bazel @@ -5,14 +5,11 @@ go_library( srcs = [ "enums.go", "v1alpha1_to_v1.go", - "v1alpha1_to_v2.go", ], importpath = "github.com/prysmaticlabs/prysm/v5/proto/migration", visibility = ["//visibility:public"], deps = [ - "//encoding/bytesutil:go_default_library", "//proto/eth/v1:go_default_library", - "//proto/eth/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_pkg_errors//:go_default_library", ], diff --git a/proto/migration/v1alpha1_to_v2.go b/proto/migration/v1alpha1_to_v2.go deleted file mode 100644 index 9636be437d22..000000000000 --- a/proto/migration/v1alpha1_to_v2.go +++ /dev/null @@ -1,32 +0,0 @@ -package migration - -import ( - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" - ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" - ethpbalpha "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" -) - -// V1Alpha1SyncCommitteeToV2 converts a v1alpha1 SyncCommittee object to its v2 equivalent. -func V1Alpha1SyncCommitteeToV2(alphaCommittee *ethpbalpha.SyncCommittee) *ethpbv2.SyncCommittee { - if alphaCommittee == nil { - return nil - } - - result := ðpbv2.SyncCommittee{ - Pubkeys: bytesutil.SafeCopy2dBytes(alphaCommittee.Pubkeys), - AggregatePubkey: bytesutil.SafeCopyBytes(alphaCommittee.AggregatePubkey), - } - return result -} - -func V2SyncCommitteeToV1Alpha1(committee *ethpbv2.SyncCommittee) *ethpbalpha.SyncCommittee { - if committee == nil { - return nil - } - - result := ðpbalpha.SyncCommittee{ - Pubkeys: bytesutil.SafeCopy2dBytes(committee.Pubkeys), - AggregatePubkey: bytesutil.SafeCopyBytes(committee.AggregatePubkey), - } - return result -} diff --git a/proto/prysm/v1alpha1/BUILD.bazel b/proto/prysm/v1alpha1/BUILD.bazel index 0c6f88327c1f..309f0e8d385e 100644 --- a/proto/prysm/v1alpha1/BUILD.bazel +++ b/proto/prysm/v1alpha1/BUILD.bazel @@ -32,7 +32,6 @@ proto_library( deps = [ "//proto/engine/v1:proto", "//proto/eth/ext:proto", - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_proto", "@com_google_protobuf//:any_proto", "@com_google_protobuf//:descriptor_proto", "@com_google_protobuf//:empty_proto", @@ -82,6 +81,11 @@ ssz_altair_objs = [ "BeaconBlockBodyAltair", "BeaconStateAltair", "ContributionAndProof", + "LightClientHeaderAltair", + "LightClientBootstrapAltair", + "LightClientUpdateAltair", + "LightClientFinalityUpdateAltair", + "LightClientOptimisticUpdateAltair", "SignedBeaconBlockAltair", "SignedContributionAndProof", "SyncAggregate", @@ -111,6 +115,11 @@ ssz_capella_objs = [ "BlindedBeaconBlockCapella", "BuilderBidCapella", "HistoricalSummary", + "LightClientHeaderCapella", + "LightClientBootstrapCapella", + "LightClientUpdateCapella", + "LightClientFinalityUpdateCapella", + "LightClientOptimisticUpdateCapella", "SignedBLSToExecutionChange", "SignedBeaconBlockCapella", "SignedBlindedBeaconBlockCapella", @@ -128,6 +137,11 @@ ssz_deneb_objs = [ "BlobSidecar", "BlobSidecars", "BuilderBidDeneb", + "LightClientHeaderDeneb", + "LightClientBootstrapDeneb", + "LightClientUpdateDeneb", + "LightClientFinalityUpdateDeneb", + "LightClientOptimisticUpdateDeneb", "SignedBeaconBlockContentsDeneb", "SignedBeaconBlockDeneb", "SignedBlindedBeaconBlockDeneb", @@ -135,117 +149,151 @@ ssz_deneb_objs = [ ssz_electra_objs = [ "AggregateAttestationAndProofElectra", + "AggregateAttestationAndProofSingle", "AttestationElectra", "AttesterSlashingElectra", "BeaconBlockElectra", - "BeaconBlockElectra", + "BeaconBlockBodyElectra", + "BeaconBlockContentsElectra", "BeaconStateElectra", "BlindedBeaconBlockBodyElectra", "BlindedBeaconBlockElectra", + "BuilderBidElectra", "Consolidation", "IndexedAttestationElectra", - "PendingBalanceDeposit", - "PendingBalanceDeposits", + "LightClientHeaderElectra", + "LightClientBootstrapElectra", + "LightClientUpdateElectra", + "LightClientFinalityUpdateElectra", + "PendingDeposit", + "PendingDeposits", "PendingConsolidation", "PendingPartialWithdrawal", "SignedAggregateAttestationAndProofElectra", + "SignedAggregateAttestationAndProofSingle", + "SignedBeaconBlockContentsElectra", "SignedBeaconBlockElectra", "SignedBlindedBeaconBlockElectra", "SignedConsolidation", + "SingleAttestation" +] + +ssz_fulu_objs = [ + "BeaconBlockContentsFulu", + "BlindedBeaconBlockFulu", + "DataColumnIdentifier", + "DataColumnSidecar", + "SignedBeaconBlockContentsFulu", + "SignedBeaconBlockFulu", + "SignedBlindedBeaconBlockFulu" ] ssz_gen_marshal( name = "ssz_generated_phase0", - go_proto = ":go_proto", out = "phase0.ssz.go", + go_proto = ":go_proto", includes = [ "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", "//math:go_default_library", + "//proto/engine/v1:go_default_library", ], objs = ssz_phase0_objs, ) ssz_gen_marshal( name = "ssz_generated_altair", - go_proto = ":go_proto", out = "altair.ssz.go", + exclude_objs = ssz_phase0_objs, + go_proto = ":go_proto", includes = [ "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", "//math:go_default_library", + "//proto/engine/v1:go_default_library", ], objs = ssz_altair_objs, - exclude_objs = ssz_phase0_objs, ) ssz_gen_marshal( name = "ssz_generated_bellatrix", - go_proto = ":go_proto", out = "bellatrix.ssz.go", + exclude_objs = ssz_phase0_objs + ssz_altair_objs, + go_proto = ":go_proto", includes = [ "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", "//math:go_default_library", + "//proto/engine/v1:go_default_library", ], objs = ssz_bellatrix_objs, - exclude_objs = ssz_phase0_objs + ssz_altair_objs, ) ssz_gen_marshal( name = "ssz_generated_capella", - go_proto = ":go_proto", out = "capella.ssz.go", + exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs, + go_proto = ":go_proto", includes = [ "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", "//math:go_default_library", + "//proto/engine/v1:go_default_library", ], objs = ssz_capella_objs, - exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs, ) ssz_gen_marshal( name = "ssz_generated_deneb", - go_proto = ":go_proto", out = "deneb.ssz.go", + exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs, + go_proto = ":go_proto", includes = [ "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", "//math:go_default_library", + "//proto/engine/v1:go_default_library", ], objs = ssz_deneb_objs, - exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs, ) ssz_gen_marshal( name = "ssz_generated_electra", - go_proto = ":go_proto", out = "electra.ssz.go", + exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs + ssz_deneb_objs, + go_proto = ":go_proto", includes = [ "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", "//math:go_default_library", + "//proto/engine/v1:go_default_library", ], objs = ssz_electra_objs, - exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs + ssz_deneb_objs, ) +ssz_gen_marshal( + name = "ssz_generated_fulu", + out = "fulu.ssz.go", + exclude_objs = ssz_phase0_objs + ssz_altair_objs + ssz_bellatrix_objs + ssz_capella_objs + ssz_deneb_objs + ssz_electra_objs, + go_proto = ":go_proto", + includes = [ + "//consensus-types/primitives:go_default_library", + "//math:go_default_library", + "//proto/engine/v1:go_default_library", + ], + objs = ssz_fulu_objs, +) ssz_gen_marshal( name = "ssz_generated_non_core", - go_proto = ":go_proto", out = "non-core.ssz.go", + go_proto = ":go_proto", includes = [ "//consensus-types/primitives:go_default_library", - "//proto/engine/v1:go_default_library", "//math:go_default_library", + "//proto/engine/v1:go_default_library", ], objs = [ "BeaconBlocksByRangeRequest", "BlobSidecarsByRangeRequest", + "DataColumnSidecarsByRangeRequest", "MetaDataV0", "MetaDataV1", + "MetaDataV2", "SignedValidatorRegistrationV1", "ValidatorRegistrationV1", "BuilderBid", @@ -267,7 +315,6 @@ go_proto_library( "//proto/engine/v1:go_default_library", "//proto/eth/ext:go_default_library", "@com_github_golang_protobuf//proto:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@googleapis//google/api:annotations_go_proto", "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", @@ -281,29 +328,6 @@ go_proto_library( ], ) -go_proto_library( - name = "go_grpc_gateway_library", - compilers = [ - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway", - ], - embed = [":go_proto"], - importpath = "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1", - protos = [":proto"], - visibility = ["//visibility:private"], - deps = [ - "//proto/engine/v1:go_default_library", - "//proto/eth/ext:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@googleapis//google/api:annotations_go_proto", - "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", - "@io_bazel_rules_go//proto/wkt:wrappers_go_proto", - "@org_golang_google_protobuf//types/descriptorpb:go_default_library", - "@org_golang_google_protobuf//types/known/emptypb:go_default_library", - ], -) - go_library( name = "go_default_library", srcs = [ @@ -313,17 +337,16 @@ go_library( "eip_7521.go", "sync_committee_mainnet.go", "sync_committee_minimal.go", # keep - ":ssz_generated_non_core", # keep - ":ssz_generated_phase0", # keep ":ssz_generated_altair", # keep ":ssz_generated_bellatrix", # keep ":ssz_generated_capella", # keep ":ssz_generated_deneb", # keep ":ssz_generated_electra", # keep + ":ssz_generated_fulu", # keep + ":ssz_generated_non_core", # keep + ":ssz_generated_phase0", # keep ], - embed = [ - ":go_grpc_gateway_library", - ], + embed = [":go_proto"], importpath = "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1", visibility = ["//visibility:public"], deps = SSZ_DEPS + [ @@ -332,10 +355,9 @@ go_library( "//proto/engine/v1:go_default_library", "//proto/eth/ext:go_default_library", "//runtime/version:go_default_library", + "//consensus-types/primitives:go_default_library", + "@com_github_pkg_errors//:go_default_library", "@com_github_golang_protobuf//proto:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//utilities:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", # keep "@googleapis//google/api:annotations_go_proto", "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", @@ -346,6 +368,7 @@ go_library( "@org_golang_google_grpc//grpclog:go_default_library", "@org_golang_google_grpc//metadata:go_default_library", "@org_golang_google_grpc//status:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//reflect/protoreflect:go_default_library", "@org_golang_google_protobuf//runtime/protoimpl:go_default_library", "@org_golang_google_protobuf//types/descriptorpb:go_default_library", @@ -360,6 +383,8 @@ ssz_proto_files( "beacon_block.proto", "beacon_state.proto", "blobs.proto", + "data_columns.proto", + "light_client.proto", "sync_committee.proto", "withdrawals.proto", ], diff --git a/proto/prysm/v1alpha1/README.md b/proto/prysm/v1alpha1/README.md deleted file mode 100644 index af9cfcca7034..000000000000 --- a/proto/prysm/v1alpha1/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# gRPC Gateway - -This package is contains generated files for applications that wish to use eth/v1alpha as a -[gRPC gateway](https://github.com/grpc-ecosystem/grpc-gateway). \ No newline at end of file diff --git a/proto/prysm/v1alpha1/altair.ssz.go b/proto/prysm/v1alpha1/altair.ssz.go index 45521fbe747e..84c8e4b6672c 100644 --- a/proto/prysm/v1alpha1/altair.ssz.go +++ b/proto/prysm/v1alpha1/altair.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: c00c1be829cdae457076ef3e840f3af313626147927e503e90fb5585cf242d36 package eth import ( @@ -7,6 +6,115 @@ import ( github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) +// MarshalSSZ ssz marshals the SignedBeaconBlockAltair object +func (s *SignedBeaconBlockAltair) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedBeaconBlockAltair object to a target array +func (s *SignedBeaconBlockAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(100) + + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if s.Block == nil { + s.Block = new(BeaconBlockAltair) + } + offset += s.Block.SizeSSZ() + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + // Field (0) 'Block' + if dst, err = s.Block.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockAltair object +func (s *SignedBeaconBlockAltair) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 100 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 100 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) + } + s.Signature = append(s.Signature, buf[4:100]...) + + // Field (0) 'Block' + { + buf = tail[o0:] + if s.Block == nil { + s.Block = new(BeaconBlockAltair) + } + if err = s.Block.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockAltair object +func (s *SignedBeaconBlockAltair) SizeSSZ() (size int) { + size = 100 + + // Field (0) 'Block' + if s.Block == nil { + s.Block = new(BeaconBlockAltair) + } + size += s.Block.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the SignedBeaconBlockAltair object +func (s *SignedBeaconBlockAltair) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedBeaconBlockAltair object with a hasher +func (s *SignedBeaconBlockAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Block' + if err = s.Block.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(s.Signature) + + hh.Merkleize(indx) + return +} + // MarshalSSZ ssz marshals the BeaconBlockAltair object func (b *BeaconBlockAltair) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) @@ -154,115 +262,6 @@ func (b *BeaconBlockAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the SignedBeaconBlockAltair object -func (s *SignedBeaconBlockAltair) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBeaconBlockAltair object to a target array -func (s *SignedBeaconBlockAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Block' - dst = ssz.WriteOffset(dst, offset) - if s.Block == nil { - s.Block = new(BeaconBlockAltair) - } - offset += s.Block.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Block' - if dst, err = s.Block.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockAltair object -func (s *SignedBeaconBlockAltair) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Block' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Block' - { - buf = tail[o0:] - if s.Block == nil { - s.Block = new(BeaconBlockAltair) - } - if err = s.Block.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockAltair object -func (s *SignedBeaconBlockAltair) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Block' - if s.Block == nil { - s.Block = new(BeaconBlockAltair) - } - size += s.Block.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBeaconBlockAltair object -func (s *SignedBeaconBlockAltair) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBeaconBlockAltair object with a hasher -func (s *SignedBeaconBlockAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Block' - if err = s.Block.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - // MarshalSSZ ssz marshals the BeaconBlockBodyAltair object func (b *BeaconBlockBodyAltair) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) @@ -1747,56 +1746,701 @@ func (s *SyncAggregatorSelectionData) HashTreeRootWith(hh *ssz.Hasher) (err erro return } -// MarshalSSZ ssz marshals the SyncCommitteeMessage object -func (s *SyncCommitteeMessage) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) +// MarshalSSZ ssz marshals the LightClientBootstrapAltair object +func (l *LightClientBootstrapAltair) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) } -// MarshalSSZTo ssz marshals the SyncCommitteeMessage object to a target array -func (s *SyncCommitteeMessage) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the LightClientBootstrapAltair object to a target array +func (l *LightClientBootstrapAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(s.Slot)) - - // Field (1) 'BlockRoot' - if size := len(s.BlockRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) + // Field (0) 'Header' + if l.Header == nil { + l.Header = new(LightClientHeaderAltair) + } + if dst, err = l.Header.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, s.BlockRoot...) - // Field (2) 'ValidatorIndex' - dst = ssz.MarshalUint64(dst, uint64(s.ValidatorIndex)) + // Field (1) 'CurrentSyncCommittee' + if l.CurrentSyncCommittee == nil { + l.CurrentSyncCommittee = new(SyncCommittee) + } + if dst, err = l.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } - // Field (3) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + // Field (2) 'CurrentSyncCommitteeBranch' + if size := len(l.CurrentSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5) return } - dst = append(dst, s.Signature...) + for ii := 0; ii < 5; ii++ { + if size := len(l.CurrentSyncCommitteeBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.CurrentSyncCommitteeBranch[ii]", size, 32) + return + } + dst = append(dst, l.CurrentSyncCommitteeBranch[ii]...) + } return } -// UnmarshalSSZ ssz unmarshals the SyncCommitteeMessage object -func (s *SyncCommitteeMessage) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the LightClientBootstrapAltair object +func (l *LightClientBootstrapAltair) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 144 { + if size != 24896 { return ssz.ErrSize } - // Field (0) 'Slot' - s.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'BlockRoot' - if cap(s.BlockRoot) == 0 { - s.BlockRoot = make([]byte, 0, len(buf[8:40])) + // Field (0) 'Header' + if l.Header == nil { + l.Header = new(LightClientHeaderAltair) + } + if err = l.Header.UnmarshalSSZ(buf[0:112]); err != nil { + return err } - s.BlockRoot = append(s.BlockRoot, buf[8:40]...) - // Field (2) 'ValidatorIndex' + // Field (1) 'CurrentSyncCommittee' + if l.CurrentSyncCommittee == nil { + l.CurrentSyncCommittee = new(SyncCommittee) + } + if err = l.CurrentSyncCommittee.UnmarshalSSZ(buf[112:24736]); err != nil { + return err + } + + // Field (2) 'CurrentSyncCommitteeBranch' + l.CurrentSyncCommitteeBranch = make([][]byte, 5) + for ii := 0; ii < 5; ii++ { + if cap(l.CurrentSyncCommitteeBranch[ii]) == 0 { + l.CurrentSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24736:24896][ii*32:(ii+1)*32])) + } + l.CurrentSyncCommitteeBranch[ii] = append(l.CurrentSyncCommitteeBranch[ii], buf[24736:24896][ii*32:(ii+1)*32]...) + } + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientBootstrapAltair object +func (l *LightClientBootstrapAltair) SizeSSZ() (size int) { + size = 24896 + return +} + +// HashTreeRoot ssz hashes the LightClientBootstrapAltair object +func (l *LightClientBootstrapAltair) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientBootstrapAltair object with a hasher +func (l *LightClientBootstrapAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Header' + if err = l.Header.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'CurrentSyncCommittee' + if err = l.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'CurrentSyncCommitteeBranch' + { + if size := len(l.CurrentSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5) + return + } + subIndx := hh.Index() + for _, i := range l.CurrentSyncCommitteeBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientUpdateAltair object +func (l *LightClientUpdateAltair) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientUpdateAltair object to a target array +func (l *LightClientUpdateAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderAltair) + } + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'NextSyncCommittee' + if l.NextSyncCommittee == nil { + l.NextSyncCommittee = new(SyncCommittee) + } + if dst, err = l.NextSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'NextSyncCommitteeBranch' + if size := len(l.NextSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5) + return + } + for ii := 0; ii < 5; ii++ { + if size := len(l.NextSyncCommitteeBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.NextSyncCommitteeBranch[ii]", size, 32) + return + } + dst = append(dst, l.NextSyncCommitteeBranch[ii]...) + } + + // Field (3) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderAltair) + } + if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (4) 'FinalityBranch' + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + for ii := 0; ii < 6; ii++ { + if size := len(l.FinalityBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32) + return + } + dst = append(dst, l.FinalityBranch[ii]...) + } + + // Field (5) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (6) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientUpdateAltair object +func (l *LightClientUpdateAltair) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 25368 { + return ssz.ErrSize + } + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderAltair) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf[0:112]); err != nil { + return err + } + + // Field (1) 'NextSyncCommittee' + if l.NextSyncCommittee == nil { + l.NextSyncCommittee = new(SyncCommittee) + } + if err = l.NextSyncCommittee.UnmarshalSSZ(buf[112:24736]); err != nil { + return err + } + + // Field (2) 'NextSyncCommitteeBranch' + l.NextSyncCommitteeBranch = make([][]byte, 5) + for ii := 0; ii < 5; ii++ { + if cap(l.NextSyncCommitteeBranch[ii]) == 0 { + l.NextSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24736:24896][ii*32:(ii+1)*32])) + } + l.NextSyncCommitteeBranch[ii] = append(l.NextSyncCommitteeBranch[ii], buf[24736:24896][ii*32:(ii+1)*32]...) + } + + // Field (3) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderAltair) + } + if err = l.FinalizedHeader.UnmarshalSSZ(buf[24896:25008]); err != nil { + return err + } + + // Field (4) 'FinalityBranch' + l.FinalityBranch = make([][]byte, 6) + for ii := 0; ii < 6; ii++ { + if cap(l.FinalityBranch[ii]) == 0 { + l.FinalityBranch[ii] = make([]byte, 0, len(buf[25008:25200][ii*32:(ii+1)*32])) + } + l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[25008:25200][ii*32:(ii+1)*32]...) + } + + // Field (5) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[25200:25360]); err != nil { + return err + } + + // Field (6) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[25360:25368])) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientUpdateAltair object +func (l *LightClientUpdateAltair) SizeSSZ() (size int) { + size = 25368 + return +} + +// HashTreeRoot ssz hashes the LightClientUpdateAltair object +func (l *LightClientUpdateAltair) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientUpdateAltair object with a hasher +func (l *LightClientUpdateAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'NextSyncCommittee' + if err = l.NextSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'NextSyncCommitteeBranch' + { + if size := len(l.NextSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5) + return + } + subIndx := hh.Index() + for _, i := range l.NextSyncCommitteeBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (3) 'FinalizedHeader' + if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (4) 'FinalityBranch' + { + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + subIndx := hh.Index() + for _, i := range l.FinalityBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (5) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (6) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientFinalityUpdateAltair object +func (l *LightClientFinalityUpdateAltair) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientFinalityUpdateAltair object to a target array +func (l *LightClientFinalityUpdateAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderAltair) + } + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderAltair) + } + if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'FinalityBranch' + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + for ii := 0; ii < 6; ii++ { + if size := len(l.FinalityBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32) + return + } + dst = append(dst, l.FinalityBranch[ii]...) + } + + // Field (3) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (4) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientFinalityUpdateAltair object +func (l *LightClientFinalityUpdateAltair) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 584 { + return ssz.ErrSize + } + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderAltair) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf[0:112]); err != nil { + return err + } + + // Field (1) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderAltair) + } + if err = l.FinalizedHeader.UnmarshalSSZ(buf[112:224]); err != nil { + return err + } + + // Field (2) 'FinalityBranch' + l.FinalityBranch = make([][]byte, 6) + for ii := 0; ii < 6; ii++ { + if cap(l.FinalityBranch[ii]) == 0 { + l.FinalityBranch[ii] = make([]byte, 0, len(buf[224:416][ii*32:(ii+1)*32])) + } + l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[224:416][ii*32:(ii+1)*32]...) + } + + // Field (3) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[416:576]); err != nil { + return err + } + + // Field (4) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[576:584])) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientFinalityUpdateAltair object +func (l *LightClientFinalityUpdateAltair) SizeSSZ() (size int) { + size = 584 + return +} + +// HashTreeRoot ssz hashes the LightClientFinalityUpdateAltair object +func (l *LightClientFinalityUpdateAltair) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientFinalityUpdateAltair object with a hasher +func (l *LightClientFinalityUpdateAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'FinalizedHeader' + if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'FinalityBranch' + { + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + subIndx := hh.Index() + for _, i := range l.FinalityBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (3) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (4) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientOptimisticUpdateAltair object +func (l *LightClientOptimisticUpdateAltair) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientOptimisticUpdateAltair object to a target array +func (l *LightClientOptimisticUpdateAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderAltair) + } + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientOptimisticUpdateAltair object +func (l *LightClientOptimisticUpdateAltair) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 280 { + return ssz.ErrSize + } + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderAltair) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf[0:112]); err != nil { + return err + } + + // Field (1) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[112:272]); err != nil { + return err + } + + // Field (2) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[272:280])) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientOptimisticUpdateAltair object +func (l *LightClientOptimisticUpdateAltair) SizeSSZ() (size int) { + size = 280 + return +} + +// HashTreeRoot ssz hashes the LightClientOptimisticUpdateAltair object +func (l *LightClientOptimisticUpdateAltair) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientOptimisticUpdateAltair object with a hasher +func (l *LightClientOptimisticUpdateAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientHeaderAltair object +func (l *LightClientHeaderAltair) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientHeaderAltair object to a target array +func (l *LightClientHeaderAltair) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Beacon' + if l.Beacon == nil { + l.Beacon = new(BeaconBlockHeader) + } + if dst, err = l.Beacon.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientHeaderAltair object +func (l *LightClientHeaderAltair) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 112 { + return ssz.ErrSize + } + + // Field (0) 'Beacon' + if l.Beacon == nil { + l.Beacon = new(BeaconBlockHeader) + } + if err = l.Beacon.UnmarshalSSZ(buf[0:112]); err != nil { + return err + } + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientHeaderAltair object +func (l *LightClientHeaderAltair) SizeSSZ() (size int) { + size = 112 + return +} + +// HashTreeRoot ssz hashes the LightClientHeaderAltair object +func (l *LightClientHeaderAltair) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientHeaderAltair object with a hasher +func (l *LightClientHeaderAltair) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Beacon' + if err = l.Beacon.HashTreeRootWith(hh); err != nil { + return + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the SyncCommitteeMessage object +func (s *SyncCommitteeMessage) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SyncCommitteeMessage object to a target array +func (s *SyncCommitteeMessage) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(s.Slot)) + + // Field (1) 'BlockRoot' + if size := len(s.BlockRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) + return + } + dst = append(dst, s.BlockRoot...) + + // Field (2) 'ValidatorIndex' + dst = ssz.MarshalUint64(dst, uint64(s.ValidatorIndex)) + + // Field (3) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + return +} + +// UnmarshalSSZ ssz unmarshals the SyncCommitteeMessage object +func (s *SyncCommitteeMessage) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 144 { + return ssz.ErrSize + } + + // Field (0) 'Slot' + s.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'BlockRoot' + if cap(s.BlockRoot) == 0 { + s.BlockRoot = make([]byte, 0, len(buf[8:40])) + } + s.BlockRoot = append(s.BlockRoot, buf[8:40]...) + + // Field (2) 'ValidatorIndex' s.ValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[40:48])) // Field (3) 'Signature' @@ -1847,36 +2491,24 @@ func (s *SyncCommitteeMessage) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the SyncCommitteeContribution object -func (s *SyncCommitteeContribution) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the SignedContributionAndProof object +func (s *SignedContributionAndProof) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the SyncCommitteeContribution object to a target array -func (s *SyncCommitteeContribution) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SignedContributionAndProof object to a target array +func (s *SignedContributionAndProof) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(s.Slot)) - - // Field (1) 'BlockRoot' - if size := len(s.BlockRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) - return + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(ContributionAndProof) } - dst = append(dst, s.BlockRoot...) - - // Field (2) 'SubcommitteeIndex' - dst = ssz.MarshalUint64(dst, s.SubcommitteeIndex) - - // Field (3) 'AggregationBits' - if size := len(s.AggregationBits); size != 16 { - err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 16) + if dst, err = s.Message.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, s.AggregationBits...) - // Field (4) 'Signature' + // Field (1) 'Signature' if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return @@ -1886,77 +2518,52 @@ func (s *SyncCommitteeContribution) MarshalSSZTo(buf []byte) (dst []byte, err er return } -// UnmarshalSSZ ssz unmarshals the SyncCommitteeContribution object -func (s *SyncCommitteeContribution) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the SignedContributionAndProof object +func (s *SignedContributionAndProof) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 160 { + if size != 360 { return ssz.ErrSize } - // Field (0) 'Slot' - s.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'BlockRoot' - if cap(s.BlockRoot) == 0 { - s.BlockRoot = make([]byte, 0, len(buf[8:40])) + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(ContributionAndProof) } - s.BlockRoot = append(s.BlockRoot, buf[8:40]...) - - // Field (2) 'SubcommitteeIndex' - s.SubcommitteeIndex = ssz.UnmarshallUint64(buf[40:48]) - - // Field (3) 'AggregationBits' - if cap(s.AggregationBits) == 0 { - s.AggregationBits = make([]byte, 0, len(buf[48:64])) + if err = s.Message.UnmarshalSSZ(buf[0:264]); err != nil { + return err } - s.AggregationBits = append(s.AggregationBits, buf[48:64]...) - // Field (4) 'Signature' + // Field (1) 'Signature' if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[64:160])) + s.Signature = make([]byte, 0, len(buf[264:360])) } - s.Signature = append(s.Signature, buf[64:160]...) + s.Signature = append(s.Signature, buf[264:360]...) return err } -// SizeSSZ returns the ssz encoded size in bytes for the SyncCommitteeContribution object -func (s *SyncCommitteeContribution) SizeSSZ() (size int) { - size = 160 +// SizeSSZ returns the ssz encoded size in bytes for the SignedContributionAndProof object +func (s *SignedContributionAndProof) SizeSSZ() (size int) { + size = 360 return } -// HashTreeRoot ssz hashes the SyncCommitteeContribution object -func (s *SyncCommitteeContribution) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the SignedContributionAndProof object +func (s *SignedContributionAndProof) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(s) } -// HashTreeRootWith ssz hashes the SyncCommitteeContribution object with a hasher -func (s *SyncCommitteeContribution) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the SignedContributionAndProof object with a hasher +func (s *SignedContributionAndProof) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Slot' - hh.PutUint64(uint64(s.Slot)) - - // Field (1) 'BlockRoot' - if size := len(s.BlockRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) - return - } - hh.PutBytes(s.BlockRoot) - - // Field (2) 'SubcommitteeIndex' - hh.PutUint64(s.SubcommitteeIndex) - - // Field (3) 'AggregationBits' - if size := len(s.AggregationBits); size != 16 { - err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 16) + // Field (0) 'Message' + if err = s.Message.HashTreeRootWith(hh); err != nil { return } - hh.PutBytes(s.AggregationBits) - // Field (4) 'Signature' + // Field (1) 'Signature' if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return @@ -2059,24 +2666,36 @@ func (c *ContributionAndProof) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the SignedContributionAndProof object -func (s *SignedContributionAndProof) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the SyncCommitteeContribution object +func (s *SyncCommitteeContribution) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the SignedContributionAndProof object to a target array -func (s *SignedContributionAndProof) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SyncCommitteeContribution object to a target array +func (s *SyncCommitteeContribution) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(ContributionAndProof) + // Field (0) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(s.Slot)) + + // Field (1) 'BlockRoot' + if size := len(s.BlockRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) + return } - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { + dst = append(dst, s.BlockRoot...) + + // Field (2) 'SubcommitteeIndex' + dst = ssz.MarshalUint64(dst, s.SubcommitteeIndex) + + // Field (3) 'AggregationBits' + if size := len(s.AggregationBits); size != 16 { + err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 16) return } + dst = append(dst, s.AggregationBits...) - // Field (1) 'Signature' + // Field (4) 'Signature' if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return @@ -2086,52 +2705,77 @@ func (s *SignedContributionAndProof) MarshalSSZTo(buf []byte) (dst []byte, err e return } -// UnmarshalSSZ ssz unmarshals the SignedContributionAndProof object -func (s *SignedContributionAndProof) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the SyncCommitteeContribution object +func (s *SyncCommitteeContribution) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 360 { + if size != 160 { return ssz.ErrSize } - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(ContributionAndProof) + // Field (0) 'Slot' + s.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'BlockRoot' + if cap(s.BlockRoot) == 0 { + s.BlockRoot = make([]byte, 0, len(buf[8:40])) } - if err = s.Message.UnmarshalSSZ(buf[0:264]); err != nil { - return err + s.BlockRoot = append(s.BlockRoot, buf[8:40]...) + + // Field (2) 'SubcommitteeIndex' + s.SubcommitteeIndex = ssz.UnmarshallUint64(buf[40:48]) + + // Field (3) 'AggregationBits' + if cap(s.AggregationBits) == 0 { + s.AggregationBits = make([]byte, 0, len(buf[48:64])) } + s.AggregationBits = append(s.AggregationBits, buf[48:64]...) - // Field (1) 'Signature' + // Field (4) 'Signature' if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[264:360])) + s.Signature = make([]byte, 0, len(buf[64:160])) } - s.Signature = append(s.Signature, buf[264:360]...) + s.Signature = append(s.Signature, buf[64:160]...) return err } -// SizeSSZ returns the ssz encoded size in bytes for the SignedContributionAndProof object -func (s *SignedContributionAndProof) SizeSSZ() (size int) { - size = 360 +// SizeSSZ returns the ssz encoded size in bytes for the SyncCommitteeContribution object +func (s *SyncCommitteeContribution) SizeSSZ() (size int) { + size = 160 return } -// HashTreeRoot ssz hashes the SignedContributionAndProof object -func (s *SignedContributionAndProof) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the SyncCommitteeContribution object +func (s *SyncCommitteeContribution) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(s) } -// HashTreeRootWith ssz hashes the SignedContributionAndProof object with a hasher -func (s *SignedContributionAndProof) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the SyncCommitteeContribution object with a hasher +func (s *SyncCommitteeContribution) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { + // Field (0) 'Slot' + hh.PutUint64(uint64(s.Slot)) + + // Field (1) 'BlockRoot' + if size := len(s.BlockRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) return } + hh.PutBytes(s.BlockRoot) - // Field (1) 'Signature' + // Field (2) 'SubcommitteeIndex' + hh.PutUint64(s.SubcommitteeIndex) + + // Field (3) 'AggregationBits' + if size := len(s.AggregationBits); size != 16 { + err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 16) + return + } + hh.PutBytes(s.AggregationBits) + + // Field (4) 'Signature' if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return diff --git a/proto/prysm/v1alpha1/attestation.go b/proto/prysm/v1alpha1/attestation.go index d59d2cfcdb5d..493595d5a329 100644 --- a/proto/prysm/v1alpha1/attestation.go +++ b/proto/prysm/v1alpha1/attestation.go @@ -16,11 +16,17 @@ type Att interface { ssz.Unmarshaler ssz.HashRoot Version() int + IsNil() bool + IsSingle() bool + IsAggregated() bool Clone() Att GetAggregationBits() bitfield.Bitlist + GetAttestingIndex() primitives.ValidatorIndex GetData() *AttestationData CommitteeBitsVal() bitfield.Bitfield GetSignature() []byte + SetSignature(sig []byte) + GetCommitteeIndex() primitives.CommitteeIndex } // IndexedAtt defines common functionality for all indexed attestation types. @@ -33,6 +39,7 @@ type IndexedAtt interface { GetAttestingIndices() []uint64 GetData() *AttestationData GetSignature() []byte + IsNil() bool } // SignedAggregateAttAndProof defines common functionality for all signed aggregate attestation types. @@ -44,6 +51,7 @@ type SignedAggregateAttAndProof interface { Version() int AggregateAttestationAndProof() AggregateAttAndProof GetSignature() []byte + IsNil() bool } // AggregateAttAndProof defines common functionality for all aggregate attestation types. @@ -56,6 +64,7 @@ type AggregateAttAndProof interface { GetAggregatorIndex() primitives.ValidatorIndex AggregateVal() Att GetSelectionProof() []byte + IsNil() bool } // AttSlashing defines common functionality for all attestation slashing types. @@ -67,6 +76,7 @@ type AttSlashing interface { Version() int FirstAttestation() IndexedAtt SecondAttestation() IndexedAtt + IsNil() bool } // Copy -- @@ -99,23 +109,43 @@ func (a *Attestation) Version() int { return version.Phase0 } +// IsNil -- +func (a *Attestation) IsNil() bool { + return a == nil || a.Data == nil +} + +// IsSingle returns true when the attestation can have only a single attester index. +func (*Attestation) IsSingle() bool { + return false +} + +// IsAggregated -- +func (a *Attestation) IsAggregated() bool { + return a.AggregationBits.Count() > 1 +} + // Clone -- func (a *Attestation) Clone() Att { return a.Copy() } // Copy -- -func (att *Attestation) Copy() *Attestation { - if att == nil { +func (a *Attestation) Copy() *Attestation { + if a == nil { return nil } return &Attestation{ - AggregationBits: bytesutil.SafeCopyBytes(att.AggregationBits), - Data: att.Data.Copy(), - Signature: bytesutil.SafeCopyBytes(att.Signature), + AggregationBits: bytesutil.SafeCopyBytes(a.AggregationBits), + Data: a.Data.Copy(), + Signature: bytesutil.SafeCopyBytes(a.Signature), } } +// GetAttestingIndex -- +func (*Attestation) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *Attestation) CommitteeBitsVal() bitfield.Bitfield { cb := primitives.NewAttestationCommitteeBits() @@ -123,11 +153,39 @@ func (a *Attestation) CommitteeBitsVal() bitfield.Bitfield { return cb } +// SetSignature -- +func (a *Attestation) SetSignature(sig []byte) { + a.Signature = sig +} + +// GetCommitteeIndex -- +func (a *Attestation) GetCommitteeIndex() primitives.CommitteeIndex { + if a == nil || a.Data == nil { + return 0 + } + return a.Data.CommitteeIndex +} + // Version -- func (a *PendingAttestation) Version() int { return version.Phase0 } +// IsNil -- +func (a *PendingAttestation) IsNil() bool { + return a == nil || a.Data == nil +} + +// IsSingle returns true when the attestation can have only a single attester index. +func (*PendingAttestation) IsSingle() bool { + return false +} + +// IsAggregated -- +func (a *PendingAttestation) IsAggregated() bool { + return a.AggregationBits.Count() > 1 +} + // Clone -- func (a *PendingAttestation) Clone() Att { return a.Copy() @@ -146,6 +204,11 @@ func (a *PendingAttestation) Copy() *PendingAttestation { } } +// GetAttestingIndex -- +func (*PendingAttestation) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *PendingAttestation) CommitteeBitsVal() bitfield.Bitfield { return nil @@ -156,73 +219,217 @@ func (a *PendingAttestation) GetSignature() []byte { return nil } +// SetSignature -- +func (a *PendingAttestation) SetSignature(_ []byte) {} + +// GetCommitteeIndex -- +func (a *PendingAttestation) GetCommitteeIndex() primitives.CommitteeIndex { + if a == nil || a.Data == nil { + return 0 + } + return a.Data.CommitteeIndex +} + // Version -- func (a *AttestationElectra) Version() int { return version.Electra } +// IsNil -- +func (a *AttestationElectra) IsNil() bool { + return a == nil || a.Data == nil +} + +// IsSingle returns true when the attestation can have only a single attester index. +func (*AttestationElectra) IsSingle() bool { + return false +} + +// IsAggregated -- +func (a *AttestationElectra) IsAggregated() bool { + return a.AggregationBits.Count() > 1 +} + // Clone -- func (a *AttestationElectra) Clone() Att { return a.Copy() } // Copy -- -func (att *AttestationElectra) Copy() *AttestationElectra { - if att == nil { +func (a *AttestationElectra) Copy() *AttestationElectra { + if a == nil { return nil } return &AttestationElectra{ - AggregationBits: bytesutil.SafeCopyBytes(att.AggregationBits), - CommitteeBits: bytesutil.SafeCopyBytes(att.CommitteeBits), - Data: att.Data.Copy(), - Signature: bytesutil.SafeCopyBytes(att.Signature), + AggregationBits: bytesutil.SafeCopyBytes(a.AggregationBits), + CommitteeBits: bytesutil.SafeCopyBytes(a.CommitteeBits), + Data: a.Data.Copy(), + Signature: bytesutil.SafeCopyBytes(a.Signature), } } +// GetAttestingIndex -- +func (*AttestationElectra) GetAttestingIndex() primitives.ValidatorIndex { + return 0 +} + // CommitteeBitsVal -- func (a *AttestationElectra) CommitteeBitsVal() bitfield.Bitfield { return a.CommitteeBits } +// SetSignature -- +func (a *AttestationElectra) SetSignature(sig []byte) { + a.Signature = sig +} + +// GetCommitteeIndex -- +func (a *AttestationElectra) GetCommitteeIndex() primitives.CommitteeIndex { + if len(a.CommitteeBits) == 0 { + return 0 + } + indices := a.CommitteeBits.BitIndices() + if len(indices) == 0 { + return 0 + } + return primitives.CommitteeIndex(uint64(indices[0])) +} + +// Version -- +func (a *SingleAttestation) Version() int { + return version.Electra +} + +// IsNil -- +func (a *SingleAttestation) IsNil() bool { + return a == nil || a.Data == nil +} + +// IsAggregated -- +func (a *SingleAttestation) IsAggregated() bool { + return false +} + +// IsSingle returns true when the attestation can have only a single attester index. +func (*SingleAttestation) IsSingle() bool { + return true +} + +// Clone -- +func (a *SingleAttestation) Clone() Att { + return a.Copy() +} + +// Copy -- +func (a *SingleAttestation) Copy() *SingleAttestation { + if a == nil { + return nil + } + return &SingleAttestation{ + CommitteeId: a.CommitteeId, + AttesterIndex: a.AttesterIndex, + Data: a.Data.Copy(), + Signature: bytesutil.SafeCopyBytes(a.Signature), + } +} + +// GetAttestingIndex -- +func (a *SingleAttestation) GetAttestingIndex() primitives.ValidatorIndex { + return a.AttesterIndex +} + +// CommitteeBitsVal -- +func (a *SingleAttestation) CommitteeBitsVal() bitfield.Bitfield { + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(uint64(a.CommitteeId), true) + return cb +} + +// GetAggregationBits -- +func (a *SingleAttestation) GetAggregationBits() bitfield.Bitlist { + return nil +} + +// SetSignature -- +func (a *SingleAttestation) SetSignature(sig []byte) { + a.Signature = sig +} + +// GetCommitteeIndex -- +func (a *SingleAttestation) GetCommitteeIndex() primitives.CommitteeIndex { + return a.CommitteeId +} + +// ToAttestationElectra converts the attestation to an AttestationElectra. +func (a *SingleAttestation) ToAttestationElectra(committee []primitives.ValidatorIndex) *AttestationElectra { + cb := primitives.NewAttestationCommitteeBits() + cb.SetBitAt(uint64(a.CommitteeId), true) + + ab := bitfield.NewBitlist(uint64(len(committee))) + for i, ix := range committee { + if a.AttesterIndex == ix { + ab.SetBitAt(uint64(i), true) + break + } + } + + return &AttestationElectra{ + AggregationBits: ab, + Data: a.Data, + Signature: a.Signature, + CommitteeBits: cb, + } +} + // Version -- func (a *IndexedAttestation) Version() int { return version.Phase0 } +// IsNil -- +func (a *IndexedAttestation) IsNil() bool { + return a == nil || a.Data == nil +} + // Version -- func (a *IndexedAttestationElectra) Version() int { return version.Electra } +// IsNil -- +func (a *IndexedAttestationElectra) IsNil() bool { + return a == nil || a.Data == nil +} + // Copy -- -func (indexedAtt *IndexedAttestation) Copy() *IndexedAttestation { +func (a *IndexedAttestation) Copy() *IndexedAttestation { var indices []uint64 - if indexedAtt == nil { + if a == nil { return nil - } else if indexedAtt.AttestingIndices != nil { - indices = make([]uint64, len(indexedAtt.AttestingIndices)) - copy(indices, indexedAtt.AttestingIndices) + } else if a.AttestingIndices != nil { + indices = make([]uint64, len(a.AttestingIndices)) + copy(indices, a.AttestingIndices) } return &IndexedAttestation{ AttestingIndices: indices, - Data: indexedAtt.Data.Copy(), - Signature: bytesutil.SafeCopyBytes(indexedAtt.Signature), + Data: a.Data.Copy(), + Signature: bytesutil.SafeCopyBytes(a.Signature), } } // Copy -- -func (indexedAtt *IndexedAttestationElectra) Copy() *IndexedAttestationElectra { +func (a *IndexedAttestationElectra) Copy() *IndexedAttestationElectra { var indices []uint64 - if indexedAtt == nil { + if a == nil { return nil - } else if indexedAtt.AttestingIndices != nil { - indices = make([]uint64, len(indexedAtt.AttestingIndices)) - copy(indices, indexedAtt.AttestingIndices) + } else if a.AttestingIndices != nil { + indices = make([]uint64, len(a.AttestingIndices)) + copy(indices, a.AttestingIndices) } return &IndexedAttestationElectra{ AttestingIndices: indices, - Data: indexedAtt.Data.Copy(), - Signature: bytesutil.SafeCopyBytes(indexedAtt.Signature), + Data: a.Data.Copy(), + Signature: bytesutil.SafeCopyBytes(a.Signature), } } @@ -231,6 +438,13 @@ func (a *AttesterSlashing) Version() int { return version.Phase0 } +// IsNil -- +func (a *AttesterSlashing) IsNil() bool { + return a == nil || + a.Attestation_1 == nil || a.Attestation_1.IsNil() || + a.Attestation_2 == nil || a.Attestation_2.IsNil() +} + // FirstAttestation -- func (a *AttesterSlashing) FirstAttestation() IndexedAtt { return a.Attestation_1 @@ -246,6 +460,13 @@ func (a *AttesterSlashingElectra) Version() int { return version.Electra } +// IsNil -- +func (a *AttesterSlashingElectra) IsNil() bool { + return a == nil || + a.Attestation_1 == nil || a.Attestation_1.IsNil() || + a.Attestation_2 == nil || a.Attestation_2.IsNil() +} + // FirstAttestation -- func (a *AttesterSlashingElectra) FirstAttestation() IndexedAtt { return a.Attestation_1 @@ -282,6 +503,11 @@ func (a *AggregateAttestationAndProof) Version() int { return version.Phase0 } +// IsNil -- +func (a *AggregateAttestationAndProof) IsNil() bool { + return a == nil || a.Aggregate == nil || a.Aggregate.IsNil() +} + // AggregateVal -- func (a *AggregateAttestationAndProof) AggregateVal() Att { return a.Aggregate @@ -292,16 +518,41 @@ func (a *AggregateAttestationAndProofElectra) Version() int { return version.Electra } +// IsNil -- +func (a *AggregateAttestationAndProofElectra) IsNil() bool { + return a == nil || a.Aggregate == nil || a.Aggregate.IsNil() +} + // AggregateVal -- func (a *AggregateAttestationAndProofElectra) AggregateVal() Att { return a.Aggregate } +// Version -- +func (a *AggregateAttestationAndProofSingle) Version() int { + return version.Electra +} + +// IsNil -- +func (a *AggregateAttestationAndProofSingle) IsNil() bool { + return a == nil || a.Aggregate == nil || a.Aggregate.IsNil() +} + +// AggregateVal -- +func (a *AggregateAttestationAndProofSingle) AggregateVal() Att { + return a.Aggregate +} + // Version -- func (a *SignedAggregateAttestationAndProof) Version() int { return version.Phase0 } +// IsNil -- +func (a *SignedAggregateAttestationAndProof) IsNil() bool { + return a == nil || a.Message == nil || a.Message.IsNil() +} + // AggregateAttestationAndProof -- func (a *SignedAggregateAttestationAndProof) AggregateAttestationAndProof() AggregateAttAndProof { return a.Message @@ -312,7 +563,27 @@ func (a *SignedAggregateAttestationAndProofElectra) Version() int { return version.Electra } +// IsNil -- +func (a *SignedAggregateAttestationAndProofElectra) IsNil() bool { + return a == nil || a.Message == nil || a.Message.IsNil() +} + // AggregateAttestationAndProof -- func (a *SignedAggregateAttestationAndProofElectra) AggregateAttestationAndProof() AggregateAttAndProof { return a.Message } + +// Version -- +func (a *SignedAggregateAttestationAndProofSingle) Version() int { + return version.Electra +} + +// IsNil -- +func (a *SignedAggregateAttestationAndProofSingle) IsNil() bool { + return a == nil || a.Message == nil || a.Message.IsNil() +} + +// AggregateAttestationAndProof -- +func (a *SignedAggregateAttestationAndProofSingle) AggregateAttestationAndProof() AggregateAttAndProof { + return a.Message +} diff --git a/proto/prysm/v1alpha1/attestation.pb.go b/proto/prysm/v1alpha1/attestation.pb.go index 6b1f970fb1ef..4f2968ef1f8c 100755 --- a/proto/prysm/v1alpha1/attestation.pb.go +++ b/proto/prysm/v1alpha1/attestation.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/attestation.proto package eth @@ -24,6 +24,124 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type SignedAggregateAttestationAndProof struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message *AggregateAttestationAndProof `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *SignedAggregateAttestationAndProof) Reset() { + *x = SignedAggregateAttestationAndProof{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedAggregateAttestationAndProof) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedAggregateAttestationAndProof) ProtoMessage() {} + +func (x *SignedAggregateAttestationAndProof) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedAggregateAttestationAndProof.ProtoReflect.Descriptor instead. +func (*SignedAggregateAttestationAndProof) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{0} +} + +func (x *SignedAggregateAttestationAndProof) GetMessage() *AggregateAttestationAndProof { + if x != nil { + return x.Message + } + return nil +} + +func (x *SignedAggregateAttestationAndProof) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +type AggregateAttestationAndProof struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AggregatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=aggregator_index,json=aggregatorIndex,proto3" json:"aggregator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + Aggregate *Attestation `protobuf:"bytes,3,opt,name=aggregate,proto3" json:"aggregate,omitempty"` + SelectionProof []byte `protobuf:"bytes,2,opt,name=selection_proof,json=selectionProof,proto3" json:"selection_proof,omitempty" ssz-size:"96"` +} + +func (x *AggregateAttestationAndProof) Reset() { + *x = AggregateAttestationAndProof{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AggregateAttestationAndProof) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AggregateAttestationAndProof) ProtoMessage() {} + +func (x *AggregateAttestationAndProof) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AggregateAttestationAndProof.ProtoReflect.Descriptor instead. +func (*AggregateAttestationAndProof) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{1} +} + +func (x *AggregateAttestationAndProof) GetAggregatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { + if x != nil { + return x.AggregatorIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *AggregateAttestationAndProof) GetAggregate() *Attestation { + if x != nil { + return x.Aggregate + } + return nil +} + +func (x *AggregateAttestationAndProof) GetSelectionProof() []byte { + if x != nil { + return x.SelectionProof + } + return nil +} + type Attestation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -37,7 +155,7 @@ type Attestation struct { func (x *Attestation) Reset() { *x = Attestation{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[0] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -50,7 +168,7 @@ func (x *Attestation) String() string { func (*Attestation) ProtoMessage() {} func (x *Attestation) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[0] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -63,7 +181,7 @@ func (x *Attestation) ProtoReflect() protoreflect.Message { // Deprecated: Use Attestation.ProtoReflect.Descriptor instead. func (*Attestation) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{0} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{2} } func (x *Attestation) GetAggregationBits() github_com_prysmaticlabs_go_bitfield.Bitlist { @@ -87,34 +205,35 @@ func (x *Attestation) GetSignature() []byte { return nil } -type AttestationElectra struct { +type AttestationData struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AggregationBits github_com_prysmaticlabs_go_bitfield.Bitlist `protobuf:"bytes,1,opt,name=aggregation_bits,json=aggregationBits,proto3" json:"aggregation_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitlist" ssz-max:"131072"` - Data *AttestationData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` - CommitteeBits github_com_prysmaticlabs_go_bitfield.Bitvector64 `protobuf:"bytes,4,opt,name=committee_bits,json=committeeBits,proto3" json:"committee_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector64" ssz-size:"8"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + CommitteeIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex `protobuf:"varint,2,opt,name=committee_index,json=committeeIndex,proto3" json:"committee_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"` + BeaconBlockRoot []byte `protobuf:"bytes,3,opt,name=beacon_block_root,json=beaconBlockRoot,proto3" json:"beacon_block_root,omitempty" ssz-size:"32"` + Source *Checkpoint `protobuf:"bytes,4,opt,name=source,proto3" json:"source,omitempty"` + Target *Checkpoint `protobuf:"bytes,5,opt,name=target,proto3" json:"target,omitempty"` } -func (x *AttestationElectra) Reset() { - *x = AttestationElectra{} +func (x *AttestationData) Reset() { + *x = AttestationData{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[1] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *AttestationElectra) String() string { +func (x *AttestationData) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AttestationElectra) ProtoMessage() {} +func (*AttestationData) ProtoMessage() {} -func (x *AttestationElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[1] +func (x *AttestationData) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -125,66 +244,72 @@ func (x *AttestationElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use AttestationElectra.ProtoReflect.Descriptor instead. -func (*AttestationElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{1} +// Deprecated: Use AttestationData.ProtoReflect.Descriptor instead. +func (*AttestationData) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{3} } -func (x *AttestationElectra) GetAggregationBits() github_com_prysmaticlabs_go_bitfield.Bitlist { +func (x *AttestationData) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { - return x.AggregationBits + return x.Slot } - return github_com_prysmaticlabs_go_bitfield.Bitlist(nil) + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) } -func (x *AttestationElectra) GetData() *AttestationData { +func (x *AttestationData) GetCommitteeIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex { if x != nil { - return x.Data + return x.CommitteeIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex(0) +} + +func (x *AttestationData) GetBeaconBlockRoot() []byte { + if x != nil { + return x.BeaconBlockRoot } return nil } -func (x *AttestationElectra) GetSignature() []byte { +func (x *AttestationData) GetSource() *Checkpoint { if x != nil { - return x.Signature + return x.Source } return nil } -func (x *AttestationElectra) GetCommitteeBits() github_com_prysmaticlabs_go_bitfield.Bitvector64 { +func (x *AttestationData) GetTarget() *Checkpoint { if x != nil { - return x.CommitteeBits + return x.Target } - return github_com_prysmaticlabs_go_bitfield.Bitvector64(nil) + return nil } -type AggregateAttestationAndProof struct { +type Checkpoint struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AggregatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=aggregator_index,json=aggregatorIndex,proto3" json:"aggregator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - Aggregate *Attestation `protobuf:"bytes,3,opt,name=aggregate,proto3" json:"aggregate,omitempty"` - SelectionProof []byte `protobuf:"bytes,2,opt,name=selection_proof,json=selectionProof,proto3" json:"selection_proof,omitempty" ssz-size:"96"` + Epoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"` + Root []byte `protobuf:"bytes,2,opt,name=root,proto3" json:"root,omitempty" ssz-size:"32"` } -func (x *AggregateAttestationAndProof) Reset() { - *x = AggregateAttestationAndProof{} +func (x *Checkpoint) Reset() { + *x = Checkpoint{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *AggregateAttestationAndProof) String() string { +func (x *Checkpoint) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AggregateAttestationAndProof) ProtoMessage() {} +func (*Checkpoint) ProtoMessage() {} -func (x *AggregateAttestationAndProof) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2] +func (x *Checkpoint) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -195,28 +320,76 @@ func (x *AggregateAttestationAndProof) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use AggregateAttestationAndProof.ProtoReflect.Descriptor instead. -func (*AggregateAttestationAndProof) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{2} +// Deprecated: Use Checkpoint.ProtoReflect.Descriptor instead. +func (*Checkpoint) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{4} } -func (x *AggregateAttestationAndProof) GetAggregatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { +func (x *Checkpoint) GetEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch { if x != nil { - return x.AggregatorIndex + return x.Epoch } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) } -func (x *AggregateAttestationAndProof) GetAggregate() *Attestation { +func (x *Checkpoint) GetRoot() []byte { if x != nil { - return x.Aggregate + return x.Root } return nil } -func (x *AggregateAttestationAndProof) GetSelectionProof() []byte { +type SignedAggregateAttestationAndProofElectra struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message *AggregateAttestationAndProofElectra `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *SignedAggregateAttestationAndProofElectra) Reset() { + *x = SignedAggregateAttestationAndProofElectra{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedAggregateAttestationAndProofElectra) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedAggregateAttestationAndProofElectra) ProtoMessage() {} + +func (x *SignedAggregateAttestationAndProofElectra) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedAggregateAttestationAndProofElectra.ProtoReflect.Descriptor instead. +func (*SignedAggregateAttestationAndProofElectra) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{5} +} + +func (x *SignedAggregateAttestationAndProofElectra) GetMessage() *AggregateAttestationAndProofElectra { + if x != nil { + return x.Message + } + return nil +} + +func (x *SignedAggregateAttestationAndProofElectra) GetSignature() []byte { if x != nil { - return x.SelectionProof + return x.Signature } return nil } @@ -227,14 +400,14 @@ type AggregateAttestationAndProofElectra struct { unknownFields protoimpl.UnknownFields AggregatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=aggregator_index,json=aggregatorIndex,proto3" json:"aggregator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - Aggregate *AttestationElectra `protobuf:"bytes,3,opt,name=aggregate,proto3" json:"aggregate,omitempty"` - SelectionProof []byte `protobuf:"bytes,2,opt,name=selection_proof,json=selectionProof,proto3" json:"selection_proof,omitempty" ssz-size:"96"` + Aggregate *AttestationElectra `protobuf:"bytes,2,opt,name=aggregate,proto3" json:"aggregate,omitempty"` + SelectionProof []byte `protobuf:"bytes,3,opt,name=selection_proof,json=selectionProof,proto3" json:"selection_proof,omitempty" ssz-size:"96"` } func (x *AggregateAttestationAndProofElectra) Reset() { *x = AggregateAttestationAndProofElectra{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -247,7 +420,7 @@ func (x *AggregateAttestationAndProofElectra) String() string { func (*AggregateAttestationAndProofElectra) ProtoMessage() {} func (x *AggregateAttestationAndProofElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -260,7 +433,7 @@ func (x *AggregateAttestationAndProofElectra) ProtoReflect() protoreflect.Messag // Deprecated: Use AggregateAttestationAndProofElectra.ProtoReflect.Descriptor instead. func (*AggregateAttestationAndProofElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{3} + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{6} } func (x *AggregateAttestationAndProofElectra) GetAggregatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { @@ -284,32 +457,34 @@ func (x *AggregateAttestationAndProofElectra) GetSelectionProof() []byte { return nil } -type SignedAggregateAttestationAndProof struct { +type AttestationElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *AggregateAttestationAndProof `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + AggregationBits github_com_prysmaticlabs_go_bitfield.Bitlist `protobuf:"bytes,1,opt,name=aggregation_bits,json=aggregationBits,proto3" json:"aggregation_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitlist" ssz-max:"131072"` + Data *AttestationData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + CommitteeBits github_com_prysmaticlabs_go_bitfield.Bitvector64 `protobuf:"bytes,4,opt,name=committee_bits,json=committeeBits,proto3" json:"committee_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector64" ssz-size:"8"` } -func (x *SignedAggregateAttestationAndProof) Reset() { - *x = SignedAggregateAttestationAndProof{} +func (x *AttestationElectra) Reset() { + *x = AttestationElectra{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *SignedAggregateAttestationAndProof) String() string { +func (x *AttestationElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedAggregateAttestationAndProof) ProtoMessage() {} +func (*AttestationElectra) ProtoMessage() {} -func (x *SignedAggregateAttestationAndProof) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4] +func (x *AttestationElectra) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -320,51 +495,65 @@ func (x *SignedAggregateAttestationAndProof) ProtoReflect() protoreflect.Message return mi.MessageOf(x) } -// Deprecated: Use SignedAggregateAttestationAndProof.ProtoReflect.Descriptor instead. -func (*SignedAggregateAttestationAndProof) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{4} +// Deprecated: Use AttestationElectra.ProtoReflect.Descriptor instead. +func (*AttestationElectra) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{7} } -func (x *SignedAggregateAttestationAndProof) GetMessage() *AggregateAttestationAndProof { +func (x *AttestationElectra) GetAggregationBits() github_com_prysmaticlabs_go_bitfield.Bitlist { if x != nil { - return x.Message + return x.AggregationBits + } + return github_com_prysmaticlabs_go_bitfield.Bitlist(nil) +} + +func (x *AttestationElectra) GetData() *AttestationData { + if x != nil { + return x.Data } return nil } -func (x *SignedAggregateAttestationAndProof) GetSignature() []byte { +func (x *AttestationElectra) GetSignature() []byte { if x != nil { return x.Signature } return nil } -type SignedAggregateAttestationAndProofElectra struct { +func (x *AttestationElectra) GetCommitteeBits() github_com_prysmaticlabs_go_bitfield.Bitvector64 { + if x != nil { + return x.CommitteeBits + } + return github_com_prysmaticlabs_go_bitfield.Bitvector64(nil) +} + +type SignedAggregateAttestationAndProofSingle struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *AggregateAttestationAndProofElectra `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Message *AggregateAttestationAndProofSingle `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SignedAggregateAttestationAndProofElectra) Reset() { - *x = SignedAggregateAttestationAndProofElectra{} +func (x *SignedAggregateAttestationAndProofSingle) Reset() { + *x = SignedAggregateAttestationAndProofSingle{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *SignedAggregateAttestationAndProofElectra) String() string { +func (x *SignedAggregateAttestationAndProofSingle) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedAggregateAttestationAndProofElectra) ProtoMessage() {} +func (*SignedAggregateAttestationAndProofSingle) ProtoMessage() {} -func (x *SignedAggregateAttestationAndProofElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[5] +func (x *SignedAggregateAttestationAndProofSingle) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -375,54 +564,52 @@ func (x *SignedAggregateAttestationAndProofElectra) ProtoReflect() protoreflect. return mi.MessageOf(x) } -// Deprecated: Use SignedAggregateAttestationAndProofElectra.ProtoReflect.Descriptor instead. -func (*SignedAggregateAttestationAndProofElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{5} +// Deprecated: Use SignedAggregateAttestationAndProofSingle.ProtoReflect.Descriptor instead. +func (*SignedAggregateAttestationAndProofSingle) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{8} } -func (x *SignedAggregateAttestationAndProofElectra) GetMessage() *AggregateAttestationAndProofElectra { +func (x *SignedAggregateAttestationAndProofSingle) GetMessage() *AggregateAttestationAndProofSingle { if x != nil { return x.Message } return nil } -func (x *SignedAggregateAttestationAndProofElectra) GetSignature() []byte { +func (x *SignedAggregateAttestationAndProofSingle) GetSignature() []byte { if x != nil { return x.Signature } return nil } -type AttestationData struct { +type AggregateAttestationAndProofSingle struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - CommitteeIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex `protobuf:"varint,2,opt,name=committee_index,json=committeeIndex,proto3" json:"committee_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"` - BeaconBlockRoot []byte `protobuf:"bytes,3,opt,name=beacon_block_root,json=beaconBlockRoot,proto3" json:"beacon_block_root,omitempty" ssz-size:"32"` - Source *Checkpoint `protobuf:"bytes,4,opt,name=source,proto3" json:"source,omitempty"` - Target *Checkpoint `protobuf:"bytes,5,opt,name=target,proto3" json:"target,omitempty"` + AggregatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=aggregator_index,json=aggregatorIndex,proto3" json:"aggregator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + Aggregate *SingleAttestation `protobuf:"bytes,3,opt,name=aggregate,proto3" json:"aggregate,omitempty"` + SelectionProof []byte `protobuf:"bytes,2,opt,name=selection_proof,json=selectionProof,proto3" json:"selection_proof,omitempty" ssz-size:"96"` } -func (x *AttestationData) Reset() { - *x = AttestationData{} +func (x *AggregateAttestationAndProofSingle) Reset() { + *x = AggregateAttestationAndProofSingle{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *AttestationData) String() string { +func (x *AggregateAttestationAndProofSingle) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AttestationData) ProtoMessage() {} +func (*AggregateAttestationAndProofSingle) ProtoMessage() {} -func (x *AttestationData) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6] +func (x *AggregateAttestationAndProofSingle) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -433,72 +620,60 @@ func (x *AttestationData) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use AttestationData.ProtoReflect.Descriptor instead. -func (*AttestationData) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{6} -} - -func (x *AttestationData) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *AttestationData) GetCommitteeIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex { - if x != nil { - return x.CommitteeIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex(0) +// Deprecated: Use AggregateAttestationAndProofSingle.ProtoReflect.Descriptor instead. +func (*AggregateAttestationAndProofSingle) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{9} } -func (x *AttestationData) GetBeaconBlockRoot() []byte { +func (x *AggregateAttestationAndProofSingle) GetAggregatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { - return x.BeaconBlockRoot + return x.AggregatorIndex } - return nil + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) } -func (x *AttestationData) GetSource() *Checkpoint { +func (x *AggregateAttestationAndProofSingle) GetAggregate() *SingleAttestation { if x != nil { - return x.Source + return x.Aggregate } return nil } -func (x *AttestationData) GetTarget() *Checkpoint { +func (x *AggregateAttestationAndProofSingle) GetSelectionProof() []byte { if x != nil { - return x.Target + return x.SelectionProof } return nil } -type Checkpoint struct { +type SingleAttestation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"` - Root []byte `protobuf:"bytes,2,opt,name=root,proto3" json:"root,omitempty" ssz-size:"32"` + CommitteeId github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex `protobuf:"varint,1,opt,name=committee_id,json=committeeId,proto3" json:"committee_id,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"` + AttesterIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=attester_index,json=attesterIndex,proto3" json:"attester_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + Data *AttestationData `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *Checkpoint) Reset() { - *x = Checkpoint{} +func (x *SingleAttestation) Reset() { + *x = SingleAttestation{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *Checkpoint) String() string { +func (x *SingleAttestation) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Checkpoint) ProtoMessage() {} +func (*SingleAttestation) ProtoMessage() {} -func (x *Checkpoint) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7] +func (x *SingleAttestation) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_attestation_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -509,21 +684,35 @@ func (x *Checkpoint) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Checkpoint.ProtoReflect.Descriptor instead. -func (*Checkpoint) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{7} +// Deprecated: Use SingleAttestation.ProtoReflect.Descriptor instead. +func (*SingleAttestation) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP(), []int{10} } -func (x *Checkpoint) GetEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch { +func (x *SingleAttestation) GetCommitteeId() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex { if x != nil { - return x.Epoch + return x.CommitteeId } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex(0) } -func (x *Checkpoint) GetRoot() []byte { +func (x *SingleAttestation) GetAttesterIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { - return x.Root + return x.AttesterIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *SingleAttestation) GetData() *AttestationData { + if x != nil { + return x.Data + } + return nil +} + +func (x *SingleAttestation) GetSignature() []byte { + if x != nil { + return x.Signature } return nil } @@ -536,21 +725,110 @@ var file_proto_prysm_v1alpha1_attestation_proto_rawDesc = []byte{ 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd4, 0x01, 0x0a, - 0x0b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x63, 0x0a, 0x10, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2c, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x2e, 0x42, 0x69, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, - 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, - 0x73, 0x12, 0x3a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x22, 0xbf, 0x02, 0x0a, 0x12, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x99, 0x01, 0x0a, + 0x22, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x12, 0x4d, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x8d, 0x02, 0x0a, 0x1c, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x7a, 0x0a, 0x10, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, + 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, + 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x40, 0x0a, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0xd4, 0x01, 0x0a, 0x0b, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x63, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, + 0x6c, 0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0f, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x3a, 0x0a, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, + 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, + 0x90, 0x03, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, + 0x61, 0x74, 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, + 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, + 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x78, + 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x39, 0x0a, 0x06, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, + 0x1a, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x22, 0xa7, 0x01, 0x0a, 0x29, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, + 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x54, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45, + 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x9b, 0x02, 0x0a, 0x23, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, + 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x7a, 0x0a, + 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x47, 0x0a, 0x09, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x22, 0xbf, 0x02, 0x0a, 0x12, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x65, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x3a, 0x82, 0xb5, 0x18, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, @@ -570,106 +848,68 @@ var file_proto_prysm_v1alpha1_attestation_proto_rawDesc = []byte{ 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x36, 0x34, 0x8a, 0xb5, 0x18, 0x01, 0x38, 0x52, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x42, 0x69, 0x74, 0x73, 0x22, 0x8d, 0x02, 0x0a, 0x1c, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, - 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x7a, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, - 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x40, 0x0a, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x9b, 0x02, 0x0a, 0x23, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, - 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x7a, 0x0a, - 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, - 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x47, 0x0a, 0x09, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x22, 0x99, 0x01, 0x0a, 0x22, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x4d, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, - 0xa7, 0x01, 0x0a, 0x29, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, - 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x54, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x90, 0x03, 0x0a, 0x0f, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x59, 0x0a, - 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, - 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x65, 0x42, 0x69, 0x74, 0x73, 0x22, 0xa5, 0x01, 0x0a, 0x28, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x53, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x12, 0x53, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x99, 0x02, + 0x0a, 0x22, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x53, 0x69, + 0x6e, 0x67, 0x6c, 0x65, 0x12, 0x7a, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, + 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, + 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x46, 0x0a, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0xe1, 0x02, 0x0a, 0x11, 0x53, 0x69, + 0x6e, 0x67, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x72, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x64, 0x12, 0x76, 0x0a, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, + 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, - 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x78, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x39, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x39, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x86, 0x01, 0x0a, - 0x0a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x04, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x42, 0x10, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, - 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3a, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x9b, 0x01, + 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, + 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -684,31 +924,37 @@ func file_proto_prysm_v1alpha1_attestation_proto_rawDescGZIP() []byte { return file_proto_prysm_v1alpha1_attestation_proto_rawDescData } -var file_proto_prysm_v1alpha1_attestation_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_proto_prysm_v1alpha1_attestation_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_proto_prysm_v1alpha1_attestation_proto_goTypes = []interface{}{ - (*Attestation)(nil), // 0: ethereum.eth.v1alpha1.Attestation - (*AttestationElectra)(nil), // 1: ethereum.eth.v1alpha1.AttestationElectra - (*AggregateAttestationAndProof)(nil), // 2: ethereum.eth.v1alpha1.AggregateAttestationAndProof - (*AggregateAttestationAndProofElectra)(nil), // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - (*SignedAggregateAttestationAndProof)(nil), // 4: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof + (*SignedAggregateAttestationAndProof)(nil), // 0: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof + (*AggregateAttestationAndProof)(nil), // 1: ethereum.eth.v1alpha1.AggregateAttestationAndProof + (*Attestation)(nil), // 2: ethereum.eth.v1alpha1.Attestation + (*AttestationData)(nil), // 3: ethereum.eth.v1alpha1.AttestationData + (*Checkpoint)(nil), // 4: ethereum.eth.v1alpha1.Checkpoint (*SignedAggregateAttestationAndProofElectra)(nil), // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra - (*AttestationData)(nil), // 6: ethereum.eth.v1alpha1.AttestationData - (*Checkpoint)(nil), // 7: ethereum.eth.v1alpha1.Checkpoint + (*AggregateAttestationAndProofElectra)(nil), // 6: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + (*AttestationElectra)(nil), // 7: ethereum.eth.v1alpha1.AttestationElectra + (*SignedAggregateAttestationAndProofSingle)(nil), // 8: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofSingle + (*AggregateAttestationAndProofSingle)(nil), // 9: ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle + (*SingleAttestation)(nil), // 10: ethereum.eth.v1alpha1.SingleAttestation } var file_proto_prysm_v1alpha1_attestation_proto_depIdxs = []int32{ - 6, // 0: ethereum.eth.v1alpha1.Attestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 6, // 1: ethereum.eth.v1alpha1.AttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 0, // 2: ethereum.eth.v1alpha1.AggregateAttestationAndProof.aggregate:type_name -> ethereum.eth.v1alpha1.Attestation - 1, // 3: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra.aggregate:type_name -> ethereum.eth.v1alpha1.AttestationElectra - 2, // 4: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof - 3, // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - 7, // 6: ethereum.eth.v1alpha1.AttestationData.source:type_name -> ethereum.eth.v1alpha1.Checkpoint - 7, // 7: ethereum.eth.v1alpha1.AttestationData.target:type_name -> ethereum.eth.v1alpha1.Checkpoint - 8, // [8:8] is the sub-list for method output_type - 8, // [8:8] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 1, // 0: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof + 2, // 1: ethereum.eth.v1alpha1.AggregateAttestationAndProof.aggregate:type_name -> ethereum.eth.v1alpha1.Attestation + 3, // 2: ethereum.eth.v1alpha1.Attestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 4, // 3: ethereum.eth.v1alpha1.AttestationData.source:type_name -> ethereum.eth.v1alpha1.Checkpoint + 4, // 4: ethereum.eth.v1alpha1.AttestationData.target:type_name -> ethereum.eth.v1alpha1.Checkpoint + 6, // 5: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + 7, // 6: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra.aggregate:type_name -> ethereum.eth.v1alpha1.AttestationElectra + 3, // 7: ethereum.eth.v1alpha1.AttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 9, // 8: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofSingle.message:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle + 10, // 9: ethereum.eth.v1alpha1.AggregateAttestationAndProofSingle.aggregate:type_name -> ethereum.eth.v1alpha1.SingleAttestation + 3, // 10: ethereum.eth.v1alpha1.SingleAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_proto_prysm_v1alpha1_attestation_proto_init() } @@ -718,7 +964,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } if !protoimpl.UnsafeEnabled { file_proto_prysm_v1alpha1_attestation_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Attestation); i { + switch v := v.(*SignedAggregateAttestationAndProof); i { case 0: return &v.state case 1: @@ -730,7 +976,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttestationElectra); i { + switch v := v.(*AggregateAttestationAndProof); i { case 0: return &v.state case 1: @@ -742,7 +988,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AggregateAttestationAndProof); i { + switch v := v.(*Attestation); i { case 0: return &v.state case 1: @@ -754,7 +1000,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AggregateAttestationAndProofElectra); i { + switch v := v.(*AttestationData); i { case 0: return &v.state case 1: @@ -766,7 +1012,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedAggregateAttestationAndProof); i { + switch v := v.(*Checkpoint); i { case 0: return &v.state case 1: @@ -790,7 +1036,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttestationData); i { + switch v := v.(*AggregateAttestationAndProofElectra); i { case 0: return &v.state case 1: @@ -802,7 +1048,43 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { } } file_proto_prysm_v1alpha1_attestation_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Checkpoint); i { + switch v := v.(*AttestationElectra); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_attestation_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignedAggregateAttestationAndProofSingle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_attestation_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AggregateAttestationAndProofSingle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_attestation_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SingleAttestation); i { case 0: return &v.state case 1: @@ -820,7 +1102,7 @@ func file_proto_prysm_v1alpha1_attestation_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_prysm_v1alpha1_attestation_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/prysm/v1alpha1/attestation.pb.gw.go b/proto/prysm/v1alpha1/attestation.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/attestation.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/attestation.proto b/proto/prysm/v1alpha1/attestation.proto index a41a3e685fcc..80b3ac791d94 100644 --- a/proto/prysm/v1alpha1/attestation.proto +++ b/proto/prysm/v1alpha1/attestation.proto @@ -24,96 +24,166 @@ option java_outer_classname = "AttestationProto"; option java_package = "org.ethereum.eth.v1alpha1"; option php_namespace = "Ethereum\\Eth\\v1alpha1"; -message Attestation { - // A bitfield representation of validator indices that have voted exactly - // the same vote and have been aggregated into this attestation. - bytes aggregation_bits = 1 [(ethereum.eth.ext.ssz_max) = "2048", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitlist"]; - - AttestationData data = 2; - - // 96 byte BLS aggregate signature. - bytes signature = 3 [(ethereum.eth.ext.ssz_size) = "96"]; -} - -message AttestationElectra { - // A bitfield representation of validator indices that have voted exactly - // the same vote and have been aggregated into this attestation. - bytes aggregation_bits = 1 [(ethereum.eth.ext.ssz_max) = "max_attesting_indices.size", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitlist"]; +// ---------------------------------------------------------------------------- +// Phase0, Altair, Bellatrix, Capella & Deneb +// ---------------------------------------------------------------------------- - AttestationData data = 2; - - // 96 byte BLS aggregate signature. - bytes signature = 3 [(ethereum.eth.ext.ssz_size) = "96"]; +message SignedAggregateAttestationAndProof { + // The aggregated attestation and selection proof itself. + AggregateAttestationAndProof message = 1; - // Represents the committee which aggregated attestation belong. - bytes committee_bits = 4 [(ethereum.eth.ext.ssz_size) = "committee_bits.size", (ethereum.eth.ext.cast_type) = "committee_bits.type"]; + // 96 byte BLS aggregate signature signed by the aggregator over the message. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message AggregateAttestationAndProof { - // The aggregator index that submitted this aggregated attestation and proof. - uint64 aggregator_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // The aggregator index that submitted this aggregated attestation and proof. + uint64 aggregator_index = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // The aggregated attestation that was submitted. + Attestation aggregate = 3; + + // 96 byte selection proof signed by the aggregator, which is the signature of + // the slot to aggregate. + bytes selection_proof = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; +} - // The aggregated attestation that was submitted. - Attestation aggregate = 3; +message Attestation { + // A bitfield representation of validator indices that have voted exactly + // the same vote and have been aggregated into this attestation. + bytes aggregation_bits = 1 [ + (ethereum.eth.ext.ssz_max) = "2048", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitlist" + ]; + + AttestationData data = 2; + + // 96 byte BLS aggregate signature. + bytes signature = 3 [ (ethereum.eth.ext.ssz_size) = "96" ]; +} - // 96 byte selection proof signed by the aggregator, which is the signature of the slot to aggregate. - bytes selection_proof = 2 [(ethereum.eth.ext.ssz_size) = "96"]; +message AttestationData { + // Attestation data includes information on Casper the Friendly Finality + // Gadget's votes See: https://arxiv.org/pdf/1710.09437.pdf + + // Slot of the attestation attesting for. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // The committee index that submitted this attestation. + uint64 committee_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.CommitteeIndex" ]; + + // 32 byte root of the LMD GHOST block vote. + bytes beacon_block_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // The most recent justified checkpoint in the beacon state + Checkpoint source = 4; + + // The checkpoint attempting to be justified for the current epoch and its + // epoch boundary block + Checkpoint target = 5; } -message AggregateAttestationAndProofElectra { - // The aggregator index that submitted this aggregated attestation and proof. - uint64 aggregator_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; +message Checkpoint { + // A checkpoint is every epoch's first slot. The goal of Casper FFG + // is to link the check points together for justification and finalization. - // The aggregated attestation that was submitted. - AttestationElectra aggregate = 3; + // Epoch the checkpoint references. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; - // 96 byte selection proof signed by the aggregator, which is the signature of the slot to aggregate. - bytes selection_proof = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // Block root of the checkpoint references. + bytes root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; } -message SignedAggregateAttestationAndProof { - // The aggregated attestation and selection proof itself. - AggregateAttestationAndProof message = 1; - - // 96 byte BLS aggregate signature signed by the aggregator over the message. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- message SignedAggregateAttestationAndProofElectra { - // The aggregated attestation and selection proof itself. - AggregateAttestationAndProofElectra message = 1; + // The aggregated attestation and selection proof itself. + AggregateAttestationAndProofElectra message = 1; - // 96 byte BLS aggregate signature signed by the aggregator over the message. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS aggregate signature signed by the aggregator over the message. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message AttestationData { - // Attestation data includes information on Casper the Friendly Finality Gadget's votes - // See: https://arxiv.org/pdf/1710.09437.pdf +message AggregateAttestationAndProofElectra { + // The aggregator index that submitted this aggregated attestation and proof. + uint64 aggregator_index = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; - // Slot of the attestation attesting for. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // The aggregated attestation that was submitted. + AttestationElectra aggregate = 2; - // The committee index that submitted this attestation. - uint64 committee_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; + // 96 byte selection proof signed by the aggregator, which is the signature of the slot to aggregate. + bytes selection_proof = 3 [ (ethereum.eth.ext.ssz_size) = "96" ]; +} - // 32 byte root of the LMD GHOST block vote. - bytes beacon_block_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; +message AttestationElectra { + // A bitfield representation of validator indices that have voted exactly + // the same vote and have been aggregated into this attestation. + bytes aggregation_bits = 1 [ + (ethereum.eth.ext.ssz_max) = "max_attesting_indices.size", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitlist" + ]; + + AttestationData data = 2; + + // 96 byte BLS aggregate signature. + bytes signature = 3 [ (ethereum.eth.ext.ssz_size) = "96" ]; + + // Represents the committee which aggregated attestation belong. + bytes committee_bits = 4 [ + (ethereum.eth.ext.ssz_size) = "committee_bits.size", + (ethereum.eth.ext.cast_type) = "committee_bits.type" + ]; +} - // The most recent justified checkpoint in the beacon state - Checkpoint source = 4; +message SignedAggregateAttestationAndProofSingle { + // The aggregated attestation and selection proof itself. + AggregateAttestationAndProofSingle message = 1; - // The checkpoint attempting to be justified for the current epoch and its epoch boundary block - Checkpoint target = 5; + // 96 byte BLS aggregate signature signed by the aggregator over the message. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message Checkpoint { - // A checkpoint is every epoch's first slot. The goal of Casper FFG - // is to link the check points together for justification and finalization. +message AggregateAttestationAndProofSingle { + // The aggregator index that submitted this aggregated attestation and proof. + uint64 aggregator_index = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; - // Epoch the checkpoint references. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // The aggregated attestation that was submitted. + SingleAttestation aggregate = 3; - // Block root of the checkpoint references. - bytes root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + // 96 byte selection proof signed by the aggregator, which is the signature of + // the slot to aggregate. + bytes selection_proof = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } + +message SingleAttestation { + uint64 committee_id = 1 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.CommitteeIndex" ]; + uint64 attester_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; + AttestationData data = 3; + bytes signature = 4 [ (ethereum.eth.ext.ssz_size) = "96" ]; +} \ No newline at end of file diff --git a/proto/prysm/v1alpha1/attestation/BUILD.bazel b/proto/prysm/v1alpha1/attestation/BUILD.bazel index b1ee168216a5..e8cbbcd73e2a 100644 --- a/proto/prysm/v1alpha1/attestation/BUILD.bazel +++ b/proto/prysm/v1alpha1/attestation/BUILD.bazel @@ -9,17 +9,16 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/signing:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//crypto/bls:go_default_library", "//crypto/hash:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/proto/prysm/v1alpha1/attestation/aggregation/attestations/attestations_test.go b/proto/prysm/v1alpha1/attestation/aggregation/attestations/attestations_test.go index 13d1d277c686..f9b84cccb046 100644 --- a/proto/prysm/v1alpha1/attestation/aggregation/attestations/attestations_test.go +++ b/proto/prysm/v1alpha1/attestation/aggregation/attestations/attestations_test.go @@ -2,6 +2,7 @@ package attestations import ( "io" + "os" "sort" "testing" @@ -19,7 +20,7 @@ import ( func TestMain(m *testing.M) { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(io.Discard) - m.Run() + os.Exit(m.Run()) } func TestAggregateAttestations_AggregatePair(t *testing.T) { diff --git a/proto/prysm/v1alpha1/attestation/attestation_utils.go b/proto/prysm/v1alpha1/attestation/attestation_utils.go index ba9db2872480..863bd380df24 100644 --- a/proto/prysm/v1alpha1/attestation/attestation_utils.go +++ b/proto/prysm/v1alpha1/attestation/attestation_utils.go @@ -15,9 +15,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" ) // ConvertToIndexed converts attestation to (almost) indexed-verifiable form. @@ -39,7 +39,7 @@ import ( // data=attestation.data, // signature=attestation.signature, // ) -func ConvertToIndexed(ctx context.Context, attestation ethpb.Att, committees ...[]primitives.ValidatorIndex) (ethpb.IndexedAtt, error) { +func ConvertToIndexed(_ context.Context, attestation ethpb.Att, committees ...[]primitives.ValidatorIndex) (ethpb.IndexedAtt, error) { attIndices, err := AttestingIndices(attestation, committees...) if err != nil { return nil, err @@ -65,7 +65,7 @@ func ConvertToIndexed(ctx context.Context, attestation ethpb.Att, committees ... // AttestingIndices returns the attesting participants indices from the attestation data. // Committees are provided as an argument rather than an imported implementation from the spec definition. -// Having committees as an argument allows for re-use of beacon committees when possible. +// Having committees as an argument allows for reuse of beacon committees when possible. // // Spec pseudocode definition (Electra version): // @@ -113,6 +113,9 @@ func AttestingIndices(att ethpb.Att, committees ...[]primitives.ValidatorIndex) committeeAttesters = append(committeeAttesters, uint64(vi)) } } + if len(committeeAttesters) == 0 { + return nil, fmt.Errorf("no attesting indices found in committee %v", c) + } attesters = append(attesters, committeeAttesters...) committeeOffset += len(c) } @@ -185,12 +188,10 @@ func IsValidAttestationIndices(ctx context.Context, indexedAttestation ethpb.Ind _, span := trace.StartSpan(ctx, "attestationutil.IsValidAttestationIndices") defer span.End() - if indexedAttestation == nil || - indexedAttestation.GetData() == nil || - indexedAttestation.GetData().Target == nil || - indexedAttestation.GetAttestingIndices() == nil { + if indexedAttestation == nil || indexedAttestation.IsNil() || indexedAttestation.GetData().Target == nil || indexedAttestation.GetData().Source == nil { return errors.New("nil or missing indexed attestation data") } + indices := indexedAttestation.GetAttestingIndices() if len(indices) == 0 { return errors.New("expected non-empty attesting indices") @@ -253,7 +254,7 @@ func CheckPointIsEqual(checkPt1, checkPt2 *ethpb.Checkpoint) bool { // attestingIndicesPhase0 returns the attesting participants indices from the attestation data. // Committees are provided as an argument rather than an imported implementation from the spec definition. -// Having committees as an argument allows for re-use of beacon committees when possible. +// Having committees as an argument allows for reuse of beacon committees when possible. // // Spec pseudocode definition (Phase0 version): // diff --git a/proto/prysm/v1alpha1/attestation/attestation_utils_test.go b/proto/prysm/v1alpha1/attestation/attestation_utils_test.go index 62d797f3adc2..a7b82632540b 100644 --- a/proto/prysm/v1alpha1/attestation/attestation_utils_test.go +++ b/proto/prysm/v1alpha1/attestation/attestation_utils_test.go @@ -106,10 +106,11 @@ func TestIsValidAttestationIndices(t *testing.T) { att: ð.IndexedAttestation{ Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, - wantedErr: "nil or missing indexed attestation data", + wantedErr: "expected non-empty attesting indices", }, { name: "Indices should be non-empty", @@ -117,6 +118,7 @@ func TestIsValidAttestationIndices(t *testing.T) { AttestingIndices: []uint64{}, Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, @@ -128,6 +130,7 @@ func TestIsValidAttestationIndices(t *testing.T) { AttestingIndices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+1), Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, @@ -139,6 +142,7 @@ func TestIsValidAttestationIndices(t *testing.T) { AttestingIndices: []uint64{3, 2, 1}, Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, @@ -150,6 +154,7 @@ func TestIsValidAttestationIndices(t *testing.T) { AttestingIndices: []uint64{1, 2, 3}, Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, @@ -160,6 +165,7 @@ func TestIsValidAttestationIndices(t *testing.T) { AttestingIndices: []uint64{1, 2}, Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, @@ -170,6 +176,7 @@ func TestIsValidAttestationIndices(t *testing.T) { AttestingIndices: []uint64{1}, Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, @@ -180,6 +187,7 @@ func TestIsValidAttestationIndices(t *testing.T) { AttestingIndices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee*params.BeaconConfig().MaxCommitteesPerSlot+1), Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, @@ -218,6 +226,7 @@ func BenchmarkIsValidAttestationIndices(b *testing.B) { AttestingIndices: indices, Data: ð.AttestationData{ Target: ð.Checkpoint{}, + Source: ð.Checkpoint{}, }, Signature: make([]byte, fieldparams.BLSSignatureLength), } diff --git a/proto/prysm/v1alpha1/attestation/id.go b/proto/prysm/v1alpha1/attestation/id.go index 2d98fbbb7e65..708db0ba0d9d 100644 --- a/proto/prysm/v1alpha1/attestation/id.go +++ b/proto/prysm/v1alpha1/attestation/id.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/crypto/hash" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" @@ -22,12 +21,12 @@ const ( ) // Id represents an attestation ID. Its uniqueness depends on the IdSource provided when constructing the Id. -type Id [33]byte +type Id [32]byte // NewId -- func NewId(att ethpb.Att, source IdSource) (Id, error) { - if err := helpers.ValidateNilAttestation(att); err != nil { - return Id{}, err + if att.IsNil() { + return Id{}, errors.New("nil attestation") } if att.Version() < 0 || att.Version() > 255 { return Id{}, errors.New("attestation version must be between 0 and 255") @@ -42,7 +41,7 @@ func NewId(att ethpb.Att, source IdSource) (Id, error) { if err != nil { return Id{}, err } - copy(id[1:], h[:]) + copy(id[1:], h[1:]) return id, nil case Data: dataHash, err := att.GetData().HashTreeRoot() @@ -61,7 +60,7 @@ func NewId(att ethpb.Att, source IdSource) (Id, error) { } h = hash.Hash(append(dataHash[:], []byte(strings.Join(stringCommitteeIndices, ","))...)) } - copy(id[1:], h[:]) + copy(id[1:], h[1:]) return id, nil default: return Id{}, errors.New("invalid source requested") diff --git a/proto/prysm/v1alpha1/beacon_block.go b/proto/prysm/v1alpha1/beacon_block.go index ddf48f5c2c5d..74e60917f182 100644 --- a/proto/prysm/v1alpha1/beacon_block.go +++ b/proto/prysm/v1alpha1/beacon_block.go @@ -1,6 +1,13 @@ package eth -import "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" +import ( + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" +) + +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- // Copy -- func (sigBlock *SignedBeaconBlock) Copy() *SignedBeaconBlock { @@ -44,6 +51,107 @@ func (body *BeaconBlockBody) Copy() *BeaconBlockBody { } } +// Copy -- +func (data *Eth1Data) Copy() *Eth1Data { + if data == nil { + return nil + } + return &Eth1Data{ + DepositRoot: bytesutil.SafeCopyBytes(data.DepositRoot), + DepositCount: data.DepositCount, + BlockHash: bytesutil.SafeCopyBytes(data.BlockHash), + } +} + +// Copy -- +func (slashing *ProposerSlashing) Copy() *ProposerSlashing { + if slashing == nil { + return nil + } + return &ProposerSlashing{ + Header_1: slashing.Header_1.Copy(), + Header_2: slashing.Header_2.Copy(), + } +} + +// Copy -- +func (header *SignedBeaconBlockHeader) Copy() *SignedBeaconBlockHeader { + if header == nil { + return nil + } + return &SignedBeaconBlockHeader{ + Header: header.Header.Copy(), + Signature: bytesutil.SafeCopyBytes(header.Signature), + } +} + +// Copy -- +func (header *BeaconBlockHeader) Copy() *BeaconBlockHeader { + if header == nil { + return nil + } + parentRoot := bytesutil.SafeCopyBytes(header.ParentRoot) + stateRoot := bytesutil.SafeCopyBytes(header.StateRoot) + bodyRoot := bytesutil.SafeCopyBytes(header.BodyRoot) + return &BeaconBlockHeader{ + Slot: header.Slot, + ProposerIndex: header.ProposerIndex, + ParentRoot: parentRoot, + StateRoot: stateRoot, + BodyRoot: bodyRoot, + } +} + +// Copy -- +func (deposit *Deposit) Copy() *Deposit { + if deposit == nil { + return nil + } + return &Deposit{ + Proof: bytesutil.SafeCopy2dBytes(deposit.Proof), + Data: deposit.Data.Copy(), + } +} + +// Copy -- +func (depData *Deposit_Data) Copy() *Deposit_Data { + if depData == nil { + return nil + } + return &Deposit_Data{ + PublicKey: bytesutil.SafeCopyBytes(depData.PublicKey), + WithdrawalCredentials: bytesutil.SafeCopyBytes(depData.WithdrawalCredentials), + Amount: depData.Amount, + Signature: bytesutil.SafeCopyBytes(depData.Signature), + } +} + +// Copy -- +func (exit *SignedVoluntaryExit) Copy() *SignedVoluntaryExit { + if exit == nil { + return nil + } + return &SignedVoluntaryExit{ + Exit: exit.Exit.Copy(), + Signature: bytesutil.SafeCopyBytes(exit.Signature), + } +} + +// Copy -- +func (exit *VoluntaryExit) Copy() *VoluntaryExit { + if exit == nil { + return nil + } + return &VoluntaryExit{ + Epoch: exit.Epoch, + ValidatorIndex: exit.ValidatorIndex, + } +} + +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- + // Copy -- func (sigBlock *SignedBeaconBlockAltair) Copy() *SignedBeaconBlockAltair { if sigBlock == nil { @@ -87,6 +195,32 @@ func (body *BeaconBlockBodyAltair) Copy() *BeaconBlockBodyAltair { } } +// Copy -- +func (a *SyncAggregate) Copy() *SyncAggregate { + if a == nil { + return nil + } + return &SyncAggregate{ + SyncCommitteeBits: bytesutil.SafeCopyBytes(a.SyncCommitteeBits), + SyncCommitteeSignature: bytesutil.SafeCopyBytes(a.SyncCommitteeSignature), + } +} + +// Copy -- +func (summary *HistoricalSummary) Copy() *HistoricalSummary { + if summary == nil { + return nil + } + return &HistoricalSummary{ + BlockSummaryRoot: bytesutil.SafeCopyBytes(summary.BlockSummaryRoot), + StateSummaryRoot: bytesutil.SafeCopyBytes(summary.StateSummaryRoot), + } +} + +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + // Copy -- func (sigBlock *SignedBeaconBlockBellatrix) Copy() *SignedBeaconBlockBellatrix { if sigBlock == nil { @@ -131,6 +265,54 @@ func (body *BeaconBlockBodyBellatrix) Copy() *BeaconBlockBodyBellatrix { } } +// Copy -- +func (sigBlock *SignedBlindedBeaconBlockBellatrix) Copy() *SignedBlindedBeaconBlockBellatrix { + if sigBlock == nil { + return nil + } + return &SignedBlindedBeaconBlockBellatrix{ + Block: sigBlock.Block.Copy(), + Signature: bytesutil.SafeCopyBytes(sigBlock.Signature), + } +} + +// Copy -- +func (block *BlindedBeaconBlockBellatrix) Copy() *BlindedBeaconBlockBellatrix { + if block == nil { + return nil + } + return &BlindedBeaconBlockBellatrix{ + Slot: block.Slot, + ProposerIndex: block.ProposerIndex, + ParentRoot: bytesutil.SafeCopyBytes(block.ParentRoot), + StateRoot: bytesutil.SafeCopyBytes(block.StateRoot), + Body: block.Body.Copy(), + } +} + +// Copy -- +func (body *BlindedBeaconBlockBodyBellatrix) Copy() *BlindedBeaconBlockBodyBellatrix { + if body == nil { + return nil + } + return &BlindedBeaconBlockBodyBellatrix{ + RandaoReveal: bytesutil.SafeCopyBytes(body.RandaoReveal), + Eth1Data: body.Eth1Data.Copy(), + Graffiti: bytesutil.SafeCopyBytes(body.Graffiti), + ProposerSlashings: CopySlice(body.ProposerSlashings), + AttesterSlashings: CopySlice(body.AttesterSlashings), + Attestations: CopySlice(body.Attestations), + Deposits: CopySlice(body.Deposits), + VoluntaryExits: CopySlice(body.VoluntaryExits), + SyncAggregate: body.SyncAggregate.Copy(), + ExecutionPayloadHeader: body.ExecutionPayloadHeader.Copy(), + } +} + +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + // Copy -- func (sigBlock *SignedBeaconBlockCapella) Copy() *SignedBeaconBlockCapella { if sigBlock == nil { @@ -222,68 +404,49 @@ func (body *BlindedBeaconBlockBodyCapella) Copy() *BlindedBeaconBlockBodyCapella } // Copy -- -func (sigBlock *SignedBlindedBeaconBlockDeneb) Copy() *SignedBlindedBeaconBlockDeneb { - if sigBlock == nil { +func (change *SignedBLSToExecutionChange) Copy() *SignedBLSToExecutionChange { + if change == nil { return nil } - return &SignedBlindedBeaconBlockDeneb{ - Message: sigBlock.Message.Copy(), - Signature: bytesutil.SafeCopyBytes(sigBlock.Signature), + return &SignedBLSToExecutionChange{ + Message: change.Message.Copy(), + Signature: bytesutil.SafeCopyBytes(change.Signature), } } // Copy -- -func (block *BlindedBeaconBlockDeneb) Copy() *BlindedBeaconBlockDeneb { - if block == nil { +func (change *BLSToExecutionChange) Copy() *BLSToExecutionChange { + if change == nil { return nil } - return &BlindedBeaconBlockDeneb{ - Slot: block.Slot, - ProposerIndex: block.ProposerIndex, - ParentRoot: bytesutil.SafeCopyBytes(block.ParentRoot), - StateRoot: bytesutil.SafeCopyBytes(block.StateRoot), - Body: block.Body.Copy(), + return &BLSToExecutionChange{ + ValidatorIndex: change.ValidatorIndex, + FromBlsPubkey: bytesutil.SafeCopyBytes(change.FromBlsPubkey), + ToExecutionAddress: bytesutil.SafeCopyBytes(change.ToExecutionAddress), } } -// Copy -- -func (body *BlindedBeaconBlockBodyDeneb) Copy() *BlindedBeaconBlockBodyDeneb { - if body == nil { - return nil - } - return &BlindedBeaconBlockBodyDeneb{ - RandaoReveal: bytesutil.SafeCopyBytes(body.RandaoReveal), - Eth1Data: body.Eth1Data.Copy(), - Graffiti: bytesutil.SafeCopyBytes(body.Graffiti), - ProposerSlashings: CopySlice(body.ProposerSlashings), - AttesterSlashings: CopySlice(body.AttesterSlashings), - Attestations: CopySlice(body.Attestations), - Deposits: CopySlice(body.Deposits), - VoluntaryExits: CopySlice(body.VoluntaryExits), - SyncAggregate: body.SyncAggregate.Copy(), - ExecutionPayloadHeader: body.ExecutionPayloadHeader.Copy(), - BlsToExecutionChanges: CopySlice(body.BlsToExecutionChanges), - BlobKzgCommitments: CopyBlobKZGs(body.BlobKzgCommitments), - } -} +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- // Copy -- -func (sigBlock *SignedBlindedBeaconBlockElectra) Copy() *SignedBlindedBeaconBlockElectra { +func (sigBlock *SignedBlindedBeaconBlockDeneb) Copy() *SignedBlindedBeaconBlockDeneb { if sigBlock == nil { return nil } - return &SignedBlindedBeaconBlockElectra{ + return &SignedBlindedBeaconBlockDeneb{ Message: sigBlock.Message.Copy(), Signature: bytesutil.SafeCopyBytes(sigBlock.Signature), } } // Copy -- -func (block *BlindedBeaconBlockElectra) Copy() *BlindedBeaconBlockElectra { +func (block *BlindedBeaconBlockDeneb) Copy() *BlindedBeaconBlockDeneb { if block == nil { return nil } - return &BlindedBeaconBlockElectra{ + return &BlindedBeaconBlockDeneb{ Slot: block.Slot, ProposerIndex: block.ProposerIndex, ParentRoot: bytesutil.SafeCopyBytes(block.ParentRoot), @@ -293,11 +456,11 @@ func (block *BlindedBeaconBlockElectra) Copy() *BlindedBeaconBlockElectra { } // Copy -- -func (body *BlindedBeaconBlockBodyElectra) Copy() *BlindedBeaconBlockBodyElectra { +func (body *BlindedBeaconBlockBodyDeneb) Copy() *BlindedBeaconBlockBodyDeneb { if body == nil { return nil } - return &BlindedBeaconBlockBodyElectra{ + return &BlindedBeaconBlockBodyDeneb{ RandaoReveal: bytesutil.SafeCopyBytes(body.RandaoReveal), Eth1Data: body.Eth1Data.Copy(), Graffiti: bytesutil.SafeCopyBytes(body.Graffiti), @@ -314,22 +477,22 @@ func (body *BlindedBeaconBlockBodyElectra) Copy() *BlindedBeaconBlockBodyElectra } // Copy -- -func (sigBlock *SignedBlindedBeaconBlockBellatrix) Copy() *SignedBlindedBeaconBlockBellatrix { +func (sigBlock *SignedBeaconBlockDeneb) Copy() *SignedBeaconBlockDeneb { if sigBlock == nil { return nil } - return &SignedBlindedBeaconBlockBellatrix{ + return &SignedBeaconBlockDeneb{ Block: sigBlock.Block.Copy(), Signature: bytesutil.SafeCopyBytes(sigBlock.Signature), } } // Copy -- -func (block *BlindedBeaconBlockBellatrix) Copy() *BlindedBeaconBlockBellatrix { +func (block *BeaconBlockDeneb) Copy() *BeaconBlockDeneb { if block == nil { return nil } - return &BlindedBeaconBlockBellatrix{ + return &BeaconBlockDeneb{ Slot: block.Slot, ProposerIndex: block.ProposerIndex, ParentRoot: bytesutil.SafeCopyBytes(block.ParentRoot), @@ -339,21 +502,23 @@ func (block *BlindedBeaconBlockBellatrix) Copy() *BlindedBeaconBlockBellatrix { } // Copy -- -func (body *BlindedBeaconBlockBodyBellatrix) Copy() *BlindedBeaconBlockBodyBellatrix { +func (body *BeaconBlockBodyDeneb) Copy() *BeaconBlockBodyDeneb { if body == nil { return nil } - return &BlindedBeaconBlockBodyBellatrix{ - RandaoReveal: bytesutil.SafeCopyBytes(body.RandaoReveal), - Eth1Data: body.Eth1Data.Copy(), - Graffiti: bytesutil.SafeCopyBytes(body.Graffiti), - ProposerSlashings: CopySlice(body.ProposerSlashings), - AttesterSlashings: CopySlice(body.AttesterSlashings), - Attestations: CopySlice(body.Attestations), - Deposits: CopySlice(body.Deposits), - VoluntaryExits: CopySlice(body.VoluntaryExits), - SyncAggregate: body.SyncAggregate.Copy(), - ExecutionPayloadHeader: body.ExecutionPayloadHeader.Copy(), + return &BeaconBlockBodyDeneb{ + RandaoReveal: bytesutil.SafeCopyBytes(body.RandaoReveal), + Eth1Data: body.Eth1Data.Copy(), + Graffiti: bytesutil.SafeCopyBytes(body.Graffiti), + ProposerSlashings: CopySlice(body.ProposerSlashings), + AttesterSlashings: CopySlice(body.AttesterSlashings), + Attestations: CopySlice(body.Attestations), + Deposits: CopySlice(body.Deposits), + VoluntaryExits: CopySlice(body.VoluntaryExits), + SyncAggregate: body.SyncAggregate.Copy(), + ExecutionPayload: body.ExecutionPayload.Copy(), + BlsToExecutionChanges: CopySlice(body.BlsToExecutionChanges), + BlobKzgCommitments: CopyBlobKZGs(body.BlobKzgCommitments), } } @@ -362,23 +527,27 @@ func CopyBlobKZGs(b [][]byte) [][]byte { return bytesutil.SafeCopy2dBytes(b) } +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + // Copy -- -func (sigBlock *SignedBeaconBlockDeneb) Copy() *SignedBeaconBlockDeneb { +func (sigBlock *SignedBlindedBeaconBlockElectra) Copy() *SignedBlindedBeaconBlockElectra { if sigBlock == nil { return nil } - return &SignedBeaconBlockDeneb{ - Block: sigBlock.Block.Copy(), + return &SignedBlindedBeaconBlockElectra{ + Message: sigBlock.Message.Copy(), Signature: bytesutil.SafeCopyBytes(sigBlock.Signature), } } // Copy -- -func (block *BeaconBlockDeneb) Copy() *BeaconBlockDeneb { +func (block *BlindedBeaconBlockElectra) Copy() *BlindedBeaconBlockElectra { if block == nil { return nil } - return &BeaconBlockDeneb{ + return &BlindedBeaconBlockElectra{ Slot: block.Slot, ProposerIndex: block.ProposerIndex, ParentRoot: bytesutil.SafeCopyBytes(block.ParentRoot), @@ -388,23 +557,24 @@ func (block *BeaconBlockDeneb) Copy() *BeaconBlockDeneb { } // Copy -- -func (body *BeaconBlockBodyDeneb) Copy() *BeaconBlockBodyDeneb { +func (body *BlindedBeaconBlockBodyElectra) Copy() *BlindedBeaconBlockBodyElectra { if body == nil { return nil } - return &BeaconBlockBodyDeneb{ - RandaoReveal: bytesutil.SafeCopyBytes(body.RandaoReveal), - Eth1Data: body.Eth1Data.Copy(), - Graffiti: bytesutil.SafeCopyBytes(body.Graffiti), - ProposerSlashings: CopySlice(body.ProposerSlashings), - AttesterSlashings: CopySlice(body.AttesterSlashings), - Attestations: CopySlice(body.Attestations), - Deposits: CopySlice(body.Deposits), - VoluntaryExits: CopySlice(body.VoluntaryExits), - SyncAggregate: body.SyncAggregate.Copy(), - ExecutionPayload: body.ExecutionPayload.Copy(), - BlsToExecutionChanges: CopySlice(body.BlsToExecutionChanges), - BlobKzgCommitments: CopyBlobKZGs(body.BlobKzgCommitments), + return &BlindedBeaconBlockBodyElectra{ + RandaoReveal: bytesutil.SafeCopyBytes(body.RandaoReveal), + Eth1Data: body.Eth1Data.Copy(), + Graffiti: bytesutil.SafeCopyBytes(body.Graffiti), + ProposerSlashings: CopySlice(body.ProposerSlashings), + AttesterSlashings: CopySlice(body.AttesterSlashings), + Attestations: CopySlice(body.Attestations), + Deposits: CopySlice(body.Deposits), + VoluntaryExits: CopySlice(body.VoluntaryExits), + SyncAggregate: body.SyncAggregate.Copy(), + ExecutionPayloadHeader: body.ExecutionPayloadHeader.Copy(), + BlsToExecutionChanges: CopySlice(body.BlsToExecutionChanges), + BlobKzgCommitments: CopyBlobKZGs(body.BlobKzgCommitments), + ExecutionRequests: CopyExecutionRequests(body.ExecutionRequests), } } @@ -451,158 +621,71 @@ func (body *BeaconBlockBodyElectra) Copy() *BeaconBlockBodyElectra { ExecutionPayload: body.ExecutionPayload.Copy(), BlsToExecutionChanges: CopySlice(body.BlsToExecutionChanges), BlobKzgCommitments: CopyBlobKZGs(body.BlobKzgCommitments), + ExecutionRequests: CopyExecutionRequests(body.ExecutionRequests), } } -// Copy -- -func (data *Eth1Data) Copy() *Eth1Data { - if data == nil { - return nil - } - return &Eth1Data{ - DepositRoot: bytesutil.SafeCopyBytes(data.DepositRoot), - DepositCount: data.DepositCount, - BlockHash: bytesutil.SafeCopyBytes(data.BlockHash), - } -} - -// Copy -- -func (slashing *ProposerSlashing) Copy() *ProposerSlashing { - if slashing == nil { - return nil - } - return &ProposerSlashing{ - Header_1: slashing.Header_1.Copy(), - Header_2: slashing.Header_2.Copy(), - } -} - -// Copy -- -func (header *SignedBeaconBlockHeader) Copy() *SignedBeaconBlockHeader { - if header == nil { - return nil - } - return &SignedBeaconBlockHeader{ - Header: header.Header.Copy(), - Signature: bytesutil.SafeCopyBytes(header.Signature), - } -} - -// Copy -- -func (header *BeaconBlockHeader) Copy() *BeaconBlockHeader { - if header == nil { +// CopyExecutionRequests copies the provided execution requests. +func CopyExecutionRequests(e *enginev1.ExecutionRequests) *enginev1.ExecutionRequests { + if e == nil { return nil } - parentRoot := bytesutil.SafeCopyBytes(header.ParentRoot) - stateRoot := bytesutil.SafeCopyBytes(header.StateRoot) - bodyRoot := bytesutil.SafeCopyBytes(header.BodyRoot) - return &BeaconBlockHeader{ - Slot: header.Slot, - ProposerIndex: header.ProposerIndex, - ParentRoot: parentRoot, - StateRoot: stateRoot, - BodyRoot: bodyRoot, + dr := make([]*enginev1.DepositRequest, len(e.Deposits)) + for i, d := range e.Deposits { + dr[i] = d.Copy() } -} - -// Copy -- -func (deposit *Deposit) Copy() *Deposit { - if deposit == nil { - return nil + wr := make([]*enginev1.WithdrawalRequest, len(e.Withdrawals)) + for i, w := range e.Withdrawals { + wr[i] = w.Copy() } - return &Deposit{ - Proof: bytesutil.SafeCopy2dBytes(deposit.Proof), - Data: deposit.Data.Copy(), + cr := make([]*enginev1.ConsolidationRequest, len(e.Consolidations)) + for i, c := range e.Consolidations { + cr[i] = c.Copy() } -} -// Copy -- -func (depData *Deposit_Data) Copy() *Deposit_Data { - if depData == nil { - return nil - } - return &Deposit_Data{ - PublicKey: bytesutil.SafeCopyBytes(depData.PublicKey), - WithdrawalCredentials: bytesutil.SafeCopyBytes(depData.WithdrawalCredentials), - Amount: depData.Amount, - Signature: bytesutil.SafeCopyBytes(depData.Signature), + return &enginev1.ExecutionRequests{ + Deposits: dr, + Withdrawals: wr, + Consolidations: cr, } } -// Copy -- -func (exit *SignedVoluntaryExit) Copy() *SignedVoluntaryExit { - if exit == nil { - return nil - } - return &SignedVoluntaryExit{ - Exit: exit.Exit.Copy(), - Signature: bytesutil.SafeCopyBytes(exit.Signature), - } -} +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- // Copy -- -func (exit *VoluntaryExit) Copy() *VoluntaryExit { - if exit == nil { - return nil - } - return &VoluntaryExit{ - Epoch: exit.Epoch, - ValidatorIndex: exit.ValidatorIndex, - } -} - -// Copy -- -func (a *SyncAggregate) Copy() *SyncAggregate { - if a == nil { - return nil - } - return &SyncAggregate{ - SyncCommitteeBits: bytesutil.SafeCopyBytes(a.SyncCommitteeBits), - SyncCommitteeSignature: bytesutil.SafeCopyBytes(a.SyncCommitteeSignature), - } -} - -// Copy -- -func (change *SignedBLSToExecutionChange) Copy() *SignedBLSToExecutionChange { - if change == nil { - return nil - } - return &SignedBLSToExecutionChange{ - Message: change.Message.Copy(), - Signature: bytesutil.SafeCopyBytes(change.Signature), - } -} - -// Copy -- -func (change *BLSToExecutionChange) Copy() *BLSToExecutionChange { - if change == nil { +func (sigBlock *SignedBlindedBeaconBlockFulu) Copy() *SignedBlindedBeaconBlockFulu { + if sigBlock == nil { return nil } - return &BLSToExecutionChange{ - ValidatorIndex: change.ValidatorIndex, - FromBlsPubkey: bytesutil.SafeCopyBytes(change.FromBlsPubkey), - ToExecutionAddress: bytesutil.SafeCopyBytes(change.ToExecutionAddress), + return &SignedBlindedBeaconBlockFulu{ + Message: sigBlock.Message.Copy(), + Signature: bytesutil.SafeCopyBytes(sigBlock.Signature), } } // Copy -- -func (summary *HistoricalSummary) Copy() *HistoricalSummary { - if summary == nil { +func (block *BlindedBeaconBlockFulu) Copy() *BlindedBeaconBlockFulu { + if block == nil { return nil } - return &HistoricalSummary{ - BlockSummaryRoot: bytesutil.SafeCopyBytes(summary.BlockSummaryRoot), - StateSummaryRoot: bytesutil.SafeCopyBytes(summary.StateSummaryRoot), + return &BlindedBeaconBlockFulu{ + Slot: block.Slot, + ProposerIndex: block.ProposerIndex, + ParentRoot: bytesutil.SafeCopyBytes(block.ParentRoot), + StateRoot: bytesutil.SafeCopyBytes(block.StateRoot), + Body: block.Body.Copy(), } } // Copy -- -func (pbd *PendingBalanceDeposit) Copy() *PendingBalanceDeposit { - if pbd == nil { +func (sigBlock *SignedBeaconBlockFulu) Copy() *SignedBeaconBlockFulu { + if sigBlock == nil { return nil } - return &PendingBalanceDeposit{ - Index: pbd.Index, - Amount: pbd.Amount, + return &SignedBeaconBlockFulu{ + Block: sigBlock.Block.Copy(), + Signature: bytesutil.SafeCopyBytes(sigBlock.Signature), } } diff --git a/proto/prysm/v1alpha1/beacon_block.pb.go b/proto/prysm/v1alpha1/beacon_block.pb.go index 7db66168e299..789b270c54a1 100755 --- a/proto/prysm/v1alpha1/beacon_block.pb.go +++ b/proto/prysm/v1alpha1/beacon_block.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/beacon_block.proto package eth @@ -42,6 +42,8 @@ type GenericSignedBeaconBlock struct { // *GenericSignedBeaconBlock_BlindedDeneb // *GenericSignedBeaconBlock_Electra // *GenericSignedBeaconBlock_BlindedElectra + // *GenericSignedBeaconBlock_Fulu + // *GenericSignedBeaconBlock_BlindedFulu Block isGenericSignedBeaconBlock_Block `protobuf_oneof:"block"` IsBlinded bool `protobuf:"varint,100,opt,name=is_blinded,json=isBlinded,proto3" json:"is_blinded,omitempty"` } @@ -155,6 +157,20 @@ func (x *GenericSignedBeaconBlock) GetBlindedElectra() *SignedBlindedBeaconBlock return nil } +func (x *GenericSignedBeaconBlock) GetFulu() *SignedBeaconBlockContentsFulu { + if x, ok := x.GetBlock().(*GenericSignedBeaconBlock_Fulu); ok { + return x.Fulu + } + return nil +} + +func (x *GenericSignedBeaconBlock) GetBlindedFulu() *SignedBlindedBeaconBlockFulu { + if x, ok := x.GetBlock().(*GenericSignedBeaconBlock_BlindedFulu); ok { + return x.BlindedFulu + } + return nil +} + func (x *GenericSignedBeaconBlock) GetIsBlinded() bool { if x != nil { return x.IsBlinded @@ -206,6 +222,14 @@ type GenericSignedBeaconBlock_BlindedElectra struct { BlindedElectra *SignedBlindedBeaconBlockElectra `protobuf:"bytes,10,opt,name=blinded_electra,json=blindedElectra,proto3,oneof"` } +type GenericSignedBeaconBlock_Fulu struct { + Fulu *SignedBeaconBlockContentsFulu `protobuf:"bytes,11,opt,name=fulu,proto3,oneof"` +} + +type GenericSignedBeaconBlock_BlindedFulu struct { + BlindedFulu *SignedBlindedBeaconBlockFulu `protobuf:"bytes,12,opt,name=blinded_fulu,json=blindedFulu,proto3,oneof"` +} + func (*GenericSignedBeaconBlock_Phase0) isGenericSignedBeaconBlock_Block() {} func (*GenericSignedBeaconBlock_Altair) isGenericSignedBeaconBlock_Block() {} @@ -226,6 +250,10 @@ func (*GenericSignedBeaconBlock_Electra) isGenericSignedBeaconBlock_Block() {} func (*GenericSignedBeaconBlock_BlindedElectra) isGenericSignedBeaconBlock_Block() {} +func (*GenericSignedBeaconBlock_Fulu) isGenericSignedBeaconBlock_Block() {} + +func (*GenericSignedBeaconBlock_BlindedFulu) isGenericSignedBeaconBlock_Block() {} + type GenericBeaconBlock struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -243,6 +271,8 @@ type GenericBeaconBlock struct { // *GenericBeaconBlock_BlindedDeneb // *GenericBeaconBlock_Electra // *GenericBeaconBlock_BlindedElectra + // *GenericBeaconBlock_Fulu + // *GenericBeaconBlock_BlindedFulu Block isGenericBeaconBlock_Block `protobuf_oneof:"block"` IsBlinded bool `protobuf:"varint,100,opt,name=is_blinded,json=isBlinded,proto3" json:"is_blinded,omitempty"` PayloadValue string `protobuf:"bytes,101,opt,name=payload_value,json=payloadValue,proto3" json:"payload_value,omitempty"` @@ -357,6 +387,20 @@ func (x *GenericBeaconBlock) GetBlindedElectra() *BlindedBeaconBlockElectra { return nil } +func (x *GenericBeaconBlock) GetFulu() *BeaconBlockContentsFulu { + if x, ok := x.GetBlock().(*GenericBeaconBlock_Fulu); ok { + return x.Fulu + } + return nil +} + +func (x *GenericBeaconBlock) GetBlindedFulu() *BlindedBeaconBlockFulu { + if x, ok := x.GetBlock().(*GenericBeaconBlock_BlindedFulu); ok { + return x.BlindedFulu + } + return nil +} + func (x *GenericBeaconBlock) GetIsBlinded() bool { if x != nil { return x.IsBlinded @@ -415,6 +459,14 @@ type GenericBeaconBlock_BlindedElectra struct { BlindedElectra *BlindedBeaconBlockElectra `protobuf:"bytes,10,opt,name=blinded_electra,json=blindedElectra,proto3,oneof"` } +type GenericBeaconBlock_Fulu struct { + Fulu *BeaconBlockContentsFulu `protobuf:"bytes,11,opt,name=fulu,proto3,oneof"` +} + +type GenericBeaconBlock_BlindedFulu struct { + BlindedFulu *BlindedBeaconBlockFulu `protobuf:"bytes,12,opt,name=blinded_fulu,json=blindedFulu,proto3,oneof"` +} + func (*GenericBeaconBlock_Phase0) isGenericBeaconBlock_Block() {} func (*GenericBeaconBlock_Altair) isGenericBeaconBlock_Block() {} @@ -435,84 +487,9 @@ func (*GenericBeaconBlock_Electra) isGenericBeaconBlock_Block() {} func (*GenericBeaconBlock_BlindedElectra) isGenericBeaconBlock_Block() {} -type BeaconBlock struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBody `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BeaconBlock) Reset() { - *x = BeaconBlock{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlock) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlock) ProtoMessage() {} - -func (x *BeaconBlock) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlock.ProtoReflect.Descriptor instead. -func (*BeaconBlock) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{2} -} - -func (x *BeaconBlock) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BeaconBlock) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BeaconBlock) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BeaconBlock) GetStateRoot() []byte { - if x != nil { - return x.StateRoot - } - return nil -} +func (*GenericBeaconBlock_Fulu) isGenericBeaconBlock_Block() {} -func (x *BeaconBlock) GetBody() *BeaconBlockBody { - if x != nil { - return x.Body - } - return nil -} +func (*GenericBeaconBlock_BlindedFulu) isGenericBeaconBlock_Block() {} type SignedBeaconBlock struct { state protoimpl.MessageState @@ -526,7 +503,7 @@ type SignedBeaconBlock struct { func (x *SignedBeaconBlock) Reset() { *x = SignedBeaconBlock{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[3] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -539,7 +516,7 @@ func (x *SignedBeaconBlock) String() string { func (*SignedBeaconBlock) ProtoMessage() {} func (x *SignedBeaconBlock) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[3] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -552,7 +529,7 @@ func (x *SignedBeaconBlock) ProtoReflect() protoreflect.Message { // Deprecated: Use SignedBeaconBlock.ProtoReflect.Descriptor instead. func (*SignedBeaconBlock) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{3} + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{2} } func (x *SignedBeaconBlock) GetBlock() *BeaconBlock { @@ -569,7 +546,7 @@ func (x *SignedBeaconBlock) GetSignature() []byte { return nil } -type BeaconBlockAltair struct { +type BeaconBlock struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -578,26 +555,26 @@ type BeaconBlockAltair struct { ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyAltair `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` + Body *BeaconBlockBody `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` } -func (x *BeaconBlockAltair) Reset() { - *x = BeaconBlockAltair{} +func (x *BeaconBlock) Reset() { + *x = BeaconBlock{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[4] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BeaconBlockAltair) String() string { +func (x *BeaconBlock) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockAltair) ProtoMessage() {} +func (*BeaconBlock) ProtoMessage() {} -func (x *BeaconBlockAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[4] +func (x *BeaconBlock) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -608,101 +585,46 @@ func (x *BeaconBlockAltair) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockAltair.ProtoReflect.Descriptor instead. -func (*BeaconBlockAltair) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{4} +// Deprecated: Use BeaconBlock.ProtoReflect.Descriptor instead. +func (*BeaconBlock) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{3} } -func (x *BeaconBlockAltair) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { +func (x *BeaconBlock) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { return x.Slot } return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) } -func (x *BeaconBlockAltair) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { +func (x *BeaconBlock) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { return x.ProposerIndex } return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) } -func (x *BeaconBlockAltair) GetParentRoot() []byte { +func (x *BeaconBlock) GetParentRoot() []byte { if x != nil { return x.ParentRoot } return nil } -func (x *BeaconBlockAltair) GetStateRoot() []byte { +func (x *BeaconBlock) GetStateRoot() []byte { if x != nil { return x.StateRoot } return nil } -func (x *BeaconBlockAltair) GetBody() *BeaconBlockBodyAltair { +func (x *BeaconBlock) GetBody() *BeaconBlockBody { if x != nil { return x.Body } return nil } -type SignedBeaconBlockAltair struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Block *BeaconBlockAltair `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBeaconBlockAltair) Reset() { - *x = SignedBeaconBlockAltair{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockAltair) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockAltair) ProtoMessage() {} - -func (x *SignedBeaconBlockAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockAltair.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockAltair) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{5} -} - -func (x *SignedBeaconBlockAltair) GetBlock() *BeaconBlockAltair { - if x != nil { - return x.Block - } - return nil -} - -func (x *SignedBeaconBlockAltair) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - type BeaconBlockBody struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -721,7 +643,7 @@ type BeaconBlockBody struct { func (x *BeaconBlockBody) Reset() { *x = BeaconBlockBody{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -734,7 +656,7 @@ func (x *BeaconBlockBody) String() string { func (*BeaconBlockBody) ProtoMessage() {} func (x *BeaconBlockBody) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -747,7 +669,7 @@ func (x *BeaconBlockBody) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconBlockBody.ProtoReflect.Descriptor instead. func (*BeaconBlockBody) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{6} + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{4} } func (x *BeaconBlockBody) GetRandaoReveal() []byte { @@ -806,39 +728,32 @@ func (x *BeaconBlockBody) GetVoluntaryExits() []*SignedVoluntaryExit { return nil } -type BeaconBlockBodyAltair struct { +type SignedBeaconBlockHeader struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + Header *BeaconBlockHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *BeaconBlockBodyAltair) Reset() { - *x = BeaconBlockBodyAltair{} +func (x *SignedBeaconBlockHeader) Reset() { + *x = SignedBeaconBlockHeader{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[7] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BeaconBlockBodyAltair) String() string { +func (x *SignedBeaconBlockHeader) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockBodyAltair) ProtoMessage() {} +func (*SignedBeaconBlockHeader) ProtoMessage() {} -func (x *BeaconBlockBodyAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[7] +func (x *SignedBeaconBlockHeader) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -849,70 +764,163 @@ func (x *BeaconBlockBodyAltair) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockBodyAltair.ProtoReflect.Descriptor instead. -func (*BeaconBlockBodyAltair) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{7} +// Deprecated: Use SignedBeaconBlockHeader.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockHeader) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{5} } -func (x *BeaconBlockBodyAltair) GetRandaoReveal() []byte { +func (x *SignedBeaconBlockHeader) GetHeader() *BeaconBlockHeader { if x != nil { - return x.RandaoReveal + return x.Header } return nil } -func (x *BeaconBlockBodyAltair) GetEth1Data() *Eth1Data { +func (x *SignedBeaconBlockHeader) GetSignature() []byte { if x != nil { - return x.Eth1Data + return x.Signature } return nil } -func (x *BeaconBlockBodyAltair) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} +type BeaconBlockHeader struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (x *BeaconBlockBodyAltair) GetProposerSlashings() []*ProposerSlashing { + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + BodyRoot []byte `protobuf:"bytes,5,opt,name=body_root,json=bodyRoot,proto3" json:"body_root,omitempty" ssz-size:"32"` +} + +func (x *BeaconBlockHeader) Reset() { + *x = BeaconBlockHeader{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BeaconBlockHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BeaconBlockHeader) ProtoMessage() {} + +func (x *BeaconBlockHeader) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BeaconBlockHeader.ProtoReflect.Descriptor instead. +func (*BeaconBlockHeader) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{6} +} + +func (x *BeaconBlockHeader) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { - return x.ProposerSlashings + return x.Slot } - return nil + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) } -func (x *BeaconBlockBodyAltair) GetAttesterSlashings() []*AttesterSlashing { +func (x *BeaconBlockHeader) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { - return x.AttesterSlashings + return x.ProposerIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *BeaconBlockHeader) GetParentRoot() []byte { + if x != nil { + return x.ParentRoot } return nil } -func (x *BeaconBlockBodyAltair) GetAttestations() []*Attestation { +func (x *BeaconBlockHeader) GetStateRoot() []byte { if x != nil { - return x.Attestations + return x.StateRoot } return nil } -func (x *BeaconBlockBodyAltair) GetDeposits() []*Deposit { +func (x *BeaconBlockHeader) GetBodyRoot() []byte { if x != nil { - return x.Deposits + return x.BodyRoot } return nil } -func (x *BeaconBlockBodyAltair) GetVoluntaryExits() []*SignedVoluntaryExit { +type Eth1Data struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DepositRoot []byte `protobuf:"bytes,1,opt,name=deposit_root,json=depositRoot,proto3" json:"deposit_root,omitempty" ssz-size:"32"` + DepositCount uint64 `protobuf:"varint,2,opt,name=deposit_count,json=depositCount,proto3" json:"deposit_count,omitempty"` + BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty" ssz-size:"32"` +} + +func (x *Eth1Data) Reset() { + *x = Eth1Data{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Eth1Data) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Eth1Data) ProtoMessage() {} + +func (x *Eth1Data) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Eth1Data.ProtoReflect.Descriptor instead. +func (*Eth1Data) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{7} +} + +func (x *Eth1Data) GetDepositRoot() []byte { if x != nil { - return x.VoluntaryExits + return x.DepositRoot } return nil } -func (x *BeaconBlockBodyAltair) GetSyncAggregate() *SyncAggregate { +func (x *Eth1Data) GetDepositCount() uint64 { if x != nil { - return x.SyncAggregate + return x.DepositCount + } + return 0 +} + +func (x *Eth1Data) GetBlockHash() []byte { + if x != nil { + return x.BlockHash } return nil } @@ -1027,17 +1035,18 @@ func (x *AttesterSlashing) GetAttestation_2() *IndexedAttestation { return nil } -type AttesterSlashingElectra struct { +type IndexedAttestation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Attestation_1 *IndexedAttestationElectra `protobuf:"bytes,1,opt,name=attestation_1,json=attestation1,proto3" json:"attestation_1,omitempty"` - Attestation_2 *IndexedAttestationElectra `protobuf:"bytes,2,opt,name=attestation_2,json=attestation2,proto3" json:"attestation_2,omitempty"` + AttestingIndices []uint64 `protobuf:"varint,1,rep,packed,name=attesting_indices,json=attestingIndices,proto3" json:"attesting_indices,omitempty" ssz-max:"2048"` + Data *AttestationData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *AttesterSlashingElectra) Reset() { - *x = AttesterSlashingElectra{} +func (x *IndexedAttestation) Reset() { + *x = IndexedAttestation{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1045,13 +1054,13 @@ func (x *AttesterSlashingElectra) Reset() { } } -func (x *AttesterSlashingElectra) String() string { +func (x *IndexedAttestation) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AttesterSlashingElectra) ProtoMessage() {} +func (*IndexedAttestation) ProtoMessage() {} -func (x *AttesterSlashingElectra) ProtoReflect() protoreflect.Message { +func (x *IndexedAttestation) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1063,21 +1072,28 @@ func (x *AttesterSlashingElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use AttesterSlashingElectra.ProtoReflect.Descriptor instead. -func (*AttesterSlashingElectra) Descriptor() ([]byte, []int) { +// Deprecated: Use IndexedAttestation.ProtoReflect.Descriptor instead. +func (*IndexedAttestation) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{10} } -func (x *AttesterSlashingElectra) GetAttestation_1() *IndexedAttestationElectra { +func (x *IndexedAttestation) GetAttestingIndices() []uint64 { if x != nil { - return x.Attestation_1 + return x.AttestingIndices } return nil } -func (x *AttesterSlashingElectra) GetAttestation_2() *IndexedAttestationElectra { +func (x *IndexedAttestation) GetData() *AttestationData { if x != nil { - return x.Attestation_2 + return x.Data + } + return nil +} + +func (x *IndexedAttestation) GetSignature() []byte { + if x != nil { + return x.Signature } return nil } @@ -1137,17 +1153,17 @@ func (x *Deposit) GetData() *Deposit_Data { return nil } -type VoluntaryExit struct { +type SignedVoluntaryExit struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Epoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"` - ValidatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + Exit *VoluntaryExit `protobuf:"bytes,1,opt,name=exit,proto3" json:"exit,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *VoluntaryExit) Reset() { - *x = VoluntaryExit{} +func (x *SignedVoluntaryExit) Reset() { + *x = SignedVoluntaryExit{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1155,13 +1171,13 @@ func (x *VoluntaryExit) Reset() { } } -func (x *VoluntaryExit) String() string { +func (x *SignedVoluntaryExit) String() string { return protoimpl.X.MessageStringOf(x) } -func (*VoluntaryExit) ProtoMessage() {} +func (*SignedVoluntaryExit) ProtoMessage() {} -func (x *VoluntaryExit) ProtoReflect() protoreflect.Message { +func (x *SignedVoluntaryExit) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1173,36 +1189,36 @@ func (x *VoluntaryExit) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use VoluntaryExit.ProtoReflect.Descriptor instead. -func (*VoluntaryExit) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedVoluntaryExit.ProtoReflect.Descriptor instead. +func (*SignedVoluntaryExit) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{12} } -func (x *VoluntaryExit) GetEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch { +func (x *SignedVoluntaryExit) GetExit() *VoluntaryExit { if x != nil { - return x.Epoch + return x.Exit } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) + return nil } -func (x *VoluntaryExit) GetValidatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { +func (x *SignedVoluntaryExit) GetSignature() []byte { if x != nil { - return x.ValidatorIndex + return x.Signature } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) + return nil } -type SignedVoluntaryExit struct { +type VoluntaryExit struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Exit *VoluntaryExit `protobuf:"bytes,1,opt,name=exit,proto3" json:"exit,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Epoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"` + ValidatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` } -func (x *SignedVoluntaryExit) Reset() { - *x = SignedVoluntaryExit{} +func (x *VoluntaryExit) Reset() { + *x = VoluntaryExit{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1210,13 +1226,13 @@ func (x *SignedVoluntaryExit) Reset() { } } -func (x *SignedVoluntaryExit) String() string { +func (x *VoluntaryExit) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedVoluntaryExit) ProtoMessage() {} +func (*VoluntaryExit) ProtoMessage() {} -func (x *SignedVoluntaryExit) ProtoReflect() protoreflect.Message { +func (x *VoluntaryExit) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1228,37 +1244,35 @@ func (x *SignedVoluntaryExit) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedVoluntaryExit.ProtoReflect.Descriptor instead. -func (*SignedVoluntaryExit) Descriptor() ([]byte, []int) { +// Deprecated: Use VoluntaryExit.ProtoReflect.Descriptor instead. +func (*VoluntaryExit) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{13} } -func (x *SignedVoluntaryExit) GetExit() *VoluntaryExit { +func (x *VoluntaryExit) GetEpoch() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch { if x != nil { - return x.Exit + return x.Epoch } - return nil + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) } -func (x *SignedVoluntaryExit) GetSignature() []byte { +func (x *VoluntaryExit) GetValidatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { - return x.Signature + return x.ValidatorIndex } - return nil + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) } -type Eth1Data struct { +type SignedValidatorRegistrationsV1 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - DepositRoot []byte `protobuf:"bytes,1,opt,name=deposit_root,json=depositRoot,proto3" json:"deposit_root,omitempty" ssz-size:"32"` - DepositCount uint64 `protobuf:"varint,2,opt,name=deposit_count,json=depositCount,proto3" json:"deposit_count,omitempty"` - BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty" ssz-size:"32"` + Messages []*SignedValidatorRegistrationV1 `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"` } -func (x *Eth1Data) Reset() { - *x = Eth1Data{} +func (x *SignedValidatorRegistrationsV1) Reset() { + *x = SignedValidatorRegistrationsV1{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1266,13 +1280,13 @@ func (x *Eth1Data) Reset() { } } -func (x *Eth1Data) String() string { +func (x *SignedValidatorRegistrationsV1) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Eth1Data) ProtoMessage() {} +func (*SignedValidatorRegistrationsV1) ProtoMessage() {} -func (x *Eth1Data) ProtoReflect() protoreflect.Message { +func (x *SignedValidatorRegistrationsV1) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1284,46 +1298,29 @@ func (x *Eth1Data) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Eth1Data.ProtoReflect.Descriptor instead. -func (*Eth1Data) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedValidatorRegistrationsV1.ProtoReflect.Descriptor instead. +func (*SignedValidatorRegistrationsV1) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{14} } -func (x *Eth1Data) GetDepositRoot() []byte { +func (x *SignedValidatorRegistrationsV1) GetMessages() []*SignedValidatorRegistrationV1 { if x != nil { - return x.DepositRoot + return x.Messages } return nil } -func (x *Eth1Data) GetDepositCount() uint64 { - if x != nil { - return x.DepositCount - } - return 0 +type SignedValidatorRegistrationV1 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message *ValidatorRegistrationV1 `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *Eth1Data) GetBlockHash() []byte { - if x != nil { - return x.BlockHash - } - return nil -} - -type BeaconBlockHeader struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - BodyRoot []byte `protobuf:"bytes,5,opt,name=body_root,json=bodyRoot,proto3" json:"body_root,omitempty" ssz-size:"32"` -} - -func (x *BeaconBlockHeader) Reset() { - *x = BeaconBlockHeader{} +func (x *SignedValidatorRegistrationV1) Reset() { + *x = SignedValidatorRegistrationV1{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1331,13 +1328,13 @@ func (x *BeaconBlockHeader) Reset() { } } -func (x *BeaconBlockHeader) String() string { +func (x *SignedValidatorRegistrationV1) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockHeader) ProtoMessage() {} +func (*SignedValidatorRegistrationV1) ProtoMessage() {} -func (x *BeaconBlockHeader) ProtoReflect() protoreflect.Message { +func (x *SignedValidatorRegistrationV1) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1349,57 +1346,38 @@ func (x *BeaconBlockHeader) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockHeader.ProtoReflect.Descriptor instead. -func (*BeaconBlockHeader) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedValidatorRegistrationV1.ProtoReflect.Descriptor instead. +func (*SignedValidatorRegistrationV1) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{15} } -func (x *BeaconBlockHeader) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BeaconBlockHeader) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BeaconBlockHeader) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BeaconBlockHeader) GetStateRoot() []byte { +func (x *SignedValidatorRegistrationV1) GetMessage() *ValidatorRegistrationV1 { if x != nil { - return x.StateRoot + return x.Message } return nil } -func (x *BeaconBlockHeader) GetBodyRoot() []byte { +func (x *SignedValidatorRegistrationV1) GetSignature() []byte { if x != nil { - return x.BodyRoot + return x.Signature } return nil } -type SignedBeaconBlockHeader struct { +type ValidatorRegistrationV1 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Header *BeaconBlockHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + FeeRecipient []byte `protobuf:"bytes,1,opt,name=fee_recipient,json=feeRecipient,proto3" json:"fee_recipient,omitempty" ssz-size:"20"` + GasLimit uint64 `protobuf:"varint,2,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` + Timestamp uint64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Pubkey []byte `protobuf:"bytes,4,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` } -func (x *SignedBeaconBlockHeader) Reset() { - *x = SignedBeaconBlockHeader{} +func (x *ValidatorRegistrationV1) Reset() { + *x = ValidatorRegistrationV1{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1407,13 +1385,13 @@ func (x *SignedBeaconBlockHeader) Reset() { } } -func (x *SignedBeaconBlockHeader) String() string { +func (x *ValidatorRegistrationV1) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBeaconBlockHeader) ProtoMessage() {} +func (*ValidatorRegistrationV1) ProtoMessage() {} -func (x *SignedBeaconBlockHeader) ProtoReflect() protoreflect.Message { +func (x *ValidatorRegistrationV1) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1425,37 +1403,50 @@ func (x *SignedBeaconBlockHeader) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBeaconBlockHeader.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockHeader) Descriptor() ([]byte, []int) { +// Deprecated: Use ValidatorRegistrationV1.ProtoReflect.Descriptor instead. +func (*ValidatorRegistrationV1) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{16} } -func (x *SignedBeaconBlockHeader) GetHeader() *BeaconBlockHeader { +func (x *ValidatorRegistrationV1) GetFeeRecipient() []byte { if x != nil { - return x.Header + return x.FeeRecipient } return nil } -func (x *SignedBeaconBlockHeader) GetSignature() []byte { +func (x *ValidatorRegistrationV1) GetGasLimit() uint64 { if x != nil { - return x.Signature + return x.GasLimit + } + return 0 +} + +func (x *ValidatorRegistrationV1) GetTimestamp() uint64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *ValidatorRegistrationV1) GetPubkey() []byte { + if x != nil { + return x.Pubkey } return nil } -type IndexedAttestation struct { +type SignedBuilderBid struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AttestingIndices []uint64 `protobuf:"varint,1,rep,packed,name=attesting_indices,json=attestingIndices,proto3" json:"attesting_indices,omitempty" ssz-max:"2048"` - Data *AttestationData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Message *BuilderBid `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *IndexedAttestation) Reset() { - *x = IndexedAttestation{} +func (x *SignedBuilderBid) Reset() { + *x = SignedBuilderBid{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1463,13 +1454,13 @@ func (x *IndexedAttestation) Reset() { } } -func (x *IndexedAttestation) String() string { +func (x *SignedBuilderBid) String() string { return protoimpl.X.MessageStringOf(x) } -func (*IndexedAttestation) ProtoMessage() {} +func (*SignedBuilderBid) ProtoMessage() {} -func (x *IndexedAttestation) ProtoReflect() protoreflect.Message { +func (x *SignedBuilderBid) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1481,44 +1472,37 @@ func (x *IndexedAttestation) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use IndexedAttestation.ProtoReflect.Descriptor instead. -func (*IndexedAttestation) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBuilderBid.ProtoReflect.Descriptor instead. +func (*SignedBuilderBid) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{17} } -func (x *IndexedAttestation) GetAttestingIndices() []uint64 { - if x != nil { - return x.AttestingIndices - } - return nil -} - -func (x *IndexedAttestation) GetData() *AttestationData { +func (x *SignedBuilderBid) GetMessage() *BuilderBid { if x != nil { - return x.Data + return x.Message } return nil } -func (x *IndexedAttestation) GetSignature() []byte { +func (x *SignedBuilderBid) GetSignature() []byte { if x != nil { return x.Signature } return nil } -type IndexedAttestationElectra struct { +type BuilderBid struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AttestingIndices []uint64 `protobuf:"varint,1,rep,packed,name=attesting_indices,json=attestingIndices,proto3" json:"attesting_indices,omitempty" ssz-max:"131072"` - Data *AttestationData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Header *v1.ExecutionPayloadHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty" ssz-size:"32"` + Pubkey []byte `protobuf:"bytes,3,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` } -func (x *IndexedAttestationElectra) Reset() { - *x = IndexedAttestationElectra{} +func (x *BuilderBid) Reset() { + *x = BuilderBid{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1526,13 +1510,13 @@ func (x *IndexedAttestationElectra) Reset() { } } -func (x *IndexedAttestationElectra) String() string { +func (x *BuilderBid) String() string { return protoimpl.X.MessageStringOf(x) } -func (*IndexedAttestationElectra) ProtoMessage() {} +func (*BuilderBid) ProtoMessage() {} -func (x *IndexedAttestationElectra) ProtoReflect() protoreflect.Message { +func (x *BuilderBid) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1544,43 +1528,43 @@ func (x *IndexedAttestationElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use IndexedAttestationElectra.ProtoReflect.Descriptor instead. -func (*IndexedAttestationElectra) Descriptor() ([]byte, []int) { +// Deprecated: Use BuilderBid.ProtoReflect.Descriptor instead. +func (*BuilderBid) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{18} } -func (x *IndexedAttestationElectra) GetAttestingIndices() []uint64 { +func (x *BuilderBid) GetHeader() *v1.ExecutionPayloadHeader { if x != nil { - return x.AttestingIndices + return x.Header } return nil } -func (x *IndexedAttestationElectra) GetData() *AttestationData { +func (x *BuilderBid) GetValue() []byte { if x != nil { - return x.Data + return x.Value } return nil } -func (x *IndexedAttestationElectra) GetSignature() []byte { +func (x *BuilderBid) GetPubkey() []byte { if x != nil { - return x.Signature + return x.Pubkey } return nil } -type SyncAggregate struct { +type SignedBeaconBlockAltair struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SyncCommitteeBits github_com_prysmaticlabs_go_bitfield.Bitvector512 `protobuf:"bytes,1,opt,name=sync_committee_bits,json=syncCommitteeBits,proto3" json:"sync_committee_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector512" ssz-size:"64"` - SyncCommitteeSignature []byte `protobuf:"bytes,2,opt,name=sync_committee_signature,json=syncCommitteeSignature,proto3" json:"sync_committee_signature,omitempty" ssz-size:"96"` + Block *BeaconBlockAltair `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SyncAggregate) Reset() { - *x = SyncAggregate{} +func (x *SignedBeaconBlockAltair) Reset() { + *x = SignedBeaconBlockAltair{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1588,13 +1572,13 @@ func (x *SyncAggregate) Reset() { } } -func (x *SyncAggregate) String() string { +func (x *SignedBeaconBlockAltair) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SyncAggregate) ProtoMessage() {} +func (*SignedBeaconBlockAltair) ProtoMessage() {} -func (x *SyncAggregate) ProtoReflect() protoreflect.Message { +func (x *SignedBeaconBlockAltair) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1606,36 +1590,39 @@ func (x *SyncAggregate) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SyncAggregate.ProtoReflect.Descriptor instead. -func (*SyncAggregate) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBeaconBlockAltair.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockAltair) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{19} } -func (x *SyncAggregate) GetSyncCommitteeBits() github_com_prysmaticlabs_go_bitfield.Bitvector512 { +func (x *SignedBeaconBlockAltair) GetBlock() *BeaconBlockAltair { if x != nil { - return x.SyncCommitteeBits + return x.Block } - return github_com_prysmaticlabs_go_bitfield.Bitvector512(nil) + return nil } -func (x *SyncAggregate) GetSyncCommitteeSignature() []byte { +func (x *SignedBeaconBlockAltair) GetSignature() []byte { if x != nil { - return x.SyncCommitteeSignature + return x.Signature } return nil } -type SignedBeaconBlockBellatrix struct { +type BeaconBlockAltair struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *BeaconBlockBellatrix `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + Body *BeaconBlockBodyAltair `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` } -func (x *SignedBeaconBlockBellatrix) Reset() { - *x = SignedBeaconBlockBellatrix{} +func (x *BeaconBlockAltair) Reset() { + *x = BeaconBlockAltair{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1643,13 +1630,13 @@ func (x *SignedBeaconBlockBellatrix) Reset() { } } -func (x *SignedBeaconBlockBellatrix) String() string { +func (x *BeaconBlockAltair) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBeaconBlockBellatrix) ProtoMessage() {} +func (*BeaconBlockAltair) ProtoMessage() {} -func (x *SignedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { +func (x *BeaconBlockAltair) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1661,105 +1648,47 @@ func (x *SignedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { +// Deprecated: Use BeaconBlockAltair.ProtoReflect.Descriptor instead. +func (*BeaconBlockAltair) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{20} } -func (x *SignedBeaconBlockBellatrix) GetBlock() *BeaconBlockBellatrix { +func (x *BeaconBlockAltair) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { - return x.Block + return x.Slot } - return nil + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) } -func (x *SignedBeaconBlockBellatrix) GetSignature() []byte { +func (x *BeaconBlockAltair) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { - return x.Signature + return x.ProposerIndex } - return nil + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) } -type BeaconBlockBellatrix struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyBellatrix `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` +func (x *BeaconBlockAltair) GetParentRoot() []byte { + if x != nil { + return x.ParentRoot + } + return nil } -func (x *BeaconBlockBellatrix) Reset() { - *x = BeaconBlockBellatrix{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconBlockBellatrix) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockBellatrix) ProtoMessage() {} - -func (x *BeaconBlockBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconBlockBellatrix.ProtoReflect.Descriptor instead. -func (*BeaconBlockBellatrix) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{21} -} - -func (x *BeaconBlockBellatrix) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BeaconBlockBellatrix) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BeaconBlockBellatrix) GetParentRoot() []byte { - if x != nil { - return x.ParentRoot - } - return nil -} - -func (x *BeaconBlockBellatrix) GetStateRoot() []byte { +func (x *BeaconBlockAltair) GetStateRoot() []byte { if x != nil { return x.StateRoot } return nil } -func (x *BeaconBlockBellatrix) GetBody() *BeaconBlockBodyBellatrix { +func (x *BeaconBlockAltair) GetBody() *BeaconBlockBodyAltair { if x != nil { return x.Body } return nil } -type BeaconBlockBodyBellatrix struct { +type BeaconBlockBodyAltair struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -1773,26 +1702,25 @@ type BeaconBlockBodyBellatrix struct { Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayload *v1.ExecutionPayload `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` } -func (x *BeaconBlockBodyBellatrix) Reset() { - *x = BeaconBlockBodyBellatrix{} +func (x *BeaconBlockBodyAltair) Reset() { + *x = BeaconBlockBodyAltair{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[22] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BeaconBlockBodyBellatrix) String() string { +func (x *BeaconBlockBodyAltair) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockBodyBellatrix) ProtoMessage() {} +func (*BeaconBlockBodyAltair) ProtoMessage() {} -func (x *BeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[22] +func (x *BeaconBlockBodyAltair) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1803,92 +1731,140 @@ func (x *BeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockBodyBellatrix.ProtoReflect.Descriptor instead. -func (*BeaconBlockBodyBellatrix) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{22} +// Deprecated: Use BeaconBlockBodyAltair.ProtoReflect.Descriptor instead. +func (*BeaconBlockBodyAltair) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{21} } -func (x *BeaconBlockBodyBellatrix) GetRandaoReveal() []byte { +func (x *BeaconBlockBodyAltair) GetRandaoReveal() []byte { if x != nil { return x.RandaoReveal } return nil } -func (x *BeaconBlockBodyBellatrix) GetEth1Data() *Eth1Data { +func (x *BeaconBlockBodyAltair) GetEth1Data() *Eth1Data { if x != nil { return x.Eth1Data } return nil } -func (x *BeaconBlockBodyBellatrix) GetGraffiti() []byte { +func (x *BeaconBlockBodyAltair) GetGraffiti() []byte { if x != nil { return x.Graffiti } return nil } -func (x *BeaconBlockBodyBellatrix) GetProposerSlashings() []*ProposerSlashing { +func (x *BeaconBlockBodyAltair) GetProposerSlashings() []*ProposerSlashing { if x != nil { return x.ProposerSlashings } return nil } -func (x *BeaconBlockBodyBellatrix) GetAttesterSlashings() []*AttesterSlashing { +func (x *BeaconBlockBodyAltair) GetAttesterSlashings() []*AttesterSlashing { if x != nil { return x.AttesterSlashings } return nil } -func (x *BeaconBlockBodyBellatrix) GetAttestations() []*Attestation { +func (x *BeaconBlockBodyAltair) GetAttestations() []*Attestation { if x != nil { return x.Attestations } return nil } -func (x *BeaconBlockBodyBellatrix) GetDeposits() []*Deposit { +func (x *BeaconBlockBodyAltair) GetDeposits() []*Deposit { if x != nil { return x.Deposits } return nil } -func (x *BeaconBlockBodyBellatrix) GetVoluntaryExits() []*SignedVoluntaryExit { +func (x *BeaconBlockBodyAltair) GetVoluntaryExits() []*SignedVoluntaryExit { if x != nil { return x.VoluntaryExits } return nil } -func (x *BeaconBlockBodyBellatrix) GetSyncAggregate() *SyncAggregate { +func (x *BeaconBlockBodyAltair) GetSyncAggregate() *SyncAggregate { if x != nil { return x.SyncAggregate } return nil } -func (x *BeaconBlockBodyBellatrix) GetExecutionPayload() *v1.ExecutionPayload { +type SyncAggregate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SyncCommitteeBits github_com_prysmaticlabs_go_bitfield.Bitvector512 `protobuf:"bytes,1,opt,name=sync_committee_bits,json=syncCommitteeBits,proto3" json:"sync_committee_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector512" ssz-size:"64"` + SyncCommitteeSignature []byte `protobuf:"bytes,2,opt,name=sync_committee_signature,json=syncCommitteeSignature,proto3" json:"sync_committee_signature,omitempty" ssz-size:"96"` +} + +func (x *SyncAggregate) Reset() { + *x = SyncAggregate{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SyncAggregate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncAggregate) ProtoMessage() {} + +func (x *SyncAggregate) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncAggregate.ProtoReflect.Descriptor instead. +func (*SyncAggregate) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{22} +} + +func (x *SyncAggregate) GetSyncCommitteeBits() github_com_prysmaticlabs_go_bitfield.Bitvector512 { if x != nil { - return x.ExecutionPayload + return x.SyncCommitteeBits + } + return github_com_prysmaticlabs_go_bitfield.Bitvector512(nil) +} + +func (x *SyncAggregate) GetSyncCommitteeSignature() []byte { + if x != nil { + return x.SyncCommitteeSignature } return nil } -type SignedBlindedBeaconBlockBellatrix struct { +type SignedBeaconBlockBellatrix struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *BlindedBeaconBlockBellatrix `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Block *BeaconBlockBellatrix `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SignedBlindedBeaconBlockBellatrix) Reset() { - *x = SignedBlindedBeaconBlockBellatrix{} +func (x *SignedBeaconBlockBellatrix) Reset() { + *x = SignedBeaconBlockBellatrix{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1896,13 +1872,13 @@ func (x *SignedBlindedBeaconBlockBellatrix) Reset() { } } -func (x *SignedBlindedBeaconBlockBellatrix) String() string { +func (x *SignedBeaconBlockBellatrix) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBlindedBeaconBlockBellatrix) ProtoMessage() {} +func (*SignedBeaconBlockBellatrix) ProtoMessage() {} -func (x *SignedBlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { +func (x *SignedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1914,26 +1890,26 @@ func (x *SignedBlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message return mi.MessageOf(x) } -// Deprecated: Use SignedBlindedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. -func (*SignedBlindedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{23} } -func (x *SignedBlindedBeaconBlockBellatrix) GetBlock() *BlindedBeaconBlockBellatrix { +func (x *SignedBeaconBlockBellatrix) GetBlock() *BeaconBlockBellatrix { if x != nil { return x.Block } return nil } -func (x *SignedBlindedBeaconBlockBellatrix) GetSignature() []byte { +func (x *SignedBeaconBlockBellatrix) GetSignature() []byte { if x != nil { return x.Signature } return nil } -type BlindedBeaconBlockBellatrix struct { +type BeaconBlockBellatrix struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -1942,11 +1918,11 @@ type BlindedBeaconBlockBellatrix struct { ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BlindedBeaconBlockBodyBellatrix `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` + Body *BeaconBlockBodyBellatrix `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` } -func (x *BlindedBeaconBlockBellatrix) Reset() { - *x = BlindedBeaconBlockBellatrix{} +func (x *BeaconBlockBellatrix) Reset() { + *x = BeaconBlockBellatrix{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1954,13 +1930,13 @@ func (x *BlindedBeaconBlockBellatrix) Reset() { } } -func (x *BlindedBeaconBlockBellatrix) String() string { +func (x *BeaconBlockBellatrix) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BlindedBeaconBlockBellatrix) ProtoMessage() {} +func (*BeaconBlockBellatrix) ProtoMessage() {} -func (x *BlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { +func (x *BeaconBlockBellatrix) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1972,65 +1948,65 @@ func (x *BlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BlindedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { +// Deprecated: Use BeaconBlockBellatrix.ProtoReflect.Descriptor instead. +func (*BeaconBlockBellatrix) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{24} } -func (x *BlindedBeaconBlockBellatrix) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { +func (x *BeaconBlockBellatrix) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { return x.Slot } return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) } -func (x *BlindedBeaconBlockBellatrix) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { +func (x *BeaconBlockBellatrix) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { return x.ProposerIndex } return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) } -func (x *BlindedBeaconBlockBellatrix) GetParentRoot() []byte { +func (x *BeaconBlockBellatrix) GetParentRoot() []byte { if x != nil { return x.ParentRoot } return nil } -func (x *BlindedBeaconBlockBellatrix) GetStateRoot() []byte { +func (x *BeaconBlockBellatrix) GetStateRoot() []byte { if x != nil { return x.StateRoot } return nil } -func (x *BlindedBeaconBlockBellatrix) GetBody() *BlindedBeaconBlockBodyBellatrix { +func (x *BeaconBlockBellatrix) GetBody() *BeaconBlockBodyBellatrix { if x != nil { return x.Body } return nil } -type BlindedBeaconBlockBodyBellatrix struct { +type BeaconBlockBodyBellatrix struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayloadHeader *v1.ExecutionPayloadHeader `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` + RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` + Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` + Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` + ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` + AttesterSlashings []*AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` + Attestations []*Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` + Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` + VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` + SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + ExecutionPayload *v1.ExecutionPayload `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` } -func (x *BlindedBeaconBlockBodyBellatrix) Reset() { - *x = BlindedBeaconBlockBodyBellatrix{} +func (x *BeaconBlockBodyBellatrix) Reset() { + *x = BeaconBlockBodyBellatrix{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2038,13 +2014,13 @@ func (x *BlindedBeaconBlockBodyBellatrix) Reset() { } } -func (x *BlindedBeaconBlockBodyBellatrix) String() string { +func (x *BeaconBlockBodyBellatrix) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BlindedBeaconBlockBodyBellatrix) ProtoMessage() {} +func (*BeaconBlockBodyBellatrix) ProtoMessage() {} -func (x *BlindedBeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { +func (x *BeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2056,93 +2032,92 @@ func (x *BlindedBeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BlindedBeaconBlockBodyBellatrix.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockBodyBellatrix) Descriptor() ([]byte, []int) { +// Deprecated: Use BeaconBlockBodyBellatrix.ProtoReflect.Descriptor instead. +func (*BeaconBlockBodyBellatrix) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{25} } -func (x *BlindedBeaconBlockBodyBellatrix) GetRandaoReveal() []byte { +func (x *BeaconBlockBodyBellatrix) GetRandaoReveal() []byte { if x != nil { return x.RandaoReveal } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetEth1Data() *Eth1Data { +func (x *BeaconBlockBodyBellatrix) GetEth1Data() *Eth1Data { if x != nil { return x.Eth1Data } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetGraffiti() []byte { +func (x *BeaconBlockBodyBellatrix) GetGraffiti() []byte { if x != nil { return x.Graffiti } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetProposerSlashings() []*ProposerSlashing { +func (x *BeaconBlockBodyBellatrix) GetProposerSlashings() []*ProposerSlashing { if x != nil { return x.ProposerSlashings } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetAttesterSlashings() []*AttesterSlashing { +func (x *BeaconBlockBodyBellatrix) GetAttesterSlashings() []*AttesterSlashing { if x != nil { return x.AttesterSlashings } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetAttestations() []*Attestation { +func (x *BeaconBlockBodyBellatrix) GetAttestations() []*Attestation { if x != nil { return x.Attestations } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetDeposits() []*Deposit { +func (x *BeaconBlockBodyBellatrix) GetDeposits() []*Deposit { if x != nil { return x.Deposits } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetVoluntaryExits() []*SignedVoluntaryExit { +func (x *BeaconBlockBodyBellatrix) GetVoluntaryExits() []*SignedVoluntaryExit { if x != nil { return x.VoluntaryExits } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetSyncAggregate() *SyncAggregate { +func (x *BeaconBlockBodyBellatrix) GetSyncAggregate() *SyncAggregate { if x != nil { return x.SyncAggregate } return nil } -func (x *BlindedBeaconBlockBodyBellatrix) GetExecutionPayloadHeader() *v1.ExecutionPayloadHeader { +func (x *BeaconBlockBodyBellatrix) GetExecutionPayload() *v1.ExecutionPayload { if x != nil { - return x.ExecutionPayloadHeader + return x.ExecutionPayload } return nil } -type SignedBeaconBlockContentsDeneb struct { +type SignedBlindedBeaconBlockBellatrix struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *SignedBeaconBlockDeneb `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` - Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` + Block *BlindedBeaconBlockBellatrix `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SignedBeaconBlockContentsDeneb) Reset() { - *x = SignedBeaconBlockContentsDeneb{} +func (x *SignedBlindedBeaconBlockBellatrix) Reset() { + *x = SignedBlindedBeaconBlockBellatrix{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2150,13 +2125,13 @@ func (x *SignedBeaconBlockContentsDeneb) Reset() { } } -func (x *SignedBeaconBlockContentsDeneb) String() string { +func (x *SignedBlindedBeaconBlockBellatrix) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBeaconBlockContentsDeneb) ProtoMessage() {} +func (*SignedBlindedBeaconBlockBellatrix) ProtoMessage() {} -func (x *SignedBeaconBlockContentsDeneb) ProtoReflect() protoreflect.Message { +func (x *SignedBlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2168,44 +2143,39 @@ func (x *SignedBeaconBlockContentsDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBeaconBlockContentsDeneb.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockContentsDeneb) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBlindedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. +func (*SignedBlindedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{26} } -func (x *SignedBeaconBlockContentsDeneb) GetBlock() *SignedBeaconBlockDeneb { +func (x *SignedBlindedBeaconBlockBellatrix) GetBlock() *BlindedBeaconBlockBellatrix { if x != nil { return x.Block } return nil } -func (x *SignedBeaconBlockContentsDeneb) GetKzgProofs() [][]byte { - if x != nil { - return x.KzgProofs - } - return nil -} - -func (x *SignedBeaconBlockContentsDeneb) GetBlobs() [][]byte { +func (x *SignedBlindedBeaconBlockBellatrix) GetSignature() []byte { if x != nil { - return x.Blobs + return x.Signature } return nil } -type BeaconBlockContentsDeneb struct { +type BlindedBeaconBlockBellatrix struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *BeaconBlockDeneb `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` - Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + Body *BlindedBeaconBlockBodyBellatrix `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` } -func (x *BeaconBlockContentsDeneb) Reset() { - *x = BeaconBlockContentsDeneb{} +func (x *BlindedBeaconBlockBellatrix) Reset() { + *x = BlindedBeaconBlockBellatrix{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2213,13 +2183,13 @@ func (x *BeaconBlockContentsDeneb) Reset() { } } -func (x *BeaconBlockContentsDeneb) String() string { +func (x *BlindedBeaconBlockBellatrix) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockContentsDeneb) ProtoMessage() {} +func (*BlindedBeaconBlockBellatrix) ProtoMessage() {} -func (x *BeaconBlockContentsDeneb) ProtoReflect() protoreflect.Message { +func (x *BlindedBeaconBlockBellatrix) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2231,43 +2201,65 @@ func (x *BeaconBlockContentsDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockContentsDeneb.ProtoReflect.Descriptor instead. -func (*BeaconBlockContentsDeneb) Descriptor() ([]byte, []int) { +// Deprecated: Use BlindedBeaconBlockBellatrix.ProtoReflect.Descriptor instead. +func (*BlindedBeaconBlockBellatrix) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{27} } -func (x *BeaconBlockContentsDeneb) GetBlock() *BeaconBlockDeneb { +func (x *BlindedBeaconBlockBellatrix) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { - return x.Block + return x.Slot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +func (x *BlindedBeaconBlockBellatrix) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { + if x != nil { + return x.ProposerIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *BlindedBeaconBlockBellatrix) GetParentRoot() []byte { + if x != nil { + return x.ParentRoot } return nil } -func (x *BeaconBlockContentsDeneb) GetKzgProofs() [][]byte { +func (x *BlindedBeaconBlockBellatrix) GetStateRoot() []byte { if x != nil { - return x.KzgProofs + return x.StateRoot } return nil } -func (x *BeaconBlockContentsDeneb) GetBlobs() [][]byte { +func (x *BlindedBeaconBlockBellatrix) GetBody() *BlindedBeaconBlockBodyBellatrix { if x != nil { - return x.Blobs + return x.Body } return nil } -type SignedBeaconBlockDeneb struct { +type BlindedBeaconBlockBodyBellatrix struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *BeaconBlockDeneb `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` + Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` + Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` + ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` + AttesterSlashings []*AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` + Attestations []*Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` + Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` + VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` + SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + ExecutionPayloadHeader *v1.ExecutionPayloadHeader `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` } -func (x *SignedBeaconBlockDeneb) Reset() { - *x = SignedBeaconBlockDeneb{} +func (x *BlindedBeaconBlockBodyBellatrix) Reset() { + *x = BlindedBeaconBlockBodyBellatrix{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2275,13 +2267,13 @@ func (x *SignedBeaconBlockDeneb) Reset() { } } -func (x *SignedBeaconBlockDeneb) String() string { +func (x *BlindedBeaconBlockBodyBellatrix) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBeaconBlockDeneb) ProtoMessage() {} +func (*BlindedBeaconBlockBodyBellatrix) ProtoMessage() {} -func (x *SignedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { +func (x *BlindedBeaconBlockBodyBellatrix) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -2293,140 +2285,107 @@ func (x *SignedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBeaconBlockDeneb.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockDeneb) Descriptor() ([]byte, []int) { +// Deprecated: Use BlindedBeaconBlockBodyBellatrix.ProtoReflect.Descriptor instead. +func (*BlindedBeaconBlockBodyBellatrix) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{28} } -func (x *SignedBeaconBlockDeneb) GetBlock() *BeaconBlockDeneb { +func (x *BlindedBeaconBlockBodyBellatrix) GetRandaoReveal() []byte { if x != nil { - return x.Block + return x.RandaoReveal } return nil } -func (x *SignedBeaconBlockDeneb) GetSignature() []byte { +func (x *BlindedBeaconBlockBodyBellatrix) GetEth1Data() *Eth1Data { if x != nil { - return x.Signature + return x.Eth1Data } return nil } -type BeaconBlockDeneb struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyDeneb `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` -} - -func (x *BeaconBlockDeneb) Reset() { - *x = BeaconBlockDeneb{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) +func (x *BlindedBeaconBlockBodyBellatrix) GetGraffiti() []byte { + if x != nil { + return x.Graffiti } + return nil } -func (x *BeaconBlockDeneb) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconBlockDeneb) ProtoMessage() {} - -func (x *BeaconBlockDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms +func (x *BlindedBeaconBlockBodyBellatrix) GetProposerSlashings() []*ProposerSlashing { + if x != nil { + return x.ProposerSlashings } - return mi.MessageOf(x) + return nil } -// Deprecated: Use BeaconBlockDeneb.ProtoReflect.Descriptor instead. -func (*BeaconBlockDeneb) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{29} +func (x *BlindedBeaconBlockBodyBellatrix) GetAttesterSlashings() []*AttesterSlashing { + if x != nil { + return x.AttesterSlashings + } + return nil } -func (x *BeaconBlockDeneb) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { +func (x *BlindedBeaconBlockBodyBellatrix) GetAttestations() []*Attestation { if x != nil { - return x.Slot + return x.Attestations } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) + return nil } -func (x *BeaconBlockDeneb) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { +func (x *BlindedBeaconBlockBodyBellatrix) GetDeposits() []*Deposit { if x != nil { - return x.ProposerIndex + return x.Deposits } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) + return nil } -func (x *BeaconBlockDeneb) GetParentRoot() []byte { +func (x *BlindedBeaconBlockBodyBellatrix) GetVoluntaryExits() []*SignedVoluntaryExit { if x != nil { - return x.ParentRoot + return x.VoluntaryExits } return nil } -func (x *BeaconBlockDeneb) GetStateRoot() []byte { +func (x *BlindedBeaconBlockBodyBellatrix) GetSyncAggregate() *SyncAggregate { if x != nil { - return x.StateRoot + return x.SyncAggregate } return nil } -func (x *BeaconBlockDeneb) GetBody() *BeaconBlockBodyDeneb { +func (x *BlindedBeaconBlockBodyBellatrix) GetExecutionPayloadHeader() *v1.ExecutionPayloadHeader { if x != nil { - return x.Body + return x.ExecutionPayloadHeader } return nil } -type BeaconBlockBodyDeneb struct { +type SignedBeaconBlockCapella struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayload *v1.ExecutionPayloadDeneb `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` - BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` - BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Block *BeaconBlockCapella `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *BeaconBlockBodyDeneb) Reset() { - *x = BeaconBlockBodyDeneb{} +func (x *SignedBeaconBlockCapella) Reset() { + *x = SignedBeaconBlockCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[30] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BeaconBlockBodyDeneb) String() string { +func (x *SignedBeaconBlockCapella) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockBodyDeneb) ProtoMessage() {} +func (*SignedBeaconBlockCapella) ProtoMessage() {} -func (x *BeaconBlockBodyDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[30] +func (x *SignedBeaconBlockCapella) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2437,166 +2396,41 @@ func (x *BeaconBlockBodyDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockBodyDeneb.ProtoReflect.Descriptor instead. -func (*BeaconBlockBodyDeneb) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{30} +// Deprecated: Use SignedBeaconBlockCapella.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockCapella) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{29} } -func (x *BeaconBlockBodyDeneb) GetRandaoReveal() []byte { +func (x *SignedBeaconBlockCapella) GetBlock() *BeaconBlockCapella { if x != nil { - return x.RandaoReveal + return x.Block } return nil } -func (x *BeaconBlockBodyDeneb) GetEth1Data() *Eth1Data { +func (x *SignedBeaconBlockCapella) GetSignature() []byte { if x != nil { - return x.Eth1Data + return x.Signature } return nil } -func (x *BeaconBlockBodyDeneb) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetProposerSlashings() []*ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetAttesterSlashings() []*AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetAttestations() []*Attestation { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetDeposits() []*Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetVoluntaryExits() []*SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetSyncAggregate() *SyncAggregate { - if x != nil { - return x.SyncAggregate - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetExecutionPayload() *v1.ExecutionPayloadDeneb { - if x != nil { - return x.ExecutionPayload - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { - if x != nil { - return x.BlsToExecutionChanges - } - return nil -} - -func (x *BeaconBlockBodyDeneb) GetBlobKzgCommitments() [][]byte { - if x != nil { - return x.BlobKzgCommitments - } - return nil -} - -type SignedBeaconBlockCapella struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Block *BeaconBlockCapella `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBeaconBlockCapella) Reset() { - *x = SignedBeaconBlockCapella{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBeaconBlockCapella) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBeaconBlockCapella) ProtoMessage() {} - -func (x *SignedBeaconBlockCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBeaconBlockCapella.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockCapella) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{31} -} - -func (x *SignedBeaconBlockCapella) GetBlock() *BeaconBlockCapella { - if x != nil { - return x.Block - } - return nil -} - -func (x *SignedBeaconBlockCapella) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -type BeaconBlockCapella struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyCapella `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` +type BeaconBlockCapella struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + Body *BeaconBlockBodyCapella `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` } func (x *BeaconBlockCapella) Reset() { *x = BeaconBlockCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[32] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2609,7 +2443,7 @@ func (x *BeaconBlockCapella) String() string { func (*BeaconBlockCapella) ProtoMessage() {} func (x *BeaconBlockCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[32] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2622,7 +2456,7 @@ func (x *BeaconBlockCapella) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconBlockCapella.ProtoReflect.Descriptor instead. func (*BeaconBlockCapella) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{32} + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{30} } func (x *BeaconBlockCapella) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { @@ -2681,7 +2515,7 @@ type BeaconBlockBodyCapella struct { func (x *BeaconBlockBodyCapella) Reset() { *x = BeaconBlockBodyCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[33] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2694,7 +2528,7 @@ func (x *BeaconBlockBodyCapella) String() string { func (*BeaconBlockBodyCapella) ProtoMessage() {} func (x *BeaconBlockBodyCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[33] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2707,7 +2541,7 @@ func (x *BeaconBlockBodyCapella) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconBlockBodyCapella.ProtoReflect.Descriptor instead. func (*BeaconBlockBodyCapella) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{33} + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{31} } func (x *BeaconBlockBodyCapella) GetRandaoReveal() []byte { @@ -2799,7 +2633,7 @@ type SignedBlindedBeaconBlockCapella struct { func (x *SignedBlindedBeaconBlockCapella) Reset() { *x = SignedBlindedBeaconBlockCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[34] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2812,7 +2646,7 @@ func (x *SignedBlindedBeaconBlockCapella) String() string { func (*SignedBlindedBeaconBlockCapella) ProtoMessage() {} func (x *SignedBlindedBeaconBlockCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[34] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2825,7 +2659,7 @@ func (x *SignedBlindedBeaconBlockCapella) ProtoReflect() protoreflect.Message { // Deprecated: Use SignedBlindedBeaconBlockCapella.ProtoReflect.Descriptor instead. func (*SignedBlindedBeaconBlockCapella) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{34} + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{32} } func (x *SignedBlindedBeaconBlockCapella) GetBlock() *BlindedBeaconBlockCapella { @@ -2857,7 +2691,7 @@ type BlindedBeaconBlockCapella struct { func (x *BlindedBeaconBlockCapella) Reset() { *x = BlindedBeaconBlockCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[35] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2870,7 +2704,7 @@ func (x *BlindedBeaconBlockCapella) String() string { func (*BlindedBeaconBlockCapella) ProtoMessage() {} func (x *BlindedBeaconBlockCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[35] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2883,7 +2717,7 @@ func (x *BlindedBeaconBlockCapella) ProtoReflect() protoreflect.Message { // Deprecated: Use BlindedBeaconBlockCapella.ProtoReflect.Descriptor instead. func (*BlindedBeaconBlockCapella) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{35} + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{33} } func (x *BlindedBeaconBlockCapella) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { @@ -2942,7 +2776,7 @@ type BlindedBeaconBlockBodyCapella struct { func (x *BlindedBeaconBlockBodyCapella) Reset() { *x = BlindedBeaconBlockBodyCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[36] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2955,7 +2789,7 @@ func (x *BlindedBeaconBlockBodyCapella) String() string { func (*BlindedBeaconBlockBodyCapella) ProtoMessage() {} func (x *BlindedBeaconBlockBodyCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[36] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2968,7 +2802,7 @@ func (x *BlindedBeaconBlockBodyCapella) ProtoReflect() protoreflect.Message { // Deprecated: Use BlindedBeaconBlockBodyCapella.ProtoReflect.Descriptor instead. func (*BlindedBeaconBlockBodyCapella) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{36} + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{34} } func (x *BlindedBeaconBlockBodyCapella) GetRandaoReveal() []byte { @@ -3048,32 +2882,32 @@ func (x *BlindedBeaconBlockBodyCapella) GetBlsToExecutionChanges() []*SignedBLST return nil } -type SignedBlindedBeaconBlockDeneb struct { +type SignedBuilderBidCapella struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *BlindedBeaconBlockDeneb `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Message *BuilderBidCapella `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SignedBlindedBeaconBlockDeneb) Reset() { - *x = SignedBlindedBeaconBlockDeneb{} +func (x *SignedBuilderBidCapella) Reset() { + *x = SignedBuilderBidCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[37] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *SignedBlindedBeaconBlockDeneb) String() string { +func (x *SignedBuilderBidCapella) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBlindedBeaconBlockDeneb) ProtoMessage() {} +func (*SignedBuilderBidCapella) ProtoMessage() {} -func (x *SignedBlindedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[37] +func (x *SignedBuilderBidCapella) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3084,54 +2918,52 @@ func (x *SignedBlindedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBlindedBeaconBlockDeneb.ProtoReflect.Descriptor instead. -func (*SignedBlindedBeaconBlockDeneb) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{37} +// Deprecated: Use SignedBuilderBidCapella.ProtoReflect.Descriptor instead. +func (*SignedBuilderBidCapella) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{35} } -func (x *SignedBlindedBeaconBlockDeneb) GetMessage() *BlindedBeaconBlockDeneb { +func (x *SignedBuilderBidCapella) GetMessage() *BuilderBidCapella { if x != nil { return x.Message } return nil } -func (x *SignedBlindedBeaconBlockDeneb) GetSignature() []byte { +func (x *SignedBuilderBidCapella) GetSignature() []byte { if x != nil { return x.Signature } return nil } -type BlindedBeaconBlockDeneb struct { +type BuilderBidCapella struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BlindedBeaconBlockBodyDeneb `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` + Header *v1.ExecutionPayloadHeaderCapella `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty" ssz-size:"32"` + Pubkey []byte `protobuf:"bytes,3,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` } -func (x *BlindedBeaconBlockDeneb) Reset() { - *x = BlindedBeaconBlockDeneb{} +func (x *BuilderBidCapella) Reset() { + *x = BuilderBidCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[38] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BlindedBeaconBlockDeneb) String() string { +func (x *BuilderBidCapella) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BlindedBeaconBlockDeneb) ProtoMessage() {} +func (*BuilderBidCapella) ProtoMessage() {} -func (x *BlindedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[38] +func (x *BuilderBidCapella) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3142,82 +2974,59 @@ func (x *BlindedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BlindedBeaconBlockDeneb.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockDeneb) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{38} -} - -func (x *BlindedBeaconBlockDeneb) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BlindedBeaconBlockDeneb) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ProposerIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +// Deprecated: Use BuilderBidCapella.ProtoReflect.Descriptor instead. +func (*BuilderBidCapella) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{36} } -func (x *BlindedBeaconBlockDeneb) GetParentRoot() []byte { +func (x *BuilderBidCapella) GetHeader() *v1.ExecutionPayloadHeaderCapella { if x != nil { - return x.ParentRoot + return x.Header } return nil } -func (x *BlindedBeaconBlockDeneb) GetStateRoot() []byte { +func (x *BuilderBidCapella) GetValue() []byte { if x != nil { - return x.StateRoot + return x.Value } return nil } -func (x *BlindedBeaconBlockDeneb) GetBody() *BlindedBeaconBlockBodyDeneb { +func (x *BuilderBidCapella) GetPubkey() []byte { if x != nil { - return x.Body + return x.Pubkey } return nil } -type BlindedBeaconBlockBodyDeneb struct { +type SignedBeaconBlockContentsDeneb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` - Attestations []*Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` - Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayloadHeader *v1.ExecutionPayloadHeaderDeneb `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` - BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` - BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Block *SignedBeaconBlockDeneb `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` } -func (x *BlindedBeaconBlockBodyDeneb) Reset() { - *x = BlindedBeaconBlockBodyDeneb{} +func (x *SignedBeaconBlockContentsDeneb) Reset() { + *x = SignedBeaconBlockContentsDeneb{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[39] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BlindedBeaconBlockBodyDeneb) String() string { +func (x *SignedBeaconBlockContentsDeneb) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BlindedBeaconBlockBodyDeneb) ProtoMessage() {} +func (*SignedBeaconBlockContentsDeneb) ProtoMessage() {} -func (x *BlindedBeaconBlockBodyDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[39] +func (x *SignedBeaconBlockContentsDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3228,122 +3037,114 @@ func (x *BlindedBeaconBlockBodyDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BlindedBeaconBlockBodyDeneb.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockBodyDeneb) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{39} +// Deprecated: Use SignedBeaconBlockContentsDeneb.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockContentsDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{37} } -func (x *BlindedBeaconBlockBodyDeneb) GetRandaoReveal() []byte { +func (x *SignedBeaconBlockContentsDeneb) GetBlock() *SignedBeaconBlockDeneb { if x != nil { - return x.RandaoReveal + return x.Block } return nil } -func (x *BlindedBeaconBlockBodyDeneb) GetEth1Data() *Eth1Data { +func (x *SignedBeaconBlockContentsDeneb) GetKzgProofs() [][]byte { if x != nil { - return x.Eth1Data + return x.KzgProofs } return nil } -func (x *BlindedBeaconBlockBodyDeneb) GetGraffiti() []byte { +func (x *SignedBeaconBlockContentsDeneb) GetBlobs() [][]byte { if x != nil { - return x.Graffiti + return x.Blobs } return nil } -func (x *BlindedBeaconBlockBodyDeneb) GetProposerSlashings() []*ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} +type SignedBeaconBlockDeneb struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (x *BlindedBeaconBlockBodyDeneb) GetAttesterSlashings() []*AttesterSlashing { - if x != nil { - return x.AttesterSlashings - } - return nil + Block *BeaconBlockDeneb `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *BlindedBeaconBlockBodyDeneb) GetAttestations() []*Attestation { - if x != nil { - return x.Attestations +func (x *SignedBeaconBlockDeneb) Reset() { + *x = SignedBeaconBlockDeneb{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return nil } -func (x *BlindedBeaconBlockBodyDeneb) GetDeposits() []*Deposit { - if x != nil { - return x.Deposits - } - return nil +func (x *SignedBeaconBlockDeneb) String() string { + return protoimpl.X.MessageStringOf(x) } -func (x *BlindedBeaconBlockBodyDeneb) GetVoluntaryExits() []*SignedVoluntaryExit { - if x != nil { - return x.VoluntaryExits - } - return nil -} +func (*SignedBeaconBlockDeneb) ProtoMessage() {} -func (x *BlindedBeaconBlockBodyDeneb) GetSyncAggregate() *SyncAggregate { - if x != nil { - return x.SyncAggregate +func (x *SignedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[38] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return nil + return mi.MessageOf(x) } -func (x *BlindedBeaconBlockBodyDeneb) GetExecutionPayloadHeader() *v1.ExecutionPayloadHeaderDeneb { - if x != nil { - return x.ExecutionPayloadHeader - } - return nil +// Deprecated: Use SignedBeaconBlockDeneb.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{38} } -func (x *BlindedBeaconBlockBodyDeneb) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { +func (x *SignedBeaconBlockDeneb) GetBlock() *BeaconBlockDeneb { if x != nil { - return x.BlsToExecutionChanges + return x.Block } return nil } -func (x *BlindedBeaconBlockBodyDeneb) GetBlobKzgCommitments() [][]byte { +func (x *SignedBeaconBlockDeneb) GetSignature() []byte { if x != nil { - return x.BlobKzgCommitments + return x.Signature } return nil } -type SignedBeaconBlockContentsElectra struct { +type BeaconBlockContentsDeneb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *SignedBeaconBlockElectra `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` - Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` + Block *BeaconBlockDeneb `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` } -func (x *SignedBeaconBlockContentsElectra) Reset() { - *x = SignedBeaconBlockContentsElectra{} +func (x *BeaconBlockContentsDeneb) Reset() { + *x = BeaconBlockContentsDeneb{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[40] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *SignedBeaconBlockContentsElectra) String() string { +func (x *BeaconBlockContentsDeneb) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBeaconBlockContentsElectra) ProtoMessage() {} +func (*BeaconBlockContentsDeneb) ProtoMessage() {} -func (x *SignedBeaconBlockContentsElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[40] +func (x *BeaconBlockContentsDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3354,59 +3155,61 @@ func (x *SignedBeaconBlockContentsElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBeaconBlockContentsElectra.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockContentsElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{40} +// Deprecated: Use BeaconBlockContentsDeneb.ProtoReflect.Descriptor instead. +func (*BeaconBlockContentsDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{39} } -func (x *SignedBeaconBlockContentsElectra) GetBlock() *SignedBeaconBlockElectra { +func (x *BeaconBlockContentsDeneb) GetBlock() *BeaconBlockDeneb { if x != nil { return x.Block } return nil } -func (x *SignedBeaconBlockContentsElectra) GetKzgProofs() [][]byte { +func (x *BeaconBlockContentsDeneb) GetKzgProofs() [][]byte { if x != nil { return x.KzgProofs } return nil } -func (x *SignedBeaconBlockContentsElectra) GetBlobs() [][]byte { +func (x *BeaconBlockContentsDeneb) GetBlobs() [][]byte { if x != nil { return x.Blobs } return nil } -type BeaconBlockContentsElectra struct { +type BeaconBlockDeneb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *BeaconBlockElectra `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` - Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + Body *BeaconBlockBodyDeneb `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` } -func (x *BeaconBlockContentsElectra) Reset() { - *x = BeaconBlockContentsElectra{} +func (x *BeaconBlockDeneb) Reset() { + *x = BeaconBlockDeneb{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[41] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BeaconBlockContentsElectra) String() string { +func (x *BeaconBlockDeneb) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockContentsElectra) ProtoMessage() {} +func (*BeaconBlockDeneb) ProtoMessage() {} -func (x *BeaconBlockContentsElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[41] +func (x *BeaconBlockDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3417,58 +3220,82 @@ func (x *BeaconBlockContentsElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockContentsElectra.ProtoReflect.Descriptor instead. -func (*BeaconBlockContentsElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{41} +// Deprecated: Use BeaconBlockDeneb.ProtoReflect.Descriptor instead. +func (*BeaconBlockDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{40} } -func (x *BeaconBlockContentsElectra) GetBlock() *BeaconBlockElectra { +func (x *BeaconBlockDeneb) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { - return x.Block + return x.Slot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +func (x *BeaconBlockDeneb) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { + if x != nil { + return x.ProposerIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *BeaconBlockDeneb) GetParentRoot() []byte { + if x != nil { + return x.ParentRoot } return nil } -func (x *BeaconBlockContentsElectra) GetKzgProofs() [][]byte { +func (x *BeaconBlockDeneb) GetStateRoot() []byte { if x != nil { - return x.KzgProofs + return x.StateRoot } return nil } -func (x *BeaconBlockContentsElectra) GetBlobs() [][]byte { +func (x *BeaconBlockDeneb) GetBody() *BeaconBlockBodyDeneb { if x != nil { - return x.Blobs + return x.Body } return nil } -type SignedBeaconBlockElectra struct { +type BeaconBlockBodyDeneb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Block *BeaconBlockElectra `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` + Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` + Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` + ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` + AttesterSlashings []*AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` + Attestations []*Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` + Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` + VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` + SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + ExecutionPayload *v1.ExecutionPayloadDeneb `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` + BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` + BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` } -func (x *SignedBeaconBlockElectra) Reset() { - *x = SignedBeaconBlockElectra{} +func (x *BeaconBlockBodyDeneb) Reset() { + *x = BeaconBlockBodyDeneb{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[42] + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *SignedBeaconBlockElectra) String() string { +func (x *BeaconBlockBodyDeneb) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBeaconBlockElectra) ProtoMessage() {} +func (*BeaconBlockBodyDeneb) ProtoMessage() {} -func (x *SignedBeaconBlockElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[42] +func (x *BeaconBlockBodyDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3479,39 +3306,164 @@ func (x *SignedBeaconBlockElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBeaconBlockElectra.ProtoReflect.Descriptor instead. -func (*SignedBeaconBlockElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{42} +// Deprecated: Use BeaconBlockBodyDeneb.ProtoReflect.Descriptor instead. +func (*BeaconBlockBodyDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{41} } -func (x *SignedBeaconBlockElectra) GetBlock() *BeaconBlockElectra { +func (x *BeaconBlockBodyDeneb) GetRandaoReveal() []byte { if x != nil { - return x.Block + return x.RandaoReveal } return nil } -func (x *SignedBeaconBlockElectra) GetSignature() []byte { +func (x *BeaconBlockBodyDeneb) GetEth1Data() *Eth1Data { if x != nil { - return x.Signature + return x.Eth1Data } return nil } -type BeaconBlockElectra struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BeaconBlockBodyElectra `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` +func (x *BeaconBlockBodyDeneb) GetGraffiti() []byte { + if x != nil { + return x.Graffiti + } + return nil } -func (x *BeaconBlockElectra) Reset() { - *x = BeaconBlockElectra{} +func (x *BeaconBlockBodyDeneb) GetProposerSlashings() []*ProposerSlashing { + if x != nil { + return x.ProposerSlashings + } + return nil +} + +func (x *BeaconBlockBodyDeneb) GetAttesterSlashings() []*AttesterSlashing { + if x != nil { + return x.AttesterSlashings + } + return nil +} + +func (x *BeaconBlockBodyDeneb) GetAttestations() []*Attestation { + if x != nil { + return x.Attestations + } + return nil +} + +func (x *BeaconBlockBodyDeneb) GetDeposits() []*Deposit { + if x != nil { + return x.Deposits + } + return nil +} + +func (x *BeaconBlockBodyDeneb) GetVoluntaryExits() []*SignedVoluntaryExit { + if x != nil { + return x.VoluntaryExits + } + return nil +} + +func (x *BeaconBlockBodyDeneb) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *BeaconBlockBodyDeneb) GetExecutionPayload() *v1.ExecutionPayloadDeneb { + if x != nil { + return x.ExecutionPayload + } + return nil +} + +func (x *BeaconBlockBodyDeneb) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { + if x != nil { + return x.BlsToExecutionChanges + } + return nil +} + +func (x *BeaconBlockBodyDeneb) GetBlobKzgCommitments() [][]byte { + if x != nil { + return x.BlobKzgCommitments + } + return nil +} + +type SignedBlindedBeaconBlockDeneb struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message *BlindedBeaconBlockDeneb `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *SignedBlindedBeaconBlockDeneb) Reset() { + *x = SignedBlindedBeaconBlockDeneb{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedBlindedBeaconBlockDeneb) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedBlindedBeaconBlockDeneb) ProtoMessage() {} + +func (x *SignedBlindedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedBlindedBeaconBlockDeneb.ProtoReflect.Descriptor instead. +func (*SignedBlindedBeaconBlockDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{42} +} + +func (x *SignedBlindedBeaconBlockDeneb) GetMessage() *BlindedBeaconBlockDeneb { + if x != nil { + return x.Message + } + return nil +} + +func (x *SignedBlindedBeaconBlockDeneb) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +type BlindedBeaconBlockDeneb struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + Body *BlindedBeaconBlockBodyDeneb `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` +} + +func (x *BlindedBeaconBlockDeneb) Reset() { + *x = BlindedBeaconBlockDeneb{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3519,13 +3471,13 @@ func (x *BeaconBlockElectra) Reset() { } } -func (x *BeaconBlockElectra) String() string { +func (x *BlindedBeaconBlockDeneb) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockElectra) ProtoMessage() {} +func (*BlindedBeaconBlockDeneb) ProtoMessage() {} -func (x *BeaconBlockElectra) ProtoReflect() protoreflect.Message { +func (x *BlindedBeaconBlockDeneb) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3537,67 +3489,67 @@ func (x *BeaconBlockElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockElectra.ProtoReflect.Descriptor instead. -func (*BeaconBlockElectra) Descriptor() ([]byte, []int) { +// Deprecated: Use BlindedBeaconBlockDeneb.ProtoReflect.Descriptor instead. +func (*BlindedBeaconBlockDeneb) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{43} } -func (x *BeaconBlockElectra) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { +func (x *BlindedBeaconBlockDeneb) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { return x.Slot } return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) } -func (x *BeaconBlockElectra) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { +func (x *BlindedBeaconBlockDeneb) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { return x.ProposerIndex } return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) } -func (x *BeaconBlockElectra) GetParentRoot() []byte { +func (x *BlindedBeaconBlockDeneb) GetParentRoot() []byte { if x != nil { return x.ParentRoot } return nil } -func (x *BeaconBlockElectra) GetStateRoot() []byte { +func (x *BlindedBeaconBlockDeneb) GetStateRoot() []byte { if x != nil { return x.StateRoot } return nil } -func (x *BeaconBlockElectra) GetBody() *BeaconBlockBodyElectra { +func (x *BlindedBeaconBlockDeneb) GetBody() *BlindedBeaconBlockBodyDeneb { if x != nil { return x.Body } return nil } -type BeaconBlockBodyElectra struct { +type BlindedBeaconBlockBodyDeneb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*AttesterSlashingElectra `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"1"` - Attestations []*AttestationElectra `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"8"` - Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayload *v1.ExecutionPayloadElectra `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` - BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` - BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` + Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` + Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` + ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` + AttesterSlashings []*AttesterSlashing `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"2"` + Attestations []*Attestation `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"128"` + Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` + VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` + SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + ExecutionPayloadHeader *v1.ExecutionPayloadHeaderDeneb `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` + BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` + BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` } -func (x *BeaconBlockBodyElectra) Reset() { - *x = BeaconBlockBodyElectra{} +func (x *BlindedBeaconBlockBodyDeneb) Reset() { + *x = BlindedBeaconBlockBodyDeneb{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3605,13 +3557,13 @@ func (x *BeaconBlockBodyElectra) Reset() { } } -func (x *BeaconBlockBodyElectra) String() string { +func (x *BlindedBeaconBlockBodyDeneb) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BeaconBlockBodyElectra) ProtoMessage() {} +func (*BlindedBeaconBlockBodyDeneb) ProtoMessage() {} -func (x *BeaconBlockBodyElectra) ProtoReflect() protoreflect.Message { +func (x *BlindedBeaconBlockBodyDeneb) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3623,106 +3575,106 @@ func (x *BeaconBlockBodyElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BeaconBlockBodyElectra.ProtoReflect.Descriptor instead. -func (*BeaconBlockBodyElectra) Descriptor() ([]byte, []int) { +// Deprecated: Use BlindedBeaconBlockBodyDeneb.ProtoReflect.Descriptor instead. +func (*BlindedBeaconBlockBodyDeneb) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{44} } -func (x *BeaconBlockBodyElectra) GetRandaoReveal() []byte { +func (x *BlindedBeaconBlockBodyDeneb) GetRandaoReveal() []byte { if x != nil { return x.RandaoReveal } return nil } -func (x *BeaconBlockBodyElectra) GetEth1Data() *Eth1Data { +func (x *BlindedBeaconBlockBodyDeneb) GetEth1Data() *Eth1Data { if x != nil { return x.Eth1Data } return nil } -func (x *BeaconBlockBodyElectra) GetGraffiti() []byte { +func (x *BlindedBeaconBlockBodyDeneb) GetGraffiti() []byte { if x != nil { return x.Graffiti } return nil } -func (x *BeaconBlockBodyElectra) GetProposerSlashings() []*ProposerSlashing { +func (x *BlindedBeaconBlockBodyDeneb) GetProposerSlashings() []*ProposerSlashing { if x != nil { return x.ProposerSlashings } return nil } -func (x *BeaconBlockBodyElectra) GetAttesterSlashings() []*AttesterSlashingElectra { +func (x *BlindedBeaconBlockBodyDeneb) GetAttesterSlashings() []*AttesterSlashing { if x != nil { return x.AttesterSlashings } return nil } -func (x *BeaconBlockBodyElectra) GetAttestations() []*AttestationElectra { +func (x *BlindedBeaconBlockBodyDeneb) GetAttestations() []*Attestation { if x != nil { return x.Attestations } return nil } -func (x *BeaconBlockBodyElectra) GetDeposits() []*Deposit { +func (x *BlindedBeaconBlockBodyDeneb) GetDeposits() []*Deposit { if x != nil { return x.Deposits } return nil } -func (x *BeaconBlockBodyElectra) GetVoluntaryExits() []*SignedVoluntaryExit { +func (x *BlindedBeaconBlockBodyDeneb) GetVoluntaryExits() []*SignedVoluntaryExit { if x != nil { return x.VoluntaryExits } return nil } -func (x *BeaconBlockBodyElectra) GetSyncAggregate() *SyncAggregate { +func (x *BlindedBeaconBlockBodyDeneb) GetSyncAggregate() *SyncAggregate { if x != nil { return x.SyncAggregate } return nil } -func (x *BeaconBlockBodyElectra) GetExecutionPayload() *v1.ExecutionPayloadElectra { +func (x *BlindedBeaconBlockBodyDeneb) GetExecutionPayloadHeader() *v1.ExecutionPayloadHeaderDeneb { if x != nil { - return x.ExecutionPayload + return x.ExecutionPayloadHeader } return nil } -func (x *BeaconBlockBodyElectra) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { +func (x *BlindedBeaconBlockBodyDeneb) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { if x != nil { return x.BlsToExecutionChanges } return nil } -func (x *BeaconBlockBodyElectra) GetBlobKzgCommitments() [][]byte { +func (x *BlindedBeaconBlockBodyDeneb) GetBlobKzgCommitments() [][]byte { if x != nil { return x.BlobKzgCommitments } return nil } -type SignedBlindedBeaconBlockElectra struct { +type SignedBuilderBidDeneb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *BlindedBeaconBlockElectra `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Message *BuilderBidDeneb `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SignedBlindedBeaconBlockElectra) Reset() { - *x = SignedBlindedBeaconBlockElectra{} +func (x *SignedBuilderBidDeneb) Reset() { + *x = SignedBuilderBidDeneb{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3730,13 +3682,13 @@ func (x *SignedBlindedBeaconBlockElectra) Reset() { } } -func (x *SignedBlindedBeaconBlockElectra) String() string { +func (x *SignedBuilderBidDeneb) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBlindedBeaconBlockElectra) ProtoMessage() {} +func (*SignedBuilderBidDeneb) ProtoMessage() {} -func (x *SignedBlindedBeaconBlockElectra) ProtoReflect() protoreflect.Message { +func (x *SignedBuilderBidDeneb) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3748,53 +3700,52 @@ func (x *SignedBlindedBeaconBlockElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBlindedBeaconBlockElectra.ProtoReflect.Descriptor instead. -func (*SignedBlindedBeaconBlockElectra) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBuilderBidDeneb.ProtoReflect.Descriptor instead. +func (*SignedBuilderBidDeneb) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{45} } -func (x *SignedBlindedBeaconBlockElectra) GetMessage() *BlindedBeaconBlockElectra { +func (x *SignedBuilderBidDeneb) GetMessage() *BuilderBidDeneb { if x != nil { return x.Message } return nil } -func (x *SignedBlindedBeaconBlockElectra) GetSignature() []byte { +func (x *SignedBuilderBidDeneb) GetSignature() []byte { if x != nil { return x.Signature } return nil } -type BlindedBeaconBlockElectra struct { +type BuilderBidDeneb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` - StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` - Body *BlindedBeaconBlockBodyElectra `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` + Header *v1.ExecutionPayloadHeaderDeneb `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + BlobKzgCommitments [][]byte `protobuf:"bytes,2,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty" ssz-size:"32"` + Pubkey []byte `protobuf:"bytes,4,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` } -func (x *BlindedBeaconBlockElectra) Reset() { - *x = BlindedBeaconBlockElectra{} - if protoimpl.UnsafeEnabled { +func (x *BuilderBidDeneb) Reset() { + *x = BuilderBidDeneb{} + if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *BlindedBeaconBlockElectra) String() string { +func (x *BuilderBidDeneb) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BlindedBeaconBlockElectra) ProtoMessage() {} +func (*BuilderBidDeneb) ProtoMessage() {} -func (x *BlindedBeaconBlockElectra) ProtoReflect() protoreflect.Message { +func (x *BuilderBidDeneb) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3806,67 +3757,53 @@ func (x *BlindedBeaconBlockElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BlindedBeaconBlockElectra.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockElectra) Descriptor() ([]byte, []int) { +// Deprecated: Use BuilderBidDeneb.ProtoReflect.Descriptor instead. +func (*BuilderBidDeneb) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{46} } -func (x *BlindedBeaconBlockElectra) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BlindedBeaconBlockElectra) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { +func (x *BuilderBidDeneb) GetHeader() *v1.ExecutionPayloadHeaderDeneb { if x != nil { - return x.ProposerIndex + return x.Header } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) + return nil } -func (x *BlindedBeaconBlockElectra) GetParentRoot() []byte { +func (x *BuilderBidDeneb) GetBlobKzgCommitments() [][]byte { if x != nil { - return x.ParentRoot + return x.BlobKzgCommitments } return nil } -func (x *BlindedBeaconBlockElectra) GetStateRoot() []byte { +func (x *BuilderBidDeneb) GetValue() []byte { if x != nil { - return x.StateRoot + return x.Value } return nil } -func (x *BlindedBeaconBlockElectra) GetBody() *BlindedBeaconBlockBodyElectra { +func (x *BuilderBidDeneb) GetPubkey() []byte { if x != nil { - return x.Body + return x.Pubkey } return nil } -type BlindedBeaconBlockBodyElectra struct { +type BuilderBidElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` - Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` - ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` - AttesterSlashings []*AttesterSlashingElectra `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"1"` - Attestations []*AttestationElectra `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"8"` - Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` - VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` - SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` - ExecutionPayloadHeader *v1.ExecutionPayloadHeaderElectra `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` - BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` - BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Header *v1.ExecutionPayloadHeaderDeneb `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + BlobKzgCommitments [][]byte `protobuf:"bytes,2,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + ExecutionRequests *v1.ExecutionRequests `protobuf:"bytes,3,opt,name=execution_requests,json=executionRequests,proto3" json:"execution_requests,omitempty"` + Value []byte `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty" ssz-size:"32"` + Pubkey []byte `protobuf:"bytes,5,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` } -func (x *BlindedBeaconBlockBodyElectra) Reset() { - *x = BlindedBeaconBlockBodyElectra{} +func (x *BuilderBidElectra) Reset() { + *x = BuilderBidElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3874,13 +3811,13 @@ func (x *BlindedBeaconBlockBodyElectra) Reset() { } } -func (x *BlindedBeaconBlockBodyElectra) String() string { +func (x *BuilderBidElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BlindedBeaconBlockBodyElectra) ProtoMessage() {} +func (*BuilderBidElectra) ProtoMessage() {} -func (x *BlindedBeaconBlockBodyElectra) ProtoReflect() protoreflect.Message { +func (x *BuilderBidElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -3892,108 +3829,57 @@ func (x *BlindedBeaconBlockBodyElectra) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BlindedBeaconBlockBodyElectra.ProtoReflect.Descriptor instead. -func (*BlindedBeaconBlockBodyElectra) Descriptor() ([]byte, []int) { +// Deprecated: Use BuilderBidElectra.ProtoReflect.Descriptor instead. +func (*BuilderBidElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{47} } -func (x *BlindedBeaconBlockBodyElectra) GetRandaoReveal() []byte { - if x != nil { - return x.RandaoReveal - } - return nil -} - -func (x *BlindedBeaconBlockBodyElectra) GetEth1Data() *Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BlindedBeaconBlockBodyElectra) GetGraffiti() []byte { - if x != nil { - return x.Graffiti - } - return nil -} - -func (x *BlindedBeaconBlockBodyElectra) GetProposerSlashings() []*ProposerSlashing { - if x != nil { - return x.ProposerSlashings - } - return nil -} - -func (x *BlindedBeaconBlockBodyElectra) GetAttesterSlashings() []*AttesterSlashingElectra { - if x != nil { - return x.AttesterSlashings - } - return nil -} - -func (x *BlindedBeaconBlockBodyElectra) GetAttestations() []*AttestationElectra { - if x != nil { - return x.Attestations - } - return nil -} - -func (x *BlindedBeaconBlockBodyElectra) GetDeposits() []*Deposit { - if x != nil { - return x.Deposits - } - return nil -} - -func (x *BlindedBeaconBlockBodyElectra) GetVoluntaryExits() []*SignedVoluntaryExit { +func (x *BuilderBidElectra) GetHeader() *v1.ExecutionPayloadHeaderDeneb { if x != nil { - return x.VoluntaryExits + return x.Header } return nil } -func (x *BlindedBeaconBlockBodyElectra) GetSyncAggregate() *SyncAggregate { +func (x *BuilderBidElectra) GetBlobKzgCommitments() [][]byte { if x != nil { - return x.SyncAggregate + return x.BlobKzgCommitments } return nil } -func (x *BlindedBeaconBlockBodyElectra) GetExecutionPayloadHeader() *v1.ExecutionPayloadHeaderElectra { +func (x *BuilderBidElectra) GetExecutionRequests() *v1.ExecutionRequests { if x != nil { - return x.ExecutionPayloadHeader + return x.ExecutionRequests } return nil } -func (x *BlindedBeaconBlockBodyElectra) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { +func (x *BuilderBidElectra) GetValue() []byte { if x != nil { - return x.BlsToExecutionChanges + return x.Value } return nil } -func (x *BlindedBeaconBlockBodyElectra) GetBlobKzgCommitments() [][]byte { +func (x *BuilderBidElectra) GetPubkey() []byte { if x != nil { - return x.BlobKzgCommitments + return x.Pubkey } return nil } -type ValidatorRegistrationV1 struct { +type SignedBuilderBidElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - FeeRecipient []byte `protobuf:"bytes,1,opt,name=fee_recipient,json=feeRecipient,proto3" json:"fee_recipient,omitempty" ssz-size:"20"` - GasLimit uint64 `protobuf:"varint,2,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"` - Timestamp uint64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Pubkey []byte `protobuf:"bytes,4,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` + Message *BuilderBidElectra `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *ValidatorRegistrationV1) Reset() { - *x = ValidatorRegistrationV1{} +func (x *SignedBuilderBidElectra) Reset() { + *x = SignedBuilderBidElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4001,13 +3887,13 @@ func (x *ValidatorRegistrationV1) Reset() { } } -func (x *ValidatorRegistrationV1) String() string { +func (x *SignedBuilderBidElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ValidatorRegistrationV1) ProtoMessage() {} +func (*SignedBuilderBidElectra) ProtoMessage() {} -func (x *ValidatorRegistrationV1) ProtoReflect() protoreflect.Message { +func (x *SignedBuilderBidElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4019,49 +3905,35 @@ func (x *ValidatorRegistrationV1) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ValidatorRegistrationV1.ProtoReflect.Descriptor instead. -func (*ValidatorRegistrationV1) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBuilderBidElectra.ProtoReflect.Descriptor instead. +func (*SignedBuilderBidElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{48} } -func (x *ValidatorRegistrationV1) GetFeeRecipient() []byte { +func (x *SignedBuilderBidElectra) GetMessage() *BuilderBidElectra { if x != nil { - return x.FeeRecipient + return x.Message } return nil } -func (x *ValidatorRegistrationV1) GetGasLimit() uint64 { - if x != nil { - return x.GasLimit - } - return 0 -} - -func (x *ValidatorRegistrationV1) GetTimestamp() uint64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *ValidatorRegistrationV1) GetPubkey() []byte { +func (x *SignedBuilderBidElectra) GetSignature() []byte { if x != nil { - return x.Pubkey + return x.Signature } return nil } -type SignedValidatorRegistrationsV1 struct { +type BlobSidecars struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Messages []*SignedValidatorRegistrationV1 `protobuf:"bytes,1,rep,name=messages,proto3" json:"messages,omitempty"` + Sidecars []*BlobSidecar `protobuf:"bytes,1,rep,name=sidecars,proto3" json:"sidecars,omitempty" ssz-max:"6"` } -func (x *SignedValidatorRegistrationsV1) Reset() { - *x = SignedValidatorRegistrationsV1{} +func (x *BlobSidecars) Reset() { + *x = BlobSidecars{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4069,13 +3941,13 @@ func (x *SignedValidatorRegistrationsV1) Reset() { } } -func (x *SignedValidatorRegistrationsV1) String() string { +func (x *BlobSidecars) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedValidatorRegistrationsV1) ProtoMessage() {} +func (*BlobSidecars) ProtoMessage() {} -func (x *SignedValidatorRegistrationsV1) ProtoReflect() protoreflect.Message { +func (x *BlobSidecars) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4087,29 +3959,33 @@ func (x *SignedValidatorRegistrationsV1) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedValidatorRegistrationsV1.ProtoReflect.Descriptor instead. -func (*SignedValidatorRegistrationsV1) Descriptor() ([]byte, []int) { +// Deprecated: Use BlobSidecars.ProtoReflect.Descriptor instead. +func (*BlobSidecars) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{49} } -func (x *SignedValidatorRegistrationsV1) GetMessages() []*SignedValidatorRegistrationV1 { +func (x *BlobSidecars) GetSidecars() []*BlobSidecar { if x != nil { - return x.Messages + return x.Sidecars } return nil } -type SignedValidatorRegistrationV1 struct { +type BlobSidecar struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *ValidatorRegistrationV1 `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` + Blob []byte `protobuf:"bytes,2,opt,name=blob,proto3" json:"blob,omitempty" ssz-size:"131072"` + KzgCommitment []byte `protobuf:"bytes,3,opt,name=kzg_commitment,json=kzgCommitment,proto3" json:"kzg_commitment,omitempty" ssz-size:"48"` + KzgProof []byte `protobuf:"bytes,4,opt,name=kzg_proof,json=kzgProof,proto3" json:"kzg_proof,omitempty" ssz-size:"48"` + SignedBlockHeader *SignedBeaconBlockHeader `protobuf:"bytes,5,opt,name=signed_block_header,json=signedBlockHeader,proto3" json:"signed_block_header,omitempty"` + CommitmentInclusionProof [][]byte `protobuf:"bytes,6,rep,name=commitment_inclusion_proof,json=commitmentInclusionProof,proto3" json:"commitment_inclusion_proof,omitempty" ssz-size:"17,32"` } -func (x *SignedValidatorRegistrationV1) Reset() { - *x = SignedValidatorRegistrationV1{} +func (x *BlobSidecar) Reset() { + *x = BlobSidecar{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4117,13 +3993,13 @@ func (x *SignedValidatorRegistrationV1) Reset() { } } -func (x *SignedValidatorRegistrationV1) String() string { +func (x *BlobSidecar) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedValidatorRegistrationV1) ProtoMessage() {} +func (*BlobSidecar) ProtoMessage() {} -func (x *SignedValidatorRegistrationV1) ProtoReflect() protoreflect.Message { +func (x *BlobSidecar) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4135,37 +4011,65 @@ func (x *SignedValidatorRegistrationV1) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedValidatorRegistrationV1.ProtoReflect.Descriptor instead. -func (*SignedValidatorRegistrationV1) Descriptor() ([]byte, []int) { +// Deprecated: Use BlobSidecar.ProtoReflect.Descriptor instead. +func (*BlobSidecar) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{50} } -func (x *SignedValidatorRegistrationV1) GetMessage() *ValidatorRegistrationV1 { +func (x *BlobSidecar) GetIndex() uint64 { if x != nil { - return x.Message + return x.Index + } + return 0 +} + +func (x *BlobSidecar) GetBlob() []byte { + if x != nil { + return x.Blob } return nil } -func (x *SignedValidatorRegistrationV1) GetSignature() []byte { +func (x *BlobSidecar) GetKzgCommitment() []byte { if x != nil { - return x.Signature + return x.KzgCommitment } return nil } -type BuilderBid struct { +func (x *BlobSidecar) GetKzgProof() []byte { + if x != nil { + return x.KzgProof + } + return nil +} + +func (x *BlobSidecar) GetSignedBlockHeader() *SignedBeaconBlockHeader { + if x != nil { + return x.SignedBlockHeader + } + return nil +} + +func (x *BlobSidecar) GetCommitmentInclusionProof() [][]byte { + if x != nil { + return x.CommitmentInclusionProof + } + return nil +} + +type SignedBeaconBlockContentsElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Header *v1.ExecutionPayloadHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty" ssz-size:"32"` - Pubkey []byte `protobuf:"bytes,3,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` + Block *SignedBeaconBlockElectra `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` } -func (x *BuilderBid) Reset() { - *x = BuilderBid{} +func (x *SignedBeaconBlockContentsElectra) Reset() { + *x = SignedBeaconBlockContentsElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4173,13 +4077,13 @@ func (x *BuilderBid) Reset() { } } -func (x *BuilderBid) String() string { +func (x *SignedBeaconBlockContentsElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BuilderBid) ProtoMessage() {} +func (*SignedBeaconBlockContentsElectra) ProtoMessage() {} -func (x *BuilderBid) ProtoReflect() protoreflect.Message { +func (x *SignedBeaconBlockContentsElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4191,43 +4095,43 @@ func (x *BuilderBid) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BuilderBid.ProtoReflect.Descriptor instead. -func (*BuilderBid) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBeaconBlockContentsElectra.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockContentsElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{51} } -func (x *BuilderBid) GetHeader() *v1.ExecutionPayloadHeader { +func (x *SignedBeaconBlockContentsElectra) GetBlock() *SignedBeaconBlockElectra { if x != nil { - return x.Header + return x.Block } return nil } -func (x *BuilderBid) GetValue() []byte { +func (x *SignedBeaconBlockContentsElectra) GetKzgProofs() [][]byte { if x != nil { - return x.Value + return x.KzgProofs } return nil } -func (x *BuilderBid) GetPubkey() []byte { +func (x *SignedBeaconBlockContentsElectra) GetBlobs() [][]byte { if x != nil { - return x.Pubkey + return x.Blobs } return nil } -type SignedBuilderBid struct { +type SignedBeaconBlockElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *BuilderBid `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Block *BeaconBlockElectra `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SignedBuilderBid) Reset() { - *x = SignedBuilderBid{} +func (x *SignedBeaconBlockElectra) Reset() { + *x = SignedBeaconBlockElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4235,13 +4139,13 @@ func (x *SignedBuilderBid) Reset() { } } -func (x *SignedBuilderBid) String() string { +func (x *SignedBeaconBlockElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBuilderBid) ProtoMessage() {} +func (*SignedBeaconBlockElectra) ProtoMessage() {} -func (x *SignedBuilderBid) ProtoReflect() protoreflect.Message { +func (x *SignedBeaconBlockElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4253,37 +4157,37 @@ func (x *SignedBuilderBid) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBuilderBid.ProtoReflect.Descriptor instead. -func (*SignedBuilderBid) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBeaconBlockElectra.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{52} } -func (x *SignedBuilderBid) GetMessage() *BuilderBid { +func (x *SignedBeaconBlockElectra) GetBlock() *BeaconBlockElectra { if x != nil { - return x.Message + return x.Block } return nil } -func (x *SignedBuilderBid) GetSignature() []byte { +func (x *SignedBeaconBlockElectra) GetSignature() []byte { if x != nil { return x.Signature } return nil } -type BuilderBidCapella struct { +type BeaconBlockContentsElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Header *v1.ExecutionPayloadHeaderCapella `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty" ssz-size:"32"` - Pubkey []byte `protobuf:"bytes,3,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` + Block *BeaconBlockElectra `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` } -func (x *BuilderBidCapella) Reset() { - *x = BuilderBidCapella{} +func (x *BeaconBlockContentsElectra) Reset() { + *x = BeaconBlockContentsElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4291,13 +4195,13 @@ func (x *BuilderBidCapella) Reset() { } } -func (x *BuilderBidCapella) String() string { +func (x *BeaconBlockContentsElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BuilderBidCapella) ProtoMessage() {} +func (*BeaconBlockContentsElectra) ProtoMessage() {} -func (x *BuilderBidCapella) ProtoReflect() protoreflect.Message { +func (x *BeaconBlockContentsElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4309,43 +4213,46 @@ func (x *BuilderBidCapella) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BuilderBidCapella.ProtoReflect.Descriptor instead. -func (*BuilderBidCapella) Descriptor() ([]byte, []int) { +// Deprecated: Use BeaconBlockContentsElectra.ProtoReflect.Descriptor instead. +func (*BeaconBlockContentsElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{53} } -func (x *BuilderBidCapella) GetHeader() *v1.ExecutionPayloadHeaderCapella { +func (x *BeaconBlockContentsElectra) GetBlock() *BeaconBlockElectra { if x != nil { - return x.Header + return x.Block } return nil } -func (x *BuilderBidCapella) GetValue() []byte { +func (x *BeaconBlockContentsElectra) GetKzgProofs() [][]byte { if x != nil { - return x.Value + return x.KzgProofs } return nil } -func (x *BuilderBidCapella) GetPubkey() []byte { +func (x *BeaconBlockContentsElectra) GetBlobs() [][]byte { if x != nil { - return x.Pubkey + return x.Blobs } return nil } -type SignedBuilderBidCapella struct { +type BeaconBlockElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *BuilderBidCapella `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + Body *BeaconBlockBodyElectra `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` } -func (x *SignedBuilderBidCapella) Reset() { - *x = SignedBuilderBidCapella{} +func (x *BeaconBlockElectra) Reset() { + *x = BeaconBlockElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4353,13 +4260,13 @@ func (x *SignedBuilderBidCapella) Reset() { } } -func (x *SignedBuilderBidCapella) String() string { +func (x *BeaconBlockElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBuilderBidCapella) ProtoMessage() {} +func (*BeaconBlockElectra) ProtoMessage() {} -func (x *SignedBuilderBidCapella) ProtoReflect() protoreflect.Message { +func (x *BeaconBlockElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4371,38 +4278,68 @@ func (x *SignedBuilderBidCapella) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBuilderBidCapella.ProtoReflect.Descriptor instead. -func (*SignedBuilderBidCapella) Descriptor() ([]byte, []int) { +// Deprecated: Use BeaconBlockElectra.ProtoReflect.Descriptor instead. +func (*BeaconBlockElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{54} } -func (x *SignedBuilderBidCapella) GetMessage() *BuilderBidCapella { +func (x *BeaconBlockElectra) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { - return x.Message + return x.Slot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +func (x *BeaconBlockElectra) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { + if x != nil { + return x.ProposerIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *BeaconBlockElectra) GetParentRoot() []byte { + if x != nil { + return x.ParentRoot } return nil } -func (x *SignedBuilderBidCapella) GetSignature() []byte { +func (x *BeaconBlockElectra) GetStateRoot() []byte { if x != nil { - return x.Signature + return x.StateRoot } return nil } -type BuilderBidDeneb struct { +func (x *BeaconBlockElectra) GetBody() *BeaconBlockBodyElectra { + if x != nil { + return x.Body + } + return nil +} + +type BeaconBlockBodyElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Header *v1.ExecutionPayloadHeaderDeneb `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - BlobKzgCommitments [][]byte `protobuf:"bytes,2,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` - Value []byte `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty" ssz-size:"32"` - Pubkey []byte `protobuf:"bytes,4,opt,name=pubkey,proto3" json:"pubkey,omitempty" ssz-size:"48"` + RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` + Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` + Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` + ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` + AttesterSlashings []*AttesterSlashingElectra `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"1"` + Attestations []*AttestationElectra `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"8"` + Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` + VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` + SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + ExecutionPayload *v1.ExecutionPayloadDeneb `protobuf:"bytes,10,opt,name=execution_payload,json=executionPayload,proto3" json:"execution_payload,omitempty"` + BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` + BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + ExecutionRequests *v1.ExecutionRequests `protobuf:"bytes,13,opt,name=execution_requests,json=executionRequests,proto3" json:"execution_requests,omitempty"` } -func (x *BuilderBidDeneb) Reset() { - *x = BuilderBidDeneb{} +func (x *BeaconBlockBodyElectra) Reset() { + *x = BeaconBlockBodyElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4410,13 +4347,13 @@ func (x *BuilderBidDeneb) Reset() { } } -func (x *BuilderBidDeneb) String() string { +func (x *BeaconBlockBodyElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BuilderBidDeneb) ProtoMessage() {} +func (*BeaconBlockBodyElectra) ProtoMessage() {} -func (x *BuilderBidDeneb) ProtoReflect() protoreflect.Message { +func (x *BeaconBlockBodyElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4428,50 +4365,113 @@ func (x *BuilderBidDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BuilderBidDeneb.ProtoReflect.Descriptor instead. -func (*BuilderBidDeneb) Descriptor() ([]byte, []int) { +// Deprecated: Use BeaconBlockBodyElectra.ProtoReflect.Descriptor instead. +func (*BeaconBlockBodyElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{55} } -func (x *BuilderBidDeneb) GetHeader() *v1.ExecutionPayloadHeaderDeneb { +func (x *BeaconBlockBodyElectra) GetRandaoReveal() []byte { if x != nil { - return x.Header + return x.RandaoReveal } return nil } -func (x *BuilderBidDeneb) GetBlobKzgCommitments() [][]byte { +func (x *BeaconBlockBodyElectra) GetEth1Data() *Eth1Data { if x != nil { - return x.BlobKzgCommitments + return x.Eth1Data } return nil } -func (x *BuilderBidDeneb) GetValue() []byte { +func (x *BeaconBlockBodyElectra) GetGraffiti() []byte { if x != nil { - return x.Value + return x.Graffiti } return nil } -func (x *BuilderBidDeneb) GetPubkey() []byte { +func (x *BeaconBlockBodyElectra) GetProposerSlashings() []*ProposerSlashing { if x != nil { - return x.Pubkey + return x.ProposerSlashings } return nil } -type SignedBuilderBidDeneb struct { +func (x *BeaconBlockBodyElectra) GetAttesterSlashings() []*AttesterSlashingElectra { + if x != nil { + return x.AttesterSlashings + } + return nil +} + +func (x *BeaconBlockBodyElectra) GetAttestations() []*AttestationElectra { + if x != nil { + return x.Attestations + } + return nil +} + +func (x *BeaconBlockBodyElectra) GetDeposits() []*Deposit { + if x != nil { + return x.Deposits + } + return nil +} + +func (x *BeaconBlockBodyElectra) GetVoluntaryExits() []*SignedVoluntaryExit { + if x != nil { + return x.VoluntaryExits + } + return nil +} + +func (x *BeaconBlockBodyElectra) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *BeaconBlockBodyElectra) GetExecutionPayload() *v1.ExecutionPayloadDeneb { + if x != nil { + return x.ExecutionPayload + } + return nil +} + +func (x *BeaconBlockBodyElectra) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { + if x != nil { + return x.BlsToExecutionChanges + } + return nil +} + +func (x *BeaconBlockBodyElectra) GetBlobKzgCommitments() [][]byte { + if x != nil { + return x.BlobKzgCommitments + } + return nil +} + +func (x *BeaconBlockBodyElectra) GetExecutionRequests() *v1.ExecutionRequests { + if x != nil { + return x.ExecutionRequests + } + return nil +} + +type SignedBlindedBeaconBlockElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *BuilderBidDeneb `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Message *BlindedBeaconBlockElectra `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SignedBuilderBidDeneb) Reset() { - *x = SignedBuilderBidDeneb{} +func (x *SignedBlindedBeaconBlockElectra) Reset() { + *x = SignedBlindedBeaconBlockElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4479,13 +4479,13 @@ func (x *SignedBuilderBidDeneb) Reset() { } } -func (x *SignedBuilderBidDeneb) String() string { +func (x *SignedBlindedBeaconBlockElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBuilderBidDeneb) ProtoMessage() {} +func (*SignedBlindedBeaconBlockElectra) ProtoMessage() {} -func (x *SignedBuilderBidDeneb) ProtoReflect() protoreflect.Message { +func (x *SignedBlindedBeaconBlockElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4497,40 +4497,39 @@ func (x *SignedBuilderBidDeneb) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBuilderBidDeneb.ProtoReflect.Descriptor instead. -func (*SignedBuilderBidDeneb) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBlindedBeaconBlockElectra.ProtoReflect.Descriptor instead. +func (*SignedBlindedBeaconBlockElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{56} } -func (x *SignedBuilderBidDeneb) GetMessage() *BuilderBidDeneb { +func (x *SignedBlindedBeaconBlockElectra) GetMessage() *BlindedBeaconBlockElectra { if x != nil { return x.Message } return nil } -func (x *SignedBuilderBidDeneb) GetSignature() []byte { +func (x *SignedBlindedBeaconBlockElectra) GetSignature() []byte { if x != nil { return x.Signature } return nil } -type BlobSidecar struct { +type BlindedBeaconBlockElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"` - Blob []byte `protobuf:"bytes,2,opt,name=blob,proto3" json:"blob,omitempty" ssz-size:"131072"` - KzgCommitment []byte `protobuf:"bytes,3,opt,name=kzg_commitment,json=kzgCommitment,proto3" json:"kzg_commitment,omitempty" ssz-size:"48"` - KzgProof []byte `protobuf:"bytes,4,opt,name=kzg_proof,json=kzgProof,proto3" json:"kzg_proof,omitempty" ssz-size:"48"` - SignedBlockHeader *SignedBeaconBlockHeader `protobuf:"bytes,5,opt,name=signed_block_header,json=signedBlockHeader,proto3" json:"signed_block_header,omitempty"` - CommitmentInclusionProof [][]byte `protobuf:"bytes,6,rep,name=commitment_inclusion_proof,json=commitmentInclusionProof,proto3" json:"commitment_inclusion_proof,omitempty" ssz-size:"17,32"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + Body *BlindedBeaconBlockBodyElectra `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` } -func (x *BlobSidecar) Reset() { - *x = BlobSidecar{} +func (x *BlindedBeaconBlockElectra) Reset() { + *x = BlindedBeaconBlockElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4538,13 +4537,13 @@ func (x *BlobSidecar) Reset() { } } -func (x *BlobSidecar) String() string { +func (x *BlindedBeaconBlockElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BlobSidecar) ProtoMessage() {} +func (*BlindedBeaconBlockElectra) ProtoMessage() {} -func (x *BlobSidecar) ProtoReflect() protoreflect.Message { +func (x *BlindedBeaconBlockElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4556,63 +4555,68 @@ func (x *BlobSidecar) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BlobSidecar.ProtoReflect.Descriptor instead. -func (*BlobSidecar) Descriptor() ([]byte, []int) { +// Deprecated: Use BlindedBeaconBlockElectra.ProtoReflect.Descriptor instead. +func (*BlindedBeaconBlockElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{57} } -func (x *BlobSidecar) GetIndex() uint64 { - if x != nil { - return x.Index - } - return 0 -} - -func (x *BlobSidecar) GetBlob() []byte { +func (x *BlindedBeaconBlockElectra) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { - return x.Blob + return x.Slot } - return nil + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) } -func (x *BlobSidecar) GetKzgCommitment() []byte { +func (x *BlindedBeaconBlockElectra) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { - return x.KzgCommitment + return x.ProposerIndex } - return nil + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) } -func (x *BlobSidecar) GetKzgProof() []byte { +func (x *BlindedBeaconBlockElectra) GetParentRoot() []byte { if x != nil { - return x.KzgProof + return x.ParentRoot } return nil } -func (x *BlobSidecar) GetSignedBlockHeader() *SignedBeaconBlockHeader { +func (x *BlindedBeaconBlockElectra) GetStateRoot() []byte { if x != nil { - return x.SignedBlockHeader + return x.StateRoot } return nil } -func (x *BlobSidecar) GetCommitmentInclusionProof() [][]byte { +func (x *BlindedBeaconBlockElectra) GetBody() *BlindedBeaconBlockBodyElectra { if x != nil { - return x.CommitmentInclusionProof + return x.Body } return nil } -type BlobSidecars struct { +type BlindedBeaconBlockBodyElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Sidecars []*BlobSidecar `protobuf:"bytes,1,rep,name=sidecars,proto3" json:"sidecars,omitempty" ssz-max:"6"` + RandaoReveal []byte `protobuf:"bytes,1,opt,name=randao_reveal,json=randaoReveal,proto3" json:"randao_reveal,omitempty" ssz-size:"96"` + Eth1Data *Eth1Data `protobuf:"bytes,2,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` + Graffiti []byte `protobuf:"bytes,3,opt,name=graffiti,proto3" json:"graffiti,omitempty" ssz-size:"32"` + ProposerSlashings []*ProposerSlashing `protobuf:"bytes,4,rep,name=proposer_slashings,json=proposerSlashings,proto3" json:"proposer_slashings,omitempty" ssz-max:"16"` + AttesterSlashings []*AttesterSlashingElectra `protobuf:"bytes,5,rep,name=attester_slashings,json=attesterSlashings,proto3" json:"attester_slashings,omitempty" ssz-max:"1"` + Attestations []*AttestationElectra `protobuf:"bytes,6,rep,name=attestations,proto3" json:"attestations,omitempty" ssz-max:"8"` + Deposits []*Deposit `protobuf:"bytes,7,rep,name=deposits,proto3" json:"deposits,omitempty" ssz-max:"16"` + VoluntaryExits []*SignedVoluntaryExit `protobuf:"bytes,8,rep,name=voluntary_exits,json=voluntaryExits,proto3" json:"voluntary_exits,omitempty" ssz-max:"16"` + SyncAggregate *SyncAggregate `protobuf:"bytes,9,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + ExecutionPayloadHeader *v1.ExecutionPayloadHeaderDeneb `protobuf:"bytes,10,opt,name=execution_payload_header,json=executionPayloadHeader,proto3" json:"execution_payload_header,omitempty"` + BlsToExecutionChanges []*SignedBLSToExecutionChange `protobuf:"bytes,11,rep,name=bls_to_execution_changes,json=blsToExecutionChanges,proto3" json:"bls_to_execution_changes,omitempty" ssz-max:"16"` + BlobKzgCommitments [][]byte `protobuf:"bytes,12,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + ExecutionRequests *v1.ExecutionRequests `protobuf:"bytes,13,opt,name=execution_requests,json=executionRequests,proto3" json:"execution_requests,omitempty"` } -func (x *BlobSidecars) Reset() { - *x = BlobSidecars{} +func (x *BlindedBeaconBlockBodyElectra) Reset() { + *x = BlindedBeaconBlockBodyElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4620,13 +4624,13 @@ func (x *BlobSidecars) Reset() { } } -func (x *BlobSidecars) String() string { +func (x *BlindedBeaconBlockBodyElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BlobSidecars) ProtoMessage() {} +func (*BlindedBeaconBlockBodyElectra) ProtoMessage() {} -func (x *BlobSidecars) ProtoReflect() protoreflect.Message { +func (x *BlindedBeaconBlockBodyElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4638,31 +4642,113 @@ func (x *BlobSidecars) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BlobSidecars.ProtoReflect.Descriptor instead. -func (*BlobSidecars) Descriptor() ([]byte, []int) { +// Deprecated: Use BlindedBeaconBlockBodyElectra.ProtoReflect.Descriptor instead. +func (*BlindedBeaconBlockBodyElectra) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{58} } -func (x *BlobSidecars) GetSidecars() []*BlobSidecar { +func (x *BlindedBeaconBlockBodyElectra) GetRandaoReveal() []byte { if x != nil { - return x.Sidecars + return x.RandaoReveal } return nil } -type Deposit_Data struct { +func (x *BlindedBeaconBlockBodyElectra) GetEth1Data() *Eth1Data { + if x != nil { + return x.Eth1Data + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetGraffiti() []byte { + if x != nil { + return x.Graffiti + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetProposerSlashings() []*ProposerSlashing { + if x != nil { + return x.ProposerSlashings + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetAttesterSlashings() []*AttesterSlashingElectra { + if x != nil { + return x.AttesterSlashings + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetAttestations() []*AttestationElectra { + if x != nil { + return x.Attestations + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetDeposits() []*Deposit { + if x != nil { + return x.Deposits + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetVoluntaryExits() []*SignedVoluntaryExit { + if x != nil { + return x.VoluntaryExits + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetExecutionPayloadHeader() *v1.ExecutionPayloadHeaderDeneb { + if x != nil { + return x.ExecutionPayloadHeader + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetBlsToExecutionChanges() []*SignedBLSToExecutionChange { + if x != nil { + return x.BlsToExecutionChanges + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetBlobKzgCommitments() [][]byte { + if x != nil { + return x.BlobKzgCommitments + } + return nil +} + +func (x *BlindedBeaconBlockBodyElectra) GetExecutionRequests() *v1.ExecutionRequests { + if x != nil { + return x.ExecutionRequests + } + return nil +} + +type AttesterSlashingElectra struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty" spec-name:"pubkey" ssz-size:"48"` - WithdrawalCredentials []byte `protobuf:"bytes,2,opt,name=withdrawal_credentials,json=withdrawalCredentials,proto3" json:"withdrawal_credentials,omitempty" ssz-size:"32"` - Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` - Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Attestation_1 *IndexedAttestationElectra `protobuf:"bytes,1,opt,name=attestation_1,json=attestation1,proto3" json:"attestation_1,omitempty"` + Attestation_2 *IndexedAttestationElectra `protobuf:"bytes,2,opt,name=attestation_2,json=attestation2,proto3" json:"attestation_2,omitempty"` } -func (x *Deposit_Data) Reset() { - *x = Deposit_Data{} +func (x *AttesterSlashingElectra) Reset() { + *x = AttesterSlashingElectra{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4670,13 +4756,13 @@ func (x *Deposit_Data) Reset() { } } -func (x *Deposit_Data) String() string { +func (x *AttesterSlashingElectra) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Deposit_Data) ProtoMessage() {} +func (*AttesterSlashingElectra) ProtoMessage() {} -func (x *Deposit_Data) ProtoReflect() protoreflect.Message { +func (x *AttesterSlashingElectra) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -4688,40 +4774,475 @@ func (x *Deposit_Data) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Deposit_Data.ProtoReflect.Descriptor instead. -func (*Deposit_Data) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{11, 0} +// Deprecated: Use AttesterSlashingElectra.ProtoReflect.Descriptor instead. +func (*AttesterSlashingElectra) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{59} } -func (x *Deposit_Data) GetPublicKey() []byte { +func (x *AttesterSlashingElectra) GetAttestation_1() *IndexedAttestationElectra { if x != nil { - return x.PublicKey + return x.Attestation_1 } return nil } -func (x *Deposit_Data) GetWithdrawalCredentials() []byte { +func (x *AttesterSlashingElectra) GetAttestation_2() *IndexedAttestationElectra { if x != nil { - return x.WithdrawalCredentials + return x.Attestation_2 } return nil } -func (x *Deposit_Data) GetAmount() uint64 { +type IndexedAttestationElectra struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestingIndices []uint64 `protobuf:"varint,1,rep,packed,name=attesting_indices,json=attestingIndices,proto3" json:"attesting_indices,omitempty" ssz-max:"131072"` + Data *AttestationData `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *IndexedAttestationElectra) Reset() { + *x = IndexedAttestationElectra{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[60] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IndexedAttestationElectra) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IndexedAttestationElectra) ProtoMessage() {} + +func (x *IndexedAttestationElectra) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[60] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IndexedAttestationElectra.ProtoReflect.Descriptor instead. +func (*IndexedAttestationElectra) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{60} +} + +func (x *IndexedAttestationElectra) GetAttestingIndices() []uint64 { if x != nil { - return x.Amount + return x.AttestingIndices } - return 0 + return nil } -func (x *Deposit_Data) GetSignature() []byte { +func (x *IndexedAttestationElectra) GetData() *AttestationData { if x != nil { - return x.Signature + return x.Data } return nil } -var File_proto_prysm_v1alpha1_beacon_block_proto protoreflect.FileDescriptor +func (x *IndexedAttestationElectra) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +type SignedBeaconBlockContentsFulu struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Block *SignedBeaconBlockFulu `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` +} + +func (x *SignedBeaconBlockContentsFulu) Reset() { + *x = SignedBeaconBlockContentsFulu{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedBeaconBlockContentsFulu) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedBeaconBlockContentsFulu) ProtoMessage() {} + +func (x *SignedBeaconBlockContentsFulu) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[61] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedBeaconBlockContentsFulu.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockContentsFulu) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{61} +} + +func (x *SignedBeaconBlockContentsFulu) GetBlock() *SignedBeaconBlockFulu { + if x != nil { + return x.Block + } + return nil +} + +func (x *SignedBeaconBlockContentsFulu) GetKzgProofs() [][]byte { + if x != nil { + return x.KzgProofs + } + return nil +} + +func (x *SignedBeaconBlockContentsFulu) GetBlobs() [][]byte { + if x != nil { + return x.Blobs + } + return nil +} + +type SignedBeaconBlockFulu struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Block *BeaconBlockElectra `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *SignedBeaconBlockFulu) Reset() { + *x = SignedBeaconBlockFulu{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[62] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedBeaconBlockFulu) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedBeaconBlockFulu) ProtoMessage() {} + +func (x *SignedBeaconBlockFulu) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[62] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedBeaconBlockFulu.ProtoReflect.Descriptor instead. +func (*SignedBeaconBlockFulu) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{62} +} + +func (x *SignedBeaconBlockFulu) GetBlock() *BeaconBlockElectra { + if x != nil { + return x.Block + } + return nil +} + +func (x *SignedBeaconBlockFulu) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +type BeaconBlockContentsFulu struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Block *BeaconBlockElectra `protobuf:"bytes,1,opt,name=block,proto3" json:"block,omitempty"` + KzgProofs [][]byte `protobuf:"bytes,2,rep,name=kzg_proofs,json=kzgProofs,proto3" json:"kzg_proofs,omitempty" ssz-max:"4096" ssz-size:"?,48"` + Blobs [][]byte `protobuf:"bytes,3,rep,name=blobs,proto3" json:"blobs,omitempty" ssz-max:"4096" ssz-size:"?,131072"` +} + +func (x *BeaconBlockContentsFulu) Reset() { + *x = BeaconBlockContentsFulu{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[63] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BeaconBlockContentsFulu) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BeaconBlockContentsFulu) ProtoMessage() {} + +func (x *BeaconBlockContentsFulu) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[63] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BeaconBlockContentsFulu.ProtoReflect.Descriptor instead. +func (*BeaconBlockContentsFulu) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{63} +} + +func (x *BeaconBlockContentsFulu) GetBlock() *BeaconBlockElectra { + if x != nil { + return x.Block + } + return nil +} + +func (x *BeaconBlockContentsFulu) GetKzgProofs() [][]byte { + if x != nil { + return x.KzgProofs + } + return nil +} + +func (x *BeaconBlockContentsFulu) GetBlobs() [][]byte { + if x != nil { + return x.Blobs + } + return nil +} + +type SignedBlindedBeaconBlockFulu struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message *BlindedBeaconBlockFulu `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *SignedBlindedBeaconBlockFulu) Reset() { + *x = SignedBlindedBeaconBlockFulu{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedBlindedBeaconBlockFulu) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedBlindedBeaconBlockFulu) ProtoMessage() {} + +func (x *SignedBlindedBeaconBlockFulu) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[64] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedBlindedBeaconBlockFulu.ProtoReflect.Descriptor instead. +func (*SignedBlindedBeaconBlockFulu) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{64} +} + +func (x *SignedBlindedBeaconBlockFulu) GetMessage() *BlindedBeaconBlockFulu { + if x != nil { + return x.Message + } + return nil +} + +func (x *SignedBlindedBeaconBlockFulu) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +type BlindedBeaconBlockFulu struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + ProposerIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=proposer_index,json=proposerIndex,proto3" json:"proposer_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + ParentRoot []byte `protobuf:"bytes,3,opt,name=parent_root,json=parentRoot,proto3" json:"parent_root,omitempty" ssz-size:"32"` + StateRoot []byte `protobuf:"bytes,4,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"` + Body *BlindedBeaconBlockBodyElectra `protobuf:"bytes,5,opt,name=body,proto3" json:"body,omitempty"` +} + +func (x *BlindedBeaconBlockFulu) Reset() { + *x = BlindedBeaconBlockFulu{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[65] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlindedBeaconBlockFulu) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlindedBeaconBlockFulu) ProtoMessage() {} + +func (x *BlindedBeaconBlockFulu) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[65] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlindedBeaconBlockFulu.ProtoReflect.Descriptor instead. +func (*BlindedBeaconBlockFulu) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{65} +} + +func (x *BlindedBeaconBlockFulu) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.Slot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +func (x *BlindedBeaconBlockFulu) GetProposerIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { + if x != nil { + return x.ProposerIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *BlindedBeaconBlockFulu) GetParentRoot() []byte { + if x != nil { + return x.ParentRoot + } + return nil +} + +func (x *BlindedBeaconBlockFulu) GetStateRoot() []byte { + if x != nil { + return x.StateRoot + } + return nil +} + +func (x *BlindedBeaconBlockFulu) GetBody() *BlindedBeaconBlockBodyElectra { + if x != nil { + return x.Body + } + return nil +} + +type Deposit_Data struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty" spec-name:"pubkey" ssz-size:"48"` + WithdrawalCredentials []byte `protobuf:"bytes,2,opt,name=withdrawal_credentials,json=withdrawalCredentials,proto3" json:"withdrawal_credentials,omitempty" ssz-size:"32"` + Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *Deposit_Data) Reset() { + *x = Deposit_Data{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[66] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Deposit_Data) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Deposit_Data) ProtoMessage() {} + +func (x *Deposit_Data) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[66] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Deposit_Data.ProtoReflect.Descriptor instead. +func (*Deposit_Data) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP(), []int{11, 0} +} + +func (x *Deposit_Data) GetPublicKey() []byte { + if x != nil { + return x.PublicKey + } + return nil +} + +func (x *Deposit_Data) GetWithdrawalCredentials() []byte { + if x != nil { + return x.WithdrawalCredentials + } + return nil +} + +func (x *Deposit_Data) GetAmount() uint64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *Deposit_Data) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +var File_proto_prysm_v1alpha1_beacon_block_proto protoreflect.FileDescriptor var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x0a, 0x27, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, @@ -4737,68 +5258,78 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x23, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x65, 0x69, 0x70, 0x5f, - 0x37, 0x32, 0x35, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa6, 0x07, 0x0a, 0x18, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x42, 0x0a, 0x06, 0x70, 0x68, 0x61, 0x73, 0x65, - 0x30, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcc, 0x08, 0x0a, 0x18, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x48, 0x00, 0x52, 0x06, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x12, 0x48, 0x0a, 0x06, 0x61, - 0x6c, 0x74, 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x06, 0x61, - 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x51, 0x0a, 0x09, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, - 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x6b, 0x12, 0x42, 0x0a, 0x06, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x06, 0x70, + 0x68, 0x61, 0x73, 0x65, 0x30, 0x12, 0x48, 0x0a, 0x06, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, + 0x6c, 0x74, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x06, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, + 0x51, 0x0a, 0x09, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, + 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x09, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, + 0x69, 0x78, 0x12, 0x67, 0x0a, 0x11, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x65, + 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, + 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, + 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x10, 0x62, 0x6c, 0x69, 0x6e, 0x64, + 0x65, 0x64, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x4b, 0x0a, 0x07, 0x63, + 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x48, 0x00, 0x52, + 0x07, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x61, 0x0a, 0x0f, 0x62, 0x6c, 0x69, 0x6e, + 0x64, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x6c, 0x69, + 0x6e, 0x64, 0x65, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x4d, 0x0a, 0x05, 0x64, + 0x65, 0x6e, 0x65, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x44, 0x65, 0x6e, 0x65, + 0x62, 0x48, 0x00, 0x52, 0x05, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x5b, 0x0a, 0x0d, 0x62, 0x6c, + 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x6c, 0x69, 0x6e, 0x64, + 0x65, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x53, 0x0a, 0x07, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x72, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, 0x09, 0x62, - 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x67, 0x0a, 0x11, 0x62, 0x6c, 0x69, 0x6e, - 0x64, 0x65, 0x64, 0x5f, 0x62, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x48, 0x00, 0x52, - 0x10, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x12, 0x4b, 0x0a, 0x07, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, - 0x6c, 0x6c, 0x61, 0x48, 0x00, 0x52, 0x07, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x61, - 0x0a, 0x0f, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x70, 0x65, 0x6c, 0x6c, - 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x48, - 0x00, 0x52, 0x0e, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, - 0x61, 0x12, 0x4d, 0x0a, 0x05, 0x64, 0x65, 0x6e, 0x65, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x48, 0x00, 0x52, 0x05, 0x64, 0x65, 0x6e, 0x65, 0x62, - 0x12, 0x5b, 0x0a, 0x0d, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x6e, 0x65, - 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x48, 0x00, 0x52, - 0x0c, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x53, 0x0a, - 0x07, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x48, 0x00, 0x52, 0x07, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x72, 0x61, 0x12, 0x61, 0x0a, 0x0f, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x72, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, - 0x74, 0x72, 0x61, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x45, 0x6c, - 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x62, 0x6c, 0x69, 0x6e, + 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, + 0x61, 0x48, 0x00, 0x52, 0x07, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x61, 0x0a, 0x0f, + 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x48, 0x00, 0x52, + 0x0e, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, + 0x4a, 0x0a, 0x04, 0x66, 0x75, 0x6c, 0x75, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x46, + 0x75, 0x6c, 0x75, 0x48, 0x00, 0x52, 0x04, 0x66, 0x75, 0x6c, 0x75, 0x12, 0x58, 0x0a, 0x0c, 0x62, + 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6c, 0x75, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x75, 0x48, 0x00, 0x52, 0x0b, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, + 0x64, 0x46, 0x75, 0x6c, 0x75, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x18, 0x64, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4a, 0x04, 0x08, - 0x65, 0x10, 0x66, 0x22, 0x83, 0x07, 0x0a, 0x12, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x42, + 0x65, 0x10, 0x66, 0x22, 0x9d, 0x08, 0x0a, 0x12, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x3c, 0x0a, 0x06, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, @@ -4849,111 +5380,275 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x6c, - 0x69, 0x6e, 0x64, 0x65, 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x1d, 0x0a, 0x0a, - 0x69, 0x73, 0x5f, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x18, 0x64, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x69, 0x73, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x65, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0xec, 0x02, 0x0a, 0x0b, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, - 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, - 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, - 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x3a, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, + 0x69, 0x6e, 0x64, 0x65, 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x44, 0x0a, 0x04, + 0x66, 0x75, 0x6c, 0x75, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x73, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x38, 0x0a, - 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xf8, 0x02, - 0x0a, 0x11, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, - 0x61, 0x69, 0x72, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, - 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, + 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x75, 0x6c, 0x75, 0x48, 0x00, 0x52, 0x04, 0x66, 0x75, + 0x6c, 0x75, 0x12, 0x52, 0x0a, 0x0c, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x75, + 0x6c, 0x75, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x75, 0x48, 0x00, 0x52, 0x0b, 0x62, 0x6c, 0x69, 0x6e, 0x64, + 0x65, 0x64, 0x46, 0x75, 0x6c, 0x75, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x62, 0x6c, 0x69, + 0x6e, 0x64, 0x65, 0x64, 0x18, 0x64, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x42, 0x6c, + 0x69, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x65, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x22, 0x73, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x38, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xec, 0x02, 0x0a, 0x0b, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, - 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x41, 0x6c, 0x74, 0x61, - 0x69, 0x72, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x7f, 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, - 0x61, 0x69, 0x72, 0x12, 0x3e, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x05, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xd1, 0x04, 0x0a, 0x0f, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2b, 0x0a, - 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, - 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, - 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, - 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, - 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, + 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, + 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, + 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, + 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xd1, 0x04, 0x0a, 0x0f, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2b, 0x0a, 0x0d, 0x72, + 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, + 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, + 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, + 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, + 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, + 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, + 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, + 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, + 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, + 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, + 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, + 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, + 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, + 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, + 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x22, 0x81, 0x01, 0x0a, 0x17, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, + 0xdb, 0x02, 0x0a, 0x11, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, + 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, + 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, + 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, + 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, + 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, + 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, + 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, + 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23, 0x0a, 0x09, 0x62, 0x6f, 0x64, 0x79, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x33, 0x32, 0x52, 0x08, 0x62, 0x6f, 0x64, 0x79, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x81, 0x01, + 0x0a, 0x08, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x29, 0x0a, 0x0c, 0x64, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x64, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, + 0x68, 0x22, 0xa8, 0x01, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, + 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x49, 0x0a, 0x08, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x5f, 0x31, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x5d, 0x0a, 0x12, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x31, 0x12, 0x49, 0x0a, 0x08, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x32, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x32, 0x22, 0xb2, 0x01, 0x0a, + 0x10, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x12, 0x4e, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4f, 0x0a, 0x0c, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, - 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x12, 0x4e, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x32, 0x22, 0xad, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x11, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x04, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x10, 0x61, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, + 0x3a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x9a, 0x02, 0x0a, 0x07, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1f, 0x0a, + 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x09, 0x8a, 0xb5, + 0x18, 0x05, 0x33, 0x33, 0x2c, 0x33, 0x32, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x37, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0xb4, 0x01, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, + 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, + 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x12, 0x3d, 0x0a, 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, + 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x77, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, + 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x75, + 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, + 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x65, 0x78, 0x69, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, + 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x52, 0x04, 0x65, 0x78, 0x69, 0x74, 0x12, + 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xe7, 0x01, 0x0a, 0x0d, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, + 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, + 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, + 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, + 0x72, 0x0a, 0x1e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, + 0x31, 0x12, 0x50, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x73, 0x22, 0x8f, 0x01, 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x12, 0x48, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x17, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, + 0x31, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, + 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1b, + 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1e, 0x0a, 0x06, 0x70, 0x75, 0x62, + 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, + 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x75, 0x0a, 0x10, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x12, 0x3b, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, - 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, - 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, - 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, + 0x64, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x22, 0x8e, 0x01, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x12, + 0x42, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x1e, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x22, 0x7f, 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x3e, 0x0a, 0x05, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, + 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x22, 0xf8, 0x02, 0x0a, 0x11, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, + 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, + 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, + 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, - 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, - 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x22, 0xa4, 0x05, + 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, + 0x79, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xa4, 0x05, 0x0a, 0x15, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, @@ -4996,91 +5691,29 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x22, 0xa8, 0x01, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x49, 0x0a, 0x08, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x5f, 0x31, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x31, 0x12, 0x49, 0x0a, 0x08, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x32, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x32, 0x22, - 0xb2, 0x01, 0x0a, 0x10, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x12, 0x4e, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x4e, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x32, 0x22, 0xc7, 0x01, 0x0a, 0x17, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, - 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, - 0x12, 0x55, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x55, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, - 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x22, 0x9a, - 0x02, 0x0a, 0x07, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x1f, 0x0a, 0x05, 0x70, 0x72, - 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x09, 0x8a, 0xb5, 0x18, 0x05, 0x33, - 0x33, 0x2c, 0x33, 0x32, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x37, 0x0a, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x1a, 0xb4, 0x01, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, - 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3d, - 0x0a, 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x65, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x16, 0x0a, - 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xe7, 0x01, 0x0a, 0x0d, - 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x5c, 0x0a, - 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, - 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, - 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x78, 0x0a, 0x0f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, - 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x75, 0x0a, 0x13, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, - 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x04, - 0x65, 0x78, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, - 0x52, 0x04, 0x65, 0x78, 0x69, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, - 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x81, 0x01, 0x0a, - 0x08, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x29, 0x0a, 0x0c, 0x64, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x64, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, - 0x22, 0xdb, 0x02, 0x0a, 0x11, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, + 0x67, 0x61, 0x74, 0x65, 0x22, 0xbe, 0x01, 0x0a, 0x0d, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x13, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x3b, 0x82, 0xb5, 0x18, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, + 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x35, 0x31, 0x32, 0x8a, 0xb5, 0x18, 0x02, 0x36, 0x34, + 0x52, 0x11, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, + 0x69, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x18, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x16, 0x73, + 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x1a, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, + 0x74, 0x72, 0x69, 0x78, 0x12, 0x41, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, + 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xfe, 0x02, + 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, + 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, @@ -5098,168 +5731,12 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x23, 0x0a, 0x09, 0x62, 0x6f, 0x64, - 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x62, 0x6f, 0x64, 0x79, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x81, - 0x01, 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x06, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x22, 0xad, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x11, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x10, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x12, 0x3a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x19, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, - 0x12, 0x37, 0x0a, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x0a, 0x92, 0xb5, 0x18, - 0x06, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x52, 0x10, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, - 0x6e, 0x67, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xbe, 0x01, 0x0a, 0x0d, - 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6b, 0x0a, - 0x13, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, - 0x62, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x3b, 0x82, 0xb5, 0x18, 0x31, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x35, 0x31, - 0x32, 0x8a, 0xb5, 0x18, 0x02, 0x36, 0x34, 0x52, 0x11, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, 0x69, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x18, 0x73, 0x79, - 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x39, 0x36, 0x52, 0x16, 0x73, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x85, 0x01, 0x0a, - 0x1a, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x41, 0x0a, 0x05, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, - 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x22, 0xfe, 0x02, 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x59, 0x0a, - 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, - 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, - 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, - 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, - 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xfa, 0x05, 0x0a, 0x18, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, - 0x69, 0x78, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, - 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, - 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, - 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, - 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, - 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, - 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, - 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, - 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, - 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, - 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, - 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, - 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, - 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, - 0x51, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x22, 0x93, 0x01, 0x0a, 0x21, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, - 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, - 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x48, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x05, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x8c, 0x03, 0x0a, 0x1b, 0x42, 0x6c, 0x69, - 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, - 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, - 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, - 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, - 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, - 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x4a, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x94, 0x06, 0x0a, 0x1f, 0x42, 0x6c, 0x69, 0x6e, - 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, + 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xfa, + 0x05, 0x0a, 0x18, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, @@ -5301,70 +5778,219 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0xc2, - 0x01, 0x0a, 0x1e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x44, 0x65, 0x6e, 0x65, - 0x62, 0x12, 0x43, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, - 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, - 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, - 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, 0x6b, 0x7a, - 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, - 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, - 0x6f, 0x62, 0x73, 0x22, 0xb6, 0x01, 0x0a, 0x18, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x44, 0x65, 0x6e, 0x65, 0x62, - 0x12, 0x3d, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x93, 0x01, 0x0a, 0x21, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, + 0x78, 0x12, 0x48, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, + 0x74, 0x72, 0x69, 0x78, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x8c, 0x03, 0x0a, 0x1b, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, + 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, + 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, + 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, + 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, + 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, + 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, + 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, + 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x4a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, + 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, + 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x72, 0x69, 0x78, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x22, 0x94, 0x06, 0x0a, 0x1f, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x65, 0x6c, 0x6c, 0x61, + 0x74, 0x72, 0x69, 0x78, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, + 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, + 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, + 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, + 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, + 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, - 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, - 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, - 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, - 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, - 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0x7d, 0x0a, 0x16, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x3d, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x05, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, + 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, + 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, + 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, + 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, + 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, + 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, + 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, + 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, + 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, + 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, + 0x78, 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x12, 0x64, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x81, 0x01, 0x0a, 0x18, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, + 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xf6, 0x02, 0x0a, 0x10, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, - 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, - 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, - 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, - 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x6f, 0x6f, 0x74, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x22, 0xb3, 0x07, 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x2b, 0x0a, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xfa, 0x02, 0x0a, 0x12, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, + 0x6c, 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, + 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, + 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, 0x70, 0x65, 0x6c, + 0x6c, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xf3, 0x06, 0x0a, 0x16, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, 0x70, 0x65, + 0x6c, 0x6c, 0x61, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, + 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, + 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, + 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, + 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, + 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, + 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x73, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, + 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, + 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, + 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, + 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, + 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x12, 0x58, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x72, 0x0a, 0x18, 0x62, 0x6c, + 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, + 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x8f, + 0x01, 0x0a, 0x1f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, + 0x6c, 0x61, 0x12, 0x46, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, + 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, + 0x6c, 0x6c, 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x22, 0x88, 0x03, 0x0a, 0x19, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x59, + 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, + 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, + 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, + 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, + 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, + 0x74, 0x12, 0x48, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, + 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x8d, 0x07, 0x0a, 0x1d, + 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, @@ -5405,104 +6031,237 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, - 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, - 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x12, 0x72, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, - 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, - 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0c, + 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x18, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, + 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x72, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, + 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, + 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x17, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, + 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x42, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, + 0x6c, 0x61, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x11, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, + 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x49, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x1e, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, + 0x22, 0xc2, 0x01, 0x0a, 0x1e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x44, 0x65, + 0x6e, 0x65, 0x62, 0x12, 0x43, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, + 0x62, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, + 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, + 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, + 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, + 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, + 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0x7d, 0x0a, 0x16, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, + 0x3d, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x18, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x44, 0x65, 0x6e, 0x65, + 0x62, 0x12, 0x3d, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, - 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x81, 0x01, 0x0a, 0x18, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, - 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, + 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, + 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, + 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0xf6, 0x02, + 0x0a, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, + 0x65, 0x62, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, + 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, + 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, 0x65, 0x6e, 0x65, 0x62, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xb3, 0x07, 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, + 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, + 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, + 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, + 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, + 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, + 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x5d, + 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4f, 0x0a, + 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, + 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, + 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, + 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, + 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, + 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, + 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, + 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x56, 0x0a, 0x11, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x6e, + 0x65, 0x62, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x72, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, + 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, + 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, + 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, + 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, + 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x8f, 0x01, 0x0a, + 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x48, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xfa, - 0x02, 0x0a, 0x12, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, - 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, - 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, + 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x84, + 0x03, 0x0a, 0x17, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, + 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, - 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, - 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xf3, 0x06, 0x0a, 0x16, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, - 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, - 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, - 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, - 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, - 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, - 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, - 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, - 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, - 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, - 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, - 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, - 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, - 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, - 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x10, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x72, 0x0a, + 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, + 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, + 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, + 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, + 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, + 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x46, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xcd, 0x07, 0x0a, 0x1b, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, + 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, + 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, + 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, + 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, + 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, + 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, + 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, + 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, + 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, + 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, + 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, + 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, + 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, + 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, + 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, + 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, + 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, + 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x12, 0x69, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x72, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, @@ -5510,17 +6269,219 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x22, 0x8f, 0x01, 0x0a, 0x1f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, - 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, - 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x46, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, - 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, - 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, + 0x73, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0c, 0x42, + 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, + 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7f, 0x0a, 0x15, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, + 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x40, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, + 0x69, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xdc, 0x01, 0x0a, 0x0f, 0x42, 0x75, 0x69, 0x6c, 0x64, + 0x65, 0x72, 0x42, 0x69, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x47, 0x0a, 0x06, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, + 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x06, 0x70, + 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0xb4, 0x02, 0x0a, 0x11, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, + 0x72, 0x42, 0x69, 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x47, 0x0a, 0x06, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x06, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, 0x7a, 0x67, + 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, + 0x34, 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x52, 0x11, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x1c, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x06, + 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x34, 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x83, 0x01, 0x0a, + 0x17, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, + 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x42, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x45, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x61, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x22, 0x55, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, + 0x72, 0x73, 0x12, 0x45, 0x0a, 0x08, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, + 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x36, 0x52, + 0x08, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x22, 0xc0, 0x02, 0x0a, 0x0b, 0x42, 0x6c, + 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, + 0x1e, 0x0a, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x0a, 0x8a, + 0xb5, 0x18, 0x06, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x52, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x12, + 0x2d, 0x0a, 0x0e, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, + 0x0d, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, + 0x0a, 0x09, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x08, 0x6b, 0x7a, 0x67, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x12, 0x5e, 0x0a, 0x13, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x11, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x47, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x09, 0x8a, 0xb5, 0x18, 0x05, 0x31, 0x37, 0x2c, + 0x33, 0x32, 0x52, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, + 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0xc6, 0x01, 0x0a, + 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, + 0x61, 0x12, 0x45, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, + 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, + 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, + 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, + 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, + 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, + 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, + 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0x81, 0x01, 0x0a, 0x18, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, + 0x72, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x05, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xba, 0x01, 0x0a, 0x1a, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, + 0x72, 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, + 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, + 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, + 0x09, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, + 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, + 0x2c, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, + 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0xfa, 0x02, 0x0a, 0x12, 0x42, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x59, 0x0a, + 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, + 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, + 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, + 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, + 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x22, 0x97, 0x08, 0x0a, 0x16, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2b, + 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, + 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, + 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, + 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, + 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, + 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x64, 0x0a, + 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x31, + 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, + 0x63, 0x74, 0x72, 0x61, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, + 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, + 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, + 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, + 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, + 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x10, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, + 0x72, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, + 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, + 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, + 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x52, 0x11, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x22, 0x93, 0x01, + 0x0a, 0x1f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, + 0x61, 0x12, 0x4a, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, + 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, + 0x63, 0x74, 0x72, 0x61, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x88, 0x03, 0x0a, 0x19, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, @@ -5543,9 +6504,9 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, - 0x79, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x8d, - 0x07, 0x0a, 0x1d, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, + 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xb1, + 0x08, 0x0a, 0x1d, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, @@ -5554,480 +6515,163 @@ var file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc = []byte{ 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, - 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, - 0x5d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4f, - 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, - 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, - 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, - 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, - 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, - 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, - 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6b, 0x0a, - 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, - 0x6c, 0x61, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x72, 0x0a, 0x18, 0x62, 0x6c, - 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, - 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x8f, - 0x01, 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, - 0x12, 0x48, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, - 0x62, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x22, 0x84, 0x03, 0x0a, 0x17, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x59, 0x0a, 0x04, - 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, - 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, - 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, - 0x46, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x44, 0x65, 0x6e, 0x65, - 0x62, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xcd, 0x07, 0x0a, 0x1b, 0x42, 0x6c, 0x69, 0x6e, - 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, - 0x64, 0x79, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, - 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, - 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, - 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, - 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, - 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x05, 0x92, 0xb5, 0x18, - 0x01, 0x32, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, - 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, - 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, - 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, - 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, - 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x12, 0x69, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, - 0x72, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, - 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, - 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, - 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x20, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x45, 0x0a, 0x05, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x05, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, - 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, 0x6b, 0x7a, 0x67, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, 0x31, 0x30, 0x37, - 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, - 0x22, 0xba, 0x01, 0x0a, 0x1a, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, - 0x3f, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, - 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, - 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, - 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0x81, 0x01, - 0x0a, 0x18, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x3f, 0x0a, 0x05, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, - 0x63, 0x74, 0x72, 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x22, 0xfa, 0x02, 0x0a, 0x12, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, - 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, - 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, - 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, - 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, - 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xc3, - 0x07, 0x0a, 0x16, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, - 0x64, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, - 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, - 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, - 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, - 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, - 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, - 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x64, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x45, 0x6c, 0x65, - 0x63, 0x74, 0x72, 0x61, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x31, 0x52, 0x11, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, - 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x42, - 0x05, 0x92, 0xb5, 0x18, 0x01, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, - 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, - 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, - 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, - 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, - 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x10, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x72, 0x0a, 0x18, - 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, - 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, - 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, - 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x1f, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, - 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x4a, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x88, 0x03, 0x0a, 0x19, 0x42, - 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, - 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, - 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0b, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, - 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, - 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x48, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xdd, 0x07, 0x0a, 0x1d, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, - 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2b, 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, - 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, - 0x76, 0x65, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, - 0x74, 0x61, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, - 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, - 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x64, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x45, 0x6c, 0x65, 0x63, 0x74, - 0x72, 0x61, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x31, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x0c, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x42, 0x05, 0x92, - 0xb5, 0x18, 0x01, 0x38, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, - 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, - 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, - 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, - 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, + 0x5e, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x12, 0x6b, 0x0a, 0x18, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, - 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6c, - 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x16, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x72, 0x0a, - 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, - 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, - 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0c, 0x42, - 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, - 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa1, 0x01, 0x0a, 0x17, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, - 0x31, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, - 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1b, - 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1e, 0x0a, 0x06, 0x70, 0x75, 0x62, - 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, - 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x72, 0x0a, 0x1e, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x31, 0x12, 0x50, 0x0a, 0x08, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, + 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x11, 0x70, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, + 0x64, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x42, 0x05, 0x92, 0xb5, 0x18, + 0x01, 0x31, 0x52, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x38, 0x52, 0x0c, 0x61, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x64, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x56, 0x31, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x8f, 0x01, - 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x12, - 0x48, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, - 0x8e, 0x01, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x12, 0x42, - 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x1e, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x22, 0x75, 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, - 0x72, 0x42, 0x69, 0x64, 0x12, 0x3b, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x75, - 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x11, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x49, 0x0a, - 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, - 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x06, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x83, 0x01, 0x0a, 0x17, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, - 0x6c, 0x61, 0x12, 0x42, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, - 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xdc, 0x01, 0x0a, - 0x0f, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, - 0x12, 0x47, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, - 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, - 0x62, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, - 0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, - 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, - 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1e, 0x0a, 0x06, 0x70, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x34, 0x38, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x7f, 0x0a, 0x15, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x44, - 0x65, 0x6e, 0x65, 0x62, 0x12, 0x40, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x75, - 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x69, 0x64, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, - 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xc0, 0x02, 0x0a, - 0x0b, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x14, 0x0a, 0x05, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x1e, 0x0a, 0x04, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x06, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x52, 0x04, 0x62, 0x6c, - 0x6f, 0x62, 0x12, 0x2d, 0x0a, 0x0e, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, - 0x34, 0x38, 0x52, 0x0d, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x12, 0x23, 0x0a, 0x09, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x08, 0x6b, 0x7a, - 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x5e, 0x0a, 0x13, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x52, 0x11, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x47, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, - 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x09, 0x8a, 0xb5, 0x18, 0x05, - 0x31, 0x37, 0x2c, 0x33, 0x32, 0x52, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, - 0x74, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, - 0x55, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x12, - 0x45, 0x0a, 0x08, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, - 0x64, 0x65, 0x63, 0x61, 0x72, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, 0x36, 0x52, 0x08, 0x73, 0x69, - 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x06, 0x92, + 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x08, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, + 0x5b, 0x0a, 0x0f, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x65, 0x78, 0x69, + 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, + 0x45, 0x78, 0x69, 0x74, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0e, 0x76, 0x6f, + 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x73, 0x12, 0x4b, 0x0a, 0x0e, + 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x69, 0x0a, 0x18, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x16, 0x65, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x72, 0x0a, 0x18, 0x62, 0x6c, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x65, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, + 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, + 0x36, 0x52, 0x15, 0x62, 0x6c, 0x73, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f, 0x62, + 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, + 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, + 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x54, 0x0a, 0x12, + 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x52, + 0x11, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x22, 0xc7, 0x01, 0x0a, 0x17, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x55, + 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x31, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x12, 0x55, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, - 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x45, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x0c, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x22, 0xb6, 0x01, 0x0a, + 0x19, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x37, 0x0a, 0x11, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x0a, 0x92, 0xb5, 0x18, 0x06, 0x31, 0x33, 0x31, 0x30, 0x37, + 0x32, 0x52, 0x10, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x64, 0x69, + 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x46, 0x75, 0x6c, 0x75, 0x12, 0x42, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x46, 0x75, 0x6c, 0x75, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, + 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, + 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, + 0x36, 0x52, 0x09, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, + 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, + 0x08, 0x3f, 0x2c, 0x31, 0x33, 0x31, 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, + 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0x7e, 0x0a, 0x15, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x75, 0x6c, + 0x75, 0x12, 0x3f, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x05, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x17, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x46, 0x75, 0x6c, 0x75, 0x12, 0x3f, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x05, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x0a, 0x0a, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, + 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, + 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x09, 0x6b, 0x7a, 0x67, + 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x08, 0x3f, 0x2c, 0x31, 0x33, 0x31, + 0x30, 0x37, 0x32, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x05, 0x62, 0x6c, 0x6f, + 0x62, 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x1c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, + 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, + 0x75, 0x6c, 0x75, 0x12, 0x47, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, + 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, + 0x75, 0x6c, 0x75, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x22, 0x85, 0x03, 0x0a, 0x16, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x75, 0x12, 0x59, 0x0a, + 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, + 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, + 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, + 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, + 0x12, 0x48, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x45, 0x6c, 0x65, + 0x63, 0x74, 0x72, 0x61, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, + 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, + 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -6042,235 +6686,255 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_rawDescGZIP() []byte { return file_proto_prysm_v1alpha1_beacon_block_proto_rawDescData } -var file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes = make([]protoimpl.MessageInfo, 60) +var file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes = make([]protoimpl.MessageInfo, 67) var file_proto_prysm_v1alpha1_beacon_block_proto_goTypes = []interface{}{ (*GenericSignedBeaconBlock)(nil), // 0: ethereum.eth.v1alpha1.GenericSignedBeaconBlock (*GenericBeaconBlock)(nil), // 1: ethereum.eth.v1alpha1.GenericBeaconBlock - (*BeaconBlock)(nil), // 2: ethereum.eth.v1alpha1.BeaconBlock - (*SignedBeaconBlock)(nil), // 3: ethereum.eth.v1alpha1.SignedBeaconBlock - (*BeaconBlockAltair)(nil), // 4: ethereum.eth.v1alpha1.BeaconBlockAltair - (*SignedBeaconBlockAltair)(nil), // 5: ethereum.eth.v1alpha1.SignedBeaconBlockAltair - (*BeaconBlockBody)(nil), // 6: ethereum.eth.v1alpha1.BeaconBlockBody - (*BeaconBlockBodyAltair)(nil), // 7: ethereum.eth.v1alpha1.BeaconBlockBodyAltair + (*SignedBeaconBlock)(nil), // 2: ethereum.eth.v1alpha1.SignedBeaconBlock + (*BeaconBlock)(nil), // 3: ethereum.eth.v1alpha1.BeaconBlock + (*BeaconBlockBody)(nil), // 4: ethereum.eth.v1alpha1.BeaconBlockBody + (*SignedBeaconBlockHeader)(nil), // 5: ethereum.eth.v1alpha1.SignedBeaconBlockHeader + (*BeaconBlockHeader)(nil), // 6: ethereum.eth.v1alpha1.BeaconBlockHeader + (*Eth1Data)(nil), // 7: ethereum.eth.v1alpha1.Eth1Data (*ProposerSlashing)(nil), // 8: ethereum.eth.v1alpha1.ProposerSlashing (*AttesterSlashing)(nil), // 9: ethereum.eth.v1alpha1.AttesterSlashing - (*AttesterSlashingElectra)(nil), // 10: ethereum.eth.v1alpha1.AttesterSlashingElectra + (*IndexedAttestation)(nil), // 10: ethereum.eth.v1alpha1.IndexedAttestation (*Deposit)(nil), // 11: ethereum.eth.v1alpha1.Deposit - (*VoluntaryExit)(nil), // 12: ethereum.eth.v1alpha1.VoluntaryExit - (*SignedVoluntaryExit)(nil), // 13: ethereum.eth.v1alpha1.SignedVoluntaryExit - (*Eth1Data)(nil), // 14: ethereum.eth.v1alpha1.Eth1Data - (*BeaconBlockHeader)(nil), // 15: ethereum.eth.v1alpha1.BeaconBlockHeader - (*SignedBeaconBlockHeader)(nil), // 16: ethereum.eth.v1alpha1.SignedBeaconBlockHeader - (*IndexedAttestation)(nil), // 17: ethereum.eth.v1alpha1.IndexedAttestation - (*IndexedAttestationElectra)(nil), // 18: ethereum.eth.v1alpha1.IndexedAttestationElectra - (*SyncAggregate)(nil), // 19: ethereum.eth.v1alpha1.SyncAggregate - (*SignedBeaconBlockBellatrix)(nil), // 20: ethereum.eth.v1alpha1.SignedBeaconBlockBellatrix - (*BeaconBlockBellatrix)(nil), // 21: ethereum.eth.v1alpha1.BeaconBlockBellatrix - (*BeaconBlockBodyBellatrix)(nil), // 22: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix - (*SignedBlindedBeaconBlockBellatrix)(nil), // 23: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockBellatrix - (*BlindedBeaconBlockBellatrix)(nil), // 24: ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix - (*BlindedBeaconBlockBodyBellatrix)(nil), // 25: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix - (*SignedBeaconBlockContentsDeneb)(nil), // 26: ethereum.eth.v1alpha1.SignedBeaconBlockContentsDeneb - (*BeaconBlockContentsDeneb)(nil), // 27: ethereum.eth.v1alpha1.BeaconBlockContentsDeneb - (*SignedBeaconBlockDeneb)(nil), // 28: ethereum.eth.v1alpha1.SignedBeaconBlockDeneb - (*BeaconBlockDeneb)(nil), // 29: ethereum.eth.v1alpha1.BeaconBlockDeneb - (*BeaconBlockBodyDeneb)(nil), // 30: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb - (*SignedBeaconBlockCapella)(nil), // 31: ethereum.eth.v1alpha1.SignedBeaconBlockCapella - (*BeaconBlockCapella)(nil), // 32: ethereum.eth.v1alpha1.BeaconBlockCapella - (*BeaconBlockBodyCapella)(nil), // 33: ethereum.eth.v1alpha1.BeaconBlockBodyCapella - (*SignedBlindedBeaconBlockCapella)(nil), // 34: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockCapella - (*BlindedBeaconBlockCapella)(nil), // 35: ethereum.eth.v1alpha1.BlindedBeaconBlockCapella - (*BlindedBeaconBlockBodyCapella)(nil), // 36: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella - (*SignedBlindedBeaconBlockDeneb)(nil), // 37: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockDeneb - (*BlindedBeaconBlockDeneb)(nil), // 38: ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb - (*BlindedBeaconBlockBodyDeneb)(nil), // 39: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb - (*SignedBeaconBlockContentsElectra)(nil), // 40: ethereum.eth.v1alpha1.SignedBeaconBlockContentsElectra - (*BeaconBlockContentsElectra)(nil), // 41: ethereum.eth.v1alpha1.BeaconBlockContentsElectra - (*SignedBeaconBlockElectra)(nil), // 42: ethereum.eth.v1alpha1.SignedBeaconBlockElectra - (*BeaconBlockElectra)(nil), // 43: ethereum.eth.v1alpha1.BeaconBlockElectra - (*BeaconBlockBodyElectra)(nil), // 44: ethereum.eth.v1alpha1.BeaconBlockBodyElectra - (*SignedBlindedBeaconBlockElectra)(nil), // 45: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockElectra - (*BlindedBeaconBlockElectra)(nil), // 46: ethereum.eth.v1alpha1.BlindedBeaconBlockElectra - (*BlindedBeaconBlockBodyElectra)(nil), // 47: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra - (*ValidatorRegistrationV1)(nil), // 48: ethereum.eth.v1alpha1.ValidatorRegistrationV1 - (*SignedValidatorRegistrationsV1)(nil), // 49: ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1 - (*SignedValidatorRegistrationV1)(nil), // 50: ethereum.eth.v1alpha1.SignedValidatorRegistrationV1 - (*BuilderBid)(nil), // 51: ethereum.eth.v1alpha1.BuilderBid - (*SignedBuilderBid)(nil), // 52: ethereum.eth.v1alpha1.SignedBuilderBid - (*BuilderBidCapella)(nil), // 53: ethereum.eth.v1alpha1.BuilderBidCapella - (*SignedBuilderBidCapella)(nil), // 54: ethereum.eth.v1alpha1.SignedBuilderBidCapella - (*BuilderBidDeneb)(nil), // 55: ethereum.eth.v1alpha1.BuilderBidDeneb - (*SignedBuilderBidDeneb)(nil), // 56: ethereum.eth.v1alpha1.SignedBuilderBidDeneb - (*BlobSidecar)(nil), // 57: ethereum.eth.v1alpha1.BlobSidecar - (*BlobSidecars)(nil), // 58: ethereum.eth.v1alpha1.BlobSidecars - (*Deposit_Data)(nil), // 59: ethereum.eth.v1alpha1.Deposit.Data - (*Attestation)(nil), // 60: ethereum.eth.v1alpha1.Attestation - (*AttestationData)(nil), // 61: ethereum.eth.v1alpha1.AttestationData - (*v1.ExecutionPayload)(nil), // 62: ethereum.engine.v1.ExecutionPayload - (*v1.ExecutionPayloadHeader)(nil), // 63: ethereum.engine.v1.ExecutionPayloadHeader - (*v1.ExecutionPayloadDeneb)(nil), // 64: ethereum.engine.v1.ExecutionPayloadDeneb - (*SignedBLSToExecutionChange)(nil), // 65: ethereum.eth.v1alpha1.SignedBLSToExecutionChange - (*v1.ExecutionPayloadCapella)(nil), // 66: ethereum.engine.v1.ExecutionPayloadCapella - (*v1.ExecutionPayloadHeaderCapella)(nil), // 67: ethereum.engine.v1.ExecutionPayloadHeaderCapella - (*v1.ExecutionPayloadHeaderDeneb)(nil), // 68: ethereum.engine.v1.ExecutionPayloadHeaderDeneb - (*AttestationElectra)(nil), // 69: ethereum.eth.v1alpha1.AttestationElectra - (*v1.ExecutionPayloadElectra)(nil), // 70: ethereum.engine.v1.ExecutionPayloadElectra - (*v1.ExecutionPayloadHeaderElectra)(nil), // 71: ethereum.engine.v1.ExecutionPayloadHeaderElectra + (*SignedVoluntaryExit)(nil), // 12: ethereum.eth.v1alpha1.SignedVoluntaryExit + (*VoluntaryExit)(nil), // 13: ethereum.eth.v1alpha1.VoluntaryExit + (*SignedValidatorRegistrationsV1)(nil), // 14: ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1 + (*SignedValidatorRegistrationV1)(nil), // 15: ethereum.eth.v1alpha1.SignedValidatorRegistrationV1 + (*ValidatorRegistrationV1)(nil), // 16: ethereum.eth.v1alpha1.ValidatorRegistrationV1 + (*SignedBuilderBid)(nil), // 17: ethereum.eth.v1alpha1.SignedBuilderBid + (*BuilderBid)(nil), // 18: ethereum.eth.v1alpha1.BuilderBid + (*SignedBeaconBlockAltair)(nil), // 19: ethereum.eth.v1alpha1.SignedBeaconBlockAltair + (*BeaconBlockAltair)(nil), // 20: ethereum.eth.v1alpha1.BeaconBlockAltair + (*BeaconBlockBodyAltair)(nil), // 21: ethereum.eth.v1alpha1.BeaconBlockBodyAltair + (*SyncAggregate)(nil), // 22: ethereum.eth.v1alpha1.SyncAggregate + (*SignedBeaconBlockBellatrix)(nil), // 23: ethereum.eth.v1alpha1.SignedBeaconBlockBellatrix + (*BeaconBlockBellatrix)(nil), // 24: ethereum.eth.v1alpha1.BeaconBlockBellatrix + (*BeaconBlockBodyBellatrix)(nil), // 25: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix + (*SignedBlindedBeaconBlockBellatrix)(nil), // 26: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockBellatrix + (*BlindedBeaconBlockBellatrix)(nil), // 27: ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix + (*BlindedBeaconBlockBodyBellatrix)(nil), // 28: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix + (*SignedBeaconBlockCapella)(nil), // 29: ethereum.eth.v1alpha1.SignedBeaconBlockCapella + (*BeaconBlockCapella)(nil), // 30: ethereum.eth.v1alpha1.BeaconBlockCapella + (*BeaconBlockBodyCapella)(nil), // 31: ethereum.eth.v1alpha1.BeaconBlockBodyCapella + (*SignedBlindedBeaconBlockCapella)(nil), // 32: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockCapella + (*BlindedBeaconBlockCapella)(nil), // 33: ethereum.eth.v1alpha1.BlindedBeaconBlockCapella + (*BlindedBeaconBlockBodyCapella)(nil), // 34: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella + (*SignedBuilderBidCapella)(nil), // 35: ethereum.eth.v1alpha1.SignedBuilderBidCapella + (*BuilderBidCapella)(nil), // 36: ethereum.eth.v1alpha1.BuilderBidCapella + (*SignedBeaconBlockContentsDeneb)(nil), // 37: ethereum.eth.v1alpha1.SignedBeaconBlockContentsDeneb + (*SignedBeaconBlockDeneb)(nil), // 38: ethereum.eth.v1alpha1.SignedBeaconBlockDeneb + (*BeaconBlockContentsDeneb)(nil), // 39: ethereum.eth.v1alpha1.BeaconBlockContentsDeneb + (*BeaconBlockDeneb)(nil), // 40: ethereum.eth.v1alpha1.BeaconBlockDeneb + (*BeaconBlockBodyDeneb)(nil), // 41: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb + (*SignedBlindedBeaconBlockDeneb)(nil), // 42: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockDeneb + (*BlindedBeaconBlockDeneb)(nil), // 43: ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb + (*BlindedBeaconBlockBodyDeneb)(nil), // 44: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb + (*SignedBuilderBidDeneb)(nil), // 45: ethereum.eth.v1alpha1.SignedBuilderBidDeneb + (*BuilderBidDeneb)(nil), // 46: ethereum.eth.v1alpha1.BuilderBidDeneb + (*BuilderBidElectra)(nil), // 47: ethereum.eth.v1alpha1.BuilderBidElectra + (*SignedBuilderBidElectra)(nil), // 48: ethereum.eth.v1alpha1.SignedBuilderBidElectra + (*BlobSidecars)(nil), // 49: ethereum.eth.v1alpha1.BlobSidecars + (*BlobSidecar)(nil), // 50: ethereum.eth.v1alpha1.BlobSidecar + (*SignedBeaconBlockContentsElectra)(nil), // 51: ethereum.eth.v1alpha1.SignedBeaconBlockContentsElectra + (*SignedBeaconBlockElectra)(nil), // 52: ethereum.eth.v1alpha1.SignedBeaconBlockElectra + (*BeaconBlockContentsElectra)(nil), // 53: ethereum.eth.v1alpha1.BeaconBlockContentsElectra + (*BeaconBlockElectra)(nil), // 54: ethereum.eth.v1alpha1.BeaconBlockElectra + (*BeaconBlockBodyElectra)(nil), // 55: ethereum.eth.v1alpha1.BeaconBlockBodyElectra + (*SignedBlindedBeaconBlockElectra)(nil), // 56: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockElectra + (*BlindedBeaconBlockElectra)(nil), // 57: ethereum.eth.v1alpha1.BlindedBeaconBlockElectra + (*BlindedBeaconBlockBodyElectra)(nil), // 58: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra + (*AttesterSlashingElectra)(nil), // 59: ethereum.eth.v1alpha1.AttesterSlashingElectra + (*IndexedAttestationElectra)(nil), // 60: ethereum.eth.v1alpha1.IndexedAttestationElectra + (*SignedBeaconBlockContentsFulu)(nil), // 61: ethereum.eth.v1alpha1.SignedBeaconBlockContentsFulu + (*SignedBeaconBlockFulu)(nil), // 62: ethereum.eth.v1alpha1.SignedBeaconBlockFulu + (*BeaconBlockContentsFulu)(nil), // 63: ethereum.eth.v1alpha1.BeaconBlockContentsFulu + (*SignedBlindedBeaconBlockFulu)(nil), // 64: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockFulu + (*BlindedBeaconBlockFulu)(nil), // 65: ethereum.eth.v1alpha1.BlindedBeaconBlockFulu + (*Deposit_Data)(nil), // 66: ethereum.eth.v1alpha1.Deposit.Data + (*Attestation)(nil), // 67: ethereum.eth.v1alpha1.Attestation + (*AttestationData)(nil), // 68: ethereum.eth.v1alpha1.AttestationData + (*v1.ExecutionPayloadHeader)(nil), // 69: ethereum.engine.v1.ExecutionPayloadHeader + (*v1.ExecutionPayload)(nil), // 70: ethereum.engine.v1.ExecutionPayload + (*v1.ExecutionPayloadCapella)(nil), // 71: ethereum.engine.v1.ExecutionPayloadCapella + (*SignedBLSToExecutionChange)(nil), // 72: ethereum.eth.v1alpha1.SignedBLSToExecutionChange + (*v1.ExecutionPayloadHeaderCapella)(nil), // 73: ethereum.engine.v1.ExecutionPayloadHeaderCapella + (*v1.ExecutionPayloadDeneb)(nil), // 74: ethereum.engine.v1.ExecutionPayloadDeneb + (*v1.ExecutionPayloadHeaderDeneb)(nil), // 75: ethereum.engine.v1.ExecutionPayloadHeaderDeneb + (*v1.ExecutionRequests)(nil), // 76: ethereum.engine.v1.ExecutionRequests + (*AttestationElectra)(nil), // 77: ethereum.eth.v1alpha1.AttestationElectra } var file_proto_prysm_v1alpha1_beacon_block_proto_depIdxs = []int32{ - 3, // 0: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.phase0:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlock - 5, // 1: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.altair:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockAltair - 20, // 2: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.bellatrix:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockBellatrix - 23, // 3: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_bellatrix:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockBellatrix - 31, // 4: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.capella:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockCapella - 34, // 5: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_capella:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockCapella - 26, // 6: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.deneb:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockContentsDeneb - 37, // 7: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_deneb:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockDeneb - 40, // 8: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.electra:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockContentsElectra - 45, // 9: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_electra:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockElectra - 2, // 10: ethereum.eth.v1alpha1.GenericBeaconBlock.phase0:type_name -> ethereum.eth.v1alpha1.BeaconBlock - 4, // 11: ethereum.eth.v1alpha1.GenericBeaconBlock.altair:type_name -> ethereum.eth.v1alpha1.BeaconBlockAltair - 21, // 12: ethereum.eth.v1alpha1.GenericBeaconBlock.bellatrix:type_name -> ethereum.eth.v1alpha1.BeaconBlockBellatrix - 24, // 13: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_bellatrix:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix - 32, // 14: ethereum.eth.v1alpha1.GenericBeaconBlock.capella:type_name -> ethereum.eth.v1alpha1.BeaconBlockCapella - 35, // 15: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_capella:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockCapella - 27, // 16: ethereum.eth.v1alpha1.GenericBeaconBlock.deneb:type_name -> ethereum.eth.v1alpha1.BeaconBlockContentsDeneb - 38, // 17: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_deneb:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb - 41, // 18: ethereum.eth.v1alpha1.GenericBeaconBlock.electra:type_name -> ethereum.eth.v1alpha1.BeaconBlockContentsElectra - 46, // 19: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_electra:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockElectra - 6, // 20: ethereum.eth.v1alpha1.BeaconBlock.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBody - 2, // 21: ethereum.eth.v1alpha1.SignedBeaconBlock.block:type_name -> ethereum.eth.v1alpha1.BeaconBlock - 7, // 22: ethereum.eth.v1alpha1.BeaconBlockAltair.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyAltair - 4, // 23: ethereum.eth.v1alpha1.SignedBeaconBlockAltair.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockAltair - 14, // 24: ethereum.eth.v1alpha1.BeaconBlockBody.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 25: ethereum.eth.v1alpha1.BeaconBlockBody.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 9, // 26: ethereum.eth.v1alpha1.BeaconBlockBody.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing - 60, // 27: ethereum.eth.v1alpha1.BeaconBlockBody.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 11, // 28: ethereum.eth.v1alpha1.BeaconBlockBody.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 29: ethereum.eth.v1alpha1.BeaconBlockBody.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 14, // 30: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 31: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 9, // 32: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing - 60, // 33: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 11, // 34: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 35: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 36: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 16, // 37: ethereum.eth.v1alpha1.ProposerSlashing.header_1:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockHeader - 16, // 38: ethereum.eth.v1alpha1.ProposerSlashing.header_2:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockHeader - 17, // 39: ethereum.eth.v1alpha1.AttesterSlashing.attestation_1:type_name -> ethereum.eth.v1alpha1.IndexedAttestation - 17, // 40: ethereum.eth.v1alpha1.AttesterSlashing.attestation_2:type_name -> ethereum.eth.v1alpha1.IndexedAttestation - 18, // 41: ethereum.eth.v1alpha1.AttesterSlashingElectra.attestation_1:type_name -> ethereum.eth.v1alpha1.IndexedAttestationElectra - 18, // 42: ethereum.eth.v1alpha1.AttesterSlashingElectra.attestation_2:type_name -> ethereum.eth.v1alpha1.IndexedAttestationElectra - 59, // 43: ethereum.eth.v1alpha1.Deposit.data:type_name -> ethereum.eth.v1alpha1.Deposit.Data - 12, // 44: ethereum.eth.v1alpha1.SignedVoluntaryExit.exit:type_name -> ethereum.eth.v1alpha1.VoluntaryExit - 15, // 45: ethereum.eth.v1alpha1.SignedBeaconBlockHeader.header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader - 61, // 46: ethereum.eth.v1alpha1.IndexedAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 61, // 47: ethereum.eth.v1alpha1.IndexedAttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 21, // 48: ethereum.eth.v1alpha1.SignedBeaconBlockBellatrix.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockBellatrix - 22, // 49: ethereum.eth.v1alpha1.BeaconBlockBellatrix.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix - 14, // 50: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 51: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 9, // 52: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing - 60, // 53: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 11, // 54: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 55: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 56: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 62, // 57: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayload - 24, // 58: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockBellatrix.block:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix - 25, // 59: ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix - 14, // 60: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 61: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 9, // 62: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing - 60, // 63: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 11, // 64: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 65: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 66: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 63, // 67: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeader - 28, // 68: ethereum.eth.v1alpha1.SignedBeaconBlockContentsDeneb.block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockDeneb - 29, // 69: ethereum.eth.v1alpha1.BeaconBlockContentsDeneb.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockDeneb - 29, // 70: ethereum.eth.v1alpha1.SignedBeaconBlockDeneb.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockDeneb - 30, // 71: ethereum.eth.v1alpha1.BeaconBlockDeneb.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyDeneb - 14, // 72: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 73: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 9, // 74: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing - 60, // 75: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 11, // 76: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 77: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 78: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 64, // 79: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayloadDeneb - 65, // 80: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange - 32, // 81: ethereum.eth.v1alpha1.SignedBeaconBlockCapella.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockCapella - 33, // 82: ethereum.eth.v1alpha1.BeaconBlockCapella.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyCapella - 14, // 83: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 84: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 9, // 85: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing - 60, // 86: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 11, // 87: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 88: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 89: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 66, // 90: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayloadCapella - 65, // 91: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange - 35, // 92: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockCapella.block:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockCapella - 36, // 93: ethereum.eth.v1alpha1.BlindedBeaconBlockCapella.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella - 14, // 94: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 95: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 9, // 96: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing - 60, // 97: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 11, // 98: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 99: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 100: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 67, // 101: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderCapella - 65, // 102: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange - 38, // 103: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockDeneb.message:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb - 39, // 104: ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb - 14, // 105: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 106: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 9, // 107: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing - 60, // 108: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 11, // 109: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 110: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 111: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 68, // 112: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb - 65, // 113: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange - 42, // 114: ethereum.eth.v1alpha1.SignedBeaconBlockContentsElectra.block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockElectra - 43, // 115: ethereum.eth.v1alpha1.BeaconBlockContentsElectra.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockElectra - 43, // 116: ethereum.eth.v1alpha1.SignedBeaconBlockElectra.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockElectra - 44, // 117: ethereum.eth.v1alpha1.BeaconBlockElectra.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyElectra - 14, // 118: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 119: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 10, // 120: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashingElectra - 69, // 121: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.attestations:type_name -> ethereum.eth.v1alpha1.AttestationElectra - 11, // 122: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 123: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 124: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 70, // 125: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayloadElectra - 65, // 126: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange - 46, // 127: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockElectra.message:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockElectra - 47, // 128: ethereum.eth.v1alpha1.BlindedBeaconBlockElectra.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra - 14, // 129: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 8, // 130: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing - 10, // 131: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashingElectra - 69, // 132: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.attestations:type_name -> ethereum.eth.v1alpha1.AttestationElectra - 11, // 133: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.deposits:type_name -> ethereum.eth.v1alpha1.Deposit - 13, // 134: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 19, // 135: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate - 71, // 136: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderElectra - 65, // 137: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange - 50, // 138: ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1.messages:type_name -> ethereum.eth.v1alpha1.SignedValidatorRegistrationV1 - 48, // 139: ethereum.eth.v1alpha1.SignedValidatorRegistrationV1.message:type_name -> ethereum.eth.v1alpha1.ValidatorRegistrationV1 - 63, // 140: ethereum.eth.v1alpha1.BuilderBid.header:type_name -> ethereum.engine.v1.ExecutionPayloadHeader - 51, // 141: ethereum.eth.v1alpha1.SignedBuilderBid.message:type_name -> ethereum.eth.v1alpha1.BuilderBid - 67, // 142: ethereum.eth.v1alpha1.BuilderBidCapella.header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderCapella - 53, // 143: ethereum.eth.v1alpha1.SignedBuilderBidCapella.message:type_name -> ethereum.eth.v1alpha1.BuilderBidCapella - 68, // 144: ethereum.eth.v1alpha1.BuilderBidDeneb.header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb - 55, // 145: ethereum.eth.v1alpha1.SignedBuilderBidDeneb.message:type_name -> ethereum.eth.v1alpha1.BuilderBidDeneb - 16, // 146: ethereum.eth.v1alpha1.BlobSidecar.signed_block_header:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockHeader - 57, // 147: ethereum.eth.v1alpha1.BlobSidecars.sidecars:type_name -> ethereum.eth.v1alpha1.BlobSidecar - 148, // [148:148] is the sub-list for method output_type - 148, // [148:148] is the sub-list for method input_type - 148, // [148:148] is the sub-list for extension type_name - 148, // [148:148] is the sub-list for extension extendee - 0, // [0:148] is the sub-list for field type_name + 2, // 0: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.phase0:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlock + 19, // 1: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.altair:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockAltair + 23, // 2: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.bellatrix:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockBellatrix + 26, // 3: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_bellatrix:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockBellatrix + 29, // 4: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.capella:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockCapella + 32, // 5: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_capella:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockCapella + 37, // 6: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.deneb:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockContentsDeneb + 42, // 7: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_deneb:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockDeneb + 51, // 8: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.electra:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockContentsElectra + 56, // 9: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_electra:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockElectra + 61, // 10: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.fulu:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockContentsFulu + 64, // 11: ethereum.eth.v1alpha1.GenericSignedBeaconBlock.blinded_fulu:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockFulu + 3, // 12: ethereum.eth.v1alpha1.GenericBeaconBlock.phase0:type_name -> ethereum.eth.v1alpha1.BeaconBlock + 20, // 13: ethereum.eth.v1alpha1.GenericBeaconBlock.altair:type_name -> ethereum.eth.v1alpha1.BeaconBlockAltair + 24, // 14: ethereum.eth.v1alpha1.GenericBeaconBlock.bellatrix:type_name -> ethereum.eth.v1alpha1.BeaconBlockBellatrix + 27, // 15: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_bellatrix:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix + 30, // 16: ethereum.eth.v1alpha1.GenericBeaconBlock.capella:type_name -> ethereum.eth.v1alpha1.BeaconBlockCapella + 33, // 17: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_capella:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockCapella + 39, // 18: ethereum.eth.v1alpha1.GenericBeaconBlock.deneb:type_name -> ethereum.eth.v1alpha1.BeaconBlockContentsDeneb + 43, // 19: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_deneb:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb + 53, // 20: ethereum.eth.v1alpha1.GenericBeaconBlock.electra:type_name -> ethereum.eth.v1alpha1.BeaconBlockContentsElectra + 57, // 21: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_electra:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockElectra + 63, // 22: ethereum.eth.v1alpha1.GenericBeaconBlock.fulu:type_name -> ethereum.eth.v1alpha1.BeaconBlockContentsFulu + 65, // 23: ethereum.eth.v1alpha1.GenericBeaconBlock.blinded_fulu:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockFulu + 3, // 24: ethereum.eth.v1alpha1.SignedBeaconBlock.block:type_name -> ethereum.eth.v1alpha1.BeaconBlock + 4, // 25: ethereum.eth.v1alpha1.BeaconBlock.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBody + 7, // 26: ethereum.eth.v1alpha1.BeaconBlockBody.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 27: ethereum.eth.v1alpha1.BeaconBlockBody.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 9, // 28: ethereum.eth.v1alpha1.BeaconBlockBody.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing + 67, // 29: ethereum.eth.v1alpha1.BeaconBlockBody.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 11, // 30: ethereum.eth.v1alpha1.BeaconBlockBody.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 31: ethereum.eth.v1alpha1.BeaconBlockBody.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 6, // 32: ethereum.eth.v1alpha1.SignedBeaconBlockHeader.header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader + 5, // 33: ethereum.eth.v1alpha1.ProposerSlashing.header_1:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockHeader + 5, // 34: ethereum.eth.v1alpha1.ProposerSlashing.header_2:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockHeader + 10, // 35: ethereum.eth.v1alpha1.AttesterSlashing.attestation_1:type_name -> ethereum.eth.v1alpha1.IndexedAttestation + 10, // 36: ethereum.eth.v1alpha1.AttesterSlashing.attestation_2:type_name -> ethereum.eth.v1alpha1.IndexedAttestation + 68, // 37: ethereum.eth.v1alpha1.IndexedAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 66, // 38: ethereum.eth.v1alpha1.Deposit.data:type_name -> ethereum.eth.v1alpha1.Deposit.Data + 13, // 39: ethereum.eth.v1alpha1.SignedVoluntaryExit.exit:type_name -> ethereum.eth.v1alpha1.VoluntaryExit + 15, // 40: ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1.messages:type_name -> ethereum.eth.v1alpha1.SignedValidatorRegistrationV1 + 16, // 41: ethereum.eth.v1alpha1.SignedValidatorRegistrationV1.message:type_name -> ethereum.eth.v1alpha1.ValidatorRegistrationV1 + 18, // 42: ethereum.eth.v1alpha1.SignedBuilderBid.message:type_name -> ethereum.eth.v1alpha1.BuilderBid + 69, // 43: ethereum.eth.v1alpha1.BuilderBid.header:type_name -> ethereum.engine.v1.ExecutionPayloadHeader + 20, // 44: ethereum.eth.v1alpha1.SignedBeaconBlockAltair.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockAltair + 21, // 45: ethereum.eth.v1alpha1.BeaconBlockAltair.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyAltair + 7, // 46: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 47: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 9, // 48: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing + 67, // 49: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 11, // 50: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 51: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 52: ethereum.eth.v1alpha1.BeaconBlockBodyAltair.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 24, // 53: ethereum.eth.v1alpha1.SignedBeaconBlockBellatrix.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockBellatrix + 25, // 54: ethereum.eth.v1alpha1.BeaconBlockBellatrix.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix + 7, // 55: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 56: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 9, // 57: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing + 67, // 58: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 11, // 59: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 60: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 61: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 70, // 62: ethereum.eth.v1alpha1.BeaconBlockBodyBellatrix.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayload + 27, // 63: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockBellatrix.block:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix + 28, // 64: ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix + 7, // 65: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 66: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 9, // 67: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing + 67, // 68: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 11, // 69: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 70: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 71: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 69, // 72: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyBellatrix.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeader + 30, // 73: ethereum.eth.v1alpha1.SignedBeaconBlockCapella.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockCapella + 31, // 74: ethereum.eth.v1alpha1.BeaconBlockCapella.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyCapella + 7, // 75: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 76: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 9, // 77: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing + 67, // 78: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 11, // 79: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 80: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 81: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 71, // 82: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayloadCapella + 72, // 83: ethereum.eth.v1alpha1.BeaconBlockBodyCapella.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange + 33, // 84: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockCapella.block:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockCapella + 34, // 85: ethereum.eth.v1alpha1.BlindedBeaconBlockCapella.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella + 7, // 86: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 87: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 9, // 88: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing + 67, // 89: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 11, // 90: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 91: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 92: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 73, // 93: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderCapella + 72, // 94: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyCapella.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange + 36, // 95: ethereum.eth.v1alpha1.SignedBuilderBidCapella.message:type_name -> ethereum.eth.v1alpha1.BuilderBidCapella + 73, // 96: ethereum.eth.v1alpha1.BuilderBidCapella.header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderCapella + 38, // 97: ethereum.eth.v1alpha1.SignedBeaconBlockContentsDeneb.block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockDeneb + 40, // 98: ethereum.eth.v1alpha1.SignedBeaconBlockDeneb.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockDeneb + 40, // 99: ethereum.eth.v1alpha1.BeaconBlockContentsDeneb.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockDeneb + 41, // 100: ethereum.eth.v1alpha1.BeaconBlockDeneb.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyDeneb + 7, // 101: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 102: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 9, // 103: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing + 67, // 104: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 11, // 105: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 106: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 107: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 74, // 108: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayloadDeneb + 72, // 109: ethereum.eth.v1alpha1.BeaconBlockBodyDeneb.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange + 43, // 110: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockDeneb.message:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb + 44, // 111: ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb + 7, // 112: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 113: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 9, // 114: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing + 67, // 115: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 11, // 116: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 117: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 118: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 75, // 119: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb + 72, // 120: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyDeneb.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange + 46, // 121: ethereum.eth.v1alpha1.SignedBuilderBidDeneb.message:type_name -> ethereum.eth.v1alpha1.BuilderBidDeneb + 75, // 122: ethereum.eth.v1alpha1.BuilderBidDeneb.header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb + 75, // 123: ethereum.eth.v1alpha1.BuilderBidElectra.header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb + 76, // 124: ethereum.eth.v1alpha1.BuilderBidElectra.execution_requests:type_name -> ethereum.engine.v1.ExecutionRequests + 47, // 125: ethereum.eth.v1alpha1.SignedBuilderBidElectra.message:type_name -> ethereum.eth.v1alpha1.BuilderBidElectra + 50, // 126: ethereum.eth.v1alpha1.BlobSidecars.sidecars:type_name -> ethereum.eth.v1alpha1.BlobSidecar + 5, // 127: ethereum.eth.v1alpha1.BlobSidecar.signed_block_header:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockHeader + 52, // 128: ethereum.eth.v1alpha1.SignedBeaconBlockContentsElectra.block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockElectra + 54, // 129: ethereum.eth.v1alpha1.SignedBeaconBlockElectra.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockElectra + 54, // 130: ethereum.eth.v1alpha1.BeaconBlockContentsElectra.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockElectra + 55, // 131: ethereum.eth.v1alpha1.BeaconBlockElectra.body:type_name -> ethereum.eth.v1alpha1.BeaconBlockBodyElectra + 7, // 132: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 133: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 59, // 134: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashingElectra + 77, // 135: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.attestations:type_name -> ethereum.eth.v1alpha1.AttestationElectra + 11, // 136: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 137: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 138: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 74, // 139: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.execution_payload:type_name -> ethereum.engine.v1.ExecutionPayloadDeneb + 72, // 140: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange + 76, // 141: ethereum.eth.v1alpha1.BeaconBlockBodyElectra.execution_requests:type_name -> ethereum.engine.v1.ExecutionRequests + 57, // 142: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockElectra.message:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockElectra + 58, // 143: ethereum.eth.v1alpha1.BlindedBeaconBlockElectra.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra + 7, // 144: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 8, // 145: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.proposer_slashings:type_name -> ethereum.eth.v1alpha1.ProposerSlashing + 59, // 146: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashingElectra + 77, // 147: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.attestations:type_name -> ethereum.eth.v1alpha1.AttestationElectra + 11, // 148: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.deposits:type_name -> ethereum.eth.v1alpha1.Deposit + 12, // 149: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.voluntary_exits:type_name -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 22, // 150: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 75, // 151: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb + 72, // 152: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.bls_to_execution_changes:type_name -> ethereum.eth.v1alpha1.SignedBLSToExecutionChange + 76, // 153: ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra.execution_requests:type_name -> ethereum.engine.v1.ExecutionRequests + 60, // 154: ethereum.eth.v1alpha1.AttesterSlashingElectra.attestation_1:type_name -> ethereum.eth.v1alpha1.IndexedAttestationElectra + 60, // 155: ethereum.eth.v1alpha1.AttesterSlashingElectra.attestation_2:type_name -> ethereum.eth.v1alpha1.IndexedAttestationElectra + 68, // 156: ethereum.eth.v1alpha1.IndexedAttestationElectra.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 62, // 157: ethereum.eth.v1alpha1.SignedBeaconBlockContentsFulu.block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockFulu + 54, // 158: ethereum.eth.v1alpha1.SignedBeaconBlockFulu.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockElectra + 54, // 159: ethereum.eth.v1alpha1.BeaconBlockContentsFulu.block:type_name -> ethereum.eth.v1alpha1.BeaconBlockElectra + 65, // 160: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockFulu.message:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockFulu + 58, // 161: ethereum.eth.v1alpha1.BlindedBeaconBlockFulu.body:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockBodyElectra + 162, // [162:162] is the sub-list for method output_type + 162, // [162:162] is the sub-list for method input_type + 162, // [162:162] is the sub-list for extension type_name + 162, // [162:162] is the sub-list for extension extendee + 0, // [0:162] is the sub-list for field type_name } func init() { file_proto_prysm_v1alpha1_beacon_block_proto_init() } @@ -6280,7 +6944,6 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } file_proto_prysm_v1alpha1_attestation_proto_init() file_proto_prysm_v1alpha1_withdrawals_proto_init() - file_proto_prysm_v1alpha1_eip_7251_proto_init() if !protoimpl.UnsafeEnabled { file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GenericSignedBeaconBlock); i { @@ -6307,7 +6970,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlock); i { + switch v := v.(*SignedBeaconBlock); i { case 0: return &v.state case 1: @@ -6319,7 +6982,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlock); i { + switch v := v.(*BeaconBlock); i { case 0: return &v.state case 1: @@ -6331,7 +6994,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockAltair); i { + switch v := v.(*BeaconBlockBody); i { case 0: return &v.state case 1: @@ -6343,7 +7006,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockAltair); i { + switch v := v.(*SignedBeaconBlockHeader); i { case 0: return &v.state case 1: @@ -6355,7 +7018,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBody); i { + switch v := v.(*BeaconBlockHeader); i { case 0: return &v.state case 1: @@ -6367,7 +7030,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyAltair); i { + switch v := v.(*Eth1Data); i { case 0: return &v.state case 1: @@ -6403,7 +7066,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttesterSlashingElectra); i { + switch v := v.(*IndexedAttestation); i { case 0: return &v.state case 1: @@ -6427,7 +7090,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VoluntaryExit); i { + switch v := v.(*SignedVoluntaryExit); i { case 0: return &v.state case 1: @@ -6439,7 +7102,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedVoluntaryExit); i { + switch v := v.(*VoluntaryExit); i { case 0: return &v.state case 1: @@ -6451,7 +7114,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Eth1Data); i { + switch v := v.(*SignedValidatorRegistrationsV1); i { case 0: return &v.state case 1: @@ -6463,7 +7126,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockHeader); i { + switch v := v.(*SignedValidatorRegistrationV1); i { case 0: return &v.state case 1: @@ -6475,7 +7138,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockHeader); i { + switch v := v.(*ValidatorRegistrationV1); i { case 0: return &v.state case 1: @@ -6487,7 +7150,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IndexedAttestation); i { + switch v := v.(*SignedBuilderBid); i { case 0: return &v.state case 1: @@ -6499,7 +7162,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*IndexedAttestationElectra); i { + switch v := v.(*BuilderBid); i { case 0: return &v.state case 1: @@ -6511,7 +7174,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncAggregate); i { + switch v := v.(*SignedBeaconBlockAltair); i { case 0: return &v.state case 1: @@ -6523,7 +7186,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockBellatrix); i { + switch v := v.(*BeaconBlockAltair); i { case 0: return &v.state case 1: @@ -6535,7 +7198,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBellatrix); i { + switch v := v.(*BeaconBlockBodyAltair); i { case 0: return &v.state case 1: @@ -6547,7 +7210,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyBellatrix); i { + switch v := v.(*SyncAggregate); i { case 0: return &v.state case 1: @@ -6559,7 +7222,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockBellatrix); i { + switch v := v.(*SignedBeaconBlockBellatrix); i { case 0: return &v.state case 1: @@ -6571,7 +7234,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBellatrix); i { + switch v := v.(*BeaconBlockBellatrix); i { case 0: return &v.state case 1: @@ -6583,7 +7246,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBodyBellatrix); i { + switch v := v.(*BeaconBlockBodyBellatrix); i { case 0: return &v.state case 1: @@ -6595,7 +7258,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockContentsDeneb); i { + switch v := v.(*SignedBlindedBeaconBlockBellatrix); i { case 0: return &v.state case 1: @@ -6607,7 +7270,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockContentsDeneb); i { + switch v := v.(*BlindedBeaconBlockBellatrix); i { case 0: return &v.state case 1: @@ -6619,7 +7282,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockDeneb); i { + switch v := v.(*BlindedBeaconBlockBodyBellatrix); i { case 0: return &v.state case 1: @@ -6631,7 +7294,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockDeneb); i { + switch v := v.(*SignedBeaconBlockCapella); i { case 0: return &v.state case 1: @@ -6643,7 +7306,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyDeneb); i { + switch v := v.(*BeaconBlockCapella); i { case 0: return &v.state case 1: @@ -6655,7 +7318,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockCapella); i { + switch v := v.(*BeaconBlockBodyCapella); i { case 0: return &v.state case 1: @@ -6667,7 +7330,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockCapella); i { + switch v := v.(*SignedBlindedBeaconBlockCapella); i { case 0: return &v.state case 1: @@ -6679,7 +7342,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyCapella); i { + switch v := v.(*BlindedBeaconBlockCapella); i { case 0: return &v.state case 1: @@ -6691,7 +7354,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockCapella); i { + switch v := v.(*BlindedBeaconBlockBodyCapella); i { case 0: return &v.state case 1: @@ -6703,7 +7366,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockCapella); i { + switch v := v.(*SignedBuilderBidCapella); i { case 0: return &v.state case 1: @@ -6715,7 +7378,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBodyCapella); i { + switch v := v.(*BuilderBidCapella); i { case 0: return &v.state case 1: @@ -6727,7 +7390,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockDeneb); i { + switch v := v.(*SignedBeaconBlockContentsDeneb); i { case 0: return &v.state case 1: @@ -6739,7 +7402,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockDeneb); i { + switch v := v.(*SignedBeaconBlockDeneb); i { case 0: return &v.state case 1: @@ -6751,7 +7414,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBodyDeneb); i { + switch v := v.(*BeaconBlockContentsDeneb); i { case 0: return &v.state case 1: @@ -6763,7 +7426,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockContentsElectra); i { + switch v := v.(*BeaconBlockDeneb); i { case 0: return &v.state case 1: @@ -6775,7 +7438,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockContentsElectra); i { + switch v := v.(*BeaconBlockBodyDeneb); i { case 0: return &v.state case 1: @@ -6787,7 +7450,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBeaconBlockElectra); i { + switch v := v.(*SignedBlindedBeaconBlockDeneb); i { case 0: return &v.state case 1: @@ -6799,7 +7462,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockElectra); i { + switch v := v.(*BlindedBeaconBlockDeneb); i { case 0: return &v.state case 1: @@ -6811,7 +7474,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconBlockBodyElectra); i { + switch v := v.(*BlindedBeaconBlockBodyDeneb); i { case 0: return &v.state case 1: @@ -6823,7 +7486,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBeaconBlockElectra); i { + switch v := v.(*SignedBuilderBidDeneb); i { case 0: return &v.state case 1: @@ -6835,7 +7498,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockElectra); i { + switch v := v.(*BuilderBidDeneb); i { case 0: return &v.state case 1: @@ -6847,7 +7510,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBeaconBlockBodyElectra); i { + switch v := v.(*BuilderBidElectra); i { case 0: return &v.state case 1: @@ -6859,7 +7522,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValidatorRegistrationV1); i { + switch v := v.(*SignedBuilderBidElectra); i { case 0: return &v.state case 1: @@ -6871,7 +7534,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedValidatorRegistrationsV1); i { + switch v := v.(*BlobSidecars); i { case 0: return &v.state case 1: @@ -6883,7 +7546,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedValidatorRegistrationV1); i { + switch v := v.(*BlobSidecar); i { case 0: return &v.state case 1: @@ -6895,7 +7558,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BuilderBid); i { + switch v := v.(*SignedBeaconBlockContentsElectra); i { case 0: return &v.state case 1: @@ -6907,7 +7570,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBuilderBid); i { + switch v := v.(*SignedBeaconBlockElectra); i { case 0: return &v.state case 1: @@ -6919,7 +7582,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BuilderBidCapella); i { + switch v := v.(*BeaconBlockContentsElectra); i { case 0: return &v.state case 1: @@ -6931,7 +7594,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBuilderBidCapella); i { + switch v := v.(*BeaconBlockElectra); i { case 0: return &v.state case 1: @@ -6943,7 +7606,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BuilderBidDeneb); i { + switch v := v.(*BeaconBlockBodyElectra); i { case 0: return &v.state case 1: @@ -6955,7 +7618,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBuilderBidDeneb); i { + switch v := v.(*SignedBlindedBeaconBlockElectra); i { case 0: return &v.state case 1: @@ -6967,7 +7630,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlobSidecar); i { + switch v := v.(*BlindedBeaconBlockElectra); i { case 0: return &v.state case 1: @@ -6979,7 +7642,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlobSidecars); i { + switch v := v.(*BlindedBeaconBlockBodyElectra); i { case 0: return &v.state case 1: @@ -6991,6 +7654,90 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { } } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AttesterSlashingElectra); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IndexedAttestationElectra); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignedBeaconBlockContentsFulu); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignedBeaconBlockFulu); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BeaconBlockContentsFulu); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignedBlindedBeaconBlockFulu); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlindedBeaconBlockFulu); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Deposit_Data); i { case 0: return &v.state @@ -7014,6 +7761,8 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { (*GenericSignedBeaconBlock_BlindedDeneb)(nil), (*GenericSignedBeaconBlock_Electra)(nil), (*GenericSignedBeaconBlock_BlindedElectra)(nil), + (*GenericSignedBeaconBlock_Fulu)(nil), + (*GenericSignedBeaconBlock_BlindedFulu)(nil), } file_proto_prysm_v1alpha1_beacon_block_proto_msgTypes[1].OneofWrappers = []interface{}{ (*GenericBeaconBlock_Phase0)(nil), @@ -7026,6 +7775,8 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { (*GenericBeaconBlock_BlindedDeneb)(nil), (*GenericBeaconBlock_Electra)(nil), (*GenericBeaconBlock_BlindedElectra)(nil), + (*GenericBeaconBlock_Fulu)(nil), + (*GenericBeaconBlock_BlindedFulu)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -7033,7 +7784,7 @@ func file_proto_prysm_v1alpha1_beacon_block_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_prysm_v1alpha1_beacon_block_proto_rawDesc, NumEnums: 0, - NumMessages: 60, + NumMessages: 67, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/prysm/v1alpha1/beacon_block.pb.gw.go b/proto/prysm/v1alpha1/beacon_block.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/beacon_block.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/beacon_block.proto b/proto/prysm/v1alpha1/beacon_block.proto index 7b93a4ae1678..2fbee2024e57 100644 --- a/proto/prysm/v1alpha1/beacon_block.proto +++ b/proto/prysm/v1alpha1/beacon_block.proto @@ -19,6 +19,7 @@ import "proto/eth/ext/options.proto"; import "proto/prysm/v1alpha1/attestation.proto"; import "proto/prysm/v1alpha1/withdrawals.proto"; import "proto/engine/v1/execution_engine.proto"; +import "proto/engine/v1/electra.proto"; option csharp_namespace = "Ethereum.Eth.v1alpha1"; option go_package = "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1;eth"; @@ -27,926 +28,1215 @@ option java_outer_classname = "BeaconBlockProto"; option java_package = "org.ethereum.eth.v1alpha1"; option php_namespace = "Ethereum\\Eth\\v1alpha1"; -message GenericSignedBeaconBlock { - oneof block { - // Representing a signed, phase 0 beacon block. - SignedBeaconBlock phase0 = 1; +// ---------------------------------------------------------------------------- +// Generic +// ---------------------------------------------------------------------------- - // Representing a signed, post-Altair fork beacon block. - SignedBeaconBlockAltair altair = 2; +message GenericSignedBeaconBlock { + oneof block { + // Representing a signed, phase 0 beacon block. + SignedBeaconBlock phase0 = 1; - // Representing a signed, post-Bellatrix fork beacon block. - SignedBeaconBlockBellatrix bellatrix = 3; + // Representing a signed, post-Altair fork beacon block. + SignedBeaconBlockAltair altair = 2; - // Representing a signed, post-Bellatrix fork blinded beacon block. - SignedBlindedBeaconBlockBellatrix blinded_bellatrix = 4; + // Representing a signed, post-Bellatrix fork beacon block. + SignedBeaconBlockBellatrix bellatrix = 3; - // Representing a signed, post-Capella fork beacon block. - SignedBeaconBlockCapella capella = 5; + // Representing a signed, post-Bellatrix fork blinded beacon block. + SignedBlindedBeaconBlockBellatrix blinded_bellatrix = 4; - // Representing a signed, post-Capella fork blinded beacon block. - SignedBlindedBeaconBlockCapella blinded_capella = 6; + // Representing a signed, post-Capella fork beacon block. + SignedBeaconBlockCapella capella = 5; - // Representing a signed, post-Deneb fork beacon block content. - SignedBeaconBlockContentsDeneb deneb = 7; + // Representing a signed, post-Capella fork blinded beacon block. + SignedBlindedBeaconBlockCapella blinded_capella = 6; - // Representing a signed, post-Deneb fork blinded beacon block. - SignedBlindedBeaconBlockDeneb blinded_deneb = 8; + // Representing a signed, post-Deneb fork beacon block content. + SignedBeaconBlockContentsDeneb deneb = 7; - // Representing a signed, post-Electra fork beacon block content. - SignedBeaconBlockContentsElectra electra = 9; + // Representing a signed, post-Deneb fork blinded beacon block. + SignedBlindedBeaconBlockDeneb blinded_deneb = 8; - // Representing a signed, post-Electra fork blinded beacon block. - SignedBlindedBeaconBlockElectra blinded_electra = 10; - } - bool is_blinded = 100; - reserved 101; // Deprecated fields -} + // Representing a signed, post-Electra fork beacon block content. + SignedBeaconBlockContentsElectra electra = 9; -message GenericBeaconBlock { - oneof block { - // Representing a phase 0 beacon block. - BeaconBlock phase0 = 1; + // Representing a signed, post-Electra fork blinded beacon block. + SignedBlindedBeaconBlockElectra blinded_electra = 10; - // Representing a post-Altair fork beacon block. - BeaconBlockAltair altair = 2; + // Representing a signed, post-Fulu fork beacon block content. + SignedBeaconBlockContentsFulu fulu = 11; - // Representing a post-Bellatrix fork beacon block. - BeaconBlockBellatrix bellatrix = 3; + // Representing a signed, post-Fulu fork blinded beacon block. + SignedBlindedBeaconBlockFulu blinded_fulu = 12; + } + bool is_blinded = 100; + reserved 101; // Deprecated fields +} - // Representing a post-Bellatrix fork blinded beacon block. - BlindedBeaconBlockBellatrix blinded_bellatrix = 4; +message GenericBeaconBlock { + oneof block { + // Representing a phase 0 beacon block. + BeaconBlock phase0 = 1; - // Representing a post-Capella fork beacon block. - BeaconBlockCapella capella = 5; + // Representing a post-Altair fork beacon block. + BeaconBlockAltair altair = 2; - // Representing a post-Capella fork blinded beacon block. - BlindedBeaconBlockCapella blinded_capella = 6; + // Representing a post-Bellatrix fork beacon block. + BeaconBlockBellatrix bellatrix = 3; - // Representing a signed, post-Deneb fork beacon block content. - BeaconBlockContentsDeneb deneb = 7; + // Representing a post-Bellatrix fork blinded beacon block. + BlindedBeaconBlockBellatrix blinded_bellatrix = 4; - // Representing a post-Deneb fork blinded beacon block. - BlindedBeaconBlockDeneb blinded_deneb = 8; + // Representing a post-Capella fork beacon block. + BeaconBlockCapella capella = 5; - // Representing a signed, post-Electra fork beacon block content. - BeaconBlockContentsElectra electra = 9; + // Representing a post-Capella fork blinded beacon block. + BlindedBeaconBlockCapella blinded_capella = 6; - // Representing a post-Electra fork blinded beacon block. - BlindedBeaconBlockElectra blinded_electra = 10; - } - bool is_blinded = 100; - string payload_value = 101; -} + // Representing a post-Deneb fork beacon block content. + BeaconBlockContentsDeneb deneb = 7; -// The Ethereum consensus beacon block. The message does not contain a validator signature. -message BeaconBlock { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Representing a post-Deneb fork blinded beacon block. + BlindedBeaconBlockDeneb blinded_deneb = 8; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Representing a post-Electra fork beacon block content. + BeaconBlockContentsElectra electra = 9; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // Representing a post-Electra fork blinded beacon block. + BlindedBeaconBlockElectra blinded_electra = 10; - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // Representing a post-Fulu fork beacon block content. + BeaconBlockContentsFulu fulu = 11; - // The block body itself. - BeaconBlockBody body = 5; + // Representing a post-Fulu fork blinded beacon block. + BlindedBeaconBlockFulu blinded_fulu = 12; + } + bool is_blinded = 100; + string payload_value = 101; } +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + // The signed version of beacon block. message SignedBeaconBlock { - // The unsigned beacon block itself. - BeaconBlock block = 1; + // The unsigned beacon block itself. + BeaconBlock block = 1; - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -// The unsigned version of a (HF1) beacon block. The message does not contain a validator signature. -message BeaconBlockAltair { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; +// The Ethereum consensus beacon block. The message does not contain a validator +// signature. +message BeaconBlock { + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // The beacon block body. - BeaconBlockBodyAltair body = 5; -} + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; -// The signed version of a (HF1) beacon block. -message SignedBeaconBlockAltair { - // The unsigned beacon block itself. - BeaconBlockAltair block = 1; + // 32 byte root of the resulting state after processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // The block body itself. + BeaconBlockBody body = 5; } // The block body of an Ethereum consensus beacon block. message BeaconBlockBody { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block + // Block operations + // Refer to spec constants at + // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; } +message SignedBeaconBlockHeader { + // The unsigned beacon block header itself. + BeaconBlockHeader header = 1; -// The block body of an (HF1) beacon block. -// The new addition for is SyncAggregate for light client support. -message BeaconBlockBodyAltair { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; - - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; - - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // 96 byte BLS signature from the validator that produced this block header. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; +} - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; +// A beacon block header is essentially a beacon block with only a reference to +// the beacon body as a 32 byte merkle tree root. This type of message is more +// lightweight than a full beacon block. The message does not contain +// a validator signature. +message BeaconBlockHeader { + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; + + // 32 byte merkle tree root of the parent ssz encoded block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // 32 byte merkle tree root of the resulting ssz encoded state after + // processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // 32 byte merkle tree root of the ssz encoded block body. + bytes body_root = 5 [ (ethereum.eth.ext.ssz_size) = "32" ]; +} - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; +// Eth1Data represents references to the Ethereum 1.x deposit contract. +message Eth1Data { + // The 32 byte deposit tree root for the last deposit included in this + // block. + bytes deposit_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // The total number of deposits included in the beacon chain since genesis + // including the deposits in this block. + uint64 deposit_count = 2; - // Sync aggregate object to track sync committee votes for light client support. [New in ] - SyncAggregate sync_aggregate = 9; + // The 32 byte block hash of the Ethereum 1.x block considered for deposit + // inclusion. + bytes block_hash = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; } // Proposer slashings are proofs that a slashable offense has been committed by // proposing two conflicting blocks from the same validator. message ProposerSlashing { - // First conflicting signed block header. - SignedBeaconBlockHeader header_1 = 2; + // First conflicting signed block header. + SignedBeaconBlockHeader header_1 = 2; - // Second conflicting signed block header. - SignedBeaconBlockHeader header_2 = 3; + // Second conflicting signed block header. + SignedBeaconBlockHeader header_2 = 3; } // Attestor slashings are proofs that a slashable offense has been committed by // attesting to two conflicting pieces of information by the same validator. message AttesterSlashing { - // First conflicting attestation. - IndexedAttestation attestation_1 = 1; + // First conflicting attestation. + IndexedAttestation attestation_1 = 1; - // Second conflicting attestation. - IndexedAttestation attestation_2 = 2; + // Second conflicting attestation. + IndexedAttestation attestation_2 = 2; } -message AttesterSlashingElectra { - // First conflicting attestation. - IndexedAttestationElectra attestation_1 = 1; +message IndexedAttestation { + repeated uint64 attesting_indices = 1 [ (ethereum.eth.ext.ssz_max) = "2048" ]; - // Second conflicting attestation. - IndexedAttestationElectra attestation_2 = 2; + AttestationData data = 2; + + // 96 bytes aggregate signature. + bytes signature = 3 [ (ethereum.eth.ext.ssz_size) = "96" ]; } // Deposit into the Ethereum consensus from the Ethereum 1.x deposit contract. message Deposit { - // DepositData that is encoded into a deposit signature. - message Data { - // 48 byte BLS public key of the validator. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; - - // A 32 byte hash of the withdrawal address public key. - bytes withdrawal_credentials = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Deposit amount in gwei. - uint64 amount = 3; + // DepositData that is encoded into a deposit signature. + message Data { + // 48 byte BLS public key of the validator. + bytes public_key = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; + + // A 32 byte hash of the withdrawal address public key. + bytes withdrawal_credentials = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // Deposit amount in gwei. + uint64 amount = 3; + + // 96 byte signature from the validators public key. + bytes signature = 4 [ (ethereum.eth.ext.ssz_size) = "96" ]; + } + // 32 byte roots in the deposit tree branch. + repeated bytes proof = 1 [ (ethereum.eth.ext.ssz_size) = "33,32" ]; + + Data data = 2; +} - // 96 byte signature from the validators public key. - bytes signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; - } - // 32 byte roots in the deposit tree branch. - repeated bytes proof = 1 [(ethereum.eth.ext.ssz_size) = "33,32"]; +// The signed version of voluntary exit. +message SignedVoluntaryExit { + // The unsigned voluntary exit itself. + VoluntaryExit exit = 1; - Data data = 2; + // Validator's 96 byte signature + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } // A message that represents a validator signaling that they want to voluntarily // withdraw from the active validator set. The message does not contain a // validator signature. message VoluntaryExit { - // The epoch on when exit request becomes valid. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // The epoch on when exit request becomes valid. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Index of the exiting validator. + uint64 validator_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; +} + +message SignedValidatorRegistrationsV1 { + repeated SignedValidatorRegistrationV1 messages = 1; +} - // Index of the exiting validator. - uint64 validator_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; +message SignedValidatorRegistrationV1 { + ValidatorRegistrationV1 message = 1; + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -// The signed version of voluntary exit. -message SignedVoluntaryExit { - // The unsigned voluntary exit itself. - VoluntaryExit exit = 1; +message ValidatorRegistrationV1 { + bytes fee_recipient = 1 [ (ethereum.eth.ext.ssz_size) = "20" ]; + uint64 gas_limit = 2; + uint64 timestamp = 3; + bytes pubkey = 4 [ (ethereum.eth.ext.ssz_size) = "48" ]; +} - // Validator's 96 byte signature - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; +message SignedBuilderBid { + BuilderBid message = 1; + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -// Eth1Data represents references to the Ethereum 1.x deposit contract. -message Eth1Data { - // The 32 byte deposit tree root for the last deposit included in this - // block. - bytes deposit_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; +message BuilderBid { + ethereum.engine.v1.ExecutionPayloadHeader header = 1; + bytes value = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes pubkey = 3 [ (ethereum.eth.ext.ssz_size) = "48" ]; +} + +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- - // The total number of deposits included in the beacon chain since genesis - // including the deposits in this block. - uint64 deposit_count = 2; +// The signed version of a (HF1) beacon block. +message SignedBeaconBlockAltair { + // The unsigned beacon block itself. + BeaconBlockAltair block = 1; - // The 32 byte block hash of the Ethereum 1.x block considered for deposit - // inclusion. - bytes block_hash = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -// A beacon block header is essentially a beacon block with only a reference to -// the beacon body as a 32 byte merkle tree root. This type of message is more -// lightweight than a full beacon block. The message does not contain -// a validator signature. -message BeaconBlockHeader { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; +// The unsigned version of a (HF1) beacon block. The message does not contain a +// validator signature. +message BeaconBlockAltair { + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte merkle tree root of the parent ssz encoded block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte merkle tree root of the resulting ssz encoded state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte merkle tree root of the ssz encoded block body. - bytes body_root = 5 [(ethereum.eth.ext.ssz_size) = "32"]; + // The beacon block body. + BeaconBlockBodyAltair body = 5; } -message SignedBeaconBlockHeader { - // The unsigned beacon block header itself. - BeaconBlockHeader header = 1; +// The block body of an (HF1) beacon block. +message BeaconBlockBodyAltair { + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // 96 byte BLS signature from the validator that produced this block header. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; -message IndexedAttestation { - repeated uint64 attesting_indices = 1 [(ethereum.eth.ext.ssz_max) = "2048"]; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - AttestationData data = 2; + // Block operations + // Refer to spec constants at + // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - // 96 bytes aggregate signature. - bytes signature = 3 [(ethereum.eth.ext.ssz_size) = "96"]; -} + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; -message IndexedAttestationElectra { - repeated uint64 attesting_indices = 1 [(ethereum.eth.ext.ssz_max) = "max_attesting_indices.size"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; + + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - AttestationData data = 2; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // 96 bytes aggregate signature. - bytes signature = 3 [(ethereum.eth.ext.ssz_size) = "96"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; + + // Sync aggregate object for the beacon chain to track sync committee votes. + // New in Altair network upgrade. + SyncAggregate sync_aggregate = 9; } -// The sync aggregate object for the beacon chain to track sync committee votes and to -// support light client infra. +// The sync aggregate object for the beacon chain to track sync committee votes +// and to support light client infra. message SyncAggregate { - // Sync committee bits as Bitvector to track votes. - bytes sync_committee_bits = 1 [(ethereum.eth.ext.ssz_size) = "sync_committee_bytes.size", (ethereum.eth.ext.cast_type) = "sync_committee_bits.type"]; - - // BLS aggregated signature of the sync committee for the ones that voted. - bytes sync_committee_signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // Sync committee bits as Bitvector to track votes. + bytes sync_committee_bits = 1 [ + (ethereum.eth.ext.ssz_size) = "sync_committee_bytes.size", + (ethereum.eth.ext.cast_type) = "sync_committee_bits.type" + ]; + + // BLS aggregated signature of the sync committee for the ones that voted. + bytes sync_committee_signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + message SignedBeaconBlockBellatrix { - // The unsigned beacon block itself. - BeaconBlockBellatrix block = 1; + // The unsigned beacon block itself. + BeaconBlockBellatrix block = 1; - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message BeaconBlockBellatrix { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The beacon block body. - BeaconBlockBodyBellatrix body = 5; + // The beacon block body. + BeaconBlockBodyBellatrix body = 5; } message BeaconBlockBodyBellatrix { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block + // Block operations + // Refer to spec constants at + // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - SyncAggregate sync_aggregate = 9; + // Sync aggregate object for the beacon chain to track sync committee votes. + SyncAggregate sync_aggregate = 9; - // Execution payload from the execution chain. New in Bellatrix network upgrade. - ethereum.engine.v1.ExecutionPayload execution_payload = 10; + // Execution payload from the execution chain. New in Bellatrix network + // upgrade. + ethereum.engine.v1.ExecutionPayload execution_payload = 10; } message SignedBlindedBeaconBlockBellatrix { - // The unsigned blinded beacon block itself. - BlindedBeaconBlockBellatrix block = 1; + // The unsigned blinded beacon block itself. + BlindedBeaconBlockBellatrix block = 1; - // 96 byte BLS signature from the validator that produced this blinded block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this blinded block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message BlindedBeaconBlockBellatrix { - // Beacon chain slot that this blinded block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Beacon chain slot that this blinded block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this blinded block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this blinded block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The blinded beacon block body. - BlindedBeaconBlockBodyBellatrix body = 5; + // The blinded beacon block body. + BlindedBeaconBlockBodyBellatrix body = 5; } message BlindedBeaconBlockBodyBellatrix { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - SyncAggregate sync_aggregate = 9; + // Sync aggregate object for the beacon chain to track sync committee votes. + SyncAggregate sync_aggregate = 9; - // Execution payload header from the execution chain. New in Bellatrix network upgrade to accommodate MEV interaction. - ethereum.engine.v1.ExecutionPayloadHeader execution_payload_header = 10; + // Execution payload header from the execution chain. New in Bellatrix network + // upgrade. + ethereum.engine.v1.ExecutionPayloadHeader execution_payload_header = 10; } -message SignedBeaconBlockContentsDeneb { - SignedBeaconBlockDeneb block = 1; - repeated bytes kzg_proofs = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "4096"]; - repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,blob.size", (ethereum.eth.ext.ssz_max) = "4096"]; -} +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- -message BeaconBlockContentsDeneb { - BeaconBlockDeneb block = 1; - repeated bytes kzg_proofs = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "4096"]; - repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,blob.size", (ethereum.eth.ext.ssz_max) = "4096"]; -} - -message SignedBeaconBlockDeneb { - // The unsigned beacon block itself. - BeaconBlockDeneb block = 1; +message SignedBeaconBlockCapella { + // The unsigned beacon block itself. + BeaconBlockCapella block = 1; - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message BeaconBlockDeneb { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; +message BeaconBlockCapella { + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The beacon block body. - BeaconBlockBodyDeneb body = 5; + // The beacon block body. + BeaconBlockBodyCapella body = 5; } -message BeaconBlockBodyDeneb { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; - - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; +message BeaconBlockBodyCapella { + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#max-operations-per-block + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // Block operations + // Refer to spec constants at + // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - SyncAggregate sync_aggregate = 9; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // Execution payload from the execution chain. New in Bellatrix network upgrade. - ethereum.engine.v1.ExecutionPayloadDeneb execution_payload = 10; + // Sync aggregate object for the beacon chain to track sync committee votes. + SyncAggregate sync_aggregate = 9; - // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; + // Execution payload from the execution chain. + ethereum.engine.v1.ExecutionPayloadCapella execution_payload = 10; - repeated bytes blob_kzg_commitments = 12 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; + // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. + repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 + [ (ethereum.eth.ext.ssz_max) = "16" ]; } -message SignedBeaconBlockCapella { - // The unsigned beacon block itself. - BeaconBlockCapella block = 1; +message SignedBlindedBeaconBlockCapella { + // The unsigned blinded beacon block itself. + BlindedBeaconBlockCapella block = 1; - // 96 byte BLS signature from the validator that produced this block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this blinded block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message BeaconBlockCapella { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; +message BlindedBeaconBlockCapella { + // Beacon chain slot that this blinded block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this blinded block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The beacon block body. - BeaconBlockBodyCapella body = 5; + // The blinded beacon block body. + BlindedBeaconBlockBodyCapella body = 5; } -message BeaconBlockBodyCapella { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; +message BlindedBeaconBlockBodyCapella { + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#max-operations-per-block + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // Sync aggregate object for the beacon chain to track sync committee votes. + SyncAggregate sync_aggregate = 9; - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - SyncAggregate sync_aggregate = 9; + // Execution payload header from the execution chain. + ethereum.engine.v1.ExecutionPayloadHeaderCapella execution_payload_header = + 10; - // Execution payload from the execution chain. New in Bellatrix network upgrade. - ethereum.engine.v1.ExecutionPayloadCapella execution_payload = 10; + // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. + repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 + [ (ethereum.eth.ext.ssz_max) = "16" ]; +} - // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; +message SignedBuilderBidCapella { + BuilderBidCapella message = 1; + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message SignedBlindedBeaconBlockCapella { - // The unsigned blinded beacon block itself. - BlindedBeaconBlockCapella block = 1; +message BuilderBidCapella { + ethereum.engine.v1.ExecutionPayloadHeaderCapella header = 1; + bytes value = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes pubkey = 3 [ (ethereum.eth.ext.ssz_size) = "48" ]; +} - // 96 byte BLS signature from the validator that produced this blinded block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + +message SignedBeaconBlockContentsDeneb { + SignedBeaconBlockDeneb block = 1; + repeated bytes kzg_proofs = 2 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "4096" + ]; + repeated bytes blobs = 3 [ + (ethereum.eth.ext.ssz_size) = "?,blob.size", + (ethereum.eth.ext.ssz_max) = "4096" + ]; } -message BlindedBeaconBlockCapella { - // Beacon chain slot that this blinded block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; +message SignedBeaconBlockDeneb { + // The unsigned beacon block itself. + BeaconBlockDeneb block = 1; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; +} - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; +message BeaconBlockContentsDeneb { + BeaconBlockDeneb block = 1; + repeated bytes kzg_proofs = 2 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "4096" + ]; + repeated bytes blobs = 3 [ + (ethereum.eth.ext.ssz_size) = "?,blob.size", + (ethereum.eth.ext.ssz_max) = "4096" + ]; +} + +message BeaconBlockDeneb { + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; + + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this blinded block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The blinded beacon block body. - BlindedBeaconBlockBodyCapella body = 5; + // The beacon block body. + BeaconBlockBodyDeneb body = 5; } -message BlindedBeaconBlockBodyCapella { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; +message BeaconBlockBodyDeneb { + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; + + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // Block operations + // Refer to spec constants at + // https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#max-operations-per-block - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - SyncAggregate sync_aggregate = 9; + // Sync aggregate object for the beacon chain to track sync committee votes.- + SyncAggregate sync_aggregate = 9; - // Execution payload header from the execution chain. New in Bellatrix network upgrade to accommodate MEV interaction. - ethereum.engine.v1.ExecutionPayloadHeaderCapella execution_payload_header = 10; + // Execution payload from the execution chain. + ethereum.engine.v1.ExecutionPayloadDeneb execution_payload = 10; - // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_BLS_TO_EXECUTION_CHANGES. + repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 + [ (ethereum.eth.ext.ssz_max) = "16" ]; + + repeated bytes blob_kzg_commitments = 12 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; } message SignedBlindedBeaconBlockDeneb { - // The unsigned blinded beacon block itself. - BlindedBeaconBlockDeneb message = 1; + // The unsigned blinded beacon block itself. + BlindedBeaconBlockDeneb message = 1; - // 96 byte BLS signature from the validator that produced this blinded block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this blinded block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message BlindedBeaconBlockDeneb { - // Beacon chain slot that this blinded block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Beacon chain slot that this blinded block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this blinded block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this blinded block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The blinded beacon block body. - BlindedBeaconBlockBodyDeneb body = 5; + // The blinded beacon block body. + BlindedBeaconBlockBodyDeneb body = 5; } message BlindedBeaconBlockBodyDeneb { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_ATTESTER_SLASHINGS. - repeated AttesterSlashing attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "2"]; + // At most MAX_ATTESTER_SLASHINGS. + repeated AttesterSlashing attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "2" ]; - // At most MAX_ATTESTATIONS. - repeated Attestation attestations = 6 [(ethereum.eth.ext.ssz_max) = "128"]; + // At most MAX_ATTESTATIONS. + repeated Attestation attestations = 6 [ (ethereum.eth.ext.ssz_max) = "128" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - SyncAggregate sync_aggregate = 9; + // Sync aggregate object for the beacon chain to track sync committee votes. + SyncAggregate sync_aggregate = 9; - // Execution payload header from the execution chain. New in Bellatrix network upgrade to accommodate MEV interaction. - ethereum.engine.v1.ExecutionPayloadHeaderDeneb execution_payload_header = 10; + // Execution payload header from the execution chain. + ethereum.engine.v1.ExecutionPayloadHeaderDeneb execution_payload_header = 10; - // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_BLS_TO_EXECUTION_CHANGES. + repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - repeated bytes blob_kzg_commitments = 12 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; + // Blob KZG commitments. New in Deneb network upgrade. + repeated bytes blob_kzg_commitments = 12 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; } -message SignedBeaconBlockContentsElectra { - SignedBeaconBlockElectra block = 1; - repeated bytes kzg_proofs = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "4096"]; - repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,blob.size", (ethereum.eth.ext.ssz_max) = "4096"]; +message SignedBuilderBidDeneb { + BuilderBidDeneb message = 1; + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message BeaconBlockContentsElectra { - BeaconBlockElectra block = 1; - repeated bytes kzg_proofs = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "4096"]; - repeated bytes blobs = 3 [(ethereum.eth.ext.ssz_size) = "?,blob.size", (ethereum.eth.ext.ssz_max) = "4096"]; +message BuilderBidDeneb { + ethereum.engine.v1.ExecutionPayloadHeaderDeneb header = 1; + repeated bytes blob_kzg_commitments = 2 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; // new in deneb + bytes value = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes pubkey = 4 [ (ethereum.eth.ext.ssz_size) = "48" ]; } -message SignedBeaconBlockElectra { - // The unsigned beacon block itself. - BeaconBlockElectra block = 1; +message BuilderBidElectra { + ethereum.engine.v1.ExecutionPayloadHeaderDeneb header = 1; + repeated bytes blob_kzg_commitments = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; + ethereum.engine.v1.ExecutionRequests execution_requests = 3; + bytes value = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes pubkey = 5 [(ethereum.eth.ext.ssz_size) = "48"]; +} - // 96 byte BLS signature from the validator that produced this block. +message SignedBuilderBidElectra { + BuilderBidElectra message = 1 ; bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; } +message BlobSidecars { + repeated BlobSidecar sidecars = 1 + [ (ethereum.eth.ext.ssz_max) = "max_blobs_per_block.size" ]; +} + +message BlobSidecar { + uint64 index = 1; + bytes blob = 2 [ (ethereum.eth.ext.ssz_size) = "blob.size" ]; + bytes kzg_commitment = 3 [ (ethereum.eth.ext.ssz_size) = "48" ]; + bytes kzg_proof = 4 [ (ethereum.eth.ext.ssz_size) = "48" ]; + SignedBeaconBlockHeader signed_block_header = 5; + repeated bytes commitment_inclusion_proof = 6 + [ (ethereum.eth.ext.ssz_size) = + "kzg_commitment_inclusion_proof_depth.size,32" ]; +} + +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +message SignedBeaconBlockContentsElectra { + SignedBeaconBlockElectra block = 1; + repeated bytes kzg_proofs = 2 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "4096" + ]; + repeated bytes blobs = 3 [ + (ethereum.eth.ext.ssz_size) = "?,blob.size", + (ethereum.eth.ext.ssz_max) = "4096" + ]; +} + +message SignedBeaconBlockElectra { + // The unsigned beacon block itself. + BeaconBlockElectra block = 1; + + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; +} + +message BeaconBlockContentsElectra { + BeaconBlockElectra block = 1; + repeated bytes kzg_proofs = 2 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "4096" + ]; + repeated bytes blobs = 3 [ + (ethereum.eth.ext.ssz_size) = "?,blob.size", + (ethereum.eth.ext.ssz_max) = "4096" + ]; +} + message BeaconBlockElectra { - // Beacon chain slot that this block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Beacon chain slot that this block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The beacon block body. - BeaconBlockBodyElectra body = 5; + // The beacon block body. + BeaconBlockBodyElectra body = 5; } message BeaconBlockBodyElectra { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; + + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // Block operations + // Refer to spec constants at + // https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#max-operations-per-block - // Block operations - // Refer to spec constants at https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#max-operations-per-block + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_ATTESTER_SLASHINGS_ELECTRA. + repeated AttesterSlashingElectra attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "1" ]; - // At most MAX_ATTESTER_SLASHINGS_ELECTRA. - repeated AttesterSlashingElectra attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "1"]; + // At most MAX_ATTESTATIONS_ELECTRA. + repeated AttestationElectra attestations = 6 + [ (ethereum.eth.ext.ssz_max) = "8" ]; - // At most MAX_ATTESTATIONS_ELECTRA. - repeated AttestationElectra attestations = 6 [(ethereum.eth.ext.ssz_max) = "8"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // Sync aggregate object for the beacon chain to track sync committee votes. + SyncAggregate sync_aggregate = 9; - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - SyncAggregate sync_aggregate = 9; + // Execution payload from the execution chain. New in Bellatrix network + // upgrade. + ethereum.engine.v1.ExecutionPayloadDeneb execution_payload = 10; - // Execution payload from the execution chain. New in Bellatrix network upgrade. - ethereum.engine.v1.ExecutionPayloadElectra execution_payload = 10; + // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. + repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; + // Blob KZG commitments. + repeated bytes blob_kzg_commitments = 12 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; - repeated bytes blob_kzg_commitments = 12 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; + // Execution requests. New in Electra network upgrade. + ethereum.engine.v1.ExecutionRequests execution_requests = 13; } message SignedBlindedBeaconBlockElectra { - // The unsigned blinded beacon block itself. - BlindedBeaconBlockElectra message = 1; + // The unsigned blinded beacon block itself. + BlindedBeaconBlockElectra message = 1; - // 96 byte BLS signature from the validator that produced this blinded block. - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // 96 byte BLS signature from the validator that produced this blinded block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message BlindedBeaconBlockElectra { - // Beacon chain slot that this blinded block represents. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Beacon chain slot that this blinded block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator index of the validator that proposed the block header. - uint64 proposer_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; - // 32 byte root of the parent block. - bytes parent_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // 32 byte root of the resulting state after processing this blinded block. - bytes state_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte root of the resulting state after processing this blinded block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // The blinded beacon block body. - BlindedBeaconBlockBodyElectra body = 5; + // The blinded beacon block body. + BlindedBeaconBlockBodyElectra body = 5; } message BlindedBeaconBlockBodyElectra { - // The validators RANDAO reveal 96 byte value. - bytes randao_reveal = 1 [(ethereum.eth.ext.ssz_size) = "96"]; + // The validators RANDAO reveal 96 byte value. + bytes randao_reveal = 1 [ (ethereum.eth.ext.ssz_size) = "96" ]; - // A reference to the Ethereum 1.x chain. - Eth1Data eth1_data = 2; + // A reference to the Ethereum 1.x chain. + Eth1Data eth1_data = 2; - // 32 byte field of arbitrary data. This field may contain any data and - // is not used for anything other than a fun message. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte field of arbitrary data. This field may contain any data and + // is not used for anything other than a fun message. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // At most MAX_PROPOSER_SLASHINGS. - repeated ProposerSlashing proposer_slashings = 4 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_PROPOSER_SLASHINGS. + repeated ProposerSlashing proposer_slashings = 4 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_ATTESTER_SLASHINGS_ELECTRA. - repeated AttesterSlashingElectra attester_slashings = 5 [(ethereum.eth.ext.ssz_max) = "1"]; + // At most MAX_ATTESTER_SLASHINGS_ELECTRA. + repeated AttesterSlashingElectra attester_slashings = 5 + [ (ethereum.eth.ext.ssz_max) = "1" ]; - // At most MAX_ATTESTATIONS_ELECTRA. - repeated AttestationElectra attestations = 6 [(ethereum.eth.ext.ssz_max) = "8"]; + // At most MAX_ATTESTATIONS_ELECTRA. + repeated AttestationElectra attestations = 6 + [ (ethereum.eth.ext.ssz_max) = "8" ]; - // At most MAX_DEPOSITS. - repeated Deposit deposits = 7 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_DEPOSITS. + repeated Deposit deposits = 7 [ (ethereum.eth.ext.ssz_max) = "16" ]; - // At most MAX_VOLUNTARY_EXITS. - repeated SignedVoluntaryExit voluntary_exits = 8 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_VOLUNTARY_EXITS. + repeated SignedVoluntaryExit voluntary_exits = 8 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - // Sync aggregate object for the beacon chain to track sync committee votes. New in Altair network upgrade. - SyncAggregate sync_aggregate = 9; + // Sync aggregate object for the beacon chain to track sync committee votes. + SyncAggregate sync_aggregate = 9; - // Execution payload header from the execution chain. New in Bellatrix network upgrade to accommodate MEV interaction. - ethereum.engine.v1.ExecutionPayloadHeaderElectra execution_payload_header = 10; + // Execution payload header from the execution chain. + ethereum.engine.v1.ExecutionPayloadHeaderDeneb execution_payload_header = 10; - // At most MAX_BLS_TO_EXECUTION_CHANGES. New in Capella network upgrade. - repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 [(ethereum.eth.ext.ssz_max) = "16"]; + // At most MAX_BLS_TO_EXECUTION_CHANGES. + repeated SignedBLSToExecutionChange bls_to_execution_changes = 11 + [ (ethereum.eth.ext.ssz_max) = "16" ]; - repeated bytes blob_kzg_commitments = 12 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; -} + // Blob KZG commitments. + repeated bytes blob_kzg_commitments = 12 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; -message ValidatorRegistrationV1 { - bytes fee_recipient = 1 [(ethereum.eth.ext.ssz_size) = "20"]; - uint64 gas_limit = 2; - uint64 timestamp = 3; - bytes pubkey = 4 [(ethereum.eth.ext.ssz_size) = "48"]; + // Execution requests. New in Electra network upgrade. + ethereum.engine.v1.ExecutionRequests execution_requests = 13; } -message SignedValidatorRegistrationsV1 { - repeated SignedValidatorRegistrationV1 messages = 1; -} +message AttesterSlashingElectra { + // First conflicting attestation. + IndexedAttestationElectra attestation_1 = 1; -message SignedValidatorRegistrationV1 { - ValidatorRegistrationV1 message = 1 ; - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // Second conflicting attestation. + IndexedAttestationElectra attestation_2 = 2; } -message BuilderBid { - ethereum.engine.v1.ExecutionPayloadHeader header = 1; - bytes value = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes pubkey = 3 [(ethereum.eth.ext.ssz_size) = "48"]; -} +message IndexedAttestationElectra { + repeated uint64 attesting_indices = 1 + [ (ethereum.eth.ext.ssz_max) = "max_attesting_indices.size" ]; -message SignedBuilderBid { - BuilderBid message = 1 ; - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; -} + AttestationData data = 2; -message BuilderBidCapella { - ethereum.engine.v1.ExecutionPayloadHeaderCapella header = 1 ; - bytes value = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes pubkey = 3 [(ethereum.eth.ext.ssz_size) = "48"]; + // 96 bytes aggregate signature. + bytes signature = 3 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message SignedBuilderBidCapella { - BuilderBidCapella message = 1 ; - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +message SignedBeaconBlockContentsFulu { + SignedBeaconBlockFulu block = 1; + repeated bytes kzg_proofs = 2 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "4096" + ]; + repeated bytes blobs = 3 [ + (ethereum.eth.ext.ssz_size) = "?,blob.size", + (ethereum.eth.ext.ssz_max) = "4096" + ]; } -message BuilderBidDeneb { - ethereum.engine.v1.ExecutionPayloadHeaderDeneb header = 1; - repeated bytes blob_kzg_commitments = 2 [(ethereum.eth.ext.ssz_size) = "?,48", (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size"]; // new in deneb - bytes value = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes pubkey = 4 [(ethereum.eth.ext.ssz_size) = "48"]; +message SignedBeaconBlockFulu { + // The unsigned beacon block itself. + BeaconBlockElectra block = 1; + + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message SignedBuilderBidDeneb { - BuilderBidDeneb message = 1 ; - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; +message BeaconBlockContentsFulu { + BeaconBlockElectra block = 1; + repeated bytes kzg_proofs = 2 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "4096" + ]; + repeated bytes blobs = 3 [ + (ethereum.eth.ext.ssz_size) = "?,blob.size", + (ethereum.eth.ext.ssz_max) = "4096" + ]; } -message BlobSidecar { - uint64 index = 1; - bytes blob = 2 [(ethereum.eth.ext.ssz_size) = "blob.size"]; - bytes kzg_commitment = 3 [(ethereum.eth.ext.ssz_size) = "48"]; - bytes kzg_proof = 4 [(ethereum.eth.ext.ssz_size) = "48"]; - SignedBeaconBlockHeader signed_block_header = 5; - repeated bytes commitment_inclusion_proof = 6 [(ethereum.eth.ext.ssz_size) = "kzg_commitment_inclusion_proof_depth.size,32"]; +message SignedBlindedBeaconBlockFulu { + // The unsigned blinded beacon block itself. + BlindedBeaconBlockFulu message = 1; + + // 96 byte BLS signature from the validator that produced this blinded block. + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -message BlobSidecars { - repeated BlobSidecar sidecars = 1 [(ethereum.eth.ext.ssz_max) = "max_blobs_per_block.size"]; +message BlindedBeaconBlockFulu { + // Beacon chain slot that this blinded block represents. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Validator index of the validator that proposed the block header. + uint64 proposer_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; + + // 32 byte root of the parent block. + bytes parent_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // 32 byte root of the resulting state after processing this blinded block. + bytes state_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // The blinded beacon block body. + BlindedBeaconBlockBodyElectra body = 5; } + diff --git a/proto/prysm/v1alpha1/beacon_block_fuzz_test.go b/proto/prysm/v1alpha1/beacon_block_fuzz_test.go index 043728777455..6570a73ea6d9 100644 --- a/proto/prysm/v1alpha1/beacon_block_fuzz_test.go +++ b/proto/prysm/v1alpha1/beacon_block_fuzz_test.go @@ -62,5 +62,5 @@ func TestCopyBeaconBlockFields_Fuzz(t *testing.T) { fuzzCopies(t, ð.SignedBLSToExecutionChange{}) fuzzCopies(t, ð.BLSToExecutionChange{}) fuzzCopies(t, ð.HistoricalSummary{}) - fuzzCopies(t, ð.PendingBalanceDeposit{}) + fuzzCopies(t, ð.PendingDeposit{}) } diff --git a/proto/prysm/v1alpha1/beacon_chain.pb.go b/proto/prysm/v1alpha1/beacon_chain.pb.go index 9b07cd75de0a..784efc00c5a9 100755 --- a/proto/prysm/v1alpha1/beacon_chain.pb.go +++ b/proto/prysm/v1alpha1/beacon_chain.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/beacon_chain.proto package eth @@ -682,6 +682,8 @@ type BeaconBlockContainer struct { // *BeaconBlockContainer_BlindedDenebBlock // *BeaconBlockContainer_ElectraBlock // *BeaconBlockContainer_BlindedElectraBlock + // *BeaconBlockContainer_FuluBlock + // *BeaconBlockContainer_BlindedFuluBlock Block isBeaconBlockContainer_Block `protobuf_oneof:"block"` } @@ -808,6 +810,20 @@ func (x *BeaconBlockContainer) GetBlindedElectraBlock() *SignedBlindedBeaconBloc return nil } +func (x *BeaconBlockContainer) GetFuluBlock() *SignedBeaconBlockFulu { + if x, ok := x.GetBlock().(*BeaconBlockContainer_FuluBlock); ok { + return x.FuluBlock + } + return nil +} + +func (x *BeaconBlockContainer) GetBlindedFuluBlock() *SignedBlindedBeaconBlockFulu { + if x, ok := x.GetBlock().(*BeaconBlockContainer_BlindedFuluBlock); ok { + return x.BlindedFuluBlock + } + return nil +} + type isBeaconBlockContainer_Block interface { isBeaconBlockContainer_Block() } @@ -852,6 +868,14 @@ type BeaconBlockContainer_BlindedElectraBlock struct { BlindedElectraBlock *SignedBlindedBeaconBlockElectra `protobuf:"bytes,12,opt,name=blinded_electra_block,json=blindedElectraBlock,proto3,oneof"` } +type BeaconBlockContainer_FuluBlock struct { + FuluBlock *SignedBeaconBlockFulu `protobuf:"bytes,13,opt,name=fulu_block,json=fuluBlock,proto3,oneof"` +} + +type BeaconBlockContainer_BlindedFuluBlock struct { + BlindedFuluBlock *SignedBlindedBeaconBlockFulu `protobuf:"bytes,14,opt,name=blinded_fulu_block,json=blindedFuluBlock,proto3,oneof"` +} + func (*BeaconBlockContainer_Phase0Block) isBeaconBlockContainer_Block() {} func (*BeaconBlockContainer_AltairBlock) isBeaconBlockContainer_Block() {} @@ -872,6 +896,10 @@ func (*BeaconBlockContainer_ElectraBlock) isBeaconBlockContainer_Block() {} func (*BeaconBlockContainer_BlindedElectraBlock) isBeaconBlockContainer_Block() {} +func (*BeaconBlockContainer_FuluBlock) isBeaconBlockContainer_Block() {} + +func (*BeaconBlockContainer_BlindedFuluBlock) isBeaconBlockContainer_Block() {} + type ChainHead struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3416,7 +3444,7 @@ var file_proto_prysm_v1alpha1_beacon_chain_proto_rawDesc = []byte{ 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x98, 0x08, 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, + 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x22, 0xcc, 0x09, 0x0a, 0x14, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, @@ -3481,898 +3509,909 @@ var file_proto_prysm_v1alpha1_beacon_chain_proto_rawDesc = []byte{ 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x48, 0x00, 0x52, 0x13, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x45, 0x6c, 0x65, - 0x63, 0x74, 0x72, 0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x22, 0xb2, 0x09, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x61, 0x64, - 0x12, 0x62, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x08, 0x68, 0x65, 0x61, 0x64, - 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x65, 0x0a, 0x0a, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, - 0x52, 0x09, 0x68, 0x65, 0x61, 0x64, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x2e, 0x0a, 0x0f, 0x68, - 0x65, 0x61, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0d, 0x68, 0x65, - 0x61, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x6c, 0x0a, 0x0e, 0x66, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x6f, 0x0a, 0x0f, 0x66, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, - 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x38, 0x0a, 0x14, 0x66, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, - 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, - 0x52, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x6c, 0x0a, 0x0e, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, - 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x63, 0x74, 0x72, 0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x4d, 0x0a, 0x0a, 0x66, 0x75, 0x6c, + 0x75, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x75, 0x48, 0x00, 0x52, 0x09, 0x66, + 0x75, 0x6c, 0x75, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x63, 0x0a, 0x12, 0x62, 0x6c, 0x69, 0x6e, + 0x64, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x6c, 0x75, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x75, 0x48, 0x00, 0x52, 0x10, 0x62, 0x6c, 0x69, + 0x6e, 0x64, 0x65, 0x64, 0x46, 0x75, 0x6c, 0x75, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x07, 0x0a, + 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0xb2, 0x09, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x48, 0x65, 0x61, 0x64, 0x12, 0x62, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x73, 0x6c, 0x6f, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x08, + 0x68, 0x65, 0x61, 0x64, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x65, 0x0a, 0x0a, 0x68, 0x65, 0x61, 0x64, + 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, + 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, - 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x53, 0x6c, - 0x6f, 0x74, 0x12, 0x6f, 0x0a, 0x0f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, - 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, - 0x6f, 0x63, 0x68, 0x52, 0x0e, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x70, - 0x6f, 0x63, 0x68, 0x12, 0x38, 0x0a, 0x14, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, - 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x12, 0x6a, 0x75, 0x73, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x7d, 0x0a, - 0x17, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, - 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x15, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, - 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x80, 0x01, 0x0a, - 0x18, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x16, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, - 0x73, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, - 0x49, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, 0x73, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x1a, - 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x70, - 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, - 0x63, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, + 0x70, 0x6f, 0x63, 0x68, 0x52, 0x09, 0x68, 0x65, 0x61, 0x64, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, + 0x2e, 0x0a, 0x0f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, + 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x0d, 0x68, 0x65, 0x61, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, + 0x6c, 0x0a, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x6f, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x6f, 0x0a, + 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x0e, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x38, + 0x0a, 0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x33, 0x32, 0x52, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x6c, 0x0a, 0x0e, 0x6a, 0x75, 0x73, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x42, 0x0e, 0x0a, - 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xef, 0x04, - 0x0a, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x12, 0x57, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x2e, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x1a, - 0x8d, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x74, 0x65, - 0x6d, 0x12, 0x7c, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, - 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x10, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x1a, - 0x67, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x55, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x2e, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0a, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x1a, 0x75, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4c, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0xfc, 0x02, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, + 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x64, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x6f, 0x0a, 0x0f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x29, 0x0a, 0x0b, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0e, - 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xd2, - 0x03, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, + 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x0e, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, + 0x65, 0x64, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x38, 0x0a, 0x14, 0x6a, 0x75, 0x73, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x12, 0x6a, + 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, + 0x74, 0x12, 0x7d, 0x0a, 0x17, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, + 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, + 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x15, 0x70, 0x72, 0x65, 0x76, 0x69, + 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x53, 0x6c, 0x6f, 0x74, + 0x12, 0x80, 0x01, 0x0a, 0x18, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, + 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x12, 0x4c, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2e, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, - 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0xc9, 0x01, 0x0a, 0x07, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, - 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x65, 0x0a, 0x05, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x83, 0x03, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, - 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, - 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, - 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, - 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, - 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1f, 0x0a, - 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x69, - 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, 0x42, - 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xb7, 0x01, 0x0a, 0x13, 0x47, 0x65, - 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x67, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x16, 0x70, 0x72, 0x65, + 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x45, 0x70, + 0x6f, 0x63, 0x68, 0x12, 0x49, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, + 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, + 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2b, + 0x0a, 0x11, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6f, 0x70, 0x74, 0x69, 0x6d, + 0x69, 0x73, 0x74, 0x69, 0x63, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x15, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, + 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x22, 0xef, 0x04, 0x0a, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x12, 0x57, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, + 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x34, 0x0a, + 0x16, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x1a, 0x8d, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x7c, 0x0a, 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, 0x0a, 0x0a, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x48, 0x00, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x4b, 0x65, 0x79, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x22, 0xcc, 0x03, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x73, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x12, 0x5b, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x69, - 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x0d, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x0a, - 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x53, 0x69, 0x7a, 0x65, 0x1a, 0xbb, 0x01, 0x0a, 0x12, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x65, 0x0a, 0x05, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x3e, 0x0a, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x22, 0xb1, 0x01, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, - 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, - 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, - 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, - 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xc4, 0x06, 0x0a, 0x10, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x3c, 0x0a, 0x15, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, - 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, - 0x34, 0x38, 0x52, 0x13, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x50, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x7c, 0x0a, 0x11, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, - 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x52, 0x10, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x12, 0x65, 0x78, 0x69, 0x74, 0x65, 0x64, 0x5f, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x10, 0x65, 0x78, 0x69, - 0x74, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x76, 0x0a, - 0x0e, 0x65, 0x78, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x65, 0x78, 0x69, 0x74, 0x65, 0x64, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x13, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, - 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x11, 0x73, 0x6c, - 0x61, 0x73, 0x68, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, - 0x78, 0x0a, 0x0f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x73, 0x6c, 0x61, 0x73, 0x68, - 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x13, 0x65, 0x6a, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, - 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, - 0x52, 0x11, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x73, 0x12, 0x78, 0x0a, 0x0f, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, + 0x78, 0x52, 0x10, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x69, + 0x63, 0x65, 0x73, 0x1a, 0x67, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x55, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x74, 0x65, 0x6d, + 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x1a, 0x75, 0x0a, 0x0f, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x4c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0xfc, 0x02, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, + 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, + 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, + 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, + 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, + 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x65, - 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0xad, 0x01, - 0x0a, 0x1b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x65, 0x72, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, - 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, + 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, + 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x22, 0xd2, 0x03, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, + 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x4c, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x73, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, + 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, + 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0xc9, 0x01, 0x0a, 0x07, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x34, 0x38, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x65, + 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, + 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x83, 0x03, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0xc6, 0x06, - 0x0a, 0x1c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x65, 0x72, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, - 0x0a, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x04, 0x52, 0x18, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x66, 0x66, 0x65, 0x63, - 0x74, 0x69, 0x76, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x70, 0x0a, 0x0f, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x47, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x52, 0x0e, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x12, 0x78, - 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x47, 0x82, 0xb5, 0x18, - 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, - 0x6f, 0x74, 0x18, 0x01, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x44, - 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x63, 0x74, 0x6c, 0x79, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x08, 0x52, 0x14, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, - 0x74, 0x6c, 0x79, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x34, - 0x0a, 0x16, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x5f, 0x76, 0x6f, 0x74, 0x65, - 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x08, 0x52, 0x14, - 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, - 0x79, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x18, 0x06, 0x20, 0x03, - 0x28, 0x08, 0x52, 0x12, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x56, 0x6f, 0x74, - 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x12, 0x47, 0x0a, 0x20, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x73, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, - 0x52, 0x1d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, - 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x45, 0x0a, 0x1f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x5f, 0x61, 0x66, 0x74, 0x65, - 0x72, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x03, 0x28, 0x04, 0x52, 0x1c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x73, 0x41, 0x66, 0x74, 0x65, 0x72, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, - 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x09, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x11, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x47, 0x0a, 0x20, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, - 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x02, 0x52, - 0x1d, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x29, - 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0b, 0x20, - 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x61, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x0c, - 0x20, 0x03, 0x28, 0x04, 0x52, 0x10, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x22, 0xc9, 0x03, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x75, - 0x72, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, - 0x63, 0x68, 0x75, 0x72, 0x6e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x40, 0x0a, 0x16, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x04, - 0x3f, 0x2c, 0x34, 0x38, 0x18, 0x01, 0x52, 0x14, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x34, 0x0a, 0x10, - 0x65, 0x78, 0x69, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, - 0x18, 0x01, 0x52, 0x0e, 0x65, 0x78, 0x69, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x73, 0x12, 0x91, 0x01, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x1a, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x16, 0x65, 0x78, 0x69, 0x74, 0x5f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, - 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x14, 0x65, 0x78, 0x69, 0x74, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x02, - 0x18, 0x01, 0x22, 0xff, 0x02, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, + 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x42, 0x0e, 0x0a, + 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xb7, 0x01, + 0x0a, 0x13, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x67, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x48, 0x00, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x27, + 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x48, 0x00, 0x52, 0x09, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xcc, 0x03, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, 0x52, - 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, - 0x69, 0x73, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, - 0x38, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x69, 0x0a, - 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x12, 0x5b, 0x0a, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x52, 0x0d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x4c, 0x69, 0x73, + 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, + 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0xbb, 0x01, 0x0a, 0x12, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, + 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, - 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, - 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, - 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x22, 0xab, 0x07, 0x0a, 0x14, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x5c, 0x0a, - 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, - 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, - 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x61, 0x0a, 0x0b, 0x61, - 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x3f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x26, - 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, - 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x8a, 0x05, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x7c, 0x0a, - 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x10, 0x62, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x78, 0x0a, 0x0f, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, - 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x6a, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, - 0x72, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, - 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3e, 0x0a, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, 0xb1, 0x01, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, + 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, + 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, + 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, + 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, + 0x00, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xc4, 0x06, 0x0a, 0x10, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, + 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, + 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, + 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x3c, 0x0a, + 0x15, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, + 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x13, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x7c, 0x0a, 0x11, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x10, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x12, 0x65, 0x78, 0x69, + 0x74, 0x65, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, + 0x10, 0x65, 0x78, 0x69, 0x74, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x73, 0x12, 0x76, 0x0a, 0x0e, 0x65, 0x78, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, + 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x65, 0x78, 0x69, 0x74, + 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x13, 0x73, 0x6c, 0x61, + 0x73, 0x68, 0x65, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, + 0x52, 0x11, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, + 0x65, 0x79, 0x73, 0x12, 0x78, 0x0a, 0x0f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x69, + 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, + 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, - 0x6c, 0x6f, 0x74, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x6f, - 0x74, 0x12, 0x6c, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x6c, - 0x6f, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x73, + 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x38, 0x0a, + 0x13, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, + 0x6b, 0x65, 0x79, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, + 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x11, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x78, 0x0a, 0x0f, 0x65, 0x6a, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x04, + 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x52, 0x0e, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x73, 0x22, 0xad, 0x01, 0x0a, 0x1b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, + 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x23, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x73, 0x22, 0xc6, 0x06, 0x0a, 0x1c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, + 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x18, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x12, 0x70, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, + 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x47, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, - 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x12, - 0x27, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x18, 0x01, 0x52, 0x09, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x00, - 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, - 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, - 0x73, 0x69, 0x73, 0x3a, 0x02, 0x18, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xf5, 0x01, 0x0a, 0x1e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, + 0x18, 0x01, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x6f, + 0x74, 0x73, 0x12, 0x78, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, + 0x47, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, + 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, + 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, + 0x69, 0x6f, 0x6e, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x34, 0x0a, 0x16, + 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x08, 0x52, 0x14, 0x63, 0x6f, + 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x5f, + 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x08, 0x52, 0x14, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x56, 0x6f, 0x74, + 0x65, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6f, 0x72, 0x72, + 0x65, 0x63, 0x74, 0x6c, 0x79, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x08, 0x52, 0x12, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, + 0x79, 0x56, 0x6f, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x12, 0x47, 0x0a, 0x20, 0x62, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x04, 0x52, 0x1d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x42, 0x65, + 0x66, 0x6f, 0x72, 0x65, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x1f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x5f, + 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x03, 0x28, 0x04, 0x52, 0x1c, 0x62, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x66, 0x74, 0x65, 0x72, 0x45, 0x70, 0x6f, 0x63, 0x68, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x11, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x47, 0x0a, 0x20, 0x61, 0x76, 0x65, + 0x72, 0x61, 0x67, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x02, 0x52, 0x1d, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, + 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, + 0x38, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x2b, 0x0a, + 0x11, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x04, 0x52, 0x10, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x22, 0xc9, 0x03, 0x0a, 0x0e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x1f, 0x0a, + 0x0b, 0x63, 0x68, 0x75, 0x72, 0x6e, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0a, 0x63, 0x68, 0x75, 0x72, 0x6e, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x40, + 0x0a, 0x16, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0a, + 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x18, 0x01, 0x52, 0x14, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, + 0x12, 0x34, 0x0a, 0x10, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, + 0x6b, 0x65, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x04, + 0x3f, 0x2c, 0x34, 0x38, 0x18, 0x01, 0x52, 0x0e, 0x65, 0x78, 0x69, 0x74, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x91, 0x01, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, + 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, + 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x1a, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x16, 0x65, + 0x78, 0x69, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, + 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, + 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x14, 0x65, 0x78, + 0x69, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x69, 0x63, + 0x65, 0x73, 0x3a, 0x02, 0x18, 0x01, 0x22, 0xff, 0x02, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, - 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x69, 0x6e, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x53, 0x0a, 0x0d, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, - 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, - 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x70, 0x61, - 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x02, 0x18, 0x01, 0x22, - 0x54, 0x0a, 0x16, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, - 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, - 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, - 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xa8, 0x01, 0x0a, 0x17, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, - 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, - 0x22, 0xb6, 0x01, 0x0a, 0x1e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, - 0x63, 0x74, 0x72, 0x61, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, - 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, - 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x0c, 0x42, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x47, 0x0a, 0x06, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x1a, 0x39, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x92, - 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x0f, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, 0x65, + 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x67, + 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, + 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x52, 0x0e, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x82, 0x02, 0x0a, 0x16, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, - 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5c, - 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, - 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, + 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, + 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, + 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0e, 0x0a, 0x0c, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xab, 0x07, 0x0a, 0x14, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, + 0x61, 0x0a, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, + 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x8a, 0x05, 0x0a, 0x13, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x7c, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, + 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x10, 0x62, + 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, + 0x78, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, + 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, + 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, + 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x6a, 0x0a, 0x0d, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x6c, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, + 0x72, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x45, 0x82, + 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, - 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1f, 0x0a, 0x0b, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x69, 0x0a, - 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, - 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, - 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x9f, 0x0a, 0x0a, 0x16, 0x49, 0x6e, 0x64, - 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x64, 0x12, 0x67, 0x0a, 0x10, 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, - 0x6c, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, - 0x56, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x2e, 0x49, 0x6e, 0x64, - 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x0f, 0x69, 0x6e, 0x64, - 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x9b, 0x09, 0x0a, - 0x0e, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x12, - 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, - 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1d, 0x0a, - 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x78, 0x0a, 0x0f, + 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, + 0x6f, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x18, + 0x01, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x06, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x6c, - 0x61, 0x73, 0x68, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x20, 0x69, 0x73, 0x5f, 0x77, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x1c, 0x69, 0x73, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x49, - 0x6e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x3a, 0x0a, - 0x1a, 0x69, 0x73, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x16, 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x43, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x3c, 0x0a, 0x1b, 0x69, 0x73, 0x5f, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, - 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, - 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, - 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x39, 0x0a, 0x19, 0x69, 0x73, 0x5f, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, 0x73, 0x43, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x72, 0x12, 0x46, 0x0a, 0x20, 0x69, 0x73, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x69, 0x73, - 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x1a, 0x69, 0x73, - 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, - 0x69, 0x73, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x21, 0x69, 0x73, 0x5f, 0x70, 0x72, - 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x1d, 0x69, 0x73, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, - 0x6f, 0x63, 0x68, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, - 0x72, 0x12, 0x44, 0x0a, 0x1f, 0x69, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, - 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x69, 0x73, 0x50, 0x72, - 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x24, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, - 0x6f, 0x63, 0x68, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x47, 0x77, 0x65, 0x69, 0x12, 0x6e, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x47, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, - 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x0f, 0x20, + 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5e, 0x0a, 0x05, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, + 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, + 0x63, 0x68, 0x48, 0x00, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1a, 0x0a, 0x07, 0x67, + 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, + 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x3a, 0x02, 0x18, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xf5, 0x01, 0x0a, 0x1e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, + 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, + 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, + 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, + 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1c, 0x0a, 0x09, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x53, 0x0a, 0x0d, 0x70, 0x61, + 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0d, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, + 0x02, 0x18, 0x01, 0x22, 0x54, 0x0a, 0x16, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, + 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xa8, 0x01, 0x0a, 0x17, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, + 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x53, 0x69, 0x7a, 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x1e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, + 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, + 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x92, 0x01, + 0x0a, 0x0c, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x47, + 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x39, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0x92, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x6c, 0x61, + 0x73, 0x68, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, + 0x0f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, + 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x82, 0x02, 0x0a, 0x16, 0x49, 0x6e, 0x64, 0x69, + 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, + 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, + 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, + 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x9f, 0x0a, 0x0a, + 0x16, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x12, 0x67, 0x0a, 0x10, 0x69, 0x6e, 0x64, 0x69, 0x76, + 0x69, 0x64, 0x75, 0x61, 0x6c, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, + 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, + 0x2e, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x52, + 0x0f, 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, + 0x1a, 0x9b, 0x09, 0x0a, 0x0e, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, + 0x6f, 0x74, 0x65, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, + 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, + 0x5f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x69, 0x73, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x20, 0x69, 0x73, 0x5f, + 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x69, 0x6e, 0x5f, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x1c, 0x69, 0x73, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, + 0x62, 0x6c, 0x65, 0x49, 0x6e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, + 0x68, 0x12, 0x3a, 0x0a, 0x1a, 0x69, 0x73, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, + 0x6e, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x49, + 0x6e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x3c, 0x0a, + 0x1b, 0x69, 0x73, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x70, 0x72, + 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x17, 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x50, 0x72, + 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x39, 0x0a, 0x19, 0x69, + 0x73, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, + 0x69, 0x73, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x20, 0x69, 0x73, 0x5f, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x1c, 0x69, 0x73, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3b, + 0x0a, 0x1a, 0x69, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x17, 0x69, 0x73, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, + 0x6f, 0x63, 0x68, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x21, 0x69, + 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x69, 0x73, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, + 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x1f, 0x69, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x76, + 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, + 0x69, 0x73, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, + 0x65, 0x61, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x24, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x65, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x67, + 0x77, 0x65, 0x69, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x47, 0x77, 0x65, 0x69, 0x12, 0x6e, 0x0a, 0x0e, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x42, 0x47, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x52, 0x11, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, - 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x63, - 0x6f, 0x72, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x69, 0x6e, 0x61, 0x63, 0x74, - 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x32, 0xa8, 0x1c, 0x0a, 0x0b, 0x42, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x9e, 0x01, 0x0a, 0x10, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x12, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xb4, 0x01, 0x0a, 0x17, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x52, 0x0d, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x12, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x42, 0x47, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x18, 0x01, + 0x52, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x69, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x69, + 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x32, 0xa8, + 0x1c, 0x0a, 0x0b, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x9e, + 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x12, 0x21, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0xb4, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2e, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xbb, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x65, 0x64, 0x12, 0xd1, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x72, 0x61, 0x12, 0xbb, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, + 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6c, + 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x12, 0x31, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, - 0x12, 0xd1, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6c, 0x65, 0x63, - 0x74, 0x72, 0x61, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xa0, 0x01, 0x0a, 0x0f, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x2d, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x12, 0xb6, 0x01, 0x0a, 0x16, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x45, + 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x6c, 0x65, + 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x72, 0x61, 0x12, 0x92, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, - 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x33, 0x12, 0x31, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x5f, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x72, 0x61, 0x12, 0xa0, 0x01, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x73, 0x0a, 0x0c, 0x47, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, + 0x65, 0x61, 0x64, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, + 0x6e, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x68, 0x65, 0x61, 0x64, 0x88, 0x02, 0x01, 0x12, 0x96, + 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, - 0x26, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, - 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x12, 0xb6, 0x01, 0x0a, 0x16, 0x41, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x6c, 0x65, 0x63, 0x74, - 0x72, 0x61, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x6f, 0x6c, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, - 0x12, 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, - 0x12, 0x92, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x73, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x48, 0x65, 0x61, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x22, - 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x68, 0x65, 0x61, 0x64, 0x88, 0x02, 0x01, 0x12, 0x96, 0x01, 0x0a, 0x14, 0x4c, - 0x69, 0x73, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x65, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x33, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x29, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x23, 0x12, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x62, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x20, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x7d, 0x0a, - 0x0c, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2a, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x1f, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0xb6, 0x01, 0x0a, - 0x1c, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x3a, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x22, 0x27, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x12, 0xa1, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x73, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x12, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x73, 0x2f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x83, 0x01, 0x0a, 0x0e, + 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2c, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x22, + 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x73, 0x12, 0x7d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x73, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, 0x65, 0x74, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x7a, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x71, 0x75, 0x65, 0x75, - 0x65, 0x12, 0xb0, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x32, 0x2e, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x22, + 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x12, 0xb6, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x12, 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, - 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x65, 0x74, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, + 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x73, + 0x65, 0x74, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x7a, 0x0a, 0x11, 0x47, 0x65, 0x74, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x51, 0x75, 0x65, 0x75, 0x65, 0x22, 0x26, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, + 0x71, 0x75, 0x65, 0x75, 0x65, 0x12, 0xb0, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, + 0x65, 0x12, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x26, 0x12, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x70, 0x65, 0x72, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x12, 0xad, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, + 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, + 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x26, 0x12, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x61, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0xbe, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, + 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, + 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, - 0x61, 0x6e, 0x63, 0x65, 0x12, 0xad, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, + 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x02, 0x01, 0x12, 0x73, 0x0a, 0x0f, 0x47, 0x65, 0x74, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1d, 0x12, 0x1b, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0xa8, + 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, + 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0xbe, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x65, 0x74, + 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, + 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0xbe, 0x01, 0x0a, 0x1d, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, - 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f, 0x65, 0x74, 0x68, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x73, 0x2f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x88, 0x02, 0x01, 0x12, 0x73, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, - 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, - 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, - 0x63, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0xa8, 0x01, 0x0a, 0x16, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x1a, 0x2d, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3e, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x38, 0x12, 0x36, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, + 0x67, 0x73, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xa8, 0x01, 0x0a, 0x16, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x2d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x12, 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x6c, 0x61, 0x73, - 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x73, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0xbe, 0x01, 0x0a, 0x1d, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x38, 0x12, 0x36, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xa8, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x12, 0x27, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x30, 0x12, 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, - 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, - 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x5f, - 0x76, 0x6f, 0x74, 0x65, 0x73, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, + 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x2f, 0x73, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x64, + 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, + 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, - 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x68, 0x61, 0x31, 0x2e, 0x49, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x56, 0x6f, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x2f, 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, + 0x75, 0x61, 0x6c, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x73, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, + 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, + 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4444,12 +4483,14 @@ var file_proto_prysm_v1alpha1_beacon_chain_proto_goTypes = []interface{}{ (*SignedBlindedBeaconBlockDeneb)(nil), // 52: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockDeneb (*SignedBeaconBlockElectra)(nil), // 53: ethereum.eth.v1alpha1.SignedBeaconBlockElectra (*SignedBlindedBeaconBlockElectra)(nil), // 54: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockElectra - (*ValidatorParticipation)(nil), // 55: ethereum.eth.v1alpha1.ValidatorParticipation - (*Validator)(nil), // 56: ethereum.eth.v1alpha1.Validator - (*emptypb.Empty)(nil), // 57: google.protobuf.Empty - (*AttesterSlashing)(nil), // 58: ethereum.eth.v1alpha1.AttesterSlashing - (*AttesterSlashingElectra)(nil), // 59: ethereum.eth.v1alpha1.AttesterSlashingElectra - (*ProposerSlashing)(nil), // 60: ethereum.eth.v1alpha1.ProposerSlashing + (*SignedBeaconBlockFulu)(nil), // 55: ethereum.eth.v1alpha1.SignedBeaconBlockFulu + (*SignedBlindedBeaconBlockFulu)(nil), // 56: ethereum.eth.v1alpha1.SignedBlindedBeaconBlockFulu + (*ValidatorParticipation)(nil), // 57: ethereum.eth.v1alpha1.ValidatorParticipation + (*Validator)(nil), // 58: ethereum.eth.v1alpha1.Validator + (*emptypb.Empty)(nil), // 59: google.protobuf.Empty + (*AttesterSlashing)(nil), // 60: ethereum.eth.v1alpha1.AttesterSlashing + (*AttesterSlashingElectra)(nil), // 61: ethereum.eth.v1alpha1.AttesterSlashingElectra + (*ProposerSlashing)(nil), // 62: ethereum.eth.v1alpha1.ProposerSlashing } var file_proto_prysm_v1alpha1_beacon_chain_proto_depIdxs = []int32{ 41, // 0: ethereum.eth.v1alpha1.ListAttestationsResponse.attestations:type_name -> ethereum.eth.v1alpha1.Attestation @@ -4467,67 +4508,69 @@ var file_proto_prysm_v1alpha1_beacon_chain_proto_depIdxs = []int32{ 52, // 12: ethereum.eth.v1alpha1.BeaconBlockContainer.blinded_deneb_block:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockDeneb 53, // 13: ethereum.eth.v1alpha1.BeaconBlockContainer.electra_block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockElectra 54, // 14: ethereum.eth.v1alpha1.BeaconBlockContainer.blinded_electra_block:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockElectra - 35, // 15: ethereum.eth.v1alpha1.BeaconCommittees.committees:type_name -> ethereum.eth.v1alpha1.BeaconCommittees.CommitteesEntry - 36, // 16: ethereum.eth.v1alpha1.ValidatorBalances.balances:type_name -> ethereum.eth.v1alpha1.ValidatorBalances.Balance - 37, // 17: ethereum.eth.v1alpha1.Validators.validator_list:type_name -> ethereum.eth.v1alpha1.Validators.ValidatorContainer - 38, // 18: ethereum.eth.v1alpha1.ValidatorAssignments.assignments:type_name -> ethereum.eth.v1alpha1.ValidatorAssignments.CommitteeAssignment - 55, // 19: ethereum.eth.v1alpha1.ValidatorParticipationResponse.participation:type_name -> ethereum.eth.v1alpha1.ValidatorParticipation - 41, // 20: ethereum.eth.v1alpha1.AttestationPoolResponse.attestations:type_name -> ethereum.eth.v1alpha1.Attestation - 42, // 21: ethereum.eth.v1alpha1.AttestationPoolElectraResponse.attestations:type_name -> ethereum.eth.v1alpha1.AttestationElectra - 39, // 22: ethereum.eth.v1alpha1.BeaconConfig.config:type_name -> ethereum.eth.v1alpha1.BeaconConfig.ConfigEntry - 40, // 23: ethereum.eth.v1alpha1.IndividualVotesRespond.individual_votes:type_name -> ethereum.eth.v1alpha1.IndividualVotesRespond.IndividualVote - 33, // 24: ethereum.eth.v1alpha1.BeaconCommittees.CommitteesList.committees:type_name -> ethereum.eth.v1alpha1.BeaconCommittees.CommitteeItem - 34, // 25: ethereum.eth.v1alpha1.BeaconCommittees.CommitteesEntry.value:type_name -> ethereum.eth.v1alpha1.BeaconCommittees.CommitteesList - 56, // 26: ethereum.eth.v1alpha1.Validators.ValidatorContainer.validator:type_name -> ethereum.eth.v1alpha1.Validator - 1, // 27: ethereum.eth.v1alpha1.BeaconChain.ListAttestations:input_type -> ethereum.eth.v1alpha1.ListAttestationsRequest - 1, // 28: ethereum.eth.v1alpha1.BeaconChain.ListAttestationsElectra:input_type -> ethereum.eth.v1alpha1.ListAttestationsRequest - 0, // 29: ethereum.eth.v1alpha1.BeaconChain.ListIndexedAttestations:input_type -> ethereum.eth.v1alpha1.ListIndexedAttestationsRequest - 0, // 30: ethereum.eth.v1alpha1.BeaconChain.ListIndexedAttestationsElectra:input_type -> ethereum.eth.v1alpha1.ListIndexedAttestationsRequest - 26, // 31: ethereum.eth.v1alpha1.BeaconChain.AttestationPool:input_type -> ethereum.eth.v1alpha1.AttestationPoolRequest - 26, // 32: ethereum.eth.v1alpha1.BeaconChain.AttestationPoolElectra:input_type -> ethereum.eth.v1alpha1.AttestationPoolRequest - 6, // 33: ethereum.eth.v1alpha1.BeaconChain.ListBeaconBlocks:input_type -> ethereum.eth.v1alpha1.ListBlocksRequest - 57, // 34: ethereum.eth.v1alpha1.BeaconChain.GetChainHead:input_type -> google.protobuf.Empty - 10, // 35: ethereum.eth.v1alpha1.BeaconChain.ListBeaconCommittees:input_type -> ethereum.eth.v1alpha1.ListCommitteesRequest - 12, // 36: ethereum.eth.v1alpha1.BeaconChain.ListValidatorBalances:input_type -> ethereum.eth.v1alpha1.ListValidatorBalancesRequest - 14, // 37: ethereum.eth.v1alpha1.BeaconChain.ListValidators:input_type -> ethereum.eth.v1alpha1.ListValidatorsRequest - 15, // 38: ethereum.eth.v1alpha1.BeaconChain.GetValidator:input_type -> ethereum.eth.v1alpha1.GetValidatorRequest - 17, // 39: ethereum.eth.v1alpha1.BeaconChain.GetValidatorActiveSetChanges:input_type -> ethereum.eth.v1alpha1.GetValidatorActiveSetChangesRequest - 57, // 40: ethereum.eth.v1alpha1.BeaconChain.GetValidatorQueue:input_type -> google.protobuf.Empty - 19, // 41: ethereum.eth.v1alpha1.BeaconChain.GetValidatorPerformance:input_type -> ethereum.eth.v1alpha1.ValidatorPerformanceRequest - 22, // 42: ethereum.eth.v1alpha1.BeaconChain.ListValidatorAssignments:input_type -> ethereum.eth.v1alpha1.ListValidatorAssignmentsRequest - 24, // 43: ethereum.eth.v1alpha1.BeaconChain.GetValidatorParticipation:input_type -> ethereum.eth.v1alpha1.GetValidatorParticipationRequest - 57, // 44: ethereum.eth.v1alpha1.BeaconChain.GetBeaconConfig:input_type -> google.protobuf.Empty - 58, // 45: ethereum.eth.v1alpha1.BeaconChain.SubmitAttesterSlashing:input_type -> ethereum.eth.v1alpha1.AttesterSlashing - 59, // 46: ethereum.eth.v1alpha1.BeaconChain.SubmitAttesterSlashingElectra:input_type -> ethereum.eth.v1alpha1.AttesterSlashingElectra - 60, // 47: ethereum.eth.v1alpha1.BeaconChain.SubmitProposerSlashing:input_type -> ethereum.eth.v1alpha1.ProposerSlashing - 31, // 48: ethereum.eth.v1alpha1.BeaconChain.GetIndividualVotes:input_type -> ethereum.eth.v1alpha1.IndividualVotesRequest - 2, // 49: ethereum.eth.v1alpha1.BeaconChain.ListAttestations:output_type -> ethereum.eth.v1alpha1.ListAttestationsResponse - 3, // 50: ethereum.eth.v1alpha1.BeaconChain.ListAttestationsElectra:output_type -> ethereum.eth.v1alpha1.ListAttestationsElectraResponse - 4, // 51: ethereum.eth.v1alpha1.BeaconChain.ListIndexedAttestations:output_type -> ethereum.eth.v1alpha1.ListIndexedAttestationsResponse - 5, // 52: ethereum.eth.v1alpha1.BeaconChain.ListIndexedAttestationsElectra:output_type -> ethereum.eth.v1alpha1.ListIndexedAttestationsElectraResponse - 27, // 53: ethereum.eth.v1alpha1.BeaconChain.AttestationPool:output_type -> ethereum.eth.v1alpha1.AttestationPoolResponse - 28, // 54: ethereum.eth.v1alpha1.BeaconChain.AttestationPoolElectra:output_type -> ethereum.eth.v1alpha1.AttestationPoolElectraResponse - 7, // 55: ethereum.eth.v1alpha1.BeaconChain.ListBeaconBlocks:output_type -> ethereum.eth.v1alpha1.ListBeaconBlocksResponse - 9, // 56: ethereum.eth.v1alpha1.BeaconChain.GetChainHead:output_type -> ethereum.eth.v1alpha1.ChainHead - 11, // 57: ethereum.eth.v1alpha1.BeaconChain.ListBeaconCommittees:output_type -> ethereum.eth.v1alpha1.BeaconCommittees - 13, // 58: ethereum.eth.v1alpha1.BeaconChain.ListValidatorBalances:output_type -> ethereum.eth.v1alpha1.ValidatorBalances - 16, // 59: ethereum.eth.v1alpha1.BeaconChain.ListValidators:output_type -> ethereum.eth.v1alpha1.Validators - 56, // 60: ethereum.eth.v1alpha1.BeaconChain.GetValidator:output_type -> ethereum.eth.v1alpha1.Validator - 18, // 61: ethereum.eth.v1alpha1.BeaconChain.GetValidatorActiveSetChanges:output_type -> ethereum.eth.v1alpha1.ActiveSetChanges - 21, // 62: ethereum.eth.v1alpha1.BeaconChain.GetValidatorQueue:output_type -> ethereum.eth.v1alpha1.ValidatorQueue - 20, // 63: ethereum.eth.v1alpha1.BeaconChain.GetValidatorPerformance:output_type -> ethereum.eth.v1alpha1.ValidatorPerformanceResponse - 23, // 64: ethereum.eth.v1alpha1.BeaconChain.ListValidatorAssignments:output_type -> ethereum.eth.v1alpha1.ValidatorAssignments - 25, // 65: ethereum.eth.v1alpha1.BeaconChain.GetValidatorParticipation:output_type -> ethereum.eth.v1alpha1.ValidatorParticipationResponse - 29, // 66: ethereum.eth.v1alpha1.BeaconChain.GetBeaconConfig:output_type -> ethereum.eth.v1alpha1.BeaconConfig - 30, // 67: ethereum.eth.v1alpha1.BeaconChain.SubmitAttesterSlashing:output_type -> ethereum.eth.v1alpha1.SubmitSlashingResponse - 30, // 68: ethereum.eth.v1alpha1.BeaconChain.SubmitAttesterSlashingElectra:output_type -> ethereum.eth.v1alpha1.SubmitSlashingResponse - 30, // 69: ethereum.eth.v1alpha1.BeaconChain.SubmitProposerSlashing:output_type -> ethereum.eth.v1alpha1.SubmitSlashingResponse - 32, // 70: ethereum.eth.v1alpha1.BeaconChain.GetIndividualVotes:output_type -> ethereum.eth.v1alpha1.IndividualVotesRespond - 49, // [49:71] is the sub-list for method output_type - 27, // [27:49] is the sub-list for method input_type - 27, // [27:27] is the sub-list for extension type_name - 27, // [27:27] is the sub-list for extension extendee - 0, // [0:27] is the sub-list for field type_name + 55, // 15: ethereum.eth.v1alpha1.BeaconBlockContainer.fulu_block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockFulu + 56, // 16: ethereum.eth.v1alpha1.BeaconBlockContainer.blinded_fulu_block:type_name -> ethereum.eth.v1alpha1.SignedBlindedBeaconBlockFulu + 35, // 17: ethereum.eth.v1alpha1.BeaconCommittees.committees:type_name -> ethereum.eth.v1alpha1.BeaconCommittees.CommitteesEntry + 36, // 18: ethereum.eth.v1alpha1.ValidatorBalances.balances:type_name -> ethereum.eth.v1alpha1.ValidatorBalances.Balance + 37, // 19: ethereum.eth.v1alpha1.Validators.validator_list:type_name -> ethereum.eth.v1alpha1.Validators.ValidatorContainer + 38, // 20: ethereum.eth.v1alpha1.ValidatorAssignments.assignments:type_name -> ethereum.eth.v1alpha1.ValidatorAssignments.CommitteeAssignment + 57, // 21: ethereum.eth.v1alpha1.ValidatorParticipationResponse.participation:type_name -> ethereum.eth.v1alpha1.ValidatorParticipation + 41, // 22: ethereum.eth.v1alpha1.AttestationPoolResponse.attestations:type_name -> ethereum.eth.v1alpha1.Attestation + 42, // 23: ethereum.eth.v1alpha1.AttestationPoolElectraResponse.attestations:type_name -> ethereum.eth.v1alpha1.AttestationElectra + 39, // 24: ethereum.eth.v1alpha1.BeaconConfig.config:type_name -> ethereum.eth.v1alpha1.BeaconConfig.ConfigEntry + 40, // 25: ethereum.eth.v1alpha1.IndividualVotesRespond.individual_votes:type_name -> ethereum.eth.v1alpha1.IndividualVotesRespond.IndividualVote + 33, // 26: ethereum.eth.v1alpha1.BeaconCommittees.CommitteesList.committees:type_name -> ethereum.eth.v1alpha1.BeaconCommittees.CommitteeItem + 34, // 27: ethereum.eth.v1alpha1.BeaconCommittees.CommitteesEntry.value:type_name -> ethereum.eth.v1alpha1.BeaconCommittees.CommitteesList + 58, // 28: ethereum.eth.v1alpha1.Validators.ValidatorContainer.validator:type_name -> ethereum.eth.v1alpha1.Validator + 1, // 29: ethereum.eth.v1alpha1.BeaconChain.ListAttestations:input_type -> ethereum.eth.v1alpha1.ListAttestationsRequest + 1, // 30: ethereum.eth.v1alpha1.BeaconChain.ListAttestationsElectra:input_type -> ethereum.eth.v1alpha1.ListAttestationsRequest + 0, // 31: ethereum.eth.v1alpha1.BeaconChain.ListIndexedAttestations:input_type -> ethereum.eth.v1alpha1.ListIndexedAttestationsRequest + 0, // 32: ethereum.eth.v1alpha1.BeaconChain.ListIndexedAttestationsElectra:input_type -> ethereum.eth.v1alpha1.ListIndexedAttestationsRequest + 26, // 33: ethereum.eth.v1alpha1.BeaconChain.AttestationPool:input_type -> ethereum.eth.v1alpha1.AttestationPoolRequest + 26, // 34: ethereum.eth.v1alpha1.BeaconChain.AttestationPoolElectra:input_type -> ethereum.eth.v1alpha1.AttestationPoolRequest + 6, // 35: ethereum.eth.v1alpha1.BeaconChain.ListBeaconBlocks:input_type -> ethereum.eth.v1alpha1.ListBlocksRequest + 59, // 36: ethereum.eth.v1alpha1.BeaconChain.GetChainHead:input_type -> google.protobuf.Empty + 10, // 37: ethereum.eth.v1alpha1.BeaconChain.ListBeaconCommittees:input_type -> ethereum.eth.v1alpha1.ListCommitteesRequest + 12, // 38: ethereum.eth.v1alpha1.BeaconChain.ListValidatorBalances:input_type -> ethereum.eth.v1alpha1.ListValidatorBalancesRequest + 14, // 39: ethereum.eth.v1alpha1.BeaconChain.ListValidators:input_type -> ethereum.eth.v1alpha1.ListValidatorsRequest + 15, // 40: ethereum.eth.v1alpha1.BeaconChain.GetValidator:input_type -> ethereum.eth.v1alpha1.GetValidatorRequest + 17, // 41: ethereum.eth.v1alpha1.BeaconChain.GetValidatorActiveSetChanges:input_type -> ethereum.eth.v1alpha1.GetValidatorActiveSetChangesRequest + 59, // 42: ethereum.eth.v1alpha1.BeaconChain.GetValidatorQueue:input_type -> google.protobuf.Empty + 19, // 43: ethereum.eth.v1alpha1.BeaconChain.GetValidatorPerformance:input_type -> ethereum.eth.v1alpha1.ValidatorPerformanceRequest + 22, // 44: ethereum.eth.v1alpha1.BeaconChain.ListValidatorAssignments:input_type -> ethereum.eth.v1alpha1.ListValidatorAssignmentsRequest + 24, // 45: ethereum.eth.v1alpha1.BeaconChain.GetValidatorParticipation:input_type -> ethereum.eth.v1alpha1.GetValidatorParticipationRequest + 59, // 46: ethereum.eth.v1alpha1.BeaconChain.GetBeaconConfig:input_type -> google.protobuf.Empty + 60, // 47: ethereum.eth.v1alpha1.BeaconChain.SubmitAttesterSlashing:input_type -> ethereum.eth.v1alpha1.AttesterSlashing + 61, // 48: ethereum.eth.v1alpha1.BeaconChain.SubmitAttesterSlashingElectra:input_type -> ethereum.eth.v1alpha1.AttesterSlashingElectra + 62, // 49: ethereum.eth.v1alpha1.BeaconChain.SubmitProposerSlashing:input_type -> ethereum.eth.v1alpha1.ProposerSlashing + 31, // 50: ethereum.eth.v1alpha1.BeaconChain.GetIndividualVotes:input_type -> ethereum.eth.v1alpha1.IndividualVotesRequest + 2, // 51: ethereum.eth.v1alpha1.BeaconChain.ListAttestations:output_type -> ethereum.eth.v1alpha1.ListAttestationsResponse + 3, // 52: ethereum.eth.v1alpha1.BeaconChain.ListAttestationsElectra:output_type -> ethereum.eth.v1alpha1.ListAttestationsElectraResponse + 4, // 53: ethereum.eth.v1alpha1.BeaconChain.ListIndexedAttestations:output_type -> ethereum.eth.v1alpha1.ListIndexedAttestationsResponse + 5, // 54: ethereum.eth.v1alpha1.BeaconChain.ListIndexedAttestationsElectra:output_type -> ethereum.eth.v1alpha1.ListIndexedAttestationsElectraResponse + 27, // 55: ethereum.eth.v1alpha1.BeaconChain.AttestationPool:output_type -> ethereum.eth.v1alpha1.AttestationPoolResponse + 28, // 56: ethereum.eth.v1alpha1.BeaconChain.AttestationPoolElectra:output_type -> ethereum.eth.v1alpha1.AttestationPoolElectraResponse + 7, // 57: ethereum.eth.v1alpha1.BeaconChain.ListBeaconBlocks:output_type -> ethereum.eth.v1alpha1.ListBeaconBlocksResponse + 9, // 58: ethereum.eth.v1alpha1.BeaconChain.GetChainHead:output_type -> ethereum.eth.v1alpha1.ChainHead + 11, // 59: ethereum.eth.v1alpha1.BeaconChain.ListBeaconCommittees:output_type -> ethereum.eth.v1alpha1.BeaconCommittees + 13, // 60: ethereum.eth.v1alpha1.BeaconChain.ListValidatorBalances:output_type -> ethereum.eth.v1alpha1.ValidatorBalances + 16, // 61: ethereum.eth.v1alpha1.BeaconChain.ListValidators:output_type -> ethereum.eth.v1alpha1.Validators + 58, // 62: ethereum.eth.v1alpha1.BeaconChain.GetValidator:output_type -> ethereum.eth.v1alpha1.Validator + 18, // 63: ethereum.eth.v1alpha1.BeaconChain.GetValidatorActiveSetChanges:output_type -> ethereum.eth.v1alpha1.ActiveSetChanges + 21, // 64: ethereum.eth.v1alpha1.BeaconChain.GetValidatorQueue:output_type -> ethereum.eth.v1alpha1.ValidatorQueue + 20, // 65: ethereum.eth.v1alpha1.BeaconChain.GetValidatorPerformance:output_type -> ethereum.eth.v1alpha1.ValidatorPerformanceResponse + 23, // 66: ethereum.eth.v1alpha1.BeaconChain.ListValidatorAssignments:output_type -> ethereum.eth.v1alpha1.ValidatorAssignments + 25, // 67: ethereum.eth.v1alpha1.BeaconChain.GetValidatorParticipation:output_type -> ethereum.eth.v1alpha1.ValidatorParticipationResponse + 29, // 68: ethereum.eth.v1alpha1.BeaconChain.GetBeaconConfig:output_type -> ethereum.eth.v1alpha1.BeaconConfig + 30, // 69: ethereum.eth.v1alpha1.BeaconChain.SubmitAttesterSlashing:output_type -> ethereum.eth.v1alpha1.SubmitSlashingResponse + 30, // 70: ethereum.eth.v1alpha1.BeaconChain.SubmitAttesterSlashingElectra:output_type -> ethereum.eth.v1alpha1.SubmitSlashingResponse + 30, // 71: ethereum.eth.v1alpha1.BeaconChain.SubmitProposerSlashing:output_type -> ethereum.eth.v1alpha1.SubmitSlashingResponse + 32, // 72: ethereum.eth.v1alpha1.BeaconChain.GetIndividualVotes:output_type -> ethereum.eth.v1alpha1.IndividualVotesRespond + 51, // [51:73] is the sub-list for method output_type + 29, // [29:51] is the sub-list for method input_type + 29, // [29:29] is the sub-list for extension type_name + 29, // [29:29] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name } func init() { file_proto_prysm_v1alpha1_beacon_chain_proto_init() } @@ -5033,6 +5076,8 @@ func file_proto_prysm_v1alpha1_beacon_chain_proto_init() { (*BeaconBlockContainer_BlindedDenebBlock)(nil), (*BeaconBlockContainer_ElectraBlock)(nil), (*BeaconBlockContainer_BlindedElectraBlock)(nil), + (*BeaconBlockContainer_FuluBlock)(nil), + (*BeaconBlockContainer_BlindedFuluBlock)(nil), } file_proto_prysm_v1alpha1_beacon_chain_proto_msgTypes[10].OneofWrappers = []interface{}{ (*ListCommitteesRequest_Epoch)(nil), diff --git a/proto/prysm/v1alpha1/beacon_chain.pb.gw.go b/proto/prysm/v1alpha1/beacon_chain.pb.gw.go deleted file mode 100755 index a7f81408911e..000000000000 --- a/proto/prysm/v1alpha1/beacon_chain.pb.gw.go +++ /dev/null @@ -1,1862 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: proto/prysm/v1alpha1/beacon_chain.proto - -/* -Package eth is a reverse proxy. - -It translates gRPC into RESTful JSON APIs. -*/ -package eth - -import ( - "context" - "io" - "net/http" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/emptypb" -) - -// Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join -var _ = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) -var _ = emptypb.Empty{} - -var ( - filter_BeaconChain_ListAttestations_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListAttestations_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListAttestationsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListAttestations_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListAttestations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListAttestations_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListAttestationsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListAttestations_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListAttestations(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_ListAttestationsElectra_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListAttestationsElectra_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListAttestationsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListAttestationsElectra_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListAttestationsElectra(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListAttestationsElectra_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListAttestationsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListAttestationsElectra_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListAttestationsElectra(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_ListIndexedAttestations_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListIndexedAttestations_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListIndexedAttestationsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListIndexedAttestations_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListIndexedAttestations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListIndexedAttestations_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListIndexedAttestationsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListIndexedAttestations_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListIndexedAttestations(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_ListIndexedAttestationsElectra_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListIndexedAttestationsElectra_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListIndexedAttestationsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListIndexedAttestationsElectra_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListIndexedAttestationsElectra(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListIndexedAttestationsElectra_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListIndexedAttestationsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListIndexedAttestationsElectra_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListIndexedAttestationsElectra(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_AttestationPool_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_AttestationPool_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttestationPoolRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_AttestationPool_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.AttestationPool(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_AttestationPool_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttestationPoolRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_AttestationPool_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.AttestationPool(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_AttestationPoolElectra_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_AttestationPoolElectra_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttestationPoolRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_AttestationPoolElectra_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.AttestationPoolElectra(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_AttestationPoolElectra_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttestationPoolRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_AttestationPoolElectra_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.AttestationPoolElectra(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_ListBeaconBlocks_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListBeaconBlocks_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListBlocksRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListBeaconBlocks_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListBeaconBlocks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListBeaconBlocks_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListBlocksRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListBeaconBlocks_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListBeaconBlocks(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconChain_GetChainHead_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetChainHead(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_GetChainHead_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetChainHead(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_ListBeaconCommittees_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListBeaconCommittees_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListCommitteesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListBeaconCommittees_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListBeaconCommittees(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListBeaconCommittees_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListCommitteesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListBeaconCommittees_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListBeaconCommittees(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_ListValidatorBalances_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListValidatorBalances_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListValidatorBalancesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListValidatorBalances_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListValidatorBalances(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListValidatorBalances_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListValidatorBalancesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListValidatorBalances_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListValidatorBalances(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_ListValidators_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListValidators_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListValidatorsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListValidators_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListValidators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListValidators_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListValidatorsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListValidators_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListValidators(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_GetValidator_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_GetValidator_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetValidatorRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetValidator_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetValidator(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_GetValidator_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetValidatorRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetValidator_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetValidator(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_GetValidatorActiveSetChanges_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_GetValidatorActiveSetChanges_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetValidatorActiveSetChangesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetValidatorActiveSetChanges_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetValidatorActiveSetChanges(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_GetValidatorActiveSetChanges_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetValidatorActiveSetChangesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetValidatorActiveSetChanges_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetValidatorActiveSetChanges(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconChain_GetValidatorQueue_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetValidatorQueue(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_GetValidatorQueue_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetValidatorQueue(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_GetValidatorPerformance_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_GetValidatorPerformance_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ValidatorPerformanceRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetValidatorPerformance_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetValidatorPerformance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_GetValidatorPerformance_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ValidatorPerformanceRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetValidatorPerformance_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetValidatorPerformance(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_ListValidatorAssignments_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_ListValidatorAssignments_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListValidatorAssignmentsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListValidatorAssignments_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ListValidatorAssignments(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_ListValidatorAssignments_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ListValidatorAssignmentsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_ListValidatorAssignments_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ListValidatorAssignments(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_GetValidatorParticipation_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_GetValidatorParticipation_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetValidatorParticipationRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetValidatorParticipation_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetValidatorParticipation(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_GetValidatorParticipation_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetValidatorParticipationRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetValidatorParticipation_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetValidatorParticipation(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconChain_GetBeaconConfig_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetBeaconConfig(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_GetBeaconConfig_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetBeaconConfig(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_SubmitAttesterSlashing_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_SubmitAttesterSlashing_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttesterSlashing - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_SubmitAttesterSlashing_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitAttesterSlashing(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_SubmitAttesterSlashing_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttesterSlashing - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_SubmitAttesterSlashing_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitAttesterSlashing(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_SubmitAttesterSlashingElectra_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_SubmitAttesterSlashingElectra_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttesterSlashingElectra - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_SubmitAttesterSlashingElectra_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitAttesterSlashingElectra(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_SubmitAttesterSlashingElectra_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttesterSlashingElectra - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_SubmitAttesterSlashingElectra_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitAttesterSlashingElectra(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_SubmitProposerSlashing_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_SubmitProposerSlashing_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ProposerSlashing - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_SubmitProposerSlashing_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitProposerSlashing(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_SubmitProposerSlashing_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ProposerSlashing - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_SubmitProposerSlashing_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitProposerSlashing(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconChain_GetIndividualVotes_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconChain_GetIndividualVotes_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconChainClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq IndividualVotesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetIndividualVotes_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetIndividualVotes(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconChain_GetIndividualVotes_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconChainServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq IndividualVotesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconChain_GetIndividualVotes_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetIndividualVotes(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterBeaconChainHandlerServer registers the http handlers for service BeaconChain to "mux". -// UnaryRPC :call BeaconChainServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterBeaconChainHandlerFromEndpoint instead. -func RegisterBeaconChainHandlerServer(ctx context.Context, mux *runtime.ServeMux, server BeaconChainServer) error { - - mux.Handle("GET", pattern_BeaconChain_ListAttestations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListAttestations") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListAttestations_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListAttestations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListAttestationsElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListAttestationsElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListAttestationsElectra_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListAttestationsElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListIndexedAttestations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListIndexedAttestations") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListIndexedAttestations_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListIndexedAttestations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListIndexedAttestationsElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListIndexedAttestationsElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListIndexedAttestationsElectra_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListIndexedAttestationsElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_AttestationPool_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/AttestationPool") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_AttestationPool_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_AttestationPool_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_AttestationPoolElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/AttestationPoolElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_AttestationPoolElectra_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_AttestationPoolElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListBeaconBlocks_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListBeaconBlocks") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListBeaconBlocks_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListBeaconBlocks_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetChainHead_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetChainHead") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_GetChainHead_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetChainHead_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListBeaconCommittees_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListBeaconCommittees") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListBeaconCommittees_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListBeaconCommittees_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListValidatorBalances_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListValidatorBalances") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListValidatorBalances_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListValidatorBalances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListValidators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListValidators") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListValidators_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidator_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidator") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_GetValidator_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidatorActiveSetChanges_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidatorActiveSetChanges") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_GetValidatorActiveSetChanges_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidatorActiveSetChanges_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidatorQueue_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidatorQueue") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_GetValidatorQueue_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidatorQueue_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidatorPerformance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidatorPerformance") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_GetValidatorPerformance_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidatorPerformance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListValidatorAssignments_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListValidatorAssignments") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_ListValidatorAssignments_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListValidatorAssignments_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidatorParticipation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidatorParticipation") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_GetValidatorParticipation_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidatorParticipation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetBeaconConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetBeaconConfig") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_GetBeaconConfig_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetBeaconConfig_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_SubmitAttesterSlashing_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/SubmitAttesterSlashing") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_SubmitAttesterSlashing_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_SubmitAttesterSlashing_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_SubmitAttesterSlashingElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/SubmitAttesterSlashingElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_SubmitAttesterSlashingElectra_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_SubmitAttesterSlashingElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_SubmitProposerSlashing_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/SubmitProposerSlashing") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_SubmitProposerSlashing_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_SubmitProposerSlashing_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetIndividualVotes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetIndividualVotes") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconChain_GetIndividualVotes_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetIndividualVotes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -// RegisterBeaconChainHandlerFromEndpoint is same as RegisterBeaconChainHandler but -// automatically dials to "endpoint" and closes the connection when "ctx" gets done. -func RegisterBeaconChainHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) - if err != nil { - return err - } - defer func() { - if err != nil { - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - return - } - go func() { - <-ctx.Done() - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - }() - }() - - return RegisterBeaconChainHandler(ctx, mux, conn) -} - -// RegisterBeaconChainHandler registers the http handlers for service BeaconChain to "mux". -// The handlers forward requests to the grpc endpoint over "conn". -func RegisterBeaconChainHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { - return RegisterBeaconChainHandlerClient(ctx, mux, NewBeaconChainClient(conn)) -} - -// RegisterBeaconChainHandlerClient registers the http handlers for service BeaconChain -// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "BeaconChainClient". -// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "BeaconChainClient" -// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "BeaconChainClient" to call the correct interceptors. -func RegisterBeaconChainHandlerClient(ctx context.Context, mux *runtime.ServeMux, client BeaconChainClient) error { - - mux.Handle("GET", pattern_BeaconChain_ListAttestations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListAttestations") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListAttestations_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListAttestations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListAttestationsElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListAttestationsElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListAttestationsElectra_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListAttestationsElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListIndexedAttestations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListIndexedAttestations") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListIndexedAttestations_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListIndexedAttestations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListIndexedAttestationsElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListIndexedAttestationsElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListIndexedAttestationsElectra_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListIndexedAttestationsElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_AttestationPool_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/AttestationPool") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_AttestationPool_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_AttestationPool_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_AttestationPoolElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/AttestationPoolElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_AttestationPoolElectra_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_AttestationPoolElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListBeaconBlocks_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListBeaconBlocks") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListBeaconBlocks_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListBeaconBlocks_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetChainHead_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetChainHead") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_GetChainHead_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetChainHead_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListBeaconCommittees_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListBeaconCommittees") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListBeaconCommittees_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListBeaconCommittees_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListValidatorBalances_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListValidatorBalances") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListValidatorBalances_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListValidatorBalances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListValidators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListValidators") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListValidators_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListValidators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidator_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidator") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_GetValidator_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidatorActiveSetChanges_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidatorActiveSetChanges") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_GetValidatorActiveSetChanges_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidatorActiveSetChanges_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidatorQueue_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidatorQueue") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_GetValidatorQueue_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidatorQueue_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidatorPerformance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidatorPerformance") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_GetValidatorPerformance_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidatorPerformance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_ListValidatorAssignments_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/ListValidatorAssignments") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_ListValidatorAssignments_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_ListValidatorAssignments_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetValidatorParticipation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetValidatorParticipation") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_GetValidatorParticipation_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetValidatorParticipation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetBeaconConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetBeaconConfig") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_GetBeaconConfig_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetBeaconConfig_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_SubmitAttesterSlashing_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/SubmitAttesterSlashing") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_SubmitAttesterSlashing_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_SubmitAttesterSlashing_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_SubmitAttesterSlashingElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/SubmitAttesterSlashingElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_SubmitAttesterSlashingElectra_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_SubmitAttesterSlashingElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_SubmitProposerSlashing_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/SubmitProposerSlashing") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_SubmitProposerSlashing_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_SubmitProposerSlashing_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconChain_GetIndividualVotes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconChain/GetIndividualVotes") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconChain_GetIndividualVotes_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconChain_GetIndividualVotes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_BeaconChain_ListAttestations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "attestations"}, "")) - - pattern_BeaconChain_ListAttestationsElectra_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "attestations_electra"}, "")) - - pattern_BeaconChain_ListIndexedAttestations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "beacon", "attestations", "indexed"}, "")) - - pattern_BeaconChain_ListIndexedAttestationsElectra_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "beacon", "attestations", "indexed_electra"}, "")) - - pattern_BeaconChain_AttestationPool_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "beacon", "attestations", "pool"}, "")) - - pattern_BeaconChain_AttestationPoolElectra_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "beacon", "attestations", "pool_electra"}, "")) - - pattern_BeaconChain_ListBeaconBlocks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha2", "beacon", "blocks"}, "")) - - pattern_BeaconChain_GetChainHead_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "chainhead"}, "")) - - pattern_BeaconChain_ListBeaconCommittees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "committees"}, "")) - - pattern_BeaconChain_ListValidatorBalances_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validators", "balances"}, "")) - - pattern_BeaconChain_ListValidators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"eth", "v1alpha1", "validators"}, "")) - - pattern_BeaconChain_GetValidator_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"eth", "v1alpha1", "validator"}, "")) - - pattern_BeaconChain_GetValidatorActiveSetChanges_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validators", "activesetchanges"}, "")) - - pattern_BeaconChain_GetValidatorQueue_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validators", "queue"}, "")) - - pattern_BeaconChain_GetValidatorPerformance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validators", "performance"}, "")) - - pattern_BeaconChain_ListValidatorAssignments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validators", "assignments"}, "")) - - pattern_BeaconChain_GetValidatorParticipation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validators", "participation"}, "")) - - pattern_BeaconChain_GetBeaconConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "config"}, "")) - - pattern_BeaconChain_SubmitAttesterSlashing_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"eth", "v1alpha1", "beacon", "slashings", "attester", "submit"}, "")) - - pattern_BeaconChain_SubmitAttesterSlashingElectra_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"eth", "v1alpha1", "beacon", "slashings", "attester", "submit_electra"}, "")) - - pattern_BeaconChain_SubmitProposerSlashing_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"eth", "v1alpha1", "beacon", "slashings", "proposer", "submit"}, "")) - - pattern_BeaconChain_GetIndividualVotes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "beacon", "individual_votes"}, "")) -) - -var ( - forward_BeaconChain_ListAttestations_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_ListAttestationsElectra_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_ListIndexedAttestations_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_ListIndexedAttestationsElectra_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_AttestationPool_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_AttestationPoolElectra_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_ListBeaconBlocks_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_GetChainHead_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_ListBeaconCommittees_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_ListValidatorBalances_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_ListValidators_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_GetValidator_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_GetValidatorActiveSetChanges_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_GetValidatorQueue_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_GetValidatorPerformance_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_ListValidatorAssignments_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_GetValidatorParticipation_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_GetBeaconConfig_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_SubmitAttesterSlashing_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_SubmitAttesterSlashingElectra_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_SubmitProposerSlashing_0 = runtime.ForwardResponseMessage - - forward_BeaconChain_GetIndividualVotes_0 = runtime.ForwardResponseMessage -) diff --git a/proto/prysm/v1alpha1/beacon_chain.proto b/proto/prysm/v1alpha1/beacon_chain.proto index b6d24cb4d5ec..47a1f1111aa9 100644 --- a/proto/prysm/v1alpha1/beacon_chain.proto +++ b/proto/prysm/v1alpha1/beacon_chain.proto @@ -32,893 +32,1093 @@ option php_namespace = "Ethereum\\Eth\\v1alpha1"; // Beacon chain API // -// The beacon chain API can be used to access data relevant to the Ethereum Beacon Chain. +// The beacon chain API can be used to access data relevant to the Ethereum +// Beacon Chain. service BeaconChain { - // Retrieve attestations by block root, slot, or epoch. - // - // The server may return an empty list when no attestations match the given - // filter criteria. This RPC should not return NOT_FOUND. Only one filter - // criteria should be used. This endpoint allows for retrieval of genesis - // information via a boolean query filter. - rpc ListAttestations(ListAttestationsRequest) returns (ListAttestationsResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/attestations" - }; - } - - // Retrieve attestations by block root, slot, or epoch. - // - // The server may return an empty list when no attestations match the given - // filter criteria. This RPC should not return NOT_FOUND. Only one filter - // criteria should be used. This endpoint allows for retrieval of genesis - // information via a boolean query filter. - rpc ListAttestationsElectra(ListAttestationsRequest) returns (ListAttestationsElectraResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/attestations_electra" - }; - } - - // Retrieve indexed attestations by block root, slot, or epoch. - // - // The server may return an empty list when no indexed attestations match the given - // filter criteria. This RPC should not return NOT_FOUND. Only one filter - // criteria should be used. This endpoint allows for retrieval of genesis - // information via a boolean query filter. - rpc ListIndexedAttestations(ListIndexedAttestationsRequest) returns (ListIndexedAttestationsResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/attestations/indexed" - }; - } - - // Retrieve indexed attestations by block root, slot, or epoch. - // - // The server may return an empty list when no indexed attestations match the given - // filter criteria. This RPC should not return NOT_FOUND. Only one filter - // criteria should be used. This endpoint allows for retrieval of genesis - // information via a boolean query filter. - rpc ListIndexedAttestationsElectra(ListIndexedAttestationsRequest) returns (ListIndexedAttestationsElectraResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/attestations/indexed_electra" - }; - } - - // Retrieve attestations from pool. - // - // The server returns a list of attestations that have been seen but not - // yet processed. Pool attestations eventually expire as the slot - // advances, so an attestation missing from this request does not imply - // that it was included in a block. The attestation may have expired. - // Refer to the Ethereum Beacon Chain specification for more details on how - // attestations are processed and when they are no longer valid. - // https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#attestations - rpc AttestationPool(AttestationPoolRequest) returns (AttestationPoolResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/attestations/pool" - }; - } - - // Retrieve attestations from pool. - // - // The server returns a list of attestations that have been seen but not - // yet processed. Pool attestations eventually expire as the slot - // advances, so an attestation missing from this request does not imply - // that it was included in a block. The attestation may have expired. - // Refer to the Ethereum Beacon Chain specification for more details on how - // attestations are processed and when they are no longer valid. - // https://github.com/ethereum/consensus-specs/blob/dev/specs/core/0_beacon-chain.md#attestations - rpc AttestationPoolElectra(AttestationPoolRequest) returns (AttestationPoolElectraResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/attestations/pool_electra" - }; - } - - // Retrieve blocks by root, slot, or epoch. - // - // The server may return multiple blocks in the case that a slot or epoch is - // provided as the filter criteria. The server may return an empty list when - // no blocks in their database match the filter criteria. This RPC should - // not return NOT_FOUND. Only one filter criteria should be used. This endpoint - // allows for retrieval of genesis information via a boolean query filter. - rpc ListBeaconBlocks(ListBlocksRequest) returns (ListBeaconBlocksResponse) { - option (google.api.http) = { - get: "/eth/v1alpha2/beacon/blocks" - }; - } - - // Retrieve information about the head of the beacon chain from the view of - // the beacon chain node. - // - // This includes the head block slot and root as well as information about - // the most recent finalized and justified slots. - // DEPRECATED: This endpoint is superseded by the /eth/v1/beacon Beacon API endpoint - rpc GetChainHead(google.protobuf.Empty) returns (ChainHead) { - option deprecated = true; - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/chainhead" - }; - } - - // Retrieve the beacon chain committees for a given epoch. - // - // If no filter criteria is specified, the response returns - // all beacon committees for the current epoch. The results are paginated by default. - // This endpoint allows for retrieval of genesis information via a boolean query filter. - rpc ListBeaconCommittees(ListCommitteesRequest) returns (BeaconCommittees) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/committees" - }; - } - - // Retrieve validator balances for a given set of public keys at a specific - // epoch in time. This endpoint allows for retrieval of genesis information - // via a boolean query filter. - rpc ListValidatorBalances(ListValidatorBalancesRequest) returns (ValidatorBalances) { - option (google.api.http) = { - get: "/eth/v1alpha1/validators/balances" - }; - } - - // Retrieve the current validator registry. - // - // The request may include an optional historical epoch to retrieve a - // specific validator set in time. This endpoint allows for retrieval of genesis - // information via a boolean query filter. - rpc ListValidators(ListValidatorsRequest) returns (Validators) { - option (google.api.http) = { - get: "/eth/v1alpha1/validators" - }; - } - - // Retrieve information about a specific validator in the registry. - // - // This request may query by validator index or public key. - rpc GetValidator(GetValidatorRequest) returns (Validator) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator" - }; - } - - // Retrieve the active set changes for a given epoch. - // - // This data includes any activations, voluntary exits, and involuntary - // ejections. This endpoint allows for retrieval of genesis - // information via a boolean query filter. - rpc GetValidatorActiveSetChanges(GetValidatorActiveSetChangesRequest) returns (ActiveSetChanges) { - option (google.api.http) = { - get: "/eth/v1alpha1/validators/activesetchanges" - }; - } - - // Retrieve the current validator queue information. - rpc GetValidatorQueue(google.protobuf.Empty) returns (ValidatorQueue) { - option (google.api.http) = { - get: "/eth/v1alpha1/validators/queue" - }; - } - - // GetValidatorPerformance reports a validator's latest balance along with other important - // metrics on rewards and penalties throughout its lifecycle in the beacon chain. - // The request takes in a list of validator public keys and returns a performance report - // for all of them respectively. - rpc GetValidatorPerformance(ValidatorPerformanceRequest) returns (ValidatorPerformanceResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validators/performance" - }; - } - - // Retrieve the validator assignments for a given epoch. - // - // This request may specify optional validator indices or public keys to - // filter validator assignments. This endpoint allows for retrieval of genesis - // information via a boolean query filter. - rpc ListValidatorAssignments(ListValidatorAssignmentsRequest) returns (ValidatorAssignments) { - option (google.api.http) = { - get: "/eth/v1alpha1/validators/assignments" - }; - } - - // Retrieve the validator participation information for a given epoch. - // - // This method returns information about the global participation of - // validator attestations. This endpoint allows for retrieval of genesis - // information via a boolean query filter. - rpc GetValidatorParticipation(GetValidatorParticipationRequest) returns (ValidatorParticipationResponse) { - option deprecated = true; - option (google.api.http) = { - get: "/eth/v1alpha1/validators/participation" - }; - } - - // Retrieve the current configuration parameters of the beacon chain. - rpc GetBeaconConfig(google.protobuf.Empty) returns (BeaconConfig) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/config" - }; - } - - // Submit an attester slashing object to the beacon node. - rpc SubmitAttesterSlashing(AttesterSlashing) returns (SubmitSlashingResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/slashings/attester/submit" - }; - } - - // Submit an attester slashing object to the beacon node. - rpc SubmitAttesterSlashingElectra(AttesterSlashingElectra) returns (SubmitSlashingResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/slashings/attester/submit_electra" - }; - } - - // Submit a proposer slashing object to the beacon node. - rpc SubmitProposerSlashing(ProposerSlashing) returns (SubmitSlashingResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/slashings/proposer/submit" - }; - } - - // Returns a list of validators individual vote status of a given epoch. - rpc GetIndividualVotes(IndividualVotesRequest) returns (IndividualVotesRespond) { - option (google.api.http) = { - get: "/eth/v1alpha1/beacon/individual_votes" - }; - } + // Retrieve attestations by block root, slot, or epoch. + // + // The server may return an empty list when no attestations match the given + // filter criteria. This RPC should not return NOT_FOUND. Only one filter + // criteria should be used. This endpoint allows for retrieval of genesis + // information via a boolean query filter. + rpc ListAttestations(ListAttestationsRequest) + returns (ListAttestationsResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/attestations" + }; + } + + // Retrieve attestations by block root, slot, or epoch. + // + // The server may return an empty list when no attestations match the given + // filter criteria. This RPC should not return NOT_FOUND. Only one filter + // criteria should be used. This endpoint allows for retrieval of genesis + // information via a boolean query filter. + rpc ListAttestationsElectra(ListAttestationsRequest) + returns (ListAttestationsElectraResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/attestations_electra" + }; + } + + // Retrieve indexed attestations by block root, slot, or epoch. + // + // The server may return an empty list when no indexed attestations match the + // given filter criteria. This RPC should not return NOT_FOUND. Only one + // filter criteria should be used. This endpoint allows for retrieval of + // genesis information via a boolean query filter. + rpc ListIndexedAttestations(ListIndexedAttestationsRequest) + returns (ListIndexedAttestationsResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/attestations/indexed" + }; + } + + // Retrieve indexed attestations by block root, slot, or epoch. + // + // The server may return an empty list when no indexed attestations match the + // given filter criteria. This RPC should not return NOT_FOUND. Only one + // filter criteria should be used. This endpoint allows for retrieval of + // genesis information via a boolean query filter. + rpc ListIndexedAttestationsElectra(ListIndexedAttestationsRequest) + returns (ListIndexedAttestationsElectraResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/attestations/indexed_electra" + }; + } + + // Retrieve attestations from pool. + // + // The server returns a list of attestations that have been seen but not + // yet processed. Pool attestations eventually expire as the slot + // advances, so an attestation missing from this request does not imply + // that it was included in a block. The attestation may have expired. + // Refer to the Ethereum Beacon Chain specification for more details on how + // attestations are processed and when they are no longer valid. + // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#attestations + rpc AttestationPool(AttestationPoolRequest) + returns (AttestationPoolResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/attestations/pool" + }; + } + + // Retrieve attestations from pool. + // + // The server returns a list of attestations that have been seen but not + // yet processed. Pool attestations eventually expire as the slot + // advances, so an attestation missing from this request does not imply + // that it was included in a block. The attestation may have expired. + // Refer to the Ethereum Beacon Chain specification for more details on how + // attestations are processed and when they are no longer valid. + // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#attestations + rpc AttestationPoolElectra(AttestationPoolRequest) + returns (AttestationPoolElectraResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/attestations/pool_electra" + }; + } + + // Retrieve blocks by root, slot, or epoch. + // + // The server may return multiple blocks in the case that a slot or epoch is + // provided as the filter criteria. The server may return an empty list when + // no blocks in their database match the filter criteria. This RPC should + // not return NOT_FOUND. Only one filter criteria should be used. This + // endpoint allows for retrieval of genesis information via a boolean query + // filter. + rpc ListBeaconBlocks(ListBlocksRequest) returns (ListBeaconBlocksResponse) { + option (google.api.http) = { + get : "/eth/v1alpha2/beacon/blocks" + }; + } + + // Retrieve information about the head of the beacon chain from the view of + // the beacon chain node. + // + // This includes the head block slot and root as well as information about + // the most recent finalized and justified slots. + // DEPRECATED: This endpoint is superseded by the /eth/v1/beacon Beacon API + // endpoint + rpc GetChainHead(google.protobuf.Empty) returns (ChainHead) { + option deprecated = true; + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/chainhead" + }; + } + + // Retrieve the beacon chain committees for a given epoch. + // + // If no filter criteria is specified, the response returns + // all beacon committees for the current epoch. The results are paginated by + // default. This endpoint allows for retrieval of genesis information via a + // boolean query filter. + rpc ListBeaconCommittees(ListCommitteesRequest) returns (BeaconCommittees) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/committees" + }; + } + + // Retrieve validator balances for a given set of public keys at a specific + // epoch in time. This endpoint allows for retrieval of genesis information + // via a boolean query filter. + rpc ListValidatorBalances(ListValidatorBalancesRequest) + returns (ValidatorBalances) { + option (google.api.http) = { + get : "/eth/v1alpha1/validators/balances" + }; + } + + // Retrieve the current validator registry. + // + // The request may include an optional historical epoch to retrieve a + // specific validator set in time. This endpoint allows for retrieval of + // genesis information via a boolean query filter. + rpc ListValidators(ListValidatorsRequest) returns (Validators) { + option (google.api.http) = { + get : "/eth/v1alpha1/validators" + }; + } + + // Retrieve information about a specific validator in the registry. + // + // This request may query by validator index or public key. + rpc GetValidator(GetValidatorRequest) returns (Validator) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator" + }; + } + + // Retrieve the active set changes for a given epoch. + // + // This data includes any activations, voluntary exits, and involuntary + // ejections. This endpoint allows for retrieval of genesis + // information via a boolean query filter. + rpc GetValidatorActiveSetChanges(GetValidatorActiveSetChangesRequest) + returns (ActiveSetChanges) { + option (google.api.http) = { + get : "/eth/v1alpha1/validators/activesetchanges" + }; + } + + // Retrieve the current validator queue information. + rpc GetValidatorQueue(google.protobuf.Empty) returns (ValidatorQueue) { + option (google.api.http) = { + get : "/eth/v1alpha1/validators/queue" + }; + } + + // GetValidatorPerformance reports a validator's latest balance along with + // other important metrics on rewards and penalties throughout its lifecycle + // in the beacon chain. The request takes in a list of validator public keys + // and returns a performance report for all of them respectively. + rpc GetValidatorPerformance(ValidatorPerformanceRequest) + returns (ValidatorPerformanceResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validators/performance" + }; + } + + // Retrieve the validator assignments for a given epoch. + // + // This request may specify optional validator indices or public keys to + // filter validator assignments. This endpoint allows for retrieval of genesis + // information via a boolean query filter. + rpc ListValidatorAssignments(ListValidatorAssignmentsRequest) + returns (ValidatorAssignments) { + option (google.api.http) = { + get : "/eth/v1alpha1/validators/assignments" + }; + } + + // Retrieve the validator participation information for a given epoch. + // + // This method returns information about the global participation of + // validator attestations. This endpoint allows for retrieval of genesis + // information via a boolean query filter. + rpc GetValidatorParticipation(GetValidatorParticipationRequest) + returns (ValidatorParticipationResponse) { + option deprecated = true; + option (google.api.http) = { + get : "/eth/v1alpha1/validators/participation" + }; + } + + // Retrieve the current configuration parameters of the beacon chain. + rpc GetBeaconConfig(google.protobuf.Empty) returns (BeaconConfig) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/config" + }; + } + + // Submit an attester slashing object to the beacon node. + rpc SubmitAttesterSlashing(AttesterSlashing) + returns (SubmitSlashingResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/slashings/attester/submit" + }; + } + + // Submit an attester slashing object to the beacon node. + rpc SubmitAttesterSlashingElectra(AttesterSlashingElectra) + returns (SubmitSlashingResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/slashings/attester/submit_electra" + }; + } + + // Submit a proposer slashing object to the beacon node. + rpc SubmitProposerSlashing(ProposerSlashing) + returns (SubmitSlashingResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/slashings/proposer/submit" + }; + } + + // Returns a list of validators individual vote status of a given epoch. + rpc GetIndividualVotes(IndividualVotesRequest) + returns (IndividualVotesRespond) { + option (google.api.http) = { + get : "/eth/v1alpha1/beacon/individual_votes" + }; + } } // Request for indexed attestations by target epoch. message ListIndexedAttestationsRequest { - oneof query_filter { - // Retrieve attestations by epoch processed. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Optional criteria to retrieve genesis epoch attestations. - bool genesis_epoch = 2; - } - - // The maximum number of IndexedAttestations to return in the response. - // This field is optional. - int32 page_size = 3; - - // A pagination token returned from a previous call to `ListIndexedAttestations` - // that indicates where this listing should continue from. - // This field is optional. - string page_token = 4; + oneof query_filter { + // Retrieve attestations by epoch processed. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Optional criteria to retrieve genesis epoch attestations. + bool genesis_epoch = 2; + } + + // The maximum number of IndexedAttestations to return in the response. + // This field is optional. + int32 page_size = 3; + + // A pagination token returned from a previous call to + // `ListIndexedAttestations` that indicates where this listing should continue + // from. This field is optional. + string page_token = 4; } // Request for attestations. message ListAttestationsRequest { - // TODO(preston): Test oneof with gRPC gateway. - - oneof query_filter { - // Filter attestations by epoch processed. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - // Optional criteria to retrieve attestations from 0 epoch. - bool genesis_epoch = 2; - } - - // The maximum number of Attestations to return in the response. - // This field is optional. - int32 page_size = 3; - - // A pagination token returned from a previous call to `ListAttestations` - // that indicates where this listing should continue from. - // This field is optional. - string page_token = 4; + oneof query_filter { + // Filter attestations by epoch processed. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Optional criteria to retrieve attestations from 0 epoch. + bool genesis_epoch = 2; + } + + // The maximum number of Attestations to return in the response. + // This field is optional. + int32 page_size = 3; + + // A pagination token returned from a previous call to `ListAttestations` + // that indicates where this listing should continue from. + // This field is optional. + string page_token = 4; } message ListAttestationsResponse { - repeated Attestation attestations = 1; + repeated Attestation attestations = 1; - // A pagination token returned from a previous call to `ListAttestations` - // that indicates from where listing should continue. - // This field is optional. - string next_page_token = 2; + // A pagination token returned from a previous call to `ListAttestations` + // that indicates from where listing should continue. + // This field is optional. + string next_page_token = 2; - // Total count of Attestations matching the request filter. - int32 total_size = 3; + // Total count of Attestations matching the request filter. + int32 total_size = 3; } message ListAttestationsElectraResponse { - repeated AttestationElectra attestations = 1; + repeated AttestationElectra attestations = 1; - // A pagination token returned from a previous call to `ListAttestations` - // that indicates from where listing should continue. - // This field is optional. - string next_page_token = 2; + // A pagination token returned from a previous call to `ListAttestations` + // that indicates from where listing should continue. + // This field is optional. + string next_page_token = 2; - // Total count of Attestations matching the request filter. - int32 total_size = 3; + // Total count of Attestations matching the request filter. + int32 total_size = 3; } message ListIndexedAttestationsResponse { - repeated IndexedAttestation indexed_attestations = 1; + repeated IndexedAttestation indexed_attestations = 1; - // A pagination token returned from a previous call to `ListIndexedAttestations` - // that indicates from where listing should continue. - // This field is optional. - string next_page_token = 2; + // A pagination token returned from a previous call to + // `ListIndexedAttestations` that indicates from where listing should + // continue. This field is optional. + string next_page_token = 2; - // Total count of Attestations matching the request filter. - int32 total_size = 3; + // Total count of Attestations matching the request filter. + int32 total_size = 3; } message ListIndexedAttestationsElectraResponse { - repeated IndexedAttestationElectra indexed_attestations = 1; + repeated IndexedAttestationElectra indexed_attestations = 1; - // A pagination token returned from a previous call to `ListIndexedAttestations` - // that indicates from where listing should continue. - // This field is optional. - string next_page_token = 2; + // A pagination token returned from a previous call to + // `ListIndexedAttestations` that indicates from where listing should + // continue. This field is optional. + string next_page_token = 2; - // Total count of Attestations matching the request filter. - int32 total_size = 3; + // Total count of Attestations matching the request filter. + int32 total_size = 3; } message ListBlocksRequest { - oneof query_filter { - // Block root filter to return a single block. - bytes root = 1; - - // Slot to lookup a block. If the slot is not yet finalized, this - // criteria may yield multiple valid blocks if the node has seen blocks - // from another fork. - uint64 slot = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // The epoch number for which to retrieve blocks. If specified, this - // will return all blocks found within the span of the specified epoch. - uint64 epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Optional criteria to retrieve genesis block. - bool genesis = 4; - } - - // The maximum number of Blocks to return in the response. - // This field is optional. - int32 page_size = 5; - - // A pagination token returned from a previous call to `ListBlocks` - // that indicates where this listing should continue from. - // This field is optional. - string page_token = 6; + oneof query_filter { + // Block root filter to return a single block. + bytes root = 1; + + // Slot to lookup a block. If the slot is not yet finalized, this + // criteria may yield multiple valid blocks if the node has seen blocks + // from another fork. + uint64 slot = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // The epoch number for which to retrieve blocks. If specified, this + // will return all blocks found within the span of the specified epoch. + uint64 epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Optional criteria to retrieve genesis block. + bool genesis = 4; + } + + // The maximum number of Blocks to return in the response. + // This field is optional. + int32 page_size = 5; + + // A pagination token returned from a previous call to `ListBlocks` + // that indicates where this listing should continue from. + // This field is optional. + string page_token = 6; } message ListBeaconBlocksResponse { - repeated BeaconBlockContainer block_containers = 1; + repeated BeaconBlockContainer block_containers = 1; - // A pagination token returned from a previous call to `ListBeaconBlocks` - // that indicates from where listing should continue. - // This field is optional. - string next_page_token = 2; + // A pagination token returned from a previous call to `ListBeaconBlocks` + // that indicates from where listing should continue. + // This field is optional. + string next_page_token = 2; - // Total count of Blocks matching the request filter. - int32 total_size = 3; + // Total count of Blocks matching the request filter. + int32 total_size = 3; } // A container that contains both the beacon block, its corresponding root, and -// whether or not it is canonical in the chain. This message returns a oneof field -// representing either a phase 0 beacon block or an Altair beacon block. +// whether or not it is canonical in the chain. This message returns a oneof +// field representing either a phase 0 beacon block or an Altair beacon block. message BeaconBlockContainer { - // 32 byte merkle tree root of contained beacon block. - bytes block_root = 1; + // 32 byte merkle tree root of contained beacon block. + bytes block_root = 1; + + // Boolean indicating whether the block is canonical. + bool canonical = 2; - // Boolean indicating whether the block is canonical. - bool canonical = 2; + // The desired block to be returned. + oneof block { + // Representing a Phase0 block. + SignedBeaconBlock phase0_block = 3; - // The desired block to be returned. - oneof block { - // Representing a Phase0 block. - SignedBeaconBlock phase0_block = 3; + // Representing an Altair block. + SignedBeaconBlockAltair altair_block = 4; - // Representing an Altair block. - SignedBeaconBlockAltair altair_block = 4; + // Representing a Bellatrix block. + SignedBeaconBlockBellatrix bellatrix_block = 5; - // Representing a Bellatrix block. - SignedBeaconBlockBellatrix bellatrix_block = 5; + // Representing a blinded Bellatrix block. + SignedBlindedBeaconBlockBellatrix blinded_bellatrix_block = 6; - // Representing a blinded Bellatrix block. - SignedBlindedBeaconBlockBellatrix blinded_bellatrix_block = 6; + // Representing a Capella block. + SignedBeaconBlockCapella capella_block = 7; - // Representing a Capella block. - SignedBeaconBlockCapella capella_block = 7; + // Representing a blinded Capella block. + SignedBlindedBeaconBlockCapella blinded_capella_block = 8; - // Representing a blinded Capella block. - SignedBlindedBeaconBlockCapella blinded_capella_block = 8; + // Representing a Deneb block. + SignedBeaconBlockDeneb deneb_block = 9; - // Representing a Deneb block. - SignedBeaconBlockDeneb deneb_block = 9; + // Representing a blinded Deneb block. + SignedBlindedBeaconBlockDeneb blinded_deneb_block = 10; - // Representing a blinded Deneb block. - SignedBlindedBeaconBlockDeneb blinded_deneb_block = 10; + // Representing an Electra block. + SignedBeaconBlockElectra electra_block = 11; - // Representing an Electra block. - SignedBeaconBlockElectra electra_block = 11; + // Representing a blinded Electra block. + SignedBlindedBeaconBlockElectra blinded_electra_block = 12; - // Representing a blinded Electra block. - SignedBlindedBeaconBlockElectra blinded_electra_block = 12; - } + // Representing a Fulu block. + SignedBeaconBlockFulu fulu_block = 13; + + // Representing a blinded Fulu block. + SignedBlindedBeaconBlockFulu blinded_fulu_block = 14; + } } // Information about the head of the beacon chain. message ChainHead { - // Slot of the head block. - uint64 head_slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Epoch of the head block. - uint64 head_epoch = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // 32 byte merkle tree root of the canonical head block in the beacon node. - bytes head_block_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Most recent slot that contains the finalized block. - uint64 finalized_slot = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Epoch of the finalized block. - uint64 finalized_epoch = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Most recent 32 byte finalized block root. - bytes finalized_block_root = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Most recent slot that contains the justified block. - uint64 justified_slot = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Epoch of the justified block. - uint64 justified_epoch = 8 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Most recent 32 byte justified block root. - bytes justified_block_root = 9 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Most recent slot that contains the previous justified block. - uint64 previous_justified_slot = 10 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Epoch of the previous justified block. - uint64 previous_justified_epoch = 11 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Previous 32 byte justified block root. - bytes previous_justified_block_root = 12 [(ethereum.eth.ext.ssz_size) = "32"]; - - // Optimistic status of the current head - bool optimistic_status = 13; + // Slot of the head block. + uint64 head_slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Epoch of the head block. + uint64 head_epoch = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // 32 byte merkle tree root of the canonical head block in the beacon node. + bytes head_block_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // Most recent slot that contains the finalized block. + uint64 finalized_slot = 4 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Epoch of the finalized block. + uint64 finalized_epoch = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Most recent 32 byte finalized block root. + bytes finalized_block_root = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // Most recent slot that contains the justified block. + uint64 justified_slot = 7 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Epoch of the justified block. + uint64 justified_epoch = 8 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Most recent 32 byte justified block root. + bytes justified_block_root = 9 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // Most recent slot that contains the previous justified block. + uint64 previous_justified_slot = 10 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Epoch of the previous justified block. + uint64 previous_justified_epoch = 11 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Previous 32 byte justified block root. + bytes previous_justified_block_root = 12 + [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // Optimistic status of the current head + bool optimistic_status = 13; } message ListCommitteesRequest { - oneof query_filter { - // Optional criteria to retrieve data at a specific epoch. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Optional criteria to retrieve genesis data. - bool genesis = 2; - } + oneof query_filter { + // Optional criteria to retrieve data at a specific epoch. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Optional criteria to retrieve genesis data. + bool genesis = 2; + } } message BeaconCommittees { - message CommitteeItem { - // A committee is a list of validator indices participating in consensus at a slot. - repeated uint64 validator_indices = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - } - - message CommitteesList { - // A list of committees. - repeated CommitteeItem committees = 1; - } - - // The epoch for which the committees in the response belong to. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // A map of validator committees by slot. - map committees = 2; - - // The number of active validators at the given epoch. - uint64 active_validator_count = 3; + message CommitteeItem { + // A committee is a list of validator indices participating in consensus at + // a slot. + repeated uint64 validator_indices = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + } + + message CommitteesList { + // A list of committees. + repeated CommitteeItem committees = 1; + } + + // The epoch for which the committees in the response belong to. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // A map of validator committees by slot. + map committees = 2; + + // The number of active validators at the given epoch. + uint64 active_validator_count = 3; } message ListValidatorBalancesRequest { - oneof query_filter { - // Optional criteria to retrieve balances at a specific epoch. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Optional criteria to retrieve the genesis list of balances. - bool genesis = 2; - } - - // Validator 48 byte BLS public keys to filter validators for the given - // epoch. - repeated bytes public_keys = 3 [(ethereum.eth.ext.ssz_size) = "?,48"]; - // Validator indices to filter validators for the given epoch. - repeated uint64 indices = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // The maximum number of Validators to return in the response. - // This field is optional. - int32 page_size = 5; - - // A pagination token returned from a previous call to `GetValidators` - // that indicates where this listing should continue from. - // This field is optional. - string page_token = 6; + oneof query_filter { + // Optional criteria to retrieve balances at a specific epoch. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Optional criteria to retrieve the genesis list of balances. + bool genesis = 2; + } + + // Validator 48 byte BLS public keys to filter validators for the given + // epoch. + repeated bytes public_keys = 3 [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + // Validator indices to filter validators for the given epoch. + repeated uint64 indices = 4 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // The maximum number of Validators to return in the response. + // This field is optional. + int32 page_size = 5; + + // A pagination token returned from a previous call to `GetValidators` + // that indicates where this listing should continue from. + // This field is optional. + string page_token = 6; } message ValidatorBalances { - // Epoch which the state was considered to determine the validator balances. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // Epoch which the state was considered to determine the validator balances. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; - message Balance { - // Validator's 48 byte BLS public key. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48"]; + message Balance { + // Validator's 48 byte BLS public key. + bytes public_key = 1 [ (ethereum.eth.ext.ssz_size) = "48" ]; - // Validator's index in the validator set. - uint64 index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator's index in the validator set. + uint64 index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; - // Validator's balance in gwei. - uint64 balance = 3; + // Validator's balance in gwei. + uint64 balance = 3; - // Validator's status, UNKNOWN if not found. - string status = 4; - } + // Validator's status, UNKNOWN if not found. + string status = 4; + } - repeated Balance balances = 2; + repeated Balance balances = 2; - // A pagination token returned from a previous call to `GetListValidatorBalances` - // that indicates from where listing should continue. - string next_page_token = 3; + // A pagination token returned from a previous call to + // `GetListValidatorBalances` that indicates from where listing should + // continue. + string next_page_token = 3; - // Total count of items matching the request filter. - int32 total_size = 4; + // Total count of items matching the request filter. + int32 total_size = 4; } message ListValidatorsRequest { - oneof query_filter { - // Optional criteria to retrieve validators at a specific epoch. - // Omitting this field or setting it to zero will retrieve a response - // with the current active validator set. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Optional criteria to retrieve the genesis set of validators. - bool genesis = 2; - } - - // Specify whether or not you want to retrieve only active validators. - bool active = 3; - - // The maximum number of Validators to return in the response. - // This field is optional. - int32 page_size = 4; - - // A pagination token returned from a previous call to `GetValidators` - // that indicates where this listing should continue from. - // This field is optional. - string page_token = 5; - - // Specify which validators you would like to retrieve by their public keys. - // This field is optional. - repeated bytes public_keys = 6; - - // Specify which validators you would like to retrieve by their indices. - // This field is optional. - repeated uint64 indices = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + oneof query_filter { + // Optional criteria to retrieve validators at a specific epoch. + // Omitting this field or setting it to zero will retrieve a response + // with the current active validator set. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Optional criteria to retrieve the genesis set of validators. + bool genesis = 2; + } + + // Specify whether or not you want to retrieve only active validators. + bool active = 3; + + // The maximum number of Validators to return in the response. + // This field is optional. + int32 page_size = 4; + + // A pagination token returned from a previous call to `GetValidators` + // that indicates where this listing should continue from. + // This field is optional. + string page_token = 5; + + // Specify which validators you would like to retrieve by their public keys. + // This field is optional. + repeated bytes public_keys = 6; + + // Specify which validators you would like to retrieve by their indices. + // This field is optional. + repeated uint64 indices = 7 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } message GetValidatorRequest { - oneof query_filter { - // Validator index in the registry. - uint64 index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 48 byte validator public key. - bytes public_key = 2 [(ethereum.eth.ext.ssz_size) = "48"]; - } + oneof query_filter { + // Validator index in the registry. + uint64 index = 1 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // 48 byte validator public key. + bytes public_key = 2 [ (ethereum.eth.ext.ssz_size) = "48" ]; + } } message Validators { - // Epoch which the state was considered to determine the active validator - // set. This field is not optional. Zero value epoch indicates the validator - // set is from the Ethereum proof of stake genesis set. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - message ValidatorContainer { - uint64 index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - Validator validator = 2; - } - - repeated ValidatorContainer validator_list = 2; - - // A pagination token returned from a previous call to `GetValidators` - // that indicates from where listing should continue. - // This field is optional. - string next_page_token = 3; - - // Total count of Validators matching the request filter. - int32 total_size = 4; + // Epoch which the state was considered to determine the active validator + // set. This field is not optional. Zero value epoch indicates the validator + // set is from the Ethereum proof of stake genesis set. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + message ValidatorContainer { + uint64 index = 1 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + Validator validator = 2; + } + + repeated ValidatorContainer validator_list = 2; + + // A pagination token returned from a previous call to `GetValidators` + // that indicates from where listing should continue. + // This field is optional. + string next_page_token = 3; + + // Total count of Validators matching the request filter. + int32 total_size = 4; } message GetValidatorActiveSetChangesRequest { - oneof query_filter { - // Optional criteria to retrieve balances at a specific epoch. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Optional criteria to retrieve the genesis list of balances. - bool genesis = 2; - } + oneof query_filter { + // Optional criteria to retrieve balances at a specific epoch. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Optional criteria to retrieve the genesis list of balances. + bool genesis = 2; + } } message ActiveSetChanges { - // Epoch which the state was considered to determine the active validator - // set. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // 48 byte validator public keys that have been activated in the given epoch. - repeated bytes activated_public_keys = 2 [(ethereum.eth.ext.ssz_size) = "?,48"]; - - // Indices of validators activated in the given epoch. - repeated uint64 activated_indices = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 48 byte validator public keys that have been voluntarily exited in the given epoch. - repeated bytes exited_public_keys = 4 [(ethereum.eth.ext.ssz_size) = "?,48"]; - - // Indices of validators exited in the given epoch. - repeated uint64 exited_indices = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 48 byte validator public keys that have been slashed in the given epoch. - repeated bytes slashed_public_keys = 6 [(ethereum.eth.ext.ssz_size) = "?,48"]; - - // Indices of validators slashed in the given epoch. - repeated uint64 slashed_indices = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // 48 byte validator public keys that have been involuntarily ejected in this epoch. - repeated bytes ejected_public_keys = 8 [(ethereum.eth.ext.ssz_size) = "?,48"]; - - // Indices of validators ejected in the given epoch. - repeated uint64 ejected_indices = 9 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Epoch which the state was considered to determine the active validator + // set. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // 48 byte validator public keys that have been activated in the given epoch. + repeated bytes activated_public_keys = 2 + [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + + // Indices of validators activated in the given epoch. + repeated uint64 activated_indices = 3 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // 48 byte validator public keys that have been voluntarily exited in the + // given epoch. + repeated bytes exited_public_keys = 4 + [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + + // Indices of validators exited in the given epoch. + repeated uint64 exited_indices = 5 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // 48 byte validator public keys that have been slashed in the given epoch. + repeated bytes slashed_public_keys = 6 + [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + + // Indices of validators slashed in the given epoch. + repeated uint64 slashed_indices = 7 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // 48 byte validator public keys that have been involuntarily ejected in this + // epoch. + repeated bytes ejected_public_keys = 8 + [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + + // Indices of validators ejected in the given epoch. + repeated uint64 ejected_indices = 9 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } message ValidatorPerformanceRequest { - // A list of 48 byte validator public keys. - repeated bytes public_keys = 1 [deprecated = true]; - // A list of validator indices to retrieve performance by their indices. - repeated uint64 indices = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // A list of 48 byte validator public keys. + repeated bytes public_keys = 1 [ deprecated = true ]; + // A list of validator indices to retrieve performance by their indices. + repeated uint64 indices = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } message ValidatorPerformanceResponse { - // A list of validator effective balances mapped 1-to-1 with the request's - // public keys. - repeated uint64 current_effective_balances = 1; - // The slot of when validator's attestation got included in the chain at previous epoch, the slot - // is mapped 1-to-1 with the request's public keys. - // Deprecated: This field can no longer be fetched from the beacon state after the Altair hard fork. - repeated uint64 inclusion_slots = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot", deprecated = true]; - // The distance of when validator submitted and got included in the chain, the distance - // is mapped 1-to-1 with the request's public keys. - // Deprecated: This field can no longer be fetched from the beacon state after the Altair hard fork. - repeated uint64 inclusion_distances = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot", deprecated = true]; - // Whether the list of validator recently correctly voted for source at previous epoch, the result - // is mapped 1-to-1 with the request's public keys. - repeated bool correctly_voted_source = 4; - // Whether the list of validator recently correctly voted for target at previous epoch, the result - // is mapped 1-to-1 with the request's public keys. - repeated bool correctly_voted_target = 5; - // Whether the list of validator recently correctly voted for head at previous epoch, the result - // is mapped 1-to-1 with the request's public keys. - repeated bool correctly_voted_head = 6; - // The balance of validators before epoch transition, the balance is mapped 1-to-1 with the requests' - // public keys. - repeated uint64 balances_before_epoch_transition = 7; - // The balance of validators after epoch transition, the balance is mapped 1-to-1 with the requests' - // public keys. - repeated uint64 balances_after_epoch_transition = 8; - // The total number of validators from the request not found in - // in the beacon chain. - repeated bytes missing_validators = 9; - // The average active validator balance in the beacon chain. - float average_active_validator_balance = 10; - // The public keys in the order they are in of the response. - repeated bytes public_keys = 11 [(ethereum.eth.ext.ssz_size) = "?,48"]; - // The inactivity score of the validator tracks validator participation. [New in Altair] - repeated uint64 inactivity_scores = 12; -} - -// DEPRECATED: Prysm Web UI and associated endpoints will be fully removed in a future hard fork. -message ValidatorQueue { - option deprecated = true; - // The amount of ether in gwei allowed to enter or exit the active - // validator set. - uint64 churn_limit = 1; - - // Ordered list of 48 byte public keys awaiting activation. 0th index is the - // next key to be processed. - repeated bytes activation_public_keys = 2 [(ethereum.eth.ext.ssz_size) = "?,48", deprecated = true]; - - // Ordered list of public keys awaiting exit. 0th index is the next key to - // be processed. - repeated bytes exit_public_keys = 3 [(ethereum.eth.ext.ssz_size) = "?,48", deprecated = true]; - - // Ordered list of validator indices awaiting activation. 0th item in the list is the - // next validator index to be processed. - repeated uint64 activation_validator_indices = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // A list of validator effective balances mapped 1-to-1 with the request's + // public keys. + repeated uint64 current_effective_balances = 1; + // The slot of when validator's attestation got included in the chain at + // previous epoch, the slot is mapped 1-to-1 with the request's public keys. + // Deprecated: This field can no longer be fetched from the beacon state after + // the Altair hard fork. + repeated uint64 inclusion_slots = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot", + deprecated = true + ]; + // The distance of when validator submitted and got included in the chain, the + // distance is mapped 1-to-1 with the request's public keys. Deprecated: This + // field can no longer be fetched from the beacon state after the Altair hard + // fork. + repeated uint64 inclusion_distances = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot", + deprecated = true + ]; + // Whether the list of validator recently correctly voted for source at + // previous epoch, the result is mapped 1-to-1 with the request's public keys. + repeated bool correctly_voted_source = 4; + // Whether the list of validator recently correctly voted for target at + // previous epoch, the result is mapped 1-to-1 with the request's public keys. + repeated bool correctly_voted_target = 5; + // Whether the list of validator recently correctly voted for head at previous + // epoch, the result is mapped 1-to-1 with the request's public keys. + repeated bool correctly_voted_head = 6; + // The balance of validators before epoch transition, the balance is mapped + // 1-to-1 with the requests' public keys. + repeated uint64 balances_before_epoch_transition = 7; + // The balance of validators after epoch transition, the balance is mapped + // 1-to-1 with the requests' public keys. + repeated uint64 balances_after_epoch_transition = 8; + // The total number of validators from the request not found in + // in the beacon chain. + repeated bytes missing_validators = 9; + // The average active validator balance in the beacon chain. + float average_active_validator_balance = 10; + // The public keys in the order they are in of the response. + repeated bytes public_keys = 11 [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + // The inactivity score of the validator tracks validator participation. [New + // in Altair] + repeated uint64 inactivity_scores = 12; +} - // Ordered list of validator indices awaiting exit. 0th item in the list is the - // next validator index to be processed. - repeated uint64 exit_validator_indices = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; +// DEPRECATED: Prysm Web UI and associated endpoints will be fully removed in a +// future hard fork. +message ValidatorQueue { + option deprecated = true; + // The amount of ether in gwei allowed to enter or exit the active + // validator set. + uint64 churn_limit = 1; + + // Ordered list of 48 byte public keys awaiting activation. 0th index is the + // next key to be processed. + repeated bytes activation_public_keys = 2 + [ (ethereum.eth.ext.ssz_size) = "?,48", deprecated = true ]; + + // Ordered list of public keys awaiting exit. 0th index is the next key to + // be processed. + repeated bytes exit_public_keys = 3 + [ (ethereum.eth.ext.ssz_size) = "?,48", deprecated = true ]; + + // Ordered list of validator indices awaiting activation. 0th item in the list + // is the next validator index to be processed. + repeated uint64 activation_validator_indices = 4 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // Ordered list of validator indices awaiting exit. 0th item in the list is + // the next validator index to be processed. + repeated uint64 exit_validator_indices = 5 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } message ListValidatorAssignmentsRequest { - oneof query_filter { - // Epoch to validator assignments for. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Whether or not to query for the genesis information. - bool genesis = 2; - } - // 48 byte validator public keys to filter assignments for the given epoch. - repeated bytes public_keys = 3 [(ethereum.eth.ext.ssz_size) = "?,48"]; - // Validator indices to filter assignments for the given epoch. - repeated uint64 indices = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // The maximum number of ValidatorAssignments to return in the response. - // This field is optional. - int32 page_size = 5; - - // A pagination token returned from a previous call to `ListValidatorAssignments` - // that indicates where this listing should continue from. - // This field is optional. - string page_token = 6; + oneof query_filter { + // Epoch to validator assignments for. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Whether or not to query for the genesis information. + bool genesis = 2; + } + // 48 byte validator public keys to filter assignments for the given epoch. + repeated bytes public_keys = 3 [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + // Validator indices to filter assignments for the given epoch. + repeated uint64 indices = 4 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // The maximum number of ValidatorAssignments to return in the response. + // This field is optional. + int32 page_size = 5; + + // A pagination token returned from a previous call to + // `ListValidatorAssignments` that indicates where this listing should + // continue from. This field is optional. + string page_token = 6; } message ValidatorAssignments { - message CommitteeAssignment { - // Beacon committees are responsible for crosslinking committee data back to the beacon chain, - // they also attest and produce beacon chain blocks. This is a list of validator indices that - // are in the same committee as requested validator, everyone in the committee is assigned to the - // same slot and same committee. - repeated uint64 beacon_committees = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // Committee index represents the committee of validator that's in. - uint64 committee_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; - - // Beacon chain slot in which the validator must perform its assigned - // duty as an attester. - uint64 attester_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // Beacon chain slots in which the validator must perform its assigned - // duty as a proposer. - repeated uint64 proposer_slots = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // 48 byte BLS public key. - bytes public_key = 5 [(ethereum.eth.ext.ssz_size) = "48", deprecated = true]; - - // Validator index in the beacon state. - uint64 validator_index = 6 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - } - - // The epoch for which this set of validator assignments is valid. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - repeated CommitteeAssignment assignments = 2; - - // A pagination token returned from a previous call to `ListValidatorAssignmentsRequest` - // that indicates where this listing should continue from. - // This field is optional. - string next_page_token = 3; - - // Total count of CommitteeAssignments matching the request filter. - int32 total_size = 4; + message CommitteeAssignment { + // Beacon committees are responsible for crosslinking committee data back to + // the beacon chain, they also attest and produce beacon chain blocks. This + // is a list of validator indices that are in the same committee as + // requested validator, everyone in the committee is assigned to the same + // slot and same committee. + repeated uint64 beacon_committees = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // Committee index represents the committee of validator that's in. + uint64 committee_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.CommitteeIndex" ]; + + // Beacon chain slot in which the validator must perform its assigned + // duty as an attester. + uint64 attester_slot = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // Beacon chain slots in which the validator must perform its assigned + // duty as a proposer. + repeated uint64 proposer_slots = 4 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + + // 48 byte BLS public key. + bytes public_key = 5 + [ (ethereum.eth.ext.ssz_size) = "48", deprecated = true ]; + + // Validator index in the beacon state. + uint64 validator_index = 6 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + } + + // The epoch for which this set of validator assignments is valid. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + repeated CommitteeAssignment assignments = 2; + + // A pagination token returned from a previous call to + // `ListValidatorAssignmentsRequest` that indicates where this listing should + // continue from. This field is optional. + string next_page_token = 3; + + // Total count of CommitteeAssignments matching the request filter. + int32 total_size = 4; } -// DEPRECATED: Prysm Web UI and associated endpoints will be fully removed in a future hard fork. +// DEPRECATED: Prysm Web UI and associated endpoints will be fully removed in a +// future hard fork. message GetValidatorParticipationRequest { - option deprecated = true; - oneof query_filter { - // Epoch to request participation information. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Whether or not to query for the genesis information. - bool genesis = 2; - } + option deprecated = true; + oneof query_filter { + // Epoch to request participation information. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Whether or not to query for the genesis information. + bool genesis = 2; + } } message ValidatorParticipationResponse { - option deprecated = true; - // Epoch which this message is applicable. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Whether or not epoch has been finalized. - bool finalized = 2; - - // The actual validator participation metrics. - ValidatorParticipation participation = 3; + option deprecated = true; + // Epoch which this message is applicable. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Whether or not epoch has been finalized. + bool finalized = 2; + + // The actual validator participation metrics. + ValidatorParticipation participation = 3; } message AttestationPoolRequest { - // The maximum number of objects to return in the response. - // This field is optional. - int32 page_size = 1; - - // A pagination token returned from a previous call - // that indicates where this listing should continue from. - // This field is optional. - string page_token = 2; + // The maximum number of objects to return in the response. + // This field is optional. + int32 page_size = 1; + + // A pagination token returned from a previous call + // that indicates where this listing should continue from. + // This field is optional. + string page_token = 2; } message AttestationPoolResponse { - // List of attestations currently in the pool of the beacon chain. - repeated Attestation attestations = 1; + // List of attestations currently in the pool of the beacon chain. + repeated Attestation attestations = 1; - // A pagination token returned from a previous call - // that indicates where this listing should continue from. - // This field is optional. - string next_page_token = 2; + // A pagination token returned from a previous call + // that indicates where this listing should continue from. + // This field is optional. + string next_page_token = 2; - // Total count of objects matching the request filter. - int32 total_size = 3; + // Total count of objects matching the request filter. + int32 total_size = 3; } message AttestationPoolElectraResponse { - // List of attestations currently in the pool of the beacon chain. - repeated AttestationElectra attestations = 1; + // List of attestations currently in the pool of the beacon chain. + repeated AttestationElectra attestations = 1; - // A pagination token returned from a previous call - // that indicates where this listing should continue from. - // This field is optional. - string next_page_token = 2; + // A pagination token returned from a previous call + // that indicates where this listing should continue from. + // This field is optional. + string next_page_token = 2; - // Total count of objects matching the request filter. - int32 total_size = 3; + // Total count of objects matching the request filter. + int32 total_size = 3; } // Information about the configuration parameters of the beacon node, such // as the slots per epoch, slots per eth1 voting period, and more. -message BeaconConfig { - map config = 1; -} +message BeaconConfig { map config = 1; } message SubmitSlashingResponse { - // Indices of the validators to be slashed by the submitted - // proposer/attester slashing object. - repeated uint64 slashed_indices = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Indices of the validators to be slashed by the submitted + // proposer/attester slashing object. + repeated uint64 slashed_indices = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } message IndividualVotesRequest { - // Epoch of the request. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - // Validator 48 byte BLS public keys to filter validators for the given epoch. - repeated bytes public_keys = 2; - // Validator indices to filter validators for the given epoch. - repeated uint64 indices = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Epoch of the request. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + // Validator 48 byte BLS public keys to filter validators for the given epoch. + repeated bytes public_keys = 2; + // Validator indices to filter validators for the given epoch. + repeated uint64 indices = 3 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } message IndividualVotesRespond { - message IndividualVote { - // The epoch of the vote status request. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - // The public key of the vote status request. - bytes public_key = 2; - // The validator index of the request. - uint64 validator_index = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - // Has the validator been slashed. - bool is_slashed = 4; - // Is the validator withdrawable. - bool is_withdrawable_in_current_epoch = 5; - // Is the validator active in current epoch. - bool is_active_in_current_epoch = 6; - // Was the validator active in previous epoch. - bool is_active_in_previous_epoch = 7; - // Did validator attest for current epoch. - bool is_current_epoch_attester = 8; - // Did validator attest target for current epoch. - bool is_current_epoch_target_attester = 9; - // Did validator attest for previous epoch. - bool is_previous_epoch_attester = 10; - // Did validator attest target for previous epoch. - bool is_previous_epoch_target_attester = 11; - // Did validator attest head for previous epoch. - bool is_previous_epoch_head_attester = 12; - // The current effective balance of the validator. - uint64 current_epoch_effective_balance_gwei = 13; - // The slots of when the validator's attestation got included in the block. Only available in phase0. - uint64 inclusion_slot = 14 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot", deprecated = true]; - // How many slots have passed until the validator's attestation got included in the block. Only available in phase0. - uint64 inclusion_distance = 15 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot", deprecated = true]; - // The inactivity score of the validator tracks validator participation. [New in Altair] - uint64 inactivity_score = 16; - } - - repeated IndividualVote individual_votes = 1; + message IndividualVote { + // The epoch of the vote status request. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + // The public key of the vote status request. + bytes public_key = 2; + // The validator index of the request. + uint64 validator_index = 3 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + // Has the validator been slashed. + bool is_slashed = 4; + // Is the validator withdrawable. + bool is_withdrawable_in_current_epoch = 5; + // Is the validator active in current epoch. + bool is_active_in_current_epoch = 6; + // Was the validator active in previous epoch. + bool is_active_in_previous_epoch = 7; + // Did validator attest for current epoch. + bool is_current_epoch_attester = 8; + // Did validator attest target for current epoch. + bool is_current_epoch_target_attester = 9; + // Did validator attest for previous epoch. + bool is_previous_epoch_attester = 10; + // Did validator attest target for previous epoch. + bool is_previous_epoch_target_attester = 11; + // Did validator attest head for previous epoch. + bool is_previous_epoch_head_attester = 12; + // The current effective balance of the validator. + uint64 current_epoch_effective_balance_gwei = 13; + // The slots of when the validator's attestation got included in the block. + // Only available in phase0. + uint64 inclusion_slot = 14 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot", + deprecated = true + ]; + // How many slots have passed until the validator's attestation got included + // in the block. Only available in phase0. + uint64 inclusion_distance = 15 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot", + deprecated = true + ]; + // The inactivity score of the validator tracks validator participation. + // [New in Altair] + uint64 inactivity_score = 16; + } + + repeated IndividualVote individual_votes = 1; } diff --git a/proto/prysm/v1alpha1/beacon_state.pb.go b/proto/prysm/v1alpha1/beacon_state.pb.go index ef5a38848e47..344aa38a59d9 100755 --- a/proto/prysm/v1alpha1/beacon_state.pb.go +++ b/proto/prysm/v1alpha1/beacon_state.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/beacon_state.proto package eth @@ -232,237 +232,6 @@ func (x *BeaconState) GetFinalizedCheckpoint() *Checkpoint { return nil } -type BeaconStateAltair struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - GenesisTime uint64 `protobuf:"varint,1001,opt,name=genesis_time,json=genesisTime,proto3" json:"genesis_time,omitempty"` - GenesisValidatorsRoot []byte `protobuf:"bytes,1002,opt,name=genesis_validators_root,json=genesisValidatorsRoot,proto3" json:"genesis_validators_root,omitempty" ssz-size:"32"` - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1003,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - Fork *Fork `protobuf:"bytes,1004,opt,name=fork,proto3" json:"fork,omitempty"` - LatestBlockHeader *BeaconBlockHeader `protobuf:"bytes,2001,opt,name=latest_block_header,json=latestBlockHeader,proto3" json:"latest_block_header,omitempty"` - BlockRoots [][]byte `protobuf:"bytes,2002,rep,name=block_roots,json=blockRoots,proto3" json:"block_roots,omitempty" ssz-size:"8192,32"` - StateRoots [][]byte `protobuf:"bytes,2003,rep,name=state_roots,json=stateRoots,proto3" json:"state_roots,omitempty" ssz-size:"8192,32"` - HistoricalRoots [][]byte `protobuf:"bytes,2004,rep,name=historical_roots,json=historicalRoots,proto3" json:"historical_roots,omitempty" ssz-max:"16777216" ssz-size:"?,32"` - Eth1Data *Eth1Data `protobuf:"bytes,3001,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` - Eth1DataVotes []*Eth1Data `protobuf:"bytes,3002,rep,name=eth1_data_votes,json=eth1DataVotes,proto3" json:"eth1_data_votes,omitempty" ssz-max:"2048"` - Eth1DepositIndex uint64 `protobuf:"varint,3003,opt,name=eth1_deposit_index,json=eth1DepositIndex,proto3" json:"eth1_deposit_index,omitempty"` - Validators []*Validator `protobuf:"bytes,4001,rep,name=validators,proto3" json:"validators,omitempty" ssz-max:"1099511627776"` - Balances []uint64 `protobuf:"varint,4002,rep,packed,name=balances,proto3" json:"balances,omitempty" ssz-max:"1099511627776"` - RandaoMixes [][]byte `protobuf:"bytes,5001,rep,name=randao_mixes,json=randaoMixes,proto3" json:"randao_mixes,omitempty" ssz-size:"65536,32"` - Slashings []uint64 `protobuf:"varint,6001,rep,packed,name=slashings,proto3" json:"slashings,omitempty" ssz-size:"8192"` - PreviousEpochParticipation []byte `protobuf:"bytes,7001,opt,name=previous_epoch_participation,json=previousEpochParticipation,proto3" json:"previous_epoch_participation,omitempty" ssz-max:"1099511627776"` - CurrentEpochParticipation []byte `protobuf:"bytes,7002,opt,name=current_epoch_participation,json=currentEpochParticipation,proto3" json:"current_epoch_participation,omitempty" ssz-max:"1099511627776"` - JustificationBits github_com_prysmaticlabs_go_bitfield.Bitvector4 `protobuf:"bytes,8001,opt,name=justification_bits,json=justificationBits,proto3" json:"justification_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector4" ssz-size:"1"` - PreviousJustifiedCheckpoint *Checkpoint `protobuf:"bytes,8002,opt,name=previous_justified_checkpoint,json=previousJustifiedCheckpoint,proto3" json:"previous_justified_checkpoint,omitempty"` - CurrentJustifiedCheckpoint *Checkpoint `protobuf:"bytes,8003,opt,name=current_justified_checkpoint,json=currentJustifiedCheckpoint,proto3" json:"current_justified_checkpoint,omitempty"` - FinalizedCheckpoint *Checkpoint `protobuf:"bytes,8004,opt,name=finalized_checkpoint,json=finalizedCheckpoint,proto3" json:"finalized_checkpoint,omitempty"` - InactivityScores []uint64 `protobuf:"varint,9001,rep,packed,name=inactivity_scores,json=inactivityScores,proto3" json:"inactivity_scores,omitempty" ssz-max:"1099511627776"` - CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,9002,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` - NextSyncCommittee *SyncCommittee `protobuf:"bytes,9003,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` -} - -func (x *BeaconStateAltair) Reset() { - *x = BeaconStateAltair{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BeaconStateAltair) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BeaconStateAltair) ProtoMessage() {} - -func (x *BeaconStateAltair) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BeaconStateAltair.ProtoReflect.Descriptor instead. -func (*BeaconStateAltair) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{1} -} - -func (x *BeaconStateAltair) GetGenesisTime() uint64 { - if x != nil { - return x.GenesisTime - } - return 0 -} - -func (x *BeaconStateAltair) GetGenesisValidatorsRoot() []byte { - if x != nil { - return x.GenesisValidatorsRoot - } - return nil -} - -func (x *BeaconStateAltair) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *BeaconStateAltair) GetFork() *Fork { - if x != nil { - return x.Fork - } - return nil -} - -func (x *BeaconStateAltair) GetLatestBlockHeader() *BeaconBlockHeader { - if x != nil { - return x.LatestBlockHeader - } - return nil -} - -func (x *BeaconStateAltair) GetBlockRoots() [][]byte { - if x != nil { - return x.BlockRoots - } - return nil -} - -func (x *BeaconStateAltair) GetStateRoots() [][]byte { - if x != nil { - return x.StateRoots - } - return nil -} - -func (x *BeaconStateAltair) GetHistoricalRoots() [][]byte { - if x != nil { - return x.HistoricalRoots - } - return nil -} - -func (x *BeaconStateAltair) GetEth1Data() *Eth1Data { - if x != nil { - return x.Eth1Data - } - return nil -} - -func (x *BeaconStateAltair) GetEth1DataVotes() []*Eth1Data { - if x != nil { - return x.Eth1DataVotes - } - return nil -} - -func (x *BeaconStateAltair) GetEth1DepositIndex() uint64 { - if x != nil { - return x.Eth1DepositIndex - } - return 0 -} - -func (x *BeaconStateAltair) GetValidators() []*Validator { - if x != nil { - return x.Validators - } - return nil -} - -func (x *BeaconStateAltair) GetBalances() []uint64 { - if x != nil { - return x.Balances - } - return nil -} - -func (x *BeaconStateAltair) GetRandaoMixes() [][]byte { - if x != nil { - return x.RandaoMixes - } - return nil -} - -func (x *BeaconStateAltair) GetSlashings() []uint64 { - if x != nil { - return x.Slashings - } - return nil -} - -func (x *BeaconStateAltair) GetPreviousEpochParticipation() []byte { - if x != nil { - return x.PreviousEpochParticipation - } - return nil -} - -func (x *BeaconStateAltair) GetCurrentEpochParticipation() []byte { - if x != nil { - return x.CurrentEpochParticipation - } - return nil -} - -func (x *BeaconStateAltair) GetJustificationBits() github_com_prysmaticlabs_go_bitfield.Bitvector4 { - if x != nil { - return x.JustificationBits - } - return github_com_prysmaticlabs_go_bitfield.Bitvector4(nil) -} - -func (x *BeaconStateAltair) GetPreviousJustifiedCheckpoint() *Checkpoint { - if x != nil { - return x.PreviousJustifiedCheckpoint - } - return nil -} - -func (x *BeaconStateAltair) GetCurrentJustifiedCheckpoint() *Checkpoint { - if x != nil { - return x.CurrentJustifiedCheckpoint - } - return nil -} - -func (x *BeaconStateAltair) GetFinalizedCheckpoint() *Checkpoint { - if x != nil { - return x.FinalizedCheckpoint - } - return nil -} - -func (x *BeaconStateAltair) GetInactivityScores() []uint64 { - if x != nil { - return x.InactivityScores - } - return nil -} - -func (x *BeaconStateAltair) GetCurrentSyncCommittee() *SyncCommittee { - if x != nil { - return x.CurrentSyncCommittee - } - return nil -} - -func (x *BeaconStateAltair) GetNextSyncCommittee() *SyncCommittee { - if x != nil { - return x.NextSyncCommittee - } - return nil -} - type Fork struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -476,7 +245,7 @@ type Fork struct { func (x *Fork) Reset() { *x = Fork{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[2] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -489,7 +258,7 @@ func (x *Fork) String() string { func (*Fork) ProtoMessage() {} func (x *Fork) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[2] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -502,7 +271,7 @@ func (x *Fork) ProtoReflect() protoreflect.Message { // Deprecated: Use Fork.ProtoReflect.Descriptor instead. func (*Fork) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{2} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{1} } func (x *Fork) GetPreviousVersion() []byte { @@ -540,7 +309,7 @@ type PendingAttestation struct { func (x *PendingAttestation) Reset() { *x = PendingAttestation{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[3] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -553,7 +322,7 @@ func (x *PendingAttestation) String() string { func (*PendingAttestation) ProtoMessage() {} func (x *PendingAttestation) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[3] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -566,7 +335,7 @@ func (x *PendingAttestation) ProtoReflect() protoreflect.Message { // Deprecated: Use PendingAttestation.ProtoReflect.Descriptor instead. func (*PendingAttestation) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{3} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{2} } func (x *PendingAttestation) GetAggregationBits() github_com_prysmaticlabs_go_bitfield.Bitlist { @@ -609,7 +378,7 @@ type HistoricalBatch struct { func (x *HistoricalBatch) Reset() { *x = HistoricalBatch{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[4] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -622,7 +391,7 @@ func (x *HistoricalBatch) String() string { func (*HistoricalBatch) ProtoMessage() {} func (x *HistoricalBatch) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[4] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -635,7 +404,7 @@ func (x *HistoricalBatch) ProtoReflect() protoreflect.Message { // Deprecated: Use HistoricalBatch.ProtoReflect.Descriptor instead. func (*HistoricalBatch) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{4} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{3} } func (x *HistoricalBatch) GetBlockRoots() [][]byte { @@ -664,7 +433,7 @@ type StateSummary struct { func (x *StateSummary) Reset() { *x = StateSummary{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -677,7 +446,7 @@ func (x *StateSummary) String() string { func (*StateSummary) ProtoMessage() {} func (x *StateSummary) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -690,7 +459,7 @@ func (x *StateSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use StateSummary.ProtoReflect.Descriptor instead. func (*StateSummary) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{5} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{4} } func (x *StateSummary) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { @@ -719,7 +488,7 @@ type SigningData struct { func (x *SigningData) Reset() { *x = SigningData{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -732,7 +501,7 @@ func (x *SigningData) String() string { func (*SigningData) ProtoMessage() {} func (x *SigningData) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[6] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -745,7 +514,7 @@ func (x *SigningData) ProtoReflect() protoreflect.Message { // Deprecated: Use SigningData.ProtoReflect.Descriptor instead. func (*SigningData) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{6} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{5} } func (x *SigningData) GetObjectRoot() []byte { @@ -774,7 +543,7 @@ type ForkData struct { func (x *ForkData) Reset() { *x = ForkData{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[7] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -787,7 +556,7 @@ func (x *ForkData) String() string { func (*ForkData) ProtoMessage() {} func (x *ForkData) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[7] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -800,7 +569,7 @@ func (x *ForkData) ProtoReflect() protoreflect.Message { // Deprecated: Use ForkData.ProtoReflect.Descriptor instead. func (*ForkData) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{7} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{6} } func (x *ForkData) GetCurrentVersion() []byte { @@ -832,7 +601,7 @@ type CheckPtInfo struct { func (x *CheckPtInfo) Reset() { *x = CheckPtInfo{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[8] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -845,7 +614,7 @@ func (x *CheckPtInfo) String() string { func (*CheckPtInfo) ProtoMessage() {} func (x *CheckPtInfo) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[8] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -858,7 +627,7 @@ func (x *CheckPtInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckPtInfo.ProtoReflect.Descriptor instead. func (*CheckPtInfo) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{8} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{7} } func (x *CheckPtInfo) GetSeed() []byte { @@ -908,6 +677,69 @@ type DepositMessage struct { func (x *DepositMessage) Reset() { *x = DepositMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DepositMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DepositMessage) ProtoMessage() {} + +func (x *DepositMessage) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DepositMessage.ProtoReflect.Descriptor instead. +func (*DepositMessage) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{8} +} + +func (x *DepositMessage) GetPublicKey() []byte { + if x != nil { + return x.PublicKey + } + return nil +} + +func (x *DepositMessage) GetWithdrawalCredentials() []byte { + if x != nil { + return x.WithdrawalCredentials + } + return nil +} + +func (x *DepositMessage) GetAmount() uint64 { + if x != nil { + return x.Amount + } + return 0 +} + +type PowBlock struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockHash []byte `protobuf:"bytes,1,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty" ssz-size:"32"` + ParentHash []byte `protobuf:"bytes,2,opt,name=parent_hash,json=parentHash,proto3" json:"parent_hash,omitempty" ssz-size:"32"` + TotalDifficulty []byte `protobuf:"bytes,3,opt,name=total_difficulty,json=totalDifficulty,proto3" json:"total_difficulty,omitempty" ssz-size:"32"` +} + +func (x *PowBlock) Reset() { + *x = PowBlock{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -915,48 +747,279 @@ func (x *DepositMessage) Reset() { } } -func (x *DepositMessage) String() string { - return protoimpl.X.MessageStringOf(x) +func (x *PowBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PowBlock) ProtoMessage() {} + +func (x *PowBlock) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PowBlock.ProtoReflect.Descriptor instead. +func (*PowBlock) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{9} +} + +func (x *PowBlock) GetBlockHash() []byte { + if x != nil { + return x.BlockHash + } + return nil +} + +func (x *PowBlock) GetParentHash() []byte { + if x != nil { + return x.ParentHash + } + return nil +} + +func (x *PowBlock) GetTotalDifficulty() []byte { + if x != nil { + return x.TotalDifficulty + } + return nil +} + +type BeaconStateAltair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GenesisTime uint64 `protobuf:"varint,1001,opt,name=genesis_time,json=genesisTime,proto3" json:"genesis_time,omitempty"` + GenesisValidatorsRoot []byte `protobuf:"bytes,1002,opt,name=genesis_validators_root,json=genesisValidatorsRoot,proto3" json:"genesis_validators_root,omitempty" ssz-size:"32"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1003,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + Fork *Fork `protobuf:"bytes,1004,opt,name=fork,proto3" json:"fork,omitempty"` + LatestBlockHeader *BeaconBlockHeader `protobuf:"bytes,2001,opt,name=latest_block_header,json=latestBlockHeader,proto3" json:"latest_block_header,omitempty"` + BlockRoots [][]byte `protobuf:"bytes,2002,rep,name=block_roots,json=blockRoots,proto3" json:"block_roots,omitempty" ssz-size:"8192,32"` + StateRoots [][]byte `protobuf:"bytes,2003,rep,name=state_roots,json=stateRoots,proto3" json:"state_roots,omitempty" ssz-size:"8192,32"` + HistoricalRoots [][]byte `protobuf:"bytes,2004,rep,name=historical_roots,json=historicalRoots,proto3" json:"historical_roots,omitempty" ssz-max:"16777216" ssz-size:"?,32"` + Eth1Data *Eth1Data `protobuf:"bytes,3001,opt,name=eth1_data,json=eth1Data,proto3" json:"eth1_data,omitempty"` + Eth1DataVotes []*Eth1Data `protobuf:"bytes,3002,rep,name=eth1_data_votes,json=eth1DataVotes,proto3" json:"eth1_data_votes,omitempty" ssz-max:"2048"` + Eth1DepositIndex uint64 `protobuf:"varint,3003,opt,name=eth1_deposit_index,json=eth1DepositIndex,proto3" json:"eth1_deposit_index,omitempty"` + Validators []*Validator `protobuf:"bytes,4001,rep,name=validators,proto3" json:"validators,omitempty" ssz-max:"1099511627776"` + Balances []uint64 `protobuf:"varint,4002,rep,packed,name=balances,proto3" json:"balances,omitempty" ssz-max:"1099511627776"` + RandaoMixes [][]byte `protobuf:"bytes,5001,rep,name=randao_mixes,json=randaoMixes,proto3" json:"randao_mixes,omitempty" ssz-size:"65536,32"` + Slashings []uint64 `protobuf:"varint,6001,rep,packed,name=slashings,proto3" json:"slashings,omitempty" ssz-size:"8192"` + PreviousEpochParticipation []byte `protobuf:"bytes,7001,opt,name=previous_epoch_participation,json=previousEpochParticipation,proto3" json:"previous_epoch_participation,omitempty" ssz-max:"1099511627776"` + CurrentEpochParticipation []byte `protobuf:"bytes,7002,opt,name=current_epoch_participation,json=currentEpochParticipation,proto3" json:"current_epoch_participation,omitempty" ssz-max:"1099511627776"` + JustificationBits github_com_prysmaticlabs_go_bitfield.Bitvector4 `protobuf:"bytes,8001,opt,name=justification_bits,json=justificationBits,proto3" json:"justification_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector4" ssz-size:"1"` + PreviousJustifiedCheckpoint *Checkpoint `protobuf:"bytes,8002,opt,name=previous_justified_checkpoint,json=previousJustifiedCheckpoint,proto3" json:"previous_justified_checkpoint,omitempty"` + CurrentJustifiedCheckpoint *Checkpoint `protobuf:"bytes,8003,opt,name=current_justified_checkpoint,json=currentJustifiedCheckpoint,proto3" json:"current_justified_checkpoint,omitempty"` + FinalizedCheckpoint *Checkpoint `protobuf:"bytes,8004,opt,name=finalized_checkpoint,json=finalizedCheckpoint,proto3" json:"finalized_checkpoint,omitempty"` + InactivityScores []uint64 `protobuf:"varint,9001,rep,packed,name=inactivity_scores,json=inactivityScores,proto3" json:"inactivity_scores,omitempty" ssz-max:"1099511627776"` + CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,9002,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` + NextSyncCommittee *SyncCommittee `protobuf:"bytes,9003,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` +} + +func (x *BeaconStateAltair) Reset() { + *x = BeaconStateAltair{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BeaconStateAltair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BeaconStateAltair) ProtoMessage() {} + +func (x *BeaconStateAltair) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BeaconStateAltair.ProtoReflect.Descriptor instead. +func (*BeaconStateAltair) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{10} +} + +func (x *BeaconStateAltair) GetGenesisTime() uint64 { + if x != nil { + return x.GenesisTime + } + return 0 +} + +func (x *BeaconStateAltair) GetGenesisValidatorsRoot() []byte { + if x != nil { + return x.GenesisValidatorsRoot + } + return nil +} + +func (x *BeaconStateAltair) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.Slot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +func (x *BeaconStateAltair) GetFork() *Fork { + if x != nil { + return x.Fork + } + return nil +} + +func (x *BeaconStateAltair) GetLatestBlockHeader() *BeaconBlockHeader { + if x != nil { + return x.LatestBlockHeader + } + return nil +} + +func (x *BeaconStateAltair) GetBlockRoots() [][]byte { + if x != nil { + return x.BlockRoots + } + return nil +} + +func (x *BeaconStateAltair) GetStateRoots() [][]byte { + if x != nil { + return x.StateRoots + } + return nil +} + +func (x *BeaconStateAltair) GetHistoricalRoots() [][]byte { + if x != nil { + return x.HistoricalRoots + } + return nil +} + +func (x *BeaconStateAltair) GetEth1Data() *Eth1Data { + if x != nil { + return x.Eth1Data + } + return nil +} + +func (x *BeaconStateAltair) GetEth1DataVotes() []*Eth1Data { + if x != nil { + return x.Eth1DataVotes + } + return nil +} + +func (x *BeaconStateAltair) GetEth1DepositIndex() uint64 { + if x != nil { + return x.Eth1DepositIndex + } + return 0 +} + +func (x *BeaconStateAltair) GetValidators() []*Validator { + if x != nil { + return x.Validators + } + return nil +} + +func (x *BeaconStateAltair) GetBalances() []uint64 { + if x != nil { + return x.Balances + } + return nil +} + +func (x *BeaconStateAltair) GetRandaoMixes() [][]byte { + if x != nil { + return x.RandaoMixes + } + return nil +} + +func (x *BeaconStateAltair) GetSlashings() []uint64 { + if x != nil { + return x.Slashings + } + return nil +} + +func (x *BeaconStateAltair) GetPreviousEpochParticipation() []byte { + if x != nil { + return x.PreviousEpochParticipation + } + return nil +} + +func (x *BeaconStateAltair) GetCurrentEpochParticipation() []byte { + if x != nil { + return x.CurrentEpochParticipation + } + return nil +} + +func (x *BeaconStateAltair) GetJustificationBits() github_com_prysmaticlabs_go_bitfield.Bitvector4 { + if x != nil { + return x.JustificationBits + } + return github_com_prysmaticlabs_go_bitfield.Bitvector4(nil) +} + +func (x *BeaconStateAltair) GetPreviousJustifiedCheckpoint() *Checkpoint { + if x != nil { + return x.PreviousJustifiedCheckpoint + } + return nil } -func (*DepositMessage) ProtoMessage() {} - -func (x *DepositMessage) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms +func (x *BeaconStateAltair) GetCurrentJustifiedCheckpoint() *Checkpoint { + if x != nil { + return x.CurrentJustifiedCheckpoint } - return mi.MessageOf(x) + return nil } -// Deprecated: Use DepositMessage.ProtoReflect.Descriptor instead. -func (*DepositMessage) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{9} +func (x *BeaconStateAltair) GetFinalizedCheckpoint() *Checkpoint { + if x != nil { + return x.FinalizedCheckpoint + } + return nil } -func (x *DepositMessage) GetPublicKey() []byte { +func (x *BeaconStateAltair) GetInactivityScores() []uint64 { if x != nil { - return x.PublicKey + return x.InactivityScores } return nil } -func (x *DepositMessage) GetWithdrawalCredentials() []byte { +func (x *BeaconStateAltair) GetCurrentSyncCommittee() *SyncCommittee { if x != nil { - return x.WithdrawalCredentials + return x.CurrentSyncCommittee } return nil } -func (x *DepositMessage) GetAmount() uint64 { +func (x *BeaconStateAltair) GetNextSyncCommittee() *SyncCommittee { if x != nil { - return x.Amount + return x.NextSyncCommittee } - return 0 + return nil } type SyncCommittee struct { @@ -971,7 +1034,7 @@ type SyncCommittee struct { func (x *SyncCommittee) Reset() { *x = SyncCommittee{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[10] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -984,7 +1047,7 @@ func (x *SyncCommittee) String() string { func (*SyncCommittee) ProtoMessage() {} func (x *SyncCommittee) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[10] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -997,7 +1060,7 @@ func (x *SyncCommittee) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncCommittee.ProtoReflect.Descriptor instead. func (*SyncCommittee) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{10} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{11} } func (x *SyncCommittee) GetPubkeys() [][]byte { @@ -1026,7 +1089,7 @@ type SyncAggregatorSelectionData struct { func (x *SyncAggregatorSelectionData) Reset() { *x = SyncAggregatorSelectionData{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[11] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1039,7 +1102,7 @@ func (x *SyncAggregatorSelectionData) String() string { func (*SyncAggregatorSelectionData) ProtoMessage() {} func (x *SyncAggregatorSelectionData) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[11] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1052,7 +1115,7 @@ func (x *SyncAggregatorSelectionData) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncAggregatorSelectionData.ProtoReflect.Descriptor instead. func (*SyncAggregatorSelectionData) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{11} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{12} } func (x *SyncAggregatorSelectionData) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { @@ -1104,7 +1167,7 @@ type BeaconStateBellatrix struct { func (x *BeaconStateBellatrix) Reset() { *x = BeaconStateBellatrix{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[12] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1117,7 +1180,7 @@ func (x *BeaconStateBellatrix) String() string { func (*BeaconStateBellatrix) ProtoMessage() {} func (x *BeaconStateBellatrix) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[12] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1130,7 +1193,7 @@ func (x *BeaconStateBellatrix) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconStateBellatrix.ProtoReflect.Descriptor instead. func (*BeaconStateBellatrix) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{12} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{13} } func (x *BeaconStateBellatrix) GetGenesisTime() uint64 { @@ -1346,7 +1409,7 @@ type BeaconStateCapella struct { func (x *BeaconStateCapella) Reset() { *x = BeaconStateCapella{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[13] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1359,7 +1422,7 @@ func (x *BeaconStateCapella) String() string { func (*BeaconStateCapella) ProtoMessage() {} func (x *BeaconStateCapella) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[13] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1372,7 +1435,7 @@ func (x *BeaconStateCapella) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconStateCapella.ProtoReflect.Descriptor instead. func (*BeaconStateCapella) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{13} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{14} } func (x *BeaconStateCapella) GetGenesisTime() uint64 { @@ -1571,6 +1634,61 @@ func (x *BeaconStateCapella) GetHistoricalSummaries() []*HistoricalSummary { return nil } +type HistoricalSummary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockSummaryRoot []byte `protobuf:"bytes,1,opt,name=block_summary_root,json=blockSummaryRoot,proto3" json:"block_summary_root,omitempty" ssz-size:"32"` + StateSummaryRoot []byte `protobuf:"bytes,2,opt,name=state_summary_root,json=stateSummaryRoot,proto3" json:"state_summary_root,omitempty" ssz-size:"32"` +} + +func (x *HistoricalSummary) Reset() { + *x = HistoricalSummary{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HistoricalSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HistoricalSummary) ProtoMessage() {} + +func (x *HistoricalSummary) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HistoricalSummary.ProtoReflect.Descriptor instead. +func (*HistoricalSummary) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{15} +} + +func (x *HistoricalSummary) GetBlockSummaryRoot() []byte { + if x != nil { + return x.BlockSummaryRoot + } + return nil +} + +func (x *HistoricalSummary) GetStateSummaryRoot() []byte { + if x != nil { + return x.StateSummaryRoot + } + return nil +} + type BeaconStateDeneb struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1609,7 +1727,7 @@ type BeaconStateDeneb struct { func (x *BeaconStateDeneb) Reset() { *x = BeaconStateDeneb{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[14] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1622,7 +1740,7 @@ func (x *BeaconStateDeneb) String() string { func (*BeaconStateDeneb) ProtoMessage() {} func (x *BeaconStateDeneb) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[14] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1635,7 +1753,7 @@ func (x *BeaconStateDeneb) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconStateDeneb.ProtoReflect.Descriptor instead. func (*BeaconStateDeneb) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{14} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{16} } func (x *BeaconStateDeneb) GetGenesisTime() uint64 { @@ -1863,7 +1981,7 @@ type BeaconStateElectra struct { InactivityScores []uint64 `protobuf:"varint,9001,rep,packed,name=inactivity_scores,json=inactivityScores,proto3" json:"inactivity_scores,omitempty" ssz-max:"1099511627776"` CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,9002,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` NextSyncCommittee *SyncCommittee `protobuf:"bytes,9003,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` - LatestExecutionPayloadHeader *v1.ExecutionPayloadHeaderElectra `protobuf:"bytes,10001,opt,name=latest_execution_payload_header,json=latestExecutionPayloadHeader,proto3" json:"latest_execution_payload_header,omitempty"` + LatestExecutionPayloadHeader *v1.ExecutionPayloadHeaderDeneb `protobuf:"bytes,10001,opt,name=latest_execution_payload_header,json=latestExecutionPayloadHeader,proto3" json:"latest_execution_payload_header,omitempty"` NextWithdrawalIndex uint64 `protobuf:"varint,11001,opt,name=next_withdrawal_index,json=nextWithdrawalIndex,proto3" json:"next_withdrawal_index,omitempty"` NextWithdrawalValidatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,11002,opt,name=next_withdrawal_validator_index,json=nextWithdrawalValidatorIndex,proto3" json:"next_withdrawal_validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` HistoricalSummaries []*HistoricalSummary `protobuf:"bytes,11003,rep,name=historical_summaries,json=historicalSummaries,proto3" json:"historical_summaries,omitempty" ssz-max:"16777216"` @@ -1873,7 +1991,7 @@ type BeaconStateElectra struct { EarliestExitEpoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,12004,opt,name=earliest_exit_epoch,json=earliestExitEpoch,proto3" json:"earliest_exit_epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"` ConsolidationBalanceToConsume github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Gwei `protobuf:"varint,12005,opt,name=consolidation_balance_to_consume,json=consolidationBalanceToConsume,proto3" json:"consolidation_balance_to_consume,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Gwei"` EarliestConsolidationEpoch github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch `protobuf:"varint,12006,opt,name=earliest_consolidation_epoch,json=earliestConsolidationEpoch,proto3" json:"earliest_consolidation_epoch,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"` - PendingBalanceDeposits []*PendingBalanceDeposit `protobuf:"bytes,12007,rep,name=pending_balance_deposits,json=pendingBalanceDeposits,proto3" json:"pending_balance_deposits,omitempty" ssz-max:"134217728"` + PendingDeposits []*PendingDeposit `protobuf:"bytes,12007,rep,name=pending_deposits,json=pendingDeposits,proto3" json:"pending_deposits,omitempty" ssz-max:"134217728"` PendingPartialWithdrawals []*PendingPartialWithdrawal `protobuf:"bytes,12008,rep,name=pending_partial_withdrawals,json=pendingPartialWithdrawals,proto3" json:"pending_partial_withdrawals,omitempty" ssz-max:"134217728"` PendingConsolidations []*PendingConsolidation `protobuf:"bytes,12009,rep,name=pending_consolidations,json=pendingConsolidations,proto3" json:"pending_consolidations,omitempty" ssz-max:"262144"` } @@ -1881,7 +1999,7 @@ type BeaconStateElectra struct { func (x *BeaconStateElectra) Reset() { *x = BeaconStateElectra{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[15] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1894,7 +2012,7 @@ func (x *BeaconStateElectra) String() string { func (*BeaconStateElectra) ProtoMessage() {} func (x *BeaconStateElectra) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[15] + mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1907,7 +2025,7 @@ func (x *BeaconStateElectra) ProtoReflect() protoreflect.Message { // Deprecated: Use BeaconStateElectra.ProtoReflect.Descriptor instead. func (*BeaconStateElectra) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{15} + return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{17} } func (x *BeaconStateElectra) GetGenesisTime() uint64 { @@ -2078,7 +2196,7 @@ func (x *BeaconStateElectra) GetNextSyncCommittee() *SyncCommittee { return nil } -func (x *BeaconStateElectra) GetLatestExecutionPayloadHeader() *v1.ExecutionPayloadHeaderElectra { +func (x *BeaconStateElectra) GetLatestExecutionPayloadHeader() *v1.ExecutionPayloadHeaderDeneb { if x != nil { return x.LatestExecutionPayloadHeader } @@ -2148,141 +2266,23 @@ func (x *BeaconStateElectra) GetEarliestConsolidationEpoch() github_com_prysmati return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) } -func (x *BeaconStateElectra) GetPendingBalanceDeposits() []*PendingBalanceDeposit { - if x != nil { - return x.PendingBalanceDeposits - } - return nil -} - -func (x *BeaconStateElectra) GetPendingPartialWithdrawals() []*PendingPartialWithdrawal { - if x != nil { - return x.PendingPartialWithdrawals - } - return nil -} - -func (x *BeaconStateElectra) GetPendingConsolidations() []*PendingConsolidation { - if x != nil { - return x.PendingConsolidations - } - return nil -} - -type PowBlock struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BlockHash []byte `protobuf:"bytes,1,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty" ssz-size:"32"` - ParentHash []byte `protobuf:"bytes,2,opt,name=parent_hash,json=parentHash,proto3" json:"parent_hash,omitempty" ssz-size:"32"` - TotalDifficulty []byte `protobuf:"bytes,3,opt,name=total_difficulty,json=totalDifficulty,proto3" json:"total_difficulty,omitempty" ssz-size:"32"` -} - -func (x *PowBlock) Reset() { - *x = PowBlock{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PowBlock) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PowBlock) ProtoMessage() {} - -func (x *PowBlock) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use PowBlock.ProtoReflect.Descriptor instead. -func (*PowBlock) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{16} -} - -func (x *PowBlock) GetBlockHash() []byte { - if x != nil { - return x.BlockHash - } - return nil -} - -func (x *PowBlock) GetParentHash() []byte { - if x != nil { - return x.ParentHash - } - return nil -} - -func (x *PowBlock) GetTotalDifficulty() []byte { +func (x *BeaconStateElectra) GetPendingDeposits() []*PendingDeposit { if x != nil { - return x.TotalDifficulty - } - return nil -} - -type HistoricalSummary struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BlockSummaryRoot []byte `protobuf:"bytes,1,opt,name=block_summary_root,json=blockSummaryRoot,proto3" json:"block_summary_root,omitempty" ssz-size:"32"` - StateSummaryRoot []byte `protobuf:"bytes,2,opt,name=state_summary_root,json=stateSummaryRoot,proto3" json:"state_summary_root,omitempty" ssz-size:"32"` -} - -func (x *HistoricalSummary) Reset() { - *x = HistoricalSummary{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HistoricalSummary) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HistoricalSummary) ProtoMessage() {} - -func (x *HistoricalSummary) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms + return x.PendingDeposits } - return mi.MessageOf(x) -} - -// Deprecated: Use HistoricalSummary.ProtoReflect.Descriptor instead. -func (*HistoricalSummary) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP(), []int{17} + return nil } -func (x *HistoricalSummary) GetBlockSummaryRoot() []byte { +func (x *BeaconStateElectra) GetPendingPartialWithdrawals() []*PendingPartialWithdrawal { if x != nil { - return x.BlockSummaryRoot + return x.PendingPartialWithdrawals } return nil } -func (x *HistoricalSummary) GetStateSummaryRoot() []byte { +func (x *BeaconStateElectra) GetPendingConsolidations() []*PendingConsolidation { if x != nil { - return x.StateSummaryRoot + return x.PendingConsolidations } return nil } @@ -2405,7 +2405,104 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_rawDesc = []byte{ 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0xd2, 0x0d, 0x0a, 0x11, + 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0xc6, 0x01, 0x0a, 0x04, + 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x30, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, + 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x05, + 0x8a, 0xb5, 0x18, 0x01, 0x34, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x05, 0x8a, 0xb5, 0x18, 0x01, 0x34, 0x52, 0x0e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x22, 0x9d, 0x03, 0x0a, 0x12, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x63, 0x0a, 0x10, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, + 0x42, 0x69, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, + 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, + 0x12, 0x3a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x6e, 0x0a, 0x0f, + 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0e, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x76, 0x0a, 0x0e, + 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x22, 0x6d, 0x0a, 0x0f, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, + 0x61, 0x6c, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x2c, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0b, 0x8a, 0xb5, + 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, + 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0b, 0x8a, 0xb5, 0x18, 0x07, + 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, + 0x6f, 0x74, 0x73, 0x22, 0x7d, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, + 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, + 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x72, 0x6f, + 0x6f, 0x74, 0x22, 0x56, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x44, 0x61, 0x74, + 0x61, 0x12, 0x27, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1e, 0x0a, 0x06, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x7a, 0x0a, 0x08, 0x46, 0x6f, + 0x72, 0x6b, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x05, 0x8a, 0xb5, 0x18, 0x01, 0x34, 0x52, 0x0e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x17, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, + 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x5f, 0x72, 0x6f, 0x6f, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, + 0x15, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xb7, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x50, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x65, + 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, + 0x0e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x64, + 0x69, 0x63, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x73, 0x12, + 0x2f, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6b, + 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, + 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, + 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x77, 0x69, + 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x8d, 0x01, 0x0a, 0x08, + 0x50, 0x6f, 0x77, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x27, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x31, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x44, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x22, 0xd2, 0x0d, 0x0a, 0x11, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, @@ -2515,94 +2612,6 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_rawDesc = []byte{ 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x11, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x22, 0xc6, 0x01, 0x0a, 0x04, 0x46, 0x6f, 0x72, 0x6b, 0x12, 0x30, 0x0a, 0x10, 0x70, 0x72, 0x65, - 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x05, 0x8a, 0xb5, 0x18, 0x01, 0x34, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, - 0x69, 0x6f, 0x75, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x0f, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x05, 0x8a, 0xb5, 0x18, 0x01, 0x34, 0x52, 0x0e, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x9d, 0x03, 0x0a, 0x12, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x63, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x62, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2c, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, - 0x32, 0x30, 0x34, 0x38, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x6e, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x64, - 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, - 0x74, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x6c, 0x61, - 0x79, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x6d, 0x0a, 0x0f, 0x48, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x2c, 0x0a, 0x0b, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0c, 0x42, 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x0b, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, - 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x22, 0x7d, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, - 0x6c, 0x6f, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x22, 0x56, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x44, 0x61, 0x74, 0x61, 0x12, 0x27, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, - 0x1e, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, - 0x7a, 0x0a, 0x08, 0x46, 0x6f, 0x72, 0x6b, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x0f, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x05, 0x8a, 0xb5, 0x18, 0x01, 0x34, 0x52, 0x0e, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x17, 0x67, - 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xb7, 0x01, 0x0a, 0x0b, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x73, - 0x65, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x12, - 0x21, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x52, 0x6f, - 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0d, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x75, 0x62, - 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x75, 0x62, - 0x4b, 0x65, 0x79, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, - 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x22, 0x98, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, - 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x16, 0x77, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x15, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, 0x72, 0x65, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x68, 0x0a, 0x0d, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x24, 0x0a, 0x07, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0a, 0x8a, 0xb5, 0x18, 0x06, 0x35, 0x31, 0x32, 0x2c, 0x34, 0x38, 0x52, 0x07, @@ -2873,376 +2882,366 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_rawDesc = []byte{ 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x0c, 0x92, 0xb5, 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52, 0x13, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, - 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x22, 0x85, 0x11, 0x0a, - 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6e, 0x65, - 0x62, 0x12, 0x22, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, - 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x17, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, - 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x15, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x5a, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0xeb, - 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, - 0x6f, 0x74, 0x12, 0x30, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0xec, 0x07, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x04, - 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x59, 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0xd1, 0x0f, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, - 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x11, 0x6c, 0x61, - 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, - 0x2d, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd2, + 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x22, 0x7f, 0x0a, 0x11, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x34, 0x0a, 0x12, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x34, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x10, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x85, 0x11, + 0x0a, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6e, + 0x65, 0x62, 0x12, 0x22, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, + 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x17, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, + 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x5f, 0x72, 0x6f, 0x6f, + 0x74, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x15, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x5a, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, + 0xeb, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, + 0x6c, 0x6f, 0x74, 0x12, 0x30, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0xec, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, + 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x59, 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0xd1, 0x0f, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x11, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x2d, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, + 0xd2, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, + 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, + 0x2d, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd3, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, - 0x33, 0x32, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x2d, - 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd3, 0x0f, - 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, - 0x32, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x40, 0x0a, - 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x73, 0x18, 0xd4, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, - 0x33, 0x32, 0x92, 0xb5, 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52, 0x0f, - 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, - 0x3d, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0xb9, 0x17, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, - 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x52, - 0x0a, 0x0f, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x76, 0x6f, 0x74, 0x65, - 0x73, 0x18, 0xba, 0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, - 0x30, 0x34, 0x38, 0x52, 0x0d, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x56, 0x6f, 0x74, - 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0xbb, 0x17, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x10, 0x65, 0x74, 0x68, 0x31, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x12, 0x54, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, - 0xa1, 0x1f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, - 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x0a, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x73, 0x18, 0xa2, 0x1f, 0x20, 0x03, 0x28, 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, - 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x08, 0x62, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, - 0x6f, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x73, 0x18, 0x89, 0x27, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0c, - 0x8a, 0xb5, 0x18, 0x08, 0x36, 0x35, 0x35, 0x33, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0b, 0x72, 0x61, - 0x6e, 0x64, 0x61, 0x6f, 0x4d, 0x69, 0x78, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x09, 0x73, 0x6c, 0x61, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0xf1, 0x2e, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x8a, - 0xb5, 0x18, 0x04, 0x38, 0x31, 0x39, 0x32, 0x52, 0x09, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x54, 0x0a, 0x1c, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0xd9, 0x36, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, - 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x1a, 0x70, 0x72, - 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x1b, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, - 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xda, 0x36, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x11, - 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, - 0x36, 0x52, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x50, - 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x12, - 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, - 0x74, 0x73, 0x18, 0xc1, 0x3e, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2f, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x34, 0x8a, 0xb5, - 0x18, 0x01, 0x31, 0x52, 0x11, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x66, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, - 0x75, 0x73, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, - 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc2, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x52, 0x1b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x64, - 0x0a, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, - 0x69, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc3, - 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x55, 0x0a, 0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc4, 0x3e, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3f, 0x0a, 0x11, 0x69, - 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, - 0x18, 0xa9, 0x46, 0x20, 0x03, 0x28, 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, - 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x10, 0x69, 0x6e, 0x61, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x5b, 0x0a, 0x16, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0xaa, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x55, 0x0a, 0x13, 0x6e, 0x65, 0x78, - 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x18, 0xab, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x11, 0x6e, - 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x12, 0x77, 0x0a, 0x1f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x18, 0x91, 0x4e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x1c, 0x6c, 0x61, 0x74, - 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x15, 0x6e, 0x65, 0x78, - 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0xf9, 0x55, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x57, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x97, - 0x01, 0x0a, 0x1f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, - 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0xfa, 0x55, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x1c, 0x6e, 0x65, 0x78, 0x74, - 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x6a, 0x0a, 0x14, 0x68, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, - 0x18, 0xfb, 0x55, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x33, 0x32, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x40, + 0x0a, 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x6f, + 0x74, 0x73, 0x18, 0xd4, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x04, 0x3f, + 0x2c, 0x33, 0x32, 0x92, 0xb5, 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52, + 0x0f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x6f, 0x74, 0x73, + 0x12, 0x3d, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0xb9, 0x17, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, + 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, + 0x52, 0x0a, 0x0f, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x76, 0x6f, 0x74, + 0x65, 0x73, 0x18, 0xba, 0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, + 0x32, 0x30, 0x34, 0x38, 0x52, 0x0d, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x56, 0x6f, + 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0xbb, 0x17, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x10, 0x65, 0x74, 0x68, 0x31, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x12, 0x54, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, + 0x18, 0xa1, 0x1f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x42, 0x0c, 0x92, 0xb5, 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52, - 0x13, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x69, 0x65, 0x73, 0x22, 0xd1, 0x19, 0x0a, 0x12, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x67, - 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0xe9, 0x07, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x3f, 0x0a, 0x17, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x67, 0x65, 0x6e, 0x65, 0x73, - 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x6f, 0x6f, 0x74, - 0x12, 0x5a, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, - 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x30, 0x0a, 0x04, - 0x66, 0x6f, 0x72, 0x6b, 0x18, 0xec, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x12, 0x59, - 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0xd1, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd2, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, - 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd3, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0b, - 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x10, 0x68, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd4, 0x0f, 0x20, 0x03, - 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x33, 0x32, 0x92, 0xb5, 0x18, 0x08, - 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52, 0x0f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, - 0x69, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x3d, 0x0a, 0x09, 0x65, 0x74, 0x68, - 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0xb9, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, - 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x0f, 0x65, 0x74, 0x68, 0x31, - 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x73, 0x18, 0xba, 0x17, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, - 0x61, 0x74, 0x61, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0d, 0x65, - 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x12, - 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0xbb, 0x17, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x74, 0x68, 0x31, 0x44, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x54, 0x0a, 0x0a, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0xa1, 0x1f, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, - 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x73, 0x12, 0x2e, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0xa2, 0x1f, - 0x20, 0x03, 0x28, 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, - 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x12, 0x30, 0x0a, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x6d, 0x69, 0x78, 0x65, - 0x73, 0x18, 0x89, 0x27, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0c, 0x8a, 0xb5, 0x18, 0x08, 0x36, 0x35, - 0x35, 0x33, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0b, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x4d, 0x69, - 0x78, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x09, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, - 0x18, 0xf1, 0x2e, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x38, 0x31, 0x39, - 0x32, 0x52, 0x09, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x1c, - 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x70, - 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xd9, 0x36, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, - 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, - 0x45, 0x70, 0x6f, 0x63, 0x68, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x1b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0xda, 0x36, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, - 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x19, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, - 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x12, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0xc1, 0x3e, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, - 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x34, 0x8a, 0xb5, 0x18, 0x01, 0x31, 0x52, 0x11, 0x6a, - 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, - 0x12, 0x66, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, 0x73, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x18, 0xc2, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x1b, 0x70, 0x72, 0x65, - 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x64, 0x0a, 0x1c, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc3, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, + 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x0a, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x73, 0x18, 0xa2, 0x1f, 0x20, 0x03, 0x28, 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18, + 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x08, + 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x0c, 0x72, 0x61, 0x6e, 0x64, + 0x61, 0x6f, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x73, 0x18, 0x89, 0x27, 0x20, 0x03, 0x28, 0x0c, 0x42, + 0x0c, 0x8a, 0xb5, 0x18, 0x08, 0x36, 0x35, 0x35, 0x33, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0b, 0x72, + 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x4d, 0x69, 0x78, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x09, 0x73, 0x6c, + 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x18, 0xf1, 0x2e, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, + 0x8a, 0xb5, 0x18, 0x04, 0x38, 0x31, 0x39, 0x32, 0x52, 0x09, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x1c, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0xd9, 0x36, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, + 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x1a, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x50, 0x61, 0x72, 0x74, + 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x1b, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, + 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xda, 0x36, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, + 0x37, 0x36, 0x52, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, + 0x12, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, + 0x69, 0x74, 0x73, 0x18, 0xc1, 0x3e, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2f, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x34, 0x8a, + 0xb5, 0x18, 0x01, 0x31, 0x52, 0x11, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x66, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, + 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc2, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x52, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4a, 0x75, 0x73, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x55, - 0x0a, 0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc4, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3f, 0x0a, 0x11, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0xa9, 0x46, 0x20, 0x03, 0x28, - 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, - 0x37, 0x37, 0x37, 0x36, 0x52, 0x10, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x5b, 0x0a, 0x16, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x18, 0xaa, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x74, 0x65, 0x65, 0x12, 0x55, 0x0a, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, - 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0xab, 0x46, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x11, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, - 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x79, 0x0a, 0x1f, 0x6c, 0x61, - 0x74, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x91, 0x4e, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x1c, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x45, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x15, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0xf9, - 0x55, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x97, 0x01, 0x0a, 0x1f, 0x6e, - 0x65, 0x78, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0xfa, - 0x55, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x1c, 0x6e, 0x65, 0x78, 0x74, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x12, 0x6a, 0x0a, 0x14, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, - 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x18, 0xfb, 0x55, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x0c, 0x92, - 0xb5, 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52, 0x13, 0x68, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, - 0x12, 0x40, 0x0a, 0x1c, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0xe1, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x53, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x83, 0x01, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x62, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, - 0x65, 0x18, 0xe2, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x47, 0x77, 0x65, 0x69, 0x52, - 0x17, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, - 0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x7d, 0x0a, 0x17, 0x65, 0x78, 0x69, 0x74, - 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6d, 0x65, 0x18, 0xe3, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x47, 0x77, 0x65, - 0x69, 0x52, 0x14, 0x65, 0x78, 0x69, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x77, 0x0a, 0x13, 0x65, 0x61, 0x72, 0x6c, 0x69, - 0x65, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0xe4, - 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x11, 0x65, - 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x45, 0x78, 0x69, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, - 0x12, 0x8f, 0x01, 0x0a, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x18, 0xe5, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, - 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x47, - 0x77, 0x65, 0x69, 0x52, 0x1d, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, - 0x6d, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x1c, 0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x5f, - 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x70, - 0x6f, 0x63, 0x68, 0x18, 0xe6, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, + 0x6e, 0x74, 0x52, 0x1b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x64, 0x0a, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, + 0xc3, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x55, 0x0a, 0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc4, 0x3e, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3f, 0x0a, 0x11, + 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x73, 0x18, 0xa9, 0x46, 0x20, 0x03, 0x28, 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, + 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x10, 0x69, 0x6e, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x5b, 0x0a, + 0x16, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0xaa, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, + 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x55, 0x0a, 0x13, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x18, 0xab, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x11, + 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x12, 0x77, 0x0a, 0x1f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x18, 0x91, 0x4e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x1c, 0x6c, 0x61, + 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x15, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0xf9, 0x55, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6e, 0x65, 0x78, 0x74, + 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, + 0x97, 0x01, 0x0a, 0x1f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0xfa, 0x55, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x1a, 0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x73, - 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x76, - 0x0a, 0x18, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x18, 0xe7, 0x5d, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, - 0x0d, 0x92, 0xb5, 0x18, 0x09, 0x31, 0x33, 0x34, 0x32, 0x31, 0x37, 0x37, 0x32, 0x38, 0x52, 0x16, - 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x7f, 0x0a, 0x1b, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 0x73, 0x18, 0xe8, 0x5d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, + 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x1c, 0x6e, 0x65, 0x78, + 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x6a, 0x0a, 0x14, 0x68, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, + 0x73, 0x18, 0xfb, 0x55, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x42, 0x0c, 0x92, 0xb5, 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, + 0x52, 0x13, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x69, 0x65, 0x73, 0x22, 0xb9, 0x19, 0x0a, 0x12, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x22, 0x0a, 0x0c, + 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0xe9, 0x07, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x3f, 0x0a, 0x17, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0xea, 0x07, 0x20, 0x01, + 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x67, 0x65, 0x6e, 0x65, + 0x73, 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x6f, 0x6f, + 0x74, 0x12, 0x5a, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x30, 0x0a, + 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x18, 0xec, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x74, - 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x42, 0x0d, 0x92, - 0xb5, 0x18, 0x09, 0x31, 0x33, 0x34, 0x32, 0x31, 0x37, 0x37, 0x32, 0x38, 0x52, 0x19, 0x70, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x12, 0x6f, 0x0a, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0xe9, 0x5d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6b, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6b, 0x12, + 0x59, 0x0a, 0x13, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0xd1, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x11, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x2d, 0x0a, 0x0b, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd2, 0x0f, 0x20, 0x03, 0x28, 0x0c, + 0x42, 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd3, 0x0f, 0x20, 0x03, 0x28, 0x0c, 0x42, + 0x0b, 0x8a, 0xb5, 0x18, 0x07, 0x38, 0x31, 0x39, 0x32, 0x2c, 0x33, 0x32, 0x52, 0x0a, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x10, 0x68, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0xd4, 0x0f, 0x20, + 0x03, 0x28, 0x0c, 0x42, 0x14, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x33, 0x32, 0x92, 0xb5, 0x18, + 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52, 0x0f, 0x68, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x69, 0x63, 0x61, 0x6c, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x3d, 0x0a, 0x09, 0x65, 0x74, + 0x68, 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0xb9, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x08, 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x0f, 0x65, 0x74, 0x68, + 0x31, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x73, 0x18, 0xba, 0x17, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x74, 0x68, 0x31, + 0x44, 0x61, 0x74, 0x61, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0d, + 0x65, 0x74, 0x68, 0x31, 0x44, 0x61, 0x74, 0x61, 0x56, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x2d, 0x0a, + 0x12, 0x65, 0x74, 0x68, 0x31, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0xbb, 0x17, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x74, 0x68, 0x31, + 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x54, 0x0a, 0x0a, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0xa1, 0x1f, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, + 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0xa2, + 0x1f, 0x20, 0x03, 0x28, 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, + 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x73, 0x12, 0x30, 0x0a, 0x0c, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x6d, 0x69, 0x78, + 0x65, 0x73, 0x18, 0x89, 0x27, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0c, 0x8a, 0xb5, 0x18, 0x08, 0x36, + 0x35, 0x35, 0x33, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0b, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x4d, + 0x69, 0x78, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x09, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, + 0x73, 0x18, 0xf1, 0x2e, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x38, 0x31, + 0x39, 0x32, 0x52, 0x09, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, + 0x1c, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, + 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xd9, 0x36, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, + 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, + 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x1b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0xda, 0x36, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, + 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x19, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, + 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x12, 0x6a, 0x75, 0x73, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0xc1, 0x3e, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, + 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x34, 0x8a, 0xb5, 0x18, 0x01, 0x31, 0x52, 0x11, + 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, + 0x73, 0x12, 0x66, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x6a, 0x75, + 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x18, 0xc2, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x1b, 0x70, 0x72, + 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x4a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x64, 0x0a, 0x1c, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc3, 0x3e, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x52, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4a, 0x75, 0x73, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x55, 0x0a, 0x14, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0xc4, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x13, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3f, 0x0a, 0x11, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0xa9, 0x46, 0x20, 0x03, + 0x28, 0x04, 0x42, 0x11, 0x92, 0xb5, 0x18, 0x0d, 0x31, 0x30, 0x39, 0x39, 0x35, 0x31, 0x31, 0x36, + 0x32, 0x37, 0x37, 0x37, 0x36, 0x52, 0x10, 0x69, 0x6e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x5b, 0x0a, 0x16, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x18, 0xaa, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x92, 0xb5, 0x18, 0x06, 0x32, 0x36, 0x32, 0x31, 0x34, - 0x34, 0x52, 0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8d, 0x01, 0x0a, 0x08, 0x50, 0x6f, 0x77, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0b, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x31, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, - 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x69, - 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x79, 0x22, 0x7f, 0x0a, 0x11, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x34, 0x0a, - 0x12, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, - 0x6f, 0x6f, 0x74, 0x12, 0x34, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, - 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x10, 0x73, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x6f, 0x6f, 0x74, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, - 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, + 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x12, 0x55, 0x0a, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, + 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0xab, 0x46, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x11, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, + 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x77, 0x0a, 0x1f, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x91, + 0x4e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x1c, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x15, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x77, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0xf9, 0x55, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, + 0x61, 0x77, 0x61, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x97, 0x01, 0x0a, 0x1f, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0xfa, 0x55, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x1c, 0x6e, 0x65, 0x78, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x12, 0x6a, 0x0a, 0x14, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, + 0x6c, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x18, 0xfb, 0x55, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x0c, 0x92, 0xb5, + 0x18, 0x08, 0x31, 0x36, 0x37, 0x37, 0x37, 0x32, 0x31, 0x36, 0x52, 0x13, 0x68, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, + 0x40, 0x0a, 0x1c, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0xe1, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x53, 0x74, 0x61, 0x72, 0x74, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x12, 0x83, 0x01, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x62, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x18, 0xe2, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, - 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x47, 0x77, 0x65, 0x69, 0x52, 0x17, + 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x7d, 0x0a, 0x17, 0x65, 0x78, 0x69, 0x74, 0x5f, + 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6d, 0x65, 0x18, 0xe3, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x47, 0x77, 0x65, 0x69, + 0x52, 0x14, 0x65, 0x78, 0x69, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x12, 0x77, 0x0a, 0x13, 0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, + 0x73, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0xe4, 0x5d, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x11, 0x65, 0x61, + 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x45, 0x78, 0x69, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, + 0x8f, 0x01, 0x0a, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6d, 0x65, 0x18, 0xe5, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, + 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x47, 0x77, + 0x65, 0x69, 0x52, 0x1d, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x54, 0x6f, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, + 0x65, 0x12, 0x89, 0x01, 0x0a, 0x1c, 0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x5f, 0x63, + 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x70, 0x6f, + 0x63, 0x68, 0x18, 0xe6, 0x5d, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, + 0x68, 0x52, 0x1a, 0x65, 0x61, 0x72, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x6f, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x60, 0x0a, + 0x10, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x73, 0x18, 0xe7, 0x5d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, + 0x0d, 0x92, 0xb5, 0x18, 0x09, 0x31, 0x33, 0x34, 0x32, 0x31, 0x37, 0x37, 0x32, 0x38, 0x52, 0x0f, + 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, + 0x7f, 0x0a, 0x1b, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, + 0x61, 0x6c, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x18, 0xe8, + 0x5d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x42, 0x0d, 0x92, 0xb5, 0x18, 0x09, 0x31, 0x33, 0x34, 0x32, + 0x31, 0x37, 0x37, 0x32, 0x38, 0x52, 0x19, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, + 0x72, 0x74, 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, + 0x12, 0x6f, 0x0a, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73, + 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xe9, 0x5d, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, + 0x92, 0xb5, 0x18, 0x06, 0x32, 0x36, 0x32, 0x31, 0x34, 0x34, 0x52, 0x15, 0x70, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, + 0x10, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, + 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, + 0x31, 0x41, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3260,23 +3259,23 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_rawDescGZIP() []byte { var file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_proto_prysm_v1alpha1_beacon_state_proto_goTypes = []interface{}{ (*BeaconState)(nil), // 0: ethereum.eth.v1alpha1.BeaconState - (*BeaconStateAltair)(nil), // 1: ethereum.eth.v1alpha1.BeaconStateAltair - (*Fork)(nil), // 2: ethereum.eth.v1alpha1.Fork - (*PendingAttestation)(nil), // 3: ethereum.eth.v1alpha1.PendingAttestation - (*HistoricalBatch)(nil), // 4: ethereum.eth.v1alpha1.HistoricalBatch - (*StateSummary)(nil), // 5: ethereum.eth.v1alpha1.StateSummary - (*SigningData)(nil), // 6: ethereum.eth.v1alpha1.SigningData - (*ForkData)(nil), // 7: ethereum.eth.v1alpha1.ForkData - (*CheckPtInfo)(nil), // 8: ethereum.eth.v1alpha1.CheckPtInfo - (*DepositMessage)(nil), // 9: ethereum.eth.v1alpha1.DepositMessage - (*SyncCommittee)(nil), // 10: ethereum.eth.v1alpha1.SyncCommittee - (*SyncAggregatorSelectionData)(nil), // 11: ethereum.eth.v1alpha1.SyncAggregatorSelectionData - (*BeaconStateBellatrix)(nil), // 12: ethereum.eth.v1alpha1.BeaconStateBellatrix - (*BeaconStateCapella)(nil), // 13: ethereum.eth.v1alpha1.BeaconStateCapella - (*BeaconStateDeneb)(nil), // 14: ethereum.eth.v1alpha1.BeaconStateDeneb - (*BeaconStateElectra)(nil), // 15: ethereum.eth.v1alpha1.BeaconStateElectra - (*PowBlock)(nil), // 16: ethereum.eth.v1alpha1.PowBlock - (*HistoricalSummary)(nil), // 17: ethereum.eth.v1alpha1.HistoricalSummary + (*Fork)(nil), // 1: ethereum.eth.v1alpha1.Fork + (*PendingAttestation)(nil), // 2: ethereum.eth.v1alpha1.PendingAttestation + (*HistoricalBatch)(nil), // 3: ethereum.eth.v1alpha1.HistoricalBatch + (*StateSummary)(nil), // 4: ethereum.eth.v1alpha1.StateSummary + (*SigningData)(nil), // 5: ethereum.eth.v1alpha1.SigningData + (*ForkData)(nil), // 6: ethereum.eth.v1alpha1.ForkData + (*CheckPtInfo)(nil), // 7: ethereum.eth.v1alpha1.CheckPtInfo + (*DepositMessage)(nil), // 8: ethereum.eth.v1alpha1.DepositMessage + (*PowBlock)(nil), // 9: ethereum.eth.v1alpha1.PowBlock + (*BeaconStateAltair)(nil), // 10: ethereum.eth.v1alpha1.BeaconStateAltair + (*SyncCommittee)(nil), // 11: ethereum.eth.v1alpha1.SyncCommittee + (*SyncAggregatorSelectionData)(nil), // 12: ethereum.eth.v1alpha1.SyncAggregatorSelectionData + (*BeaconStateBellatrix)(nil), // 13: ethereum.eth.v1alpha1.BeaconStateBellatrix + (*BeaconStateCapella)(nil), // 14: ethereum.eth.v1alpha1.BeaconStateCapella + (*HistoricalSummary)(nil), // 15: ethereum.eth.v1alpha1.HistoricalSummary + (*BeaconStateDeneb)(nil), // 16: ethereum.eth.v1alpha1.BeaconStateDeneb + (*BeaconStateElectra)(nil), // 17: ethereum.eth.v1alpha1.BeaconStateElectra (*BeaconBlockHeader)(nil), // 18: ethereum.eth.v1alpha1.BeaconBlockHeader (*Eth1Data)(nil), // 19: ethereum.eth.v1alpha1.Eth1Data (*Validator)(nil), // 20: ethereum.eth.v1alpha1.Validator @@ -3285,35 +3284,34 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_goTypes = []interface{}{ (*v1.ExecutionPayloadHeader)(nil), // 23: ethereum.engine.v1.ExecutionPayloadHeader (*v1.ExecutionPayloadHeaderCapella)(nil), // 24: ethereum.engine.v1.ExecutionPayloadHeaderCapella (*v1.ExecutionPayloadHeaderDeneb)(nil), // 25: ethereum.engine.v1.ExecutionPayloadHeaderDeneb - (*v1.ExecutionPayloadHeaderElectra)(nil), // 26: ethereum.engine.v1.ExecutionPayloadHeaderElectra - (*PendingBalanceDeposit)(nil), // 27: ethereum.eth.v1alpha1.PendingBalanceDeposit - (*PendingPartialWithdrawal)(nil), // 28: ethereum.eth.v1alpha1.PendingPartialWithdrawal - (*PendingConsolidation)(nil), // 29: ethereum.eth.v1alpha1.PendingConsolidation + (*PendingDeposit)(nil), // 26: ethereum.eth.v1alpha1.PendingDeposit + (*PendingPartialWithdrawal)(nil), // 27: ethereum.eth.v1alpha1.PendingPartialWithdrawal + (*PendingConsolidation)(nil), // 28: ethereum.eth.v1alpha1.PendingConsolidation } var file_proto_prysm_v1alpha1_beacon_state_proto_depIdxs = []int32{ - 2, // 0: ethereum.eth.v1alpha1.BeaconState.fork:type_name -> ethereum.eth.v1alpha1.Fork + 1, // 0: ethereum.eth.v1alpha1.BeaconState.fork:type_name -> ethereum.eth.v1alpha1.Fork 18, // 1: ethereum.eth.v1alpha1.BeaconState.latest_block_header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader 19, // 2: ethereum.eth.v1alpha1.BeaconState.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data 19, // 3: ethereum.eth.v1alpha1.BeaconState.eth1_data_votes:type_name -> ethereum.eth.v1alpha1.Eth1Data 20, // 4: ethereum.eth.v1alpha1.BeaconState.validators:type_name -> ethereum.eth.v1alpha1.Validator - 3, // 5: ethereum.eth.v1alpha1.BeaconState.previous_epoch_attestations:type_name -> ethereum.eth.v1alpha1.PendingAttestation - 3, // 6: ethereum.eth.v1alpha1.BeaconState.current_epoch_attestations:type_name -> ethereum.eth.v1alpha1.PendingAttestation + 2, // 5: ethereum.eth.v1alpha1.BeaconState.previous_epoch_attestations:type_name -> ethereum.eth.v1alpha1.PendingAttestation + 2, // 6: ethereum.eth.v1alpha1.BeaconState.current_epoch_attestations:type_name -> ethereum.eth.v1alpha1.PendingAttestation 21, // 7: ethereum.eth.v1alpha1.BeaconState.previous_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 8: ethereum.eth.v1alpha1.BeaconState.current_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 9: ethereum.eth.v1alpha1.BeaconState.finalized_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint - 2, // 10: ethereum.eth.v1alpha1.BeaconStateAltair.fork:type_name -> ethereum.eth.v1alpha1.Fork - 18, // 11: ethereum.eth.v1alpha1.BeaconStateAltair.latest_block_header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader - 19, // 12: ethereum.eth.v1alpha1.BeaconStateAltair.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data - 19, // 13: ethereum.eth.v1alpha1.BeaconStateAltair.eth1_data_votes:type_name -> ethereum.eth.v1alpha1.Eth1Data - 20, // 14: ethereum.eth.v1alpha1.BeaconStateAltair.validators:type_name -> ethereum.eth.v1alpha1.Validator - 21, // 15: ethereum.eth.v1alpha1.BeaconStateAltair.previous_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint - 21, // 16: ethereum.eth.v1alpha1.BeaconStateAltair.current_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint - 21, // 17: ethereum.eth.v1alpha1.BeaconStateAltair.finalized_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint - 10, // 18: ethereum.eth.v1alpha1.BeaconStateAltair.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee - 10, // 19: ethereum.eth.v1alpha1.BeaconStateAltair.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee - 22, // 20: ethereum.eth.v1alpha1.PendingAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData - 2, // 21: ethereum.eth.v1alpha1.CheckPtInfo.fork:type_name -> ethereum.eth.v1alpha1.Fork - 2, // 22: ethereum.eth.v1alpha1.BeaconStateBellatrix.fork:type_name -> ethereum.eth.v1alpha1.Fork + 22, // 10: ethereum.eth.v1alpha1.PendingAttestation.data:type_name -> ethereum.eth.v1alpha1.AttestationData + 1, // 11: ethereum.eth.v1alpha1.CheckPtInfo.fork:type_name -> ethereum.eth.v1alpha1.Fork + 1, // 12: ethereum.eth.v1alpha1.BeaconStateAltair.fork:type_name -> ethereum.eth.v1alpha1.Fork + 18, // 13: ethereum.eth.v1alpha1.BeaconStateAltair.latest_block_header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader + 19, // 14: ethereum.eth.v1alpha1.BeaconStateAltair.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data + 19, // 15: ethereum.eth.v1alpha1.BeaconStateAltair.eth1_data_votes:type_name -> ethereum.eth.v1alpha1.Eth1Data + 20, // 16: ethereum.eth.v1alpha1.BeaconStateAltair.validators:type_name -> ethereum.eth.v1alpha1.Validator + 21, // 17: ethereum.eth.v1alpha1.BeaconStateAltair.previous_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint + 21, // 18: ethereum.eth.v1alpha1.BeaconStateAltair.current_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint + 21, // 19: ethereum.eth.v1alpha1.BeaconStateAltair.finalized_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint + 11, // 20: ethereum.eth.v1alpha1.BeaconStateAltair.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 11, // 21: ethereum.eth.v1alpha1.BeaconStateAltair.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 1, // 22: ethereum.eth.v1alpha1.BeaconStateBellatrix.fork:type_name -> ethereum.eth.v1alpha1.Fork 18, // 23: ethereum.eth.v1alpha1.BeaconStateBellatrix.latest_block_header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader 19, // 24: ethereum.eth.v1alpha1.BeaconStateBellatrix.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data 19, // 25: ethereum.eth.v1alpha1.BeaconStateBellatrix.eth1_data_votes:type_name -> ethereum.eth.v1alpha1.Eth1Data @@ -3321,10 +3319,10 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_depIdxs = []int32{ 21, // 27: ethereum.eth.v1alpha1.BeaconStateBellatrix.previous_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 28: ethereum.eth.v1alpha1.BeaconStateBellatrix.current_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 29: ethereum.eth.v1alpha1.BeaconStateBellatrix.finalized_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint - 10, // 30: ethereum.eth.v1alpha1.BeaconStateBellatrix.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee - 10, // 31: ethereum.eth.v1alpha1.BeaconStateBellatrix.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 11, // 30: ethereum.eth.v1alpha1.BeaconStateBellatrix.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 11, // 31: ethereum.eth.v1alpha1.BeaconStateBellatrix.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee 23, // 32: ethereum.eth.v1alpha1.BeaconStateBellatrix.latest_execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeader - 2, // 33: ethereum.eth.v1alpha1.BeaconStateCapella.fork:type_name -> ethereum.eth.v1alpha1.Fork + 1, // 33: ethereum.eth.v1alpha1.BeaconStateCapella.fork:type_name -> ethereum.eth.v1alpha1.Fork 18, // 34: ethereum.eth.v1alpha1.BeaconStateCapella.latest_block_header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader 19, // 35: ethereum.eth.v1alpha1.BeaconStateCapella.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data 19, // 36: ethereum.eth.v1alpha1.BeaconStateCapella.eth1_data_votes:type_name -> ethereum.eth.v1alpha1.Eth1Data @@ -3332,11 +3330,11 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_depIdxs = []int32{ 21, // 38: ethereum.eth.v1alpha1.BeaconStateCapella.previous_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 39: ethereum.eth.v1alpha1.BeaconStateCapella.current_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 40: ethereum.eth.v1alpha1.BeaconStateCapella.finalized_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint - 10, // 41: ethereum.eth.v1alpha1.BeaconStateCapella.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee - 10, // 42: ethereum.eth.v1alpha1.BeaconStateCapella.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 11, // 41: ethereum.eth.v1alpha1.BeaconStateCapella.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 11, // 42: ethereum.eth.v1alpha1.BeaconStateCapella.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee 24, // 43: ethereum.eth.v1alpha1.BeaconStateCapella.latest_execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderCapella - 17, // 44: ethereum.eth.v1alpha1.BeaconStateCapella.historical_summaries:type_name -> ethereum.eth.v1alpha1.HistoricalSummary - 2, // 45: ethereum.eth.v1alpha1.BeaconStateDeneb.fork:type_name -> ethereum.eth.v1alpha1.Fork + 15, // 44: ethereum.eth.v1alpha1.BeaconStateCapella.historical_summaries:type_name -> ethereum.eth.v1alpha1.HistoricalSummary + 1, // 45: ethereum.eth.v1alpha1.BeaconStateDeneb.fork:type_name -> ethereum.eth.v1alpha1.Fork 18, // 46: ethereum.eth.v1alpha1.BeaconStateDeneb.latest_block_header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader 19, // 47: ethereum.eth.v1alpha1.BeaconStateDeneb.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data 19, // 48: ethereum.eth.v1alpha1.BeaconStateDeneb.eth1_data_votes:type_name -> ethereum.eth.v1alpha1.Eth1Data @@ -3344,11 +3342,11 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_depIdxs = []int32{ 21, // 50: ethereum.eth.v1alpha1.BeaconStateDeneb.previous_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 51: ethereum.eth.v1alpha1.BeaconStateDeneb.current_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 52: ethereum.eth.v1alpha1.BeaconStateDeneb.finalized_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint - 10, // 53: ethereum.eth.v1alpha1.BeaconStateDeneb.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee - 10, // 54: ethereum.eth.v1alpha1.BeaconStateDeneb.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 11, // 53: ethereum.eth.v1alpha1.BeaconStateDeneb.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 11, // 54: ethereum.eth.v1alpha1.BeaconStateDeneb.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee 25, // 55: ethereum.eth.v1alpha1.BeaconStateDeneb.latest_execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb - 17, // 56: ethereum.eth.v1alpha1.BeaconStateDeneb.historical_summaries:type_name -> ethereum.eth.v1alpha1.HistoricalSummary - 2, // 57: ethereum.eth.v1alpha1.BeaconStateElectra.fork:type_name -> ethereum.eth.v1alpha1.Fork + 15, // 56: ethereum.eth.v1alpha1.BeaconStateDeneb.historical_summaries:type_name -> ethereum.eth.v1alpha1.HistoricalSummary + 1, // 57: ethereum.eth.v1alpha1.BeaconStateElectra.fork:type_name -> ethereum.eth.v1alpha1.Fork 18, // 58: ethereum.eth.v1alpha1.BeaconStateElectra.latest_block_header:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader 19, // 59: ethereum.eth.v1alpha1.BeaconStateElectra.eth1_data:type_name -> ethereum.eth.v1alpha1.Eth1Data 19, // 60: ethereum.eth.v1alpha1.BeaconStateElectra.eth1_data_votes:type_name -> ethereum.eth.v1alpha1.Eth1Data @@ -3356,13 +3354,13 @@ var file_proto_prysm_v1alpha1_beacon_state_proto_depIdxs = []int32{ 21, // 62: ethereum.eth.v1alpha1.BeaconStateElectra.previous_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 63: ethereum.eth.v1alpha1.BeaconStateElectra.current_justified_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint 21, // 64: ethereum.eth.v1alpha1.BeaconStateElectra.finalized_checkpoint:type_name -> ethereum.eth.v1alpha1.Checkpoint - 10, // 65: ethereum.eth.v1alpha1.BeaconStateElectra.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee - 10, // 66: ethereum.eth.v1alpha1.BeaconStateElectra.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee - 26, // 67: ethereum.eth.v1alpha1.BeaconStateElectra.latest_execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderElectra - 17, // 68: ethereum.eth.v1alpha1.BeaconStateElectra.historical_summaries:type_name -> ethereum.eth.v1alpha1.HistoricalSummary - 27, // 69: ethereum.eth.v1alpha1.BeaconStateElectra.pending_balance_deposits:type_name -> ethereum.eth.v1alpha1.PendingBalanceDeposit - 28, // 70: ethereum.eth.v1alpha1.BeaconStateElectra.pending_partial_withdrawals:type_name -> ethereum.eth.v1alpha1.PendingPartialWithdrawal - 29, // 71: ethereum.eth.v1alpha1.BeaconStateElectra.pending_consolidations:type_name -> ethereum.eth.v1alpha1.PendingConsolidation + 11, // 65: ethereum.eth.v1alpha1.BeaconStateElectra.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 11, // 66: ethereum.eth.v1alpha1.BeaconStateElectra.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 25, // 67: ethereum.eth.v1alpha1.BeaconStateElectra.latest_execution_payload_header:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb + 15, // 68: ethereum.eth.v1alpha1.BeaconStateElectra.historical_summaries:type_name -> ethereum.eth.v1alpha1.HistoricalSummary + 26, // 69: ethereum.eth.v1alpha1.BeaconStateElectra.pending_deposits:type_name -> ethereum.eth.v1alpha1.PendingDeposit + 27, // 70: ethereum.eth.v1alpha1.BeaconStateElectra.pending_partial_withdrawals:type_name -> ethereum.eth.v1alpha1.PendingPartialWithdrawal + 28, // 71: ethereum.eth.v1alpha1.BeaconStateElectra.pending_consolidations:type_name -> ethereum.eth.v1alpha1.PendingConsolidation 72, // [72:72] is the sub-list for method output_type 72, // [72:72] is the sub-list for method input_type 72, // [72:72] is the sub-list for extension type_name @@ -3393,7 +3391,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconStateAltair); i { + switch v := v.(*Fork); i { case 0: return &v.state case 1: @@ -3405,7 +3403,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Fork); i { + switch v := v.(*PendingAttestation); i { case 0: return &v.state case 1: @@ -3417,7 +3415,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PendingAttestation); i { + switch v := v.(*HistoricalBatch); i { case 0: return &v.state case 1: @@ -3429,7 +3427,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HistoricalBatch); i { + switch v := v.(*StateSummary); i { case 0: return &v.state case 1: @@ -3441,7 +3439,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StateSummary); i { + switch v := v.(*SigningData); i { case 0: return &v.state case 1: @@ -3453,7 +3451,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SigningData); i { + switch v := v.(*ForkData); i { case 0: return &v.state case 1: @@ -3465,7 +3463,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ForkData); i { + switch v := v.(*CheckPtInfo); i { case 0: return &v.state case 1: @@ -3477,7 +3475,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CheckPtInfo); i { + switch v := v.(*DepositMessage); i { case 0: return &v.state case 1: @@ -3489,7 +3487,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DepositMessage); i { + switch v := v.(*PowBlock); i { case 0: return &v.state case 1: @@ -3501,7 +3499,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncCommittee); i { + switch v := v.(*BeaconStateAltair); i { case 0: return &v.state case 1: @@ -3513,7 +3511,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncAggregatorSelectionData); i { + switch v := v.(*SyncCommittee); i { case 0: return &v.state case 1: @@ -3525,7 +3523,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconStateBellatrix); i { + switch v := v.(*SyncAggregatorSelectionData); i { case 0: return &v.state case 1: @@ -3537,7 +3535,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconStateCapella); i { + switch v := v.(*BeaconStateBellatrix); i { case 0: return &v.state case 1: @@ -3549,7 +3547,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconStateDeneb); i { + switch v := v.(*BeaconStateCapella); i { case 0: return &v.state case 1: @@ -3561,7 +3559,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BeaconStateElectra); i { + switch v := v.(*HistoricalSummary); i { case 0: return &v.state case 1: @@ -3573,7 +3571,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PowBlock); i { + switch v := v.(*BeaconStateDeneb); i { case 0: return &v.state case 1: @@ -3585,7 +3583,7 @@ func file_proto_prysm_v1alpha1_beacon_state_proto_init() { } } file_proto_prysm_v1alpha1_beacon_state_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HistoricalSummary); i { + switch v := v.(*BeaconStateElectra); i { case 0: return &v.state case 1: diff --git a/proto/prysm/v1alpha1/beacon_state.pb.gw.go b/proto/prysm/v1alpha1/beacon_state.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/beacon_state.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/beacon_state.proto b/proto/prysm/v1alpha1/beacon_state.proto index 8206df1d4ba7..26f460cf6b49 100644 --- a/proto/prysm/v1alpha1/beacon_state.proto +++ b/proto/prysm/v1alpha1/beacon_state.proto @@ -16,113 +16,103 @@ option java_outer_classname = "BeaconStateProto"; option java_package = "org.ethereum.eth.v1alpha1"; option php_namespace = "Ethereum\\Eth\\v1alpha1"; +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + message BeaconState { // Versioning [1001-2000] uint64 genesis_time = 1001; - bytes genesis_validators_root = 1002 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 slot = 1003 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + bytes genesis_validators_root = 1002 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 slot = 1003 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; Fork fork = 1004; // History [2001-3000] BeaconBlockHeader latest_block_header = 2001; - repeated bytes block_roots = 2002 [(ethereum.eth.ext.ssz_size) = "block_roots.size"]; - repeated bytes state_roots = 2003 [(ethereum.eth.ext.ssz_size) = "state_roots.size"]; - repeated bytes historical_roots = 2004 [(ethereum.eth.ext.ssz_size) = "?,32", (ethereum.eth.ext.ssz_max) = "16777216"]; + repeated bytes block_roots = 2002 + [ (ethereum.eth.ext.ssz_size) = "block_roots.size" ]; + repeated bytes state_roots = 2003 + [ (ethereum.eth.ext.ssz_size) = "state_roots.size" ]; + repeated bytes historical_roots = 2004 [ + (ethereum.eth.ext.ssz_size) = "?,32", + (ethereum.eth.ext.ssz_max) = "16777216" + ]; // Eth1 [3001-4000] Eth1Data eth1_data = 3001; - repeated Eth1Data eth1_data_votes = 3002 [(ethereum.eth.ext.ssz_max) = "eth1_data_votes.size"]; + repeated Eth1Data eth1_data_votes = 3002 + [ (ethereum.eth.ext.ssz_max) = "eth1_data_votes.size" ]; uint64 eth1_deposit_index = 3003; // Registry [4001-5000] - repeated Validator validators = 4001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - repeated uint64 balances = 4002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + repeated Validator validators = 4001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + repeated uint64 balances = 4002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Randomness [5001-6000] - repeated bytes randao_mixes = 5001 [(ethereum.eth.ext.ssz_size) = "randao_mixes.size"]; + repeated bytes randao_mixes = 5001 + [ (ethereum.eth.ext.ssz_size) = "randao_mixes.size" ]; // Slashings [6001-7000] - repeated uint64 slashings = 6001 [(ethereum.eth.ext.ssz_size) = "slashings.size"]; + repeated uint64 slashings = 6001 + [ (ethereum.eth.ext.ssz_size) = "slashings.size" ]; // Attestations [7001-8000] - repeated PendingAttestation previous_epoch_attestations = 7001 [(ethereum.eth.ext.ssz_max) = "previous_epoch_attestations.max"]; - repeated PendingAttestation current_epoch_attestations = 7002 [(ethereum.eth.ext.ssz_max) = "current_epoch_attestations.max"]; + repeated PendingAttestation previous_epoch_attestations = 7001 + [ (ethereum.eth.ext.ssz_max) = "previous_epoch_attestations.max" ]; + repeated PendingAttestation current_epoch_attestations = 7002 + [ (ethereum.eth.ext.ssz_max) = "current_epoch_attestations.max" ]; // Finality [8001-9000] // Spec type [4]Bitvector which means this would be a fixed size of 4 bits. - bytes justification_bits = 8001 [(ethereum.eth.ext.ssz_size) = "1", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector4"]; + bytes justification_bits = 8001 [ + (ethereum.eth.ext.ssz_size) = "1", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector4" + ]; Checkpoint previous_justified_checkpoint = 8002; Checkpoint current_justified_checkpoint = 8003; Checkpoint finalized_checkpoint = 8004; } -// The beacon state for Altair hard fork 1. -// Reference: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#beaconstate -message BeaconStateAltair { - // Versioning [1001-2000] - uint64 genesis_time = 1001; - bytes genesis_validators_root = 1002 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 slot = 1003 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - Fork fork = 1004; - - // History [2001-3000] - BeaconBlockHeader latest_block_header = 2001; - repeated bytes block_roots = 2002 [(ethereum.eth.ext.ssz_size) = "block_roots.size"]; - repeated bytes state_roots = 2003 [(ethereum.eth.ext.ssz_size) = "state_roots.size"]; - repeated bytes historical_roots = 2004 [(ethereum.eth.ext.ssz_size) = "?,32", (ethereum.eth.ext.ssz_max) = "16777216"]; - - // Eth1 [3001-4000] - Eth1Data eth1_data = 3001; - repeated Eth1Data eth1_data_votes = 3002 [(ethereum.eth.ext.ssz_max) = "eth1_data_votes.size"]; - uint64 eth1_deposit_index = 3003; - - // Registry [4001-5000] - repeated Validator validators = 4001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - repeated uint64 balances = 4002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - - // Randomness [5001-6000] - repeated bytes randao_mixes = 5001 [(ethereum.eth.ext.ssz_size) = "randao_mixes.size"]; - - // Slashings [6001-7000] - repeated uint64 slashings = 6001 [(ethereum.eth.ext.ssz_size) = "slashings.size"]; - - // Participation [7001-8000] - bytes previous_epoch_participation = 7001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; // [New in Altair, replaced previous_epoch_attestations] - bytes current_epoch_participation = 7002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; // [New in Altair, replaced current_epoch_attestations] - - // Finality [8001-9000] - // Spec type [4]Bitvector which means this would be a fixed size of 4 bits. - bytes justification_bits = 8001 [(ethereum.eth.ext.ssz_size) = "1", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector4"]; - Checkpoint previous_justified_checkpoint = 8002; - Checkpoint current_justified_checkpoint = 8003; - Checkpoint finalized_checkpoint = 8004; - - // New Altair fields [9001-10000] - repeated uint64 inactivity_scores = 9001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; // [New in Altair] - SyncCommittee current_sync_committee = 9002; // [New in Altair] - SyncCommittee next_sync_committee = 9003; // [New in Altair] -} - message Fork { - bytes previous_version = 1 [(ethereum.eth.ext.ssz_size) = "4"]; - bytes current_version = 2 [(ethereum.eth.ext.ssz_size) = "4"]; - uint64 epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + bytes previous_version = 1 [ (ethereum.eth.ext.ssz_size) = "4" ]; + bytes current_version = 2 [ (ethereum.eth.ext.ssz_size) = "4" ]; + uint64 epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; } message PendingAttestation { // Bitfield representation of validator indices that have voted exactly // the same vote and have been aggregated into this attestation. - bytes aggregation_bits = 1 [(ethereum.eth.ext.ssz_max) = "2048", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitlist"]; + bytes aggregation_bits = 1 [ + (ethereum.eth.ext.ssz_max) = "2048", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitlist" + ]; AttestationData data = 2; // The difference of when attestation gets created and get included on chain. - uint64 inclusion_delay = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 inclusion_delay = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; // The proposer who included the attestation in the block. - uint64 proposer_index = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + uint64 proposer_index = 4 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; } message HistoricalBatch { - repeated bytes block_roots = 1 [(ethereum.eth.ext.ssz_size) = "block_roots.size"]; - repeated bytes state_roots = 2 [(ethereum.eth.ext.ssz_size) = "state_roots.size"]; + repeated bytes block_roots = 1 + [ (ethereum.eth.ext.ssz_size) = "block_roots.size" ]; + repeated bytes state_roots = 2 + [ (ethereum.eth.ext.ssz_size) = "state_roots.size" ]; } // The state summary object is defined for summarizing a state @@ -131,29 +121,34 @@ message HistoricalBatch { // and blocks. message StateSummary { // The slot of the state. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; // The block root of the state. bytes root = 2; } message SigningData { // The root of the object being signed. - bytes object_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes object_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; // The domain for the particular object being signed. - bytes domain = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes domain = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message ForkData { // The current version of the fork. - bytes current_version = 4 [(ethereum.eth.ext.ssz_size) = "4"]; + bytes current_version = 4 [ (ethereum.eth.ext.ssz_size) = "4" ]; // The genesis validators root of the fork. - bytes genesis_validators_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes genesis_validators_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message CheckPtInfo { - // The randao seed which the check point refers to, this will be used to retrieve shuffled indices. + // The randao seed which the check point refers to, this will be used to + // retrieve shuffled indices. bytes seed = 1; - // The genesis root which the check point refers to. This ensures same seed can't happen on different chain. + // The genesis root which the check point refers to. This ensures same seed + // can't happen on different chain. bytes genesis_root = 2; // Validators that were active at that check point. repeated uint64 active_indices = 3; @@ -163,264 +158,478 @@ message CheckPtInfo { Fork fork = 5; } -// DepositMessage serves as a subset of deposit data in order to derive the signing root. +// DepositMessage serves as a subset of deposit data in order to derive the +// signing root. message DepositMessage { // 48 byte BLS public key of the validator. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; + bytes public_key = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; // A 32 byte hash of the withdrawal address public key. - bytes withdrawal_credentials = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes withdrawal_credentials = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Deposit amount in gwei. uint64 amount = 3; } -// SyncCommittee serves as committees to facilitate light client syncing to beacon chain. +// PowBlock is a definition from Bellatrix fork choice spec to represent a block +// with total difficulty in the PoW chain. Spec: class PowBlock(Container): +// block_hash: Hash32 +// parent_hash: Hash32 +// total_difficulty: uint256 +message PowBlock { + bytes block_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes parent_hash = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes total_difficulty = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; +} + +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- + +// The beacon state for Altair hard fork 1. +// Reference: +// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#beaconstate +message BeaconStateAltair { + // Versioning [1001-2000] + uint64 genesis_time = 1001; + bytes genesis_validators_root = 1002 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 slot = 1003 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + Fork fork = 1004; + + // History [2001-3000] + BeaconBlockHeader latest_block_header = 2001; + repeated bytes block_roots = 2002 + [ (ethereum.eth.ext.ssz_size) = "block_roots.size" ]; + repeated bytes state_roots = 2003 + [ (ethereum.eth.ext.ssz_size) = "state_roots.size" ]; + repeated bytes historical_roots = 2004 [ + (ethereum.eth.ext.ssz_size) = "?,32", + (ethereum.eth.ext.ssz_max) = "16777216" + ]; + + // Eth1 [3001-4000] + Eth1Data eth1_data = 3001; + repeated Eth1Data eth1_data_votes = 3002 + [ (ethereum.eth.ext.ssz_max) = "eth1_data_votes.size" ]; + uint64 eth1_deposit_index = 3003; + + // Registry [4001-5000] + repeated Validator validators = 4001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + repeated uint64 balances = 4002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + + // Randomness [5001-6000] + repeated bytes randao_mixes = 5001 + [ (ethereum.eth.ext.ssz_size) = "randao_mixes.size" ]; + + // Slashings [6001-7000] + repeated uint64 slashings = 6001 + [ (ethereum.eth.ext.ssz_size) = "slashings.size" ]; + + // Participation [7001-8000] + bytes previous_epoch_participation = 7001 [ + (ethereum.eth.ext.ssz_max) = "1099511627776" + ]; // [New in Altair, replaced previous_epoch_attestations] + bytes current_epoch_participation = 7002 [ + (ethereum.eth.ext.ssz_max) = "1099511627776" + ]; // [New in Altair, replaced current_epoch_attestations] + + // Finality [8001-9000] + // Spec type [4]Bitvector which means this would be a fixed size of 4 bits. + bytes justification_bits = 8001 [ + (ethereum.eth.ext.ssz_size) = "1", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector4" + ]; + Checkpoint previous_justified_checkpoint = 8002; + Checkpoint current_justified_checkpoint = 8003; + Checkpoint finalized_checkpoint = 8004; + + // New Altair fields [9001-10000] + repeated uint64 inactivity_scores = 9001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // [New in Altair] + SyncCommittee current_sync_committee = 9002; // [New in Altair] + SyncCommittee next_sync_committee = 9003; // [New in Altair] +} + +// SyncCommittee serves as committees to facilitate light client syncing to +// beacon chain. message SyncCommittee { - repeated bytes pubkeys = 1 [(ethereum.eth.ext.ssz_size) = "sync_committee_bits.size,48"]; - bytes aggregate_pubkey = 2 [(ethereum.eth.ext.ssz_size) = "48"]; + repeated bytes pubkeys = 1 + [ (ethereum.eth.ext.ssz_size) = "sync_committee_bits.size,48" ]; + bytes aggregate_pubkey = 2 [ (ethereum.eth.ext.ssz_size) = "48" ]; } -// SyncAggregatorSelectionData is used to sign over and then check whether the aggregator is selected within a subcommittee. +// SyncAggregatorSelectionData is used to sign over and then check whether the +// aggregator is selected within a subcommittee. message SyncAggregatorSelectionData { // Slot of this signing data. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; // Subcommittee index of this signing data. uint64 subcommittee_index = 2; } +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + message BeaconStateBellatrix { // Versioning [1001-2000] uint64 genesis_time = 1001; - bytes genesis_validators_root = 1002 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 slot = 1003 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + bytes genesis_validators_root = 1002 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 slot = 1003 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; Fork fork = 1004; // History [2001-3000] BeaconBlockHeader latest_block_header = 2001; - repeated bytes block_roots = 2002 [(ethereum.eth.ext.ssz_size) = "block_roots.size"]; - repeated bytes state_roots = 2003 [(ethereum.eth.ext.ssz_size) = "state_roots.size"]; - repeated bytes historical_roots = 2004 [(ethereum.eth.ext.ssz_size) = "?,32", (ethereum.eth.ext.ssz_max) = "16777216"]; + repeated bytes block_roots = 2002 + [ (ethereum.eth.ext.ssz_size) = "block_roots.size" ]; + repeated bytes state_roots = 2003 + [ (ethereum.eth.ext.ssz_size) = "state_roots.size" ]; + repeated bytes historical_roots = 2004 [ + (ethereum.eth.ext.ssz_size) = "?,32", + (ethereum.eth.ext.ssz_max) = "16777216" + ]; // Eth1 [3001-4000] Eth1Data eth1_data = 3001; - repeated Eth1Data eth1_data_votes = 3002 [(ethereum.eth.ext.ssz_max) = "eth1_data_votes.size"]; + repeated Eth1Data eth1_data_votes = 3002 + [ (ethereum.eth.ext.ssz_max) = "eth1_data_votes.size" ]; uint64 eth1_deposit_index = 3003; // Registry [4001-5000] - repeated Validator validators = 4001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - repeated uint64 balances = 4002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + repeated Validator validators = 4001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + repeated uint64 balances = 4002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Randomness [5001-6000] - repeated bytes randao_mixes = 5001 [(ethereum.eth.ext.ssz_size) = "randao_mixes.size"]; + repeated bytes randao_mixes = 5001 + [ (ethereum.eth.ext.ssz_size) = "randao_mixes.size" ]; // Slashings [6001-7000] - repeated uint64 slashings = 6001 [(ethereum.eth.ext.ssz_size) = "slashings.size"]; + repeated uint64 slashings = 6001 + [ (ethereum.eth.ext.ssz_size) = "slashings.size" ]; // Participation [7001-8000] - bytes previous_epoch_participation = 7001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - bytes current_epoch_participation = 7002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + bytes previous_epoch_participation = 7001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + bytes current_epoch_participation = 7002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Finality [8001-9000] // Spec type [4]Bitvector which means this would be a fixed size of 4 bits. - bytes justification_bits = 8001 [(ethereum.eth.ext.ssz_size) = "1", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector4"]; + bytes justification_bits = 8001 [ + (ethereum.eth.ext.ssz_size) = "1", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector4" + ]; Checkpoint previous_justified_checkpoint = 8002; Checkpoint current_justified_checkpoint = 8003; Checkpoint finalized_checkpoint = 8004; // Altair fields [9001-10000] - repeated uint64 inactivity_scores = 9001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - SyncCommittee current_sync_committee = 9002; // [New in Altair] - SyncCommittee next_sync_committee = 9003; // [New in Altair] + repeated uint64 inactivity_scores = 9001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + SyncCommittee current_sync_committee = 9002; + SyncCommittee next_sync_committee = 9003; // Bellatrix fields [10001-11000] - ethereum.engine.v1.ExecutionPayloadHeader latest_execution_payload_header = 10001; // [New in Bellatrix] + ethereum.engine.v1.ExecutionPayloadHeader latest_execution_payload_header = + 10001; // [New in Bellatrix] } +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + message BeaconStateCapella { // Versioning [1001-2000] uint64 genesis_time = 1001; - bytes genesis_validators_root = 1002 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 slot = 1003 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + bytes genesis_validators_root = 1002 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 slot = 1003 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; Fork fork = 1004; // History [2001-3000] BeaconBlockHeader latest_block_header = 2001; - repeated bytes block_roots = 2002 [(ethereum.eth.ext.ssz_size) = "block_roots.size"]; - repeated bytes state_roots = 2003 [(ethereum.eth.ext.ssz_size) = "state_roots.size"]; - repeated bytes historical_roots = 2004 [(ethereum.eth.ext.ssz_size) = "?,32", (ethereum.eth.ext.ssz_max) = "16777216"]; + repeated bytes block_roots = 2002 + [ (ethereum.eth.ext.ssz_size) = "block_roots.size" ]; + repeated bytes state_roots = 2003 + [ (ethereum.eth.ext.ssz_size) = "state_roots.size" ]; + repeated bytes historical_roots = 2004 [ + (ethereum.eth.ext.ssz_size) = "?,32", + (ethereum.eth.ext.ssz_max) = "16777216" + ]; // Eth1 [3001-4000] Eth1Data eth1_data = 3001; - repeated Eth1Data eth1_data_votes = 3002 [(ethereum.eth.ext.ssz_max) = "eth1_data_votes.size"]; + repeated Eth1Data eth1_data_votes = 3002 + [ (ethereum.eth.ext.ssz_max) = "eth1_data_votes.size" ]; uint64 eth1_deposit_index = 3003; // Registry [4001-5000] - repeated Validator validators = 4001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - repeated uint64 balances = 4002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + repeated Validator validators = 4001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + repeated uint64 balances = 4002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Randomness [5001-6000] - repeated bytes randao_mixes = 5001 [(ethereum.eth.ext.ssz_size) = "randao_mixes.size"]; + repeated bytes randao_mixes = 5001 + [ (ethereum.eth.ext.ssz_size) = "randao_mixes.size" ]; // Slashings [6001-7000] - repeated uint64 slashings = 6001 [(ethereum.eth.ext.ssz_size) = "slashings.size"]; + repeated uint64 slashings = 6001 + [ (ethereum.eth.ext.ssz_size) = "slashings.size" ]; // Participation [7001-8000] - bytes previous_epoch_participation = 7001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - bytes current_epoch_participation = 7002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + bytes previous_epoch_participation = 7001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + bytes current_epoch_participation = 7002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Finality [8001-9000] // Spec type [4]Bitvector which means this would be a fixed size of 4 bits. - bytes justification_bits = 8001 [(ethereum.eth.ext.ssz_size) = "1", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector4"]; + bytes justification_bits = 8001 [ + (ethereum.eth.ext.ssz_size) = "1", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector4" + ]; Checkpoint previous_justified_checkpoint = 8002; Checkpoint current_justified_checkpoint = 8003; Checkpoint finalized_checkpoint = 8004; // Altair fields [9001-10000] - repeated uint64 inactivity_scores = 9001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - SyncCommittee current_sync_committee = 9002; // [New in Altair] - SyncCommittee next_sync_committee = 9003; // [New in Altair] + repeated uint64 inactivity_scores = 9001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + SyncCommittee current_sync_committee = 9002; + SyncCommittee next_sync_committee = 9003; // Bellatrix fields [10001-11000] - ethereum.engine.v1.ExecutionPayloadHeaderCapella latest_execution_payload_header = 10001; // [New in Bellatrix] + ethereum.engine.v1.ExecutionPayloadHeaderCapella + latest_execution_payload_header = 10001; // Capella fields [11001-12000] uint64 next_withdrawal_index = 11001; // [New in Capella] - uint64 next_withdrawal_validator_index = 11002 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; // [New in Capella] - repeated HistoricalSummary historical_summaries = 11003 [(ethereum.eth.ext.ssz_max) = "16777216"]; // [New in Capella] + uint64 next_withdrawal_validator_index = 11002 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; // [New in Capella] + repeated HistoricalSummary historical_summaries = 11003 + [ (ethereum.eth.ext.ssz_max) = "16777216" ]; // [New in Capella] } +// HistoricalSummary matches the components of the phase0 `HistoricalBatch` +// making the two hash_tree_root-compatible. +message HistoricalSummary { + bytes block_summary_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes state_summary_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; +} + +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + message BeaconStateDeneb { // Versioning [1001-2000] uint64 genesis_time = 1001; - bytes genesis_validators_root = 1002 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 slot = 1003 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + bytes genesis_validators_root = 1002 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 slot = 1003 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; Fork fork = 1004; // History [2001-3000] BeaconBlockHeader latest_block_header = 2001; - repeated bytes block_roots = 2002 [(ethereum.eth.ext.ssz_size) = "block_roots.size"]; - repeated bytes state_roots = 2003 [(ethereum.eth.ext.ssz_size) = "state_roots.size"]; - repeated bytes historical_roots = 2004 [(ethereum.eth.ext.ssz_size) = "?,32", (ethereum.eth.ext.ssz_max) = "16777216"]; + repeated bytes block_roots = 2002 + [ (ethereum.eth.ext.ssz_size) = "block_roots.size" ]; + repeated bytes state_roots = 2003 + [ (ethereum.eth.ext.ssz_size) = "state_roots.size" ]; + repeated bytes historical_roots = 2004 [ + (ethereum.eth.ext.ssz_size) = "?,32", + (ethereum.eth.ext.ssz_max) = "16777216" + ]; // Eth1 [3001-4000] Eth1Data eth1_data = 3001; - repeated Eth1Data eth1_data_votes = 3002 [(ethereum.eth.ext.ssz_max) = "eth1_data_votes.size"]; + repeated Eth1Data eth1_data_votes = 3002 + [ (ethereum.eth.ext.ssz_max) = "eth1_data_votes.size" ]; uint64 eth1_deposit_index = 3003; // Registry [4001-5000] - repeated Validator validators = 4001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - repeated uint64 balances = 4002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + repeated Validator validators = 4001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + repeated uint64 balances = 4002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Randomness [5001-6000] - repeated bytes randao_mixes = 5001 [(ethereum.eth.ext.ssz_size) = "randao_mixes.size"]; + repeated bytes randao_mixes = 5001 + [ (ethereum.eth.ext.ssz_size) = "randao_mixes.size" ]; // Slashings [6001-7000] - repeated uint64 slashings = 6001 [(ethereum.eth.ext.ssz_size) = "slashings.size"]; + repeated uint64 slashings = 6001 + [ (ethereum.eth.ext.ssz_size) = "slashings.size" ]; // Participation [7001-8000] - bytes previous_epoch_participation = 7001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - bytes current_epoch_participation = 7002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + bytes previous_epoch_participation = 7001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + bytes current_epoch_participation = 7002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Finality [8001-9000] // Spec type [4]Bitvector which means this would be a fixed size of 4 bits. - bytes justification_bits = 8001 [(ethereum.eth.ext.ssz_size) = "1", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector4"]; + bytes justification_bits = 8001 [ + (ethereum.eth.ext.ssz_size) = "1", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector4" + ]; Checkpoint previous_justified_checkpoint = 8002; Checkpoint current_justified_checkpoint = 8003; Checkpoint finalized_checkpoint = 8004; // Fields introduced in Altair fork [9001-10000] - repeated uint64 inactivity_scores = 9001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + repeated uint64 inactivity_scores = 9001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; SyncCommittee current_sync_committee = 9002; SyncCommittee next_sync_committee = 9003; // Fields introduced in Bellatrix fork [10001-11000] - ethereum.engine.v1.ExecutionPayloadHeaderDeneb latest_execution_payload_header = 10001; // [New in Deneb] + ethereum.engine.v1.ExecutionPayloadHeaderDeneb + latest_execution_payload_header = 10001; // [New in Deneb] // Fields introduced in Capella fork [11001-12000] uint64 next_withdrawal_index = 11001; - uint64 next_withdrawal_validator_index = 11002 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - repeated HistoricalSummary historical_summaries = 11003 [(ethereum.eth.ext.ssz_max) = "16777216"]; + uint64 next_withdrawal_validator_index = 11002 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + repeated HistoricalSummary historical_summaries = 11003 + [ (ethereum.eth.ext.ssz_max) = "16777216" ]; } +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + message BeaconStateElectra { // Versioning [1001-2000] uint64 genesis_time = 1001; - bytes genesis_validators_root = 1002 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 slot = 1003 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + bytes genesis_validators_root = 1002 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 slot = 1003 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; Fork fork = 1004; // History [2001-3000] BeaconBlockHeader latest_block_header = 2001; - repeated bytes block_roots = 2002 [(ethereum.eth.ext.ssz_size) = "block_roots.size"]; - repeated bytes state_roots = 2003 [(ethereum.eth.ext.ssz_size) = "state_roots.size"]; - repeated bytes historical_roots = 2004 [(ethereum.eth.ext.ssz_size) = "?,32", (ethereum.eth.ext.ssz_max) = "16777216"]; + repeated bytes block_roots = 2002 + [ (ethereum.eth.ext.ssz_size) = "block_roots.size" ]; + repeated bytes state_roots = 2003 + [ (ethereum.eth.ext.ssz_size) = "state_roots.size" ]; + repeated bytes historical_roots = 2004 [ + (ethereum.eth.ext.ssz_size) = "?,32", + (ethereum.eth.ext.ssz_max) = "16777216" + ]; // Eth1 [3001-4000] Eth1Data eth1_data = 3001; - repeated Eth1Data eth1_data_votes = 3002 [(ethereum.eth.ext.ssz_max) = "eth1_data_votes.size"]; + repeated Eth1Data eth1_data_votes = 3002 + [ (ethereum.eth.ext.ssz_max) = "eth1_data_votes.size" ]; uint64 eth1_deposit_index = 3003; // Registry [4001-5000] - repeated Validator validators = 4001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - repeated uint64 balances = 4002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + repeated Validator validators = 4001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + repeated uint64 balances = 4002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Randomness [5001-6000] - repeated bytes randao_mixes = 5001 [(ethereum.eth.ext.ssz_size) = "randao_mixes.size"]; + repeated bytes randao_mixes = 5001 + [ (ethereum.eth.ext.ssz_size) = "randao_mixes.size" ]; // Slashings [6001-7000] - repeated uint64 slashings = 6001 [(ethereum.eth.ext.ssz_size) = "slashings.size"]; + repeated uint64 slashings = 6001 + [ (ethereum.eth.ext.ssz_size) = "slashings.size" ]; // Participation [7001-8000] - bytes previous_epoch_participation = 7001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; - bytes current_epoch_participation = 7002 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + bytes previous_epoch_participation = 7001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; + bytes current_epoch_participation = 7002 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; // Finality [8001-9000] // Spec type [4]Bitvector which means this would be a fixed size of 4 bits. - bytes justification_bits = 8001 [(ethereum.eth.ext.ssz_size) = "1", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector4"]; + bytes justification_bits = 8001 [ + (ethereum.eth.ext.ssz_size) = "1", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector4" + ]; Checkpoint previous_justified_checkpoint = 8002; Checkpoint current_justified_checkpoint = 8003; Checkpoint finalized_checkpoint = 8004; // Fields introduced in Altair fork [9001-10000] - repeated uint64 inactivity_scores = 9001 [(ethereum.eth.ext.ssz_max) = "1099511627776"]; + repeated uint64 inactivity_scores = 9001 + [ (ethereum.eth.ext.ssz_max) = "1099511627776" ]; SyncCommittee current_sync_committee = 9002; SyncCommittee next_sync_committee = 9003; // Fields introduced in Bellatrix fork [10001-11000] - ethereum.engine.v1.ExecutionPayloadHeaderElectra latest_execution_payload_header = 10001; // [New in Electra] + ethereum.engine.v1.ExecutionPayloadHeaderDeneb + latest_execution_payload_header = 10001; // Fields introduced in Capella fork [11001-12000] uint64 next_withdrawal_index = 11001; - uint64 next_withdrawal_validator_index = 11002 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - repeated HistoricalSummary historical_summaries = 11003 [(ethereum.eth.ext.ssz_max) = "16777216"]; - - // Fields introduced in EIP-7251 fork [12001-13000] + uint64 next_withdrawal_validator_index = 11002 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + repeated HistoricalSummary historical_summaries = 11003 + [ (ethereum.eth.ext.ssz_max) = "16777216" ]; + + // Fields introduced in Electra fork [12001-13000] uint64 deposit_requests_start_index = 12001; - uint64 deposit_balance_to_consume = 12002 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Gwei"]; - uint64 exit_balance_to_consume = 12003 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Gwei"]; - uint64 earliest_exit_epoch = 12004 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - uint64 consolidation_balance_to_consume = 12005 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Gwei"]; - uint64 earliest_consolidation_epoch = 12006 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - repeated PendingBalanceDeposit pending_balance_deposits = 12007 [(ethereum.eth.ext.ssz_max) = "pending_balance_deposits_limit"]; - repeated PendingPartialWithdrawal pending_partial_withdrawals = 12008 [(ethereum.eth.ext.ssz_max) = "pending_partial_withdrawals_limit"]; - repeated PendingConsolidation pending_consolidations = 12009 [(ethereum.eth.ext.ssz_max) = "pending_consolidations_limit"]; -} - -// PowBlock is a definition from Bellatrix fork choice spec to represent a block with total difficulty in the PoW chain. -// Spec: -// class PowBlock(Container): -// block_hash: Hash32 -// parent_hash: Hash32 -// total_difficulty: uint256 -message PowBlock { - bytes block_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes parent_hash = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes total_difficulty = 3 [(ethereum.eth.ext.ssz_size) = "32"]; -} - -// HistoricalSummary matches the components of the phase0 `HistoricalBatch` making the two hash_tree_root-compatible. -message HistoricalSummary { - bytes block_summary_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes state_summary_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + uint64 deposit_balance_to_consume = 12002 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Gwei" + ]; + uint64 exit_balance_to_consume = 12003 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Gwei" + ]; + uint64 earliest_exit_epoch = 12004 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + uint64 consolidation_balance_to_consume = 12005 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Gwei" + ]; + uint64 earliest_consolidation_epoch = 12006 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + repeated PendingDeposit pending_deposits = 12007 + [ (ethereum.eth.ext.ssz_max) = "pending_deposits_limit" ]; + repeated PendingPartialWithdrawal pending_partial_withdrawals = 12008 + [ (ethereum.eth.ext.ssz_max) = "pending_partial_withdrawals_limit" ]; + repeated PendingConsolidation pending_consolidations = 12009 + [ (ethereum.eth.ext.ssz_max) = "pending_consolidations_limit" ]; } diff --git a/proto/prysm/v1alpha1/bellatrix.ssz.go b/proto/prysm/v1alpha1/bellatrix.ssz.go index 6f1c86000129..c7adfed44990 100644 --- a/proto/prysm/v1alpha1/bellatrix.ssz.go +++ b/proto/prysm/v1alpha1/bellatrix.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 61890aa32d72c0c0325f0bf6dd44776068840a9d50a102e4c3c53ac46cf66567 package eth import ( diff --git a/proto/prysm/v1alpha1/blobs.pb.go b/proto/prysm/v1alpha1/blobs.pb.go index deb6e49df9da..1e3d5ab747c7 100755 --- a/proto/prysm/v1alpha1/blobs.pb.go +++ b/proto/prysm/v1alpha1/blobs.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/blobs.proto package eth @@ -70,6 +70,61 @@ func (x *BlindedBlobSidecars) GetSidecars() []*BlindedBlobSidecar { return nil } +type SignedBlindedBlobSidecar struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message *BlindedBlobSidecar `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` +} + +func (x *SignedBlindedBlobSidecar) Reset() { + *x = SignedBlindedBlobSidecar{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_blobs_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignedBlindedBlobSidecar) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignedBlindedBlobSidecar) ProtoMessage() {} + +func (x *SignedBlindedBlobSidecar) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_blobs_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignedBlindedBlobSidecar.ProtoReflect.Descriptor instead. +func (*SignedBlindedBlobSidecar) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_blobs_proto_rawDescGZIP(), []int{1} +} + +func (x *SignedBlindedBlobSidecar) GetMessage() *BlindedBlobSidecar { + if x != nil { + return x.Message + } + return nil +} + +func (x *SignedBlindedBlobSidecar) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + type BlindedBlobSidecar struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -88,7 +143,7 @@ type BlindedBlobSidecar struct { func (x *BlindedBlobSidecar) Reset() { *x = BlindedBlobSidecar{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_blobs_proto_msgTypes[1] + mi := &file_proto_prysm_v1alpha1_blobs_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -101,7 +156,7 @@ func (x *BlindedBlobSidecar) String() string { func (*BlindedBlobSidecar) ProtoMessage() {} func (x *BlindedBlobSidecar) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_blobs_proto_msgTypes[1] + mi := &file_proto_prysm_v1alpha1_blobs_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -114,7 +169,7 @@ func (x *BlindedBlobSidecar) ProtoReflect() protoreflect.Message { // Deprecated: Use BlindedBlobSidecar.ProtoReflect.Descriptor instead. func (*BlindedBlobSidecar) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_blobs_proto_rawDescGZIP(), []int{1} + return file_proto_prysm_v1alpha1_blobs_proto_rawDescGZIP(), []int{2} } func (x *BlindedBlobSidecar) GetBlockRoot() []byte { @@ -173,61 +228,6 @@ func (x *BlindedBlobSidecar) GetKzgProof() []byte { return nil } -type SignedBlindedBlobSidecar struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Message *BlindedBlobSidecar `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` -} - -func (x *SignedBlindedBlobSidecar) Reset() { - *x = SignedBlindedBlobSidecar{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_blobs_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SignedBlindedBlobSidecar) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SignedBlindedBlobSidecar) ProtoMessage() {} - -func (x *SignedBlindedBlobSidecar) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_blobs_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SignedBlindedBlobSidecar.ProtoReflect.Descriptor instead. -func (*SignedBlindedBlobSidecar) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_blobs_proto_rawDescGZIP(), []int{2} -} - -func (x *SignedBlindedBlobSidecar) GetMessage() *BlindedBlobSidecar { - if x != nil { - return x.Message - } - return nil -} - -func (x *SignedBlindedBlobSidecar) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - type BlobIdentifier struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -297,45 +297,45 @@ var file_proto_prysm_v1alpha1_blobs_proto_rawDesc = []byte{ 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x42, 0x05, 0x92, 0xb5, 0x18, 0x01, - 0x36, 0x52, 0x08, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x22, 0xd1, 0x03, 0x0a, 0x12, - 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, - 0x61, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, - 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, - 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, - 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x6c, - 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x76, - 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x23, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x62, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x0e, 0x6b, - 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0d, 0x6b, 0x7a, 0x67, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x09, 0x6b, 0x7a, - 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x08, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, - 0x85, 0x01, 0x0a, 0x18, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, - 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x43, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, - 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x4d, 0x0a, 0x0e, 0x42, 0x6c, 0x6f, 0x62, 0x49, + 0x36, 0x52, 0x08, 0x73, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x18, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, + 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x43, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, + 0x65, 0x63, 0x61, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x22, 0xd1, 0x03, 0x0a, 0x12, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, + 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, + 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, + 0x6f, 0x74, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x50, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x76, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, + 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, + 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x23, + 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x62, 0x52, + 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x0e, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x34, 0x38, 0x52, 0x0d, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x09, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x08, 0x6b, + 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x4d, 0x0a, 0x0e, 0x42, 0x6c, 0x6f, 0x62, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, @@ -368,13 +368,13 @@ func file_proto_prysm_v1alpha1_blobs_proto_rawDescGZIP() []byte { var file_proto_prysm_v1alpha1_blobs_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_proto_prysm_v1alpha1_blobs_proto_goTypes = []interface{}{ (*BlindedBlobSidecars)(nil), // 0: ethereum.eth.v1alpha1.BlindedBlobSidecars - (*BlindedBlobSidecar)(nil), // 1: ethereum.eth.v1alpha1.BlindedBlobSidecar - (*SignedBlindedBlobSidecar)(nil), // 2: ethereum.eth.v1alpha1.SignedBlindedBlobSidecar + (*SignedBlindedBlobSidecar)(nil), // 1: ethereum.eth.v1alpha1.SignedBlindedBlobSidecar + (*BlindedBlobSidecar)(nil), // 2: ethereum.eth.v1alpha1.BlindedBlobSidecar (*BlobIdentifier)(nil), // 3: ethereum.eth.v1alpha1.BlobIdentifier } var file_proto_prysm_v1alpha1_blobs_proto_depIdxs = []int32{ - 1, // 0: ethereum.eth.v1alpha1.BlindedBlobSidecars.sidecars:type_name -> ethereum.eth.v1alpha1.BlindedBlobSidecar - 1, // 1: ethereum.eth.v1alpha1.SignedBlindedBlobSidecar.message:type_name -> ethereum.eth.v1alpha1.BlindedBlobSidecar + 2, // 0: ethereum.eth.v1alpha1.BlindedBlobSidecars.sidecars:type_name -> ethereum.eth.v1alpha1.BlindedBlobSidecar + 2, // 1: ethereum.eth.v1alpha1.SignedBlindedBlobSidecar.message:type_name -> ethereum.eth.v1alpha1.BlindedBlobSidecar 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name @@ -401,7 +401,7 @@ func file_proto_prysm_v1alpha1_blobs_proto_init() { } } file_proto_prysm_v1alpha1_blobs_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlindedBlobSidecar); i { + switch v := v.(*SignedBlindedBlobSidecar); i { case 0: return &v.state case 1: @@ -413,7 +413,7 @@ func file_proto_prysm_v1alpha1_blobs_proto_init() { } } file_proto_prysm_v1alpha1_blobs_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBlindedBlobSidecar); i { + switch v := v.(*BlindedBlobSidecar); i { case 0: return &v.state case 1: diff --git a/proto/prysm/v1alpha1/blobs.pb.gw.go b/proto/prysm/v1alpha1/blobs.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/blobs.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/blobs.proto b/proto/prysm/v1alpha1/blobs.proto index f41b7a97117b..d8093b4d822c 100644 --- a/proto/prysm/v1alpha1/blobs.proto +++ b/proto/prysm/v1alpha1/blobs.proto @@ -25,26 +25,32 @@ option java_package = "org.ethereum.eth.v1alpha1"; option php_namespace = "Ethereum\\Eth\\v1alpha1"; message BlindedBlobSidecars { - repeated BlindedBlobSidecar sidecars = 1 [(ethereum.eth.ext.ssz_max) = "max_blobs_per_block.size"]; -} - -message BlindedBlobSidecar { - bytes block_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 index = 2; - uint64 slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - bytes block_parent_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 proposer_index = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - bytes blob_root = 6 [(ethereum.eth.ext.ssz_size) = "32"]; - bytes kzg_commitment = 7 [(ethereum.eth.ext.ssz_size) = "48"]; - bytes kzg_proof = 8 [(ethereum.eth.ext.ssz_size) = "48"]; + repeated BlindedBlobSidecar sidecars = 1 + [ (ethereum.eth.ext.ssz_max) = "max_blobs_per_block.size" ]; } message SignedBlindedBlobSidecar { BlindedBlobSidecar message = 1; - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; +} + +message BlindedBlobSidecar { + bytes block_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 index = 2; + uint64 slot = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + bytes block_parent_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 proposer_index = 5 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; + bytes blob_root = 6 [ (ethereum.eth.ext.ssz_size) = "32" ]; + bytes kzg_commitment = 7 [ (ethereum.eth.ext.ssz_size) = "48" ]; + bytes kzg_proof = 8 [ (ethereum.eth.ext.ssz_size) = "48" ]; } message BlobIdentifier { - bytes block_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes block_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; uint64 index = 2; } \ No newline at end of file diff --git a/proto/prysm/v1alpha1/capella.ssz.go b/proto/prysm/v1alpha1/capella.ssz.go index 48057c5b2a16..503f6a720fff 100644 --- a/proto/prysm/v1alpha1/capella.ssz.go +++ b/proto/prysm/v1alpha1/capella.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 13b762a7d53ab6cf5d5ffb582d580edb05efc65de762692f09af914819d3bb3e package eth import ( @@ -2729,92 +2728,872 @@ func (h *HistoricalSummary) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the BLSToExecutionChange object -func (b *BLSToExecutionChange) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the LightClientBootstrapCapella object +func (l *LightClientBootstrapCapella) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientBootstrapCapella object to a target array +func (l *LightClientBootstrapCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(24788) + + // Offset (0) 'Header' + dst = ssz.WriteOffset(dst, offset) + if l.Header == nil { + l.Header = new(LightClientHeaderCapella) + } + offset += l.Header.SizeSSZ() + + // Field (1) 'CurrentSyncCommittee' + if l.CurrentSyncCommittee == nil { + l.CurrentSyncCommittee = new(SyncCommittee) + } + if dst, err = l.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'CurrentSyncCommitteeBranch' + if size := len(l.CurrentSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5) + return + } + for ii := 0; ii < 5; ii++ { + if size := len(l.CurrentSyncCommitteeBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.CurrentSyncCommitteeBranch[ii]", size, 32) + return + } + dst = append(dst, l.CurrentSyncCommitteeBranch[ii]...) + } + + // Field (0) 'Header' + if dst, err = l.Header.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientBootstrapCapella object +func (l *LightClientBootstrapCapella) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 24788 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Header' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 24788 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'CurrentSyncCommittee' + if l.CurrentSyncCommittee == nil { + l.CurrentSyncCommittee = new(SyncCommittee) + } + if err = l.CurrentSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil { + return err + } + + // Field (2) 'CurrentSyncCommitteeBranch' + l.CurrentSyncCommitteeBranch = make([][]byte, 5) + for ii := 0; ii < 5; ii++ { + if cap(l.CurrentSyncCommitteeBranch[ii]) == 0 { + l.CurrentSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24788][ii*32:(ii+1)*32])) + } + l.CurrentSyncCommitteeBranch[ii] = append(l.CurrentSyncCommitteeBranch[ii], buf[24628:24788][ii*32:(ii+1)*32]...) + } + + // Field (0) 'Header' + { + buf = tail[o0:] + if l.Header == nil { + l.Header = new(LightClientHeaderCapella) + } + if err = l.Header.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientBootstrapCapella object +func (l *LightClientBootstrapCapella) SizeSSZ() (size int) { + size = 24788 + + // Field (0) 'Header' + if l.Header == nil { + l.Header = new(LightClientHeaderCapella) + } + size += l.Header.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientBootstrapCapella object +func (l *LightClientBootstrapCapella) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientBootstrapCapella object with a hasher +func (l *LightClientBootstrapCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Header' + if err = l.Header.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'CurrentSyncCommittee' + if err = l.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'CurrentSyncCommitteeBranch' + { + if size := len(l.CurrentSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5) + return + } + subIndx := hh.Index() + for _, i := range l.CurrentSyncCommitteeBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientUpdateCapella object +func (l *LightClientUpdateCapella) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientUpdateCapella object to a target array +func (l *LightClientUpdateCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(25152) + + // Offset (0) 'AttestedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + offset += l.AttestedHeader.SizeSSZ() + + // Field (1) 'NextSyncCommittee' + if l.NextSyncCommittee == nil { + l.NextSyncCommittee = new(SyncCommittee) + } + if dst, err = l.NextSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'NextSyncCommitteeBranch' + if size := len(l.NextSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5) + return + } + for ii := 0; ii < 5; ii++ { + if size := len(l.NextSyncCommitteeBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.NextSyncCommitteeBranch[ii]", size, 32) + return + } + dst = append(dst, l.NextSyncCommitteeBranch[ii]...) + } + + // Offset (3) 'FinalizedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderCapella) + } + offset += l.FinalizedHeader.SizeSSZ() + + // Field (4) 'FinalityBranch' + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + for ii := 0; ii < 6; ii++ { + if size := len(l.FinalityBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32) + return + } + dst = append(dst, l.FinalityBranch[ii]...) + } + + // Field (5) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (6) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + // Field (0) 'AttestedHeader' + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (3) 'FinalizedHeader' + if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientUpdateCapella object +func (l *LightClientUpdateCapella) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 25152 { + return ssz.ErrSize + } + + tail := buf + var o0, o3 uint64 + + // Offset (0) 'AttestedHeader' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 25152 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'NextSyncCommittee' + if l.NextSyncCommittee == nil { + l.NextSyncCommittee = new(SyncCommittee) + } + if err = l.NextSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil { + return err + } + + // Field (2) 'NextSyncCommitteeBranch' + l.NextSyncCommitteeBranch = make([][]byte, 5) + for ii := 0; ii < 5; ii++ { + if cap(l.NextSyncCommitteeBranch[ii]) == 0 { + l.NextSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24788][ii*32:(ii+1)*32])) + } + l.NextSyncCommitteeBranch[ii] = append(l.NextSyncCommitteeBranch[ii], buf[24628:24788][ii*32:(ii+1)*32]...) + } + + // Offset (3) 'FinalizedHeader' + if o3 = ssz.ReadOffset(buf[24788:24792]); o3 > size || o0 > o3 { + return ssz.ErrOffset + } + + // Field (4) 'FinalityBranch' + l.FinalityBranch = make([][]byte, 6) + for ii := 0; ii < 6; ii++ { + if cap(l.FinalityBranch[ii]) == 0 { + l.FinalityBranch[ii] = make([]byte, 0, len(buf[24792:24984][ii*32:(ii+1)*32])) + } + l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[24792:24984][ii*32:(ii+1)*32]...) + } + + // Field (5) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[24984:25144]); err != nil { + return err + } + + // Field (6) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[25144:25152])) + + // Field (0) 'AttestedHeader' + { + buf = tail[o0:o3] + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (3) 'FinalizedHeader' + { + buf = tail[o3:] + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderCapella) + } + if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientUpdateCapella object +func (l *LightClientUpdateCapella) SizeSSZ() (size int) { + size = 25152 + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + size += l.AttestedHeader.SizeSSZ() + + // Field (3) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderCapella) + } + size += l.FinalizedHeader.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientUpdateCapella object +func (l *LightClientUpdateCapella) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientUpdateCapella object with a hasher +func (l *LightClientUpdateCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'NextSyncCommittee' + if err = l.NextSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'NextSyncCommitteeBranch' + { + if size := len(l.NextSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5) + return + } + subIndx := hh.Index() + for _, i := range l.NextSyncCommitteeBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (3) 'FinalizedHeader' + if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (4) 'FinalityBranch' + { + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + subIndx := hh.Index() + for _, i := range l.FinalityBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (5) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (6) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientFinalityUpdateCapella object +func (l *LightClientFinalityUpdateCapella) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientFinalityUpdateCapella object to a target array +func (l *LightClientFinalityUpdateCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(368) + + // Offset (0) 'AttestedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + offset += l.AttestedHeader.SizeSSZ() + + // Offset (1) 'FinalizedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderCapella) + } + offset += l.FinalizedHeader.SizeSSZ() + + // Field (2) 'FinalityBranch' + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + for ii := 0; ii < 6; ii++ { + if size := len(l.FinalityBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32) + return + } + dst = append(dst, l.FinalityBranch[ii]...) + } + + // Field (3) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (4) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + // Field (0) 'AttestedHeader' + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'FinalizedHeader' + if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientFinalityUpdateCapella object +func (l *LightClientFinalityUpdateCapella) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 368 { + return ssz.ErrSize + } + + tail := buf + var o0, o1 uint64 + + // Offset (0) 'AttestedHeader' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 368 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (1) 'FinalizedHeader' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Field (2) 'FinalityBranch' + l.FinalityBranch = make([][]byte, 6) + for ii := 0; ii < 6; ii++ { + if cap(l.FinalityBranch[ii]) == 0 { + l.FinalityBranch[ii] = make([]byte, 0, len(buf[8:200][ii*32:(ii+1)*32])) + } + l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[8:200][ii*32:(ii+1)*32]...) + } + + // Field (3) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[200:360]); err != nil { + return err + } + + // Field (4) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[360:368])) + + // Field (0) 'AttestedHeader' + { + buf = tail[o0:o1] + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (1) 'FinalizedHeader' + { + buf = tail[o1:] + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderCapella) + } + if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientFinalityUpdateCapella object +func (l *LightClientFinalityUpdateCapella) SizeSSZ() (size int) { + size = 368 + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + size += l.AttestedHeader.SizeSSZ() + + // Field (1) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderCapella) + } + size += l.FinalizedHeader.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientFinalityUpdateCapella object +func (l *LightClientFinalityUpdateCapella) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientFinalityUpdateCapella object with a hasher +func (l *LightClientFinalityUpdateCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'FinalizedHeader' + if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'FinalityBranch' + { + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + subIndx := hh.Index() + for _, i := range l.FinalityBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (3) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (4) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return } -// MarshalSSZTo ssz marshals the BLSToExecutionChange object to a target array -func (b *BLSToExecutionChange) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZ ssz marshals the LightClientOptimisticUpdateCapella object +func (l *LightClientOptimisticUpdateCapella) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientOptimisticUpdateCapella object to a target array +func (l *LightClientOptimisticUpdateCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf + offset := int(172) - // Field (0) 'ValidatorIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ValidatorIndex)) + // Offset (0) 'AttestedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + offset += l.AttestedHeader.SizeSSZ() - // Field (1) 'FromBlsPubkey' - if size := len(b.FromBlsPubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.FromBlsPubkey", size, 48) + // Field (1) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, b.FromBlsPubkey...) - // Field (2) 'ToExecutionAddress' - if size := len(b.ToExecutionAddress); size != 20 { - err = ssz.ErrBytesLengthFn("--.ToExecutionAddress", size, 20) + // Field (2) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + // Field (0) 'AttestedHeader' + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, b.ToExecutionAddress...) return } -// UnmarshalSSZ ssz unmarshals the BLSToExecutionChange object -func (b *BLSToExecutionChange) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the LightClientOptimisticUpdateCapella object +func (l *LightClientOptimisticUpdateCapella) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 76 { + if size < 172 { return ssz.ErrSize } - // Field (0) 'ValidatorIndex' - b.ValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) + tail := buf + var o0 uint64 - // Field (1) 'FromBlsPubkey' - if cap(b.FromBlsPubkey) == 0 { - b.FromBlsPubkey = make([]byte, 0, len(buf[8:56])) + // Offset (0) 'AttestedHeader' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset } - b.FromBlsPubkey = append(b.FromBlsPubkey, buf[8:56]...) - // Field (2) 'ToExecutionAddress' - if cap(b.ToExecutionAddress) == 0 { - b.ToExecutionAddress = make([]byte, 0, len(buf[56:76])) + if o0 != 172 { + return ssz.ErrInvalidVariableOffset } - b.ToExecutionAddress = append(b.ToExecutionAddress, buf[56:76]...) + // Field (1) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[4:164]); err != nil { + return err + } + + // Field (2) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[164:172])) + + // Field (0) 'AttestedHeader' + { + buf = tail[o0:] + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } return err } -// SizeSSZ returns the ssz encoded size in bytes for the BLSToExecutionChange object -func (b *BLSToExecutionChange) SizeSSZ() (size int) { - size = 76 +// SizeSSZ returns the ssz encoded size in bytes for the LightClientOptimisticUpdateCapella object +func (l *LightClientOptimisticUpdateCapella) SizeSSZ() (size int) { + size = 172 + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderCapella) + } + size += l.AttestedHeader.SizeSSZ() + return } -// HashTreeRoot ssz hashes the BLSToExecutionChange object -func (b *BLSToExecutionChange) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) +// HashTreeRoot ssz hashes the LightClientOptimisticUpdateCapella object +func (l *LightClientOptimisticUpdateCapella) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) } -// HashTreeRootWith ssz hashes the BLSToExecutionChange object with a hasher -func (b *BLSToExecutionChange) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the LightClientOptimisticUpdateCapella object with a hasher +func (l *LightClientOptimisticUpdateCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'ValidatorIndex' - hh.PutUint64(uint64(b.ValidatorIndex)) + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } - // Field (1) 'FromBlsPubkey' - if size := len(b.FromBlsPubkey); size != 48 { - err = ssz.ErrBytesLengthFn("--.FromBlsPubkey", size, 48) + // Field (1) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { return } - hh.PutBytes(b.FromBlsPubkey) - // Field (2) 'ToExecutionAddress' - if size := len(b.ToExecutionAddress); size != 20 { - err = ssz.ErrBytesLengthFn("--.ToExecutionAddress", size, 20) + // Field (2) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientHeaderCapella object +func (l *LightClientHeaderCapella) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientHeaderCapella object to a target array +func (l *LightClientHeaderCapella) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(244) + + // Field (0) 'Beacon' + if l.Beacon == nil { + l.Beacon = new(BeaconBlockHeader) + } + if dst, err = l.Beacon.MarshalSSZTo(dst); err != nil { return } - hh.PutBytes(b.ToExecutionAddress) + + // Offset (1) 'Execution' + dst = ssz.WriteOffset(dst, offset) + if l.Execution == nil { + l.Execution = new(v1.ExecutionPayloadHeaderCapella) + } + offset += l.Execution.SizeSSZ() + + // Field (2) 'ExecutionBranch' + if size := len(l.ExecutionBranch); size != 4 { + err = ssz.ErrVectorLengthFn("--.ExecutionBranch", size, 4) + return + } + for ii := 0; ii < 4; ii++ { + if size := len(l.ExecutionBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.ExecutionBranch[ii]", size, 32) + return + } + dst = append(dst, l.ExecutionBranch[ii]...) + } + + // Field (1) 'Execution' + if dst, err = l.Execution.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientHeaderCapella object +func (l *LightClientHeaderCapella) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 244 { + return ssz.ErrSize + } + + tail := buf + var o1 uint64 + + // Field (0) 'Beacon' + if l.Beacon == nil { + l.Beacon = new(BeaconBlockHeader) + } + if err = l.Beacon.UnmarshalSSZ(buf[0:112]); err != nil { + return err + } + + // Offset (1) 'Execution' + if o1 = ssz.ReadOffset(buf[112:116]); o1 > size { + return ssz.ErrOffset + } + + if o1 != 244 { + return ssz.ErrInvalidVariableOffset + } + + // Field (2) 'ExecutionBranch' + l.ExecutionBranch = make([][]byte, 4) + for ii := 0; ii < 4; ii++ { + if cap(l.ExecutionBranch[ii]) == 0 { + l.ExecutionBranch[ii] = make([]byte, 0, len(buf[116:244][ii*32:(ii+1)*32])) + } + l.ExecutionBranch[ii] = append(l.ExecutionBranch[ii], buf[116:244][ii*32:(ii+1)*32]...) + } + + // Field (1) 'Execution' + { + buf = tail[o1:] + if l.Execution == nil { + l.Execution = new(v1.ExecutionPayloadHeaderCapella) + } + if err = l.Execution.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientHeaderCapella object +func (l *LightClientHeaderCapella) SizeSSZ() (size int) { + size = 244 + + // Field (1) 'Execution' + if l.Execution == nil { + l.Execution = new(v1.ExecutionPayloadHeaderCapella) + } + size += l.Execution.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientHeaderCapella object +func (l *LightClientHeaderCapella) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientHeaderCapella object with a hasher +func (l *LightClientHeaderCapella) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Beacon' + if err = l.Beacon.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Execution' + if err = l.Execution.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'ExecutionBranch' + { + if size := len(l.ExecutionBranch); size != 4 { + err = ssz.ErrVectorLengthFn("--.ExecutionBranch", size, 4) + return + } + subIndx := hh.Index() + for _, i := range l.ExecutionBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } hh.Merkleize(indx) return @@ -2902,3 +3681,94 @@ func (s *SignedBLSToExecutionChange) HashTreeRootWith(hh *ssz.Hasher) (err error hh.Merkleize(indx) return } + +// MarshalSSZ ssz marshals the BLSToExecutionChange object +func (b *BLSToExecutionChange) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BLSToExecutionChange object to a target array +func (b *BLSToExecutionChange) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'ValidatorIndex' + dst = ssz.MarshalUint64(dst, uint64(b.ValidatorIndex)) + + // Field (1) 'FromBlsPubkey' + if size := len(b.FromBlsPubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.FromBlsPubkey", size, 48) + return + } + dst = append(dst, b.FromBlsPubkey...) + + // Field (2) 'ToExecutionAddress' + if size := len(b.ToExecutionAddress); size != 20 { + err = ssz.ErrBytesLengthFn("--.ToExecutionAddress", size, 20) + return + } + dst = append(dst, b.ToExecutionAddress...) + + return +} + +// UnmarshalSSZ ssz unmarshals the BLSToExecutionChange object +func (b *BLSToExecutionChange) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 76 { + return ssz.ErrSize + } + + // Field (0) 'ValidatorIndex' + b.ValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'FromBlsPubkey' + if cap(b.FromBlsPubkey) == 0 { + b.FromBlsPubkey = make([]byte, 0, len(buf[8:56])) + } + b.FromBlsPubkey = append(b.FromBlsPubkey, buf[8:56]...) + + // Field (2) 'ToExecutionAddress' + if cap(b.ToExecutionAddress) == 0 { + b.ToExecutionAddress = make([]byte, 0, len(buf[56:76])) + } + b.ToExecutionAddress = append(b.ToExecutionAddress, buf[56:76]...) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the BLSToExecutionChange object +func (b *BLSToExecutionChange) SizeSSZ() (size int) { + size = 76 + return +} + +// HashTreeRoot ssz hashes the BLSToExecutionChange object +func (b *BLSToExecutionChange) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) +} + +// HashTreeRootWith ssz hashes the BLSToExecutionChange object with a hasher +func (b *BLSToExecutionChange) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'ValidatorIndex' + hh.PutUint64(uint64(b.ValidatorIndex)) + + // Field (1) 'FromBlsPubkey' + if size := len(b.FromBlsPubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.FromBlsPubkey", size, 48) + return + } + hh.PutBytes(b.FromBlsPubkey) + + // Field (2) 'ToExecutionAddress' + if size := len(b.ToExecutionAddress); size != 20 { + err = ssz.ErrBytesLengthFn("--.ToExecutionAddress", size, 20) + return + } + hh.PutBytes(b.ToExecutionAddress) + + hh.Merkleize(indx) + return +} diff --git a/proto/prysm/v1alpha1/cloners_test.go b/proto/prysm/v1alpha1/cloners_test.go index 2cd98fc7b7c8..eb6e9cdd6a46 100644 --- a/proto/prysm/v1alpha1/cloners_test.go +++ b/proto/prysm/v1alpha1/cloners_test.go @@ -884,6 +884,8 @@ func genPayloadDeneb() *enginev1.ExecutionPayloadDeneb { } } +var genPayloadElectra = genPayloadDeneb + func genPayloadHeader() *enginev1.ExecutionPayloadHeader { return &enginev1.ExecutionPayloadHeader{ ParentHash: bytes(32), @@ -945,6 +947,8 @@ func genPayloadHeaderDeneb() *enginev1.ExecutionPayloadHeaderDeneb { } } +var genPayloadHeaderElectra = genPayloadHeaderDeneb + func genWithdrawals(num int) []*enginev1.Withdrawal { ws := make([]*enginev1.Withdrawal, num) for i := 0; i < num; i++ { @@ -1049,34 +1053,10 @@ func genBlindedBeaconBlockBodyElectra() *v1alpha1.BlindedBeaconBlockBodyElectra Deposits: genDeposits(5), VoluntaryExits: genSignedVoluntaryExits(12), SyncAggregate: genSyncAggregate(), - ExecutionPayloadHeader: genExecutionPayloadHeaderElectra(), + ExecutionPayloadHeader: genPayloadHeaderElectra(), BlsToExecutionChanges: genBLSToExecutionChanges(10), BlobKzgCommitments: getKZGCommitments(4), - } -} - -func genExecutionPayloadHeaderElectra() *enginev1.ExecutionPayloadHeaderElectra { - return &enginev1.ExecutionPayloadHeaderElectra{ - ParentHash: bytes(32), - FeeRecipient: bytes(20), - StateRoot: bytes(32), - ReceiptsRoot: bytes(32), - LogsBloom: bytes(256), - PrevRandao: bytes(32), - BlockNumber: 1, - GasLimit: 2, - GasUsed: 3, - Timestamp: 4, - ExtraData: bytes(32), - BaseFeePerGas: bytes(32), - BlockHash: bytes(32), - TransactionsRoot: bytes(32), - WithdrawalsRoot: bytes(32), - BlobGasUsed: 5, - ExcessBlobGas: 6, - DepositRequestsRoot: bytes(32), - WithdrawalRequestsRoot: bytes(32), - ConsolidationRequestsRoot: bytes(32), + ExecutionRequests: genExecutionRequests(), } } @@ -1108,34 +1088,18 @@ func genBeaconBlockBodyElectra() *v1alpha1.BeaconBlockBodyElectra { Deposits: genDeposits(5), VoluntaryExits: genSignedVoluntaryExits(12), SyncAggregate: genSyncAggregate(), - ExecutionPayload: genExecutionPayloadElectra(), + ExecutionPayload: genPayloadElectra(), BlsToExecutionChanges: genBLSToExecutionChanges(10), BlobKzgCommitments: getKZGCommitments(4), + ExecutionRequests: genExecutionRequests(), } } -func genExecutionPayloadElectra() *enginev1.ExecutionPayloadElectra { - return &enginev1.ExecutionPayloadElectra{ - ParentHash: bytes(32), - FeeRecipient: bytes(20), - StateRoot: bytes(32), - ReceiptsRoot: bytes(32), - LogsBloom: bytes(256), - PrevRandao: bytes(32), - BlockNumber: 1, - GasLimit: 2, - GasUsed: 3, - Timestamp: 4, - ExtraData: bytes(32), - BaseFeePerGas: bytes(32), - BlockHash: bytes(32), - Transactions: [][]byte{{'a'}, {'b'}, {'c'}}, - Withdrawals: genWithdrawals(10), - BlobGasUsed: 5, - ExcessBlobGas: 6, - DepositRequests: genDepositRequests(10), - WithdrawalRequests: genWithdrawalRequests(10), - ConsolidationRequests: genConsolidationRequests(10), +func genExecutionRequests() *enginev1.ExecutionRequests { + return &enginev1.ExecutionRequests{ + Deposits: genDepositRequests(10), + Withdrawals: genWithdrawalRequests(10), + Consolidations: genConsolidationRequests(10), } } @@ -1188,49 +1152,3 @@ func genConsolidationRequest() *enginev1.ConsolidationRequest { TargetPubkey: bytes(48), } } - -func genPendingPartialWithdrawals(num int) []*v1alpha1.PendingPartialWithdrawal { - ppws := make([]*v1alpha1.PendingPartialWithdrawal, num) - for i := 0; i < num; i++ { - ppws[i] = genPendingPartialWithdrawal() - } - return ppws -} - -func genPendingPartialWithdrawal() *v1alpha1.PendingPartialWithdrawal { - return &v1alpha1.PendingPartialWithdrawal{ - Index: 123456, - Amount: 55555, - WithdrawableEpoch: 444444, - } -} - -func genPendingConsolidations(num int) []*v1alpha1.PendingConsolidation { - pcs := make([]*v1alpha1.PendingConsolidation, num) - for i := 0; i < num; i++ { - pcs[i] = genPendingConsolidation() - } - return pcs -} - -func genPendingConsolidation() *v1alpha1.PendingConsolidation { - return &v1alpha1.PendingConsolidation{ - SourceIndex: 1, - TargetIndex: 2, - } -} - -func genPendingBalanceDeposits(num int) []*v1alpha1.PendingBalanceDeposit { - pbds := make([]*v1alpha1.PendingBalanceDeposit, num) - for i := 0; i < num; i++ { - pbds[i] = genPendingBalanceDeposit() - } - return pbds -} - -func genPendingBalanceDeposit() *v1alpha1.PendingBalanceDeposit { - return &v1alpha1.PendingBalanceDeposit{ - Index: 123456, - Amount: 55555, - } -} diff --git a/proto/prysm/v1alpha1/data_columns.pb.go b/proto/prysm/v1alpha1/data_columns.pb.go new file mode 100755 index 000000000000..3fbed6a7ff5b --- /dev/null +++ b/proto/prysm/v1alpha1/data_columns.pb.go @@ -0,0 +1,299 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.7 +// source: proto/prysm/v1alpha1/data_columns.proto + +package eth + +import ( + reflect "reflect" + sync "sync" + + _ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type DataColumnSidecar struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ColumnIndex uint64 `protobuf:"varint,1,opt,name=column_index,json=columnIndex,proto3" json:"column_index,omitempty"` + DataColumn [][]byte `protobuf:"bytes,2,rep,name=data_column,json=dataColumn,proto3" json:"data_column,omitempty" ssz-max:"4096" ssz-size:"?,2048"` + KzgCommitments [][]byte `protobuf:"bytes,3,rep,name=kzg_commitments,json=kzgCommitments,proto3" json:"kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"` + KzgProof [][]byte `protobuf:"bytes,4,rep,name=kzg_proof,json=kzgProof,proto3" json:"kzg_proof,omitempty" ssz-max:"4096" ssz-size:"?,48"` + SignedBlockHeader *SignedBeaconBlockHeader `protobuf:"bytes,5,opt,name=signed_block_header,json=signedBlockHeader,proto3" json:"signed_block_header,omitempty"` + KzgCommitmentsInclusionProof [][]byte `protobuf:"bytes,6,rep,name=kzg_commitments_inclusion_proof,json=kzgCommitmentsInclusionProof,proto3" json:"kzg_commitments_inclusion_proof,omitempty" ssz-size:"4,32"` +} + +func (x *DataColumnSidecar) Reset() { + *x = DataColumnSidecar{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_data_columns_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DataColumnSidecar) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DataColumnSidecar) ProtoMessage() {} + +func (x *DataColumnSidecar) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_data_columns_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DataColumnSidecar.ProtoReflect.Descriptor instead. +func (*DataColumnSidecar) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_data_columns_proto_rawDescGZIP(), []int{0} +} + +func (x *DataColumnSidecar) GetColumnIndex() uint64 { + if x != nil { + return x.ColumnIndex + } + return 0 +} + +func (x *DataColumnSidecar) GetDataColumn() [][]byte { + if x != nil { + return x.DataColumn + } + return nil +} + +func (x *DataColumnSidecar) GetKzgCommitments() [][]byte { + if x != nil { + return x.KzgCommitments + } + return nil +} + +func (x *DataColumnSidecar) GetKzgProof() [][]byte { + if x != nil { + return x.KzgProof + } + return nil +} + +func (x *DataColumnSidecar) GetSignedBlockHeader() *SignedBeaconBlockHeader { + if x != nil { + return x.SignedBlockHeader + } + return nil +} + +func (x *DataColumnSidecar) GetKzgCommitmentsInclusionProof() [][]byte { + if x != nil { + return x.KzgCommitmentsInclusionProof + } + return nil +} + +type DataColumnIdentifier struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlockRoot []byte `protobuf:"bytes,1,opt,name=block_root,json=blockRoot,proto3" json:"block_root,omitempty" ssz-size:"32"` + ColumnIndex uint64 `protobuf:"varint,2,opt,name=column_index,json=columnIndex,proto3" json:"column_index,omitempty"` +} + +func (x *DataColumnIdentifier) Reset() { + *x = DataColumnIdentifier{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_data_columns_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DataColumnIdentifier) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DataColumnIdentifier) ProtoMessage() {} + +func (x *DataColumnIdentifier) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_data_columns_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DataColumnIdentifier.ProtoReflect.Descriptor instead. +func (*DataColumnIdentifier) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_data_columns_proto_rawDescGZIP(), []int{1} +} + +func (x *DataColumnIdentifier) GetBlockRoot() []byte { + if x != nil { + return x.BlockRoot + } + return nil +} + +func (x *DataColumnIdentifier) GetColumnIndex() uint64 { + if x != nil { + return x.ColumnIndex + } + return 0 +} + +var File_proto_prysm_v1alpha1_data_columns_proto protoreflect.FileDescriptor + +var file_proto_prysm_v1alpha1_data_columns_proto_rawDesc = []byte{ + 0x0a, 0x27, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x75, + 0x6d, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x86, 0x03, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x43, + 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x12, 0x21, 0x0a, 0x0c, + 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, + 0x33, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0c, 0x42, 0x12, 0x8a, 0xb5, 0x18, 0x06, 0x3f, 0x2c, 0x32, 0x30, 0x34, 0x38, + 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x43, 0x6f, + 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x39, 0x0a, 0x0f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, + 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, + 0x0e, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, + 0x2d, 0x0a, 0x09, 0x6b, 0x7a, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x92, 0xb5, 0x18, 0x04, + 0x34, 0x30, 0x39, 0x36, 0x52, 0x08, 0x6b, 0x7a, 0x67, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x5e, + 0x0a, 0x13, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x11, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4f, + 0x0a, 0x1f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x34, 0x2c, 0x33, + 0x32, 0x52, 0x1c, 0x6b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, + 0x60, 0x0a, 0x14, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x21, + 0x0a, 0x0c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, + 0x10, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, + 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_prysm_v1alpha1_data_columns_proto_rawDescOnce sync.Once + file_proto_prysm_v1alpha1_data_columns_proto_rawDescData = file_proto_prysm_v1alpha1_data_columns_proto_rawDesc +) + +func file_proto_prysm_v1alpha1_data_columns_proto_rawDescGZIP() []byte { + file_proto_prysm_v1alpha1_data_columns_proto_rawDescOnce.Do(func() { + file_proto_prysm_v1alpha1_data_columns_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_prysm_v1alpha1_data_columns_proto_rawDescData) + }) + return file_proto_prysm_v1alpha1_data_columns_proto_rawDescData +} + +var file_proto_prysm_v1alpha1_data_columns_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_proto_prysm_v1alpha1_data_columns_proto_goTypes = []interface{}{ + (*DataColumnSidecar)(nil), // 0: ethereum.eth.v1alpha1.DataColumnSidecar + (*DataColumnIdentifier)(nil), // 1: ethereum.eth.v1alpha1.DataColumnIdentifier + (*SignedBeaconBlockHeader)(nil), // 2: ethereum.eth.v1alpha1.SignedBeaconBlockHeader +} +var file_proto_prysm_v1alpha1_data_columns_proto_depIdxs = []int32{ + 2, // 0: ethereum.eth.v1alpha1.DataColumnSidecar.signed_block_header:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockHeader + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_proto_prysm_v1alpha1_data_columns_proto_init() } +func file_proto_prysm_v1alpha1_data_columns_proto_init() { + if File_proto_prysm_v1alpha1_data_columns_proto != nil { + return + } + file_proto_prysm_v1alpha1_beacon_block_proto_init() + if !protoimpl.UnsafeEnabled { + file_proto_prysm_v1alpha1_data_columns_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DataColumnSidecar); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_data_columns_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DataColumnIdentifier); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_prysm_v1alpha1_data_columns_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_prysm_v1alpha1_data_columns_proto_goTypes, + DependencyIndexes: file_proto_prysm_v1alpha1_data_columns_proto_depIdxs, + MessageInfos: file_proto_prysm_v1alpha1_data_columns_proto_msgTypes, + }.Build() + File_proto_prysm_v1alpha1_data_columns_proto = out.File + file_proto_prysm_v1alpha1_data_columns_proto_rawDesc = nil + file_proto_prysm_v1alpha1_data_columns_proto_goTypes = nil + file_proto_prysm_v1alpha1_data_columns_proto_depIdxs = nil +} diff --git a/proto/prysm/v1alpha1/data_columns.proto b/proto/prysm/v1alpha1/data_columns.proto new file mode 100644 index 000000000000..f1c03471d8f2 --- /dev/null +++ b/proto/prysm/v1alpha1/data_columns.proto @@ -0,0 +1,51 @@ +// Copyright 2024 Offchain Labs. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; + +package ethereum.eth.v1alpha1; + +import "proto/eth/ext/options.proto"; +import "proto/prysm/v1alpha1/beacon_block.proto"; + +option csharp_namespace = "Ethereum.Eth.v1alpha1"; +option go_package = "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1;eth"; +option java_multiple_files = true; +option java_outer_classname = "DataColumnsProto"; +option java_package = "org.ethereum.eth.v1alpha1"; +option php_namespace = "Ethereum\\Eth\\v1alpha1"; + +message DataColumnSidecar { + uint64 column_index = 1; + repeated bytes data_column = 2 [ + (ethereum.eth.ext.ssz_size) = "?,bytes_per_cell.size", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; + repeated bytes kzg_commitments = 3 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; + repeated bytes kzg_proof = 4 [ + (ethereum.eth.ext.ssz_size) = "?,48", + (ethereum.eth.ext.ssz_max) = "max_blob_commitments.size" + ]; + SignedBeaconBlockHeader signed_block_header = 5; + repeated bytes kzg_commitments_inclusion_proof = 6 + [ (ethereum.eth.ext.ssz_size) = + "kzg_commitments_inclusion_proof_depth.size,32" ]; +} + +message DataColumnIdentifier { + bytes block_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 column_index = 2; +} \ No newline at end of file diff --git a/proto/prysm/v1alpha1/debug.pb.go b/proto/prysm/v1alpha1/debug.pb.go index 1ae0501d8175..7917e23464e9 100755 --- a/proto/prysm/v1alpha1/debug.pb.go +++ b/proto/prysm/v1alpha1/debug.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/debug.proto package eth diff --git a/proto/prysm/v1alpha1/debug.pb.gw.go b/proto/prysm/v1alpha1/debug.pb.gw.go deleted file mode 100755 index 750a64dc7280..000000000000 --- a/proto/prysm/v1alpha1/debug.pb.gw.go +++ /dev/null @@ -1,487 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: proto/prysm/v1alpha1/debug.proto - -/* -Package eth is a reverse proxy. - -It translates gRPC into RESTful JSON APIs. -*/ -package eth - -import ( - "context" - "io" - "net/http" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/emptypb" -) - -// Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join -var _ = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) -var _ = emptypb.Empty{} - -var ( - filter_Debug_GetBeaconState_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_Debug_GetBeaconState_0(ctx context.Context, marshaler runtime.Marshaler, client DebugClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq BeaconStateRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Debug_GetBeaconState_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetBeaconState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Debug_GetBeaconState_0(ctx context.Context, marshaler runtime.Marshaler, server DebugServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq BeaconStateRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Debug_GetBeaconState_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetBeaconState(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_Debug_GetBlock_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_Debug_GetBlock_0(ctx context.Context, marshaler runtime.Marshaler, client DebugClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq BlockRequestByRoot - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Debug_GetBlock_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetBlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Debug_GetBlock_0(ctx context.Context, marshaler runtime.Marshaler, server DebugServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq BlockRequestByRoot - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Debug_GetBlock_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetBlock(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_Debug_SetLoggingLevel_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_Debug_SetLoggingLevel_0(ctx context.Context, marshaler runtime.Marshaler, client DebugClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq LoggingLevelRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Debug_SetLoggingLevel_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SetLoggingLevel(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Debug_SetLoggingLevel_0(ctx context.Context, marshaler runtime.Marshaler, server DebugServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq LoggingLevelRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Debug_SetLoggingLevel_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SetLoggingLevel(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Debug_ListPeers_0(ctx context.Context, marshaler runtime.Marshaler, client DebugClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.ListPeers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Debug_ListPeers_0(ctx context.Context, marshaler runtime.Marshaler, server DebugServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.ListPeers(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_Debug_GetPeer_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_Debug_GetPeer_0(ctx context.Context, marshaler runtime.Marshaler, client DebugClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq PeerRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Debug_GetPeer_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetPeer(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Debug_GetPeer_0(ctx context.Context, marshaler runtime.Marshaler, server DebugServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq PeerRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Debug_GetPeer_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetPeer(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterDebugHandlerServer registers the http handlers for service Debug to "mux". -// UnaryRPC :call DebugServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterDebugHandlerFromEndpoint instead. -func RegisterDebugHandlerServer(ctx context.Context, mux *runtime.ServeMux, server DebugServer) error { - - mux.Handle("GET", pattern_Debug_GetBeaconState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/GetBeaconState") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Debug_GetBeaconState_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_GetBeaconState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Debug_GetBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/GetBlock") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Debug_GetBlock_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_GetBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Debug_SetLoggingLevel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/SetLoggingLevel") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Debug_SetLoggingLevel_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_SetLoggingLevel_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Debug_ListPeers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/ListPeers") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Debug_ListPeers_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_ListPeers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Debug_GetPeer_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/GetPeer") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Debug_GetPeer_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_GetPeer_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -// RegisterDebugHandlerFromEndpoint is same as RegisterDebugHandler but -// automatically dials to "endpoint" and closes the connection when "ctx" gets done. -func RegisterDebugHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) - if err != nil { - return err - } - defer func() { - if err != nil { - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - return - } - go func() { - <-ctx.Done() - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - }() - }() - - return RegisterDebugHandler(ctx, mux, conn) -} - -// RegisterDebugHandler registers the http handlers for service Debug to "mux". -// The handlers forward requests to the grpc endpoint over "conn". -func RegisterDebugHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { - return RegisterDebugHandlerClient(ctx, mux, NewDebugClient(conn)) -} - -// RegisterDebugHandlerClient registers the http handlers for service Debug -// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "DebugClient". -// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "DebugClient" -// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "DebugClient" to call the correct interceptors. -func RegisterDebugHandlerClient(ctx context.Context, mux *runtime.ServeMux, client DebugClient) error { - - mux.Handle("GET", pattern_Debug_GetBeaconState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/GetBeaconState") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Debug_GetBeaconState_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_GetBeaconState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Debug_GetBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/GetBlock") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Debug_GetBlock_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_GetBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Debug_SetLoggingLevel_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/SetLoggingLevel") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Debug_SetLoggingLevel_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_SetLoggingLevel_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Debug_ListPeers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/ListPeers") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Debug_ListPeers_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_ListPeers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Debug_GetPeer_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Debug/GetPeer") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Debug_GetPeer_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Debug_GetPeer_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Debug_GetBeaconState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "debug", "state"}, "")) - - pattern_Debug_GetBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "debug", "block"}, "")) - - pattern_Debug_SetLoggingLevel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "debug", "logging"}, "")) - - pattern_Debug_ListPeers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "debug", "peers"}, "")) - - pattern_Debug_GetPeer_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "debug", "peer"}, "")) -) - -var ( - forward_Debug_GetBeaconState_0 = runtime.ForwardResponseMessage - - forward_Debug_GetBlock_0 = runtime.ForwardResponseMessage - - forward_Debug_SetLoggingLevel_0 = runtime.ForwardResponseMessage - - forward_Debug_ListPeers_0 = runtime.ForwardResponseMessage - - forward_Debug_GetPeer_0 = runtime.ForwardResponseMessage -) diff --git a/proto/prysm/v1alpha1/debug.proto b/proto/prysm/v1alpha1/debug.proto index 172d6f6a9793..d46a46b630a3 100644 --- a/proto/prysm/v1alpha1/debug.proto +++ b/proto/prysm/v1alpha1/debug.proto @@ -19,147 +19,154 @@ option php_namespace = "Ethereum\\Eth\\v1alpha1"; // // The debug service in Prysm provides API access to various utilities // for debugging the beacon node's functionality at runtime, such as being able -// to retrieve the beacon state by block root or state root from the node directly. +// to retrieve the beacon state by block root or state root from the node +// directly. service Debug { - // Returns a beacon state by filter criteria from the beacon node. - rpc GetBeaconState(BeaconStateRequest) returns (SSZResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/debug/state" - }; - } - // Returns a beacon state by filter criteria from the beacon node. - rpc GetBlock(BlockRequestByRoot) returns (SSZResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/debug/block" - }; - } - // SetLoggingLevel sets the log-level of the beacon node programmatically. - rpc SetLoggingLevel(LoggingLevelRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/eth/v1alpha1/debug/logging" - }; - } - // Returns all the related data for every peer tracked by the host node. - rpc ListPeers(google.protobuf.Empty) returns (DebugPeerResponses){ - option (google.api.http) = { - get: "/eth/v1alpha1/debug/peers" - }; - } - // Returns requested peer with specified peer id if it exists. - rpc GetPeer(ethereum.eth.v1alpha1.PeerRequest) returns (DebugPeerResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/debug/peer" - }; - } + // Returns a beacon state by filter criteria from the beacon node. + rpc GetBeaconState(BeaconStateRequest) returns (SSZResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/debug/state" + }; + } + // Returns a beacon state by filter criteria from the beacon node. + rpc GetBlock(BlockRequestByRoot) returns (SSZResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/debug/block" + }; + } + // SetLoggingLevel sets the log-level of the beacon node programmatically. + rpc SetLoggingLevel(LoggingLevelRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { + post : "/eth/v1alpha1/debug/logging" + }; + } + // Returns all the related data for every peer tracked by the host node. + rpc ListPeers(google.protobuf.Empty) returns (DebugPeerResponses) { + option (google.api.http) = { + get : "/eth/v1alpha1/debug/peers" + }; + } + // Returns requested peer with specified peer id if it exists. + rpc GetPeer(ethereum.eth.v1alpha1.PeerRequest) returns (DebugPeerResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/debug/peer" + }; + } } message InclusionSlotRequest { - uint64 id = 1; - uint64 slot = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 id = 1; + uint64 slot = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; } message InclusionSlotResponse { - uint64 slot = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 slot = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; } message BeaconStateRequest { - oneof query_filter { - // The slot corresponding to a desired beacon state. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + oneof query_filter { + // The slot corresponding to a desired beacon state. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // The block root corresponding to a desired beacon state. - bytes block_root = 2; - } + // The block root corresponding to a desired beacon state. + bytes block_root = 2; + } } -message BlockRequestByRoot { - bytes block_root = 1; -} +message BlockRequestByRoot { bytes block_root = 1; } message SSZResponse { - // Returns an ssz-encoded byte slice as a response. - bytes encoded = 1; + // Returns an ssz-encoded byte slice as a response. + bytes encoded = 1; } message LoggingLevelRequest { - // The logging levels available in Prysm as an enum. - enum Level { - INFO = 0; - DEBUG = 1; - TRACE = 2; - } - Level level = 1; + // The logging levels available in Prysm as an enum. + enum Level { + INFO = 0; + DEBUG = 1; + TRACE = 2; + } + Level level = 1; } -message DebugPeerResponses { - repeated DebugPeerResponse responses = 1; -} +message DebugPeerResponses { repeated DebugPeerResponse responses = 1; } message DebugPeerResponse { - // Peer related metadata that is useful for debugging. - message PeerInfo { - // Metadata of the peer, containing their bitfield - // and sequence number. - MetaDataV0 metadataV0 = 1; - MetaDataV1 metadataV1 = 2; - // List of protocols the peer supports. - repeated string protocols = 3; - // Number of times peer has been penalised. - uint64 fault_count = 4; - // Protocol Version peer is running. - string protocol_version = 5; - // Agent Version peer is running. - string agent_version = 6; - // Latency of responses from peer(in ms). - uint64 peer_latency = 7; - } - // Listening addresses know of the peer. - repeated string listening_addresses = 1; - // Direction of current connection. - ethereum.eth.v1alpha1.PeerDirection direction = 2; - // Current connection between host and peer. - ethereum.eth.v1alpha1.ConnectionState connection_state = 3; - // Peer ID of peer. - string peer_id = 4; - // ENR of peer at the current moment. - string enr = 5; - // Peer Info of the peer containing all relevant metadata. - PeerInfo peer_info = 6; - // Peer Status of the peer. - Status peer_status = 7; - // Last know update time for peer status. - uint64 last_updated = 8; - // Score Info of the peer. - ScoreInfo score_info = 9; + // Peer related metadata that is useful for debugging. + message PeerInfo { + // Metadata of the peer, containing their bitfield + // and sequence number. + MetaDataV0 metadataV0 = 1; + MetaDataV1 metadataV1 = 2; + // List of protocols the peer supports. + repeated string protocols = 3; + // Number of times peer has been penalised. + uint64 fault_count = 4; + // Protocol Version peer is running. + string protocol_version = 5; + // Agent Version peer is running. + string agent_version = 6; + // Latency of responses from peer(in ms). + uint64 peer_latency = 7; + } + // Listening addresses know of the peer. + repeated string listening_addresses = 1; + // Direction of current connection. + ethereum.eth.v1alpha1.PeerDirection direction = 2; + // Current connection between host and peer. + ethereum.eth.v1alpha1.ConnectionState connection_state = 3; + // Peer ID of peer. + string peer_id = 4; + // ENR of peer at the current moment. + string enr = 5; + // Peer Info of the peer containing all relevant metadata. + PeerInfo peer_info = 6; + // Peer Status of the peer. + Status peer_status = 7; + // Last know update time for peer status. + uint64 last_updated = 8; + // Score Info of the peer. + ScoreInfo score_info = 9; } // The Scoring related information of the particular peer. message ScoreInfo { - float overall_score = 1; - // Amount of processed blocks provided by - // the peer. - uint64 processed_blocks = 2; - // Related block provider score. - float block_provider_score = 3; - // Relevant scores by particular topic. - map topic_scores = 4; - // Gossip Score for peer. - float gossip_score = 5; - // Behaviour penalty of peer. - float behaviour_penalty = 6; - // Returns the current validation error(if it exists). - string validation_error = 7; + float overall_score = 1; + // Amount of processed blocks provided by + // the peer. + uint64 processed_blocks = 2; + // Related block provider score. + float block_provider_score = 3; + // Relevant scores by particular topic. + map topic_scores = 4; + // Gossip Score for peer. + float gossip_score = 5; + // Behaviour penalty of peer. + float behaviour_penalty = 6; + // Returns the current validation error(if it exists). + string validation_error = 7; } message TopicScoreSnapshot { - // Time a peer has spent in the gossip mesh. - uint64 time_in_mesh = 1; - // This is the number of first message deliveries in the topic. - float first_message_deliveries = 2; - // This is the number of message deliveries in the mesh, within the MeshMessageDeliveriesWindow of - // message validation.It effectively tracks first and near-first - // deliveries, ie a message seen from a mesh peer before we have forwarded it to them. - float mesh_message_deliveries = 3; - // This is the number of invalid messages in the topic from the peer. - float invalid_message_deliveries = 4; + // Time a peer has spent in the gossip mesh. + uint64 time_in_mesh = 1; + // This is the number of first message deliveries in the topic. + float first_message_deliveries = 2; + // This is the number of message deliveries in the mesh, within the + // MeshMessageDeliveriesWindow of message validation.It effectively tracks + // first and near-first deliveries, ie a message seen from a mesh peer before + // we have forwarded it to them. + float mesh_message_deliveries = 3; + // This is the number of invalid messages in the topic from the peer. + float invalid_message_deliveries = 4; } diff --git a/proto/prysm/v1alpha1/deneb.ssz.go b/proto/prysm/v1alpha1/deneb.ssz.go index deeeacdb81df..4eeab97e97c8 100644 --- a/proto/prysm/v1alpha1/deneb.ssz.go +++ b/proto/prysm/v1alpha1/deneb.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: adfca9994daf736f0526568d87329503d997b98308a409e71cd510115380af5a package eth import ( @@ -217,6 +216,115 @@ func (s *SignedBeaconBlockContentsDeneb) HashTreeRootWith(hh *ssz.Hasher) (err e return } +// MarshalSSZ ssz marshals the SignedBeaconBlockDeneb object +func (s *SignedBeaconBlockDeneb) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedBeaconBlockDeneb object to a target array +func (s *SignedBeaconBlockDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(100) + + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if s.Block == nil { + s.Block = new(BeaconBlockDeneb) + } + offset += s.Block.SizeSSZ() + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + // Field (0) 'Block' + if dst, err = s.Block.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockDeneb object +func (s *SignedBeaconBlockDeneb) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 100 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 100 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) + } + s.Signature = append(s.Signature, buf[4:100]...) + + // Field (0) 'Block' + { + buf = tail[o0:] + if s.Block == nil { + s.Block = new(BeaconBlockDeneb) + } + if err = s.Block.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockDeneb object +func (s *SignedBeaconBlockDeneb) SizeSSZ() (size int) { + size = 100 + + // Field (0) 'Block' + if s.Block == nil { + s.Block = new(BeaconBlockDeneb) + } + size += s.Block.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the SignedBeaconBlockDeneb object +func (s *SignedBeaconBlockDeneb) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedBeaconBlockDeneb object with a hasher +func (s *SignedBeaconBlockDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Block' + if err = s.Block.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(s.Signature) + + hh.Merkleize(indx) + return +} + // MarshalSSZ ssz marshals the BeaconBlockContentsDeneb object func (b *BeaconBlockContentsDeneb) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) @@ -426,115 +534,6 @@ func (b *BeaconBlockContentsDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) return } -// MarshalSSZ ssz marshals the SignedBeaconBlockDeneb object -func (s *SignedBeaconBlockDeneb) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBeaconBlockDeneb object to a target array -func (s *SignedBeaconBlockDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Block' - dst = ssz.WriteOffset(dst, offset) - if s.Block == nil { - s.Block = new(BeaconBlockDeneb) - } - offset += s.Block.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Block' - if dst, err = s.Block.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockDeneb object -func (s *SignedBeaconBlockDeneb) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Block' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Block' - { - buf = tail[o0:] - if s.Block == nil { - s.Block = new(BeaconBlockDeneb) - } - if err = s.Block.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockDeneb object -func (s *SignedBeaconBlockDeneb) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Block' - if s.Block == nil { - s.Block = new(BeaconBlockDeneb) - } - size += s.Block.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBeaconBlockDeneb object -func (s *SignedBeaconBlockDeneb) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBeaconBlockDeneb object with a hasher -func (s *SignedBeaconBlockDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Block' - if err = s.Block.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - // MarshalSSZ ssz marshals the BeaconBlockDeneb object func (b *BeaconBlockDeneb) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) @@ -2341,38 +2340,145 @@ func (b *BuilderBidDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the BlobSidecar object -func (b *BlobSidecar) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the BlobSidecars object +func (b *BlobSidecars) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) } -// MarshalSSZTo ssz marshals the BlobSidecar object to a target array -func (b *BlobSidecar) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the BlobSidecars object to a target array +func (b *BlobSidecars) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf + offset := int(4) - // Field (0) 'Index' - dst = ssz.MarshalUint64(dst, b.Index) - - // Field (1) 'Blob' - if size := len(b.Blob); size != 131072 { - err = ssz.ErrBytesLengthFn("--.Blob", size, 131072) - return - } - dst = append(dst, b.Blob...) + // Offset (0) 'Sidecars' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Sidecars) * 131928 - // Field (2) 'KzgCommitment' - if size := len(b.KzgCommitment); size != 48 { - err = ssz.ErrBytesLengthFn("--.KzgCommitment", size, 48) + // Field (0) 'Sidecars' + if size := len(b.Sidecars); size > 6 { + err = ssz.ErrListTooBigFn("--.Sidecars", size, 6) return } - dst = append(dst, b.KzgCommitment...) - - // Field (3) 'KzgProof' - if size := len(b.KzgProof); size != 48 { - err = ssz.ErrBytesLengthFn("--.KzgProof", size, 48) - return + for ii := 0; ii < len(b.Sidecars); ii++ { + if dst, err = b.Sidecars[ii].MarshalSSZTo(dst); err != nil { + return + } } - dst = append(dst, b.KzgProof...) + + return +} + +// UnmarshalSSZ ssz unmarshals the BlobSidecars object +func (b *BlobSidecars) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 4 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Sidecars' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 4 { + return ssz.ErrInvalidVariableOffset + } + + // Field (0) 'Sidecars' + { + buf = tail[o0:] + num, err := ssz.DivideInt2(len(buf), 131928, 6) + if err != nil { + return err + } + b.Sidecars = make([]*BlobSidecar, num) + for ii := 0; ii < num; ii++ { + if b.Sidecars[ii] == nil { + b.Sidecars[ii] = new(BlobSidecar) + } + if err = b.Sidecars[ii].UnmarshalSSZ(buf[ii*131928 : (ii+1)*131928]); err != nil { + return err + } + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the BlobSidecars object +func (b *BlobSidecars) SizeSSZ() (size int) { + size = 4 + + // Field (0) 'Sidecars' + size += len(b.Sidecars) * 131928 + + return +} + +// HashTreeRoot ssz hashes the BlobSidecars object +func (b *BlobSidecars) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) +} + +// HashTreeRootWith ssz hashes the BlobSidecars object with a hasher +func (b *BlobSidecars) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Sidecars' + { + subIndx := hh.Index() + num := uint64(len(b.Sidecars)) + if num > 6 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.Sidecars { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 6) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the BlobSidecar object +func (b *BlobSidecar) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BlobSidecar object to a target array +func (b *BlobSidecar) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Index' + dst = ssz.MarshalUint64(dst, b.Index) + + // Field (1) 'Blob' + if size := len(b.Blob); size != 131072 { + err = ssz.ErrBytesLengthFn("--.Blob", size, 131072) + return + } + dst = append(dst, b.Blob...) + + // Field (2) 'KzgCommitment' + if size := len(b.KzgCommitment); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgCommitment", size, 48) + return + } + dst = append(dst, b.KzgCommitment...) + + // Field (3) 'KzgProof' + if size := len(b.KzgProof); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgProof", size, 48) + return + } + dst = append(dst, b.KzgProof...) // Field (4) 'SignedBlockHeader' if b.SignedBlockHeader == nil { @@ -2512,113 +2618,6 @@ func (b *BlobSidecar) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the BlobSidecars object -func (b *BlobSidecars) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) -} - -// MarshalSSZTo ssz marshals the BlobSidecars object to a target array -func (b *BlobSidecars) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(4) - - // Offset (0) 'Sidecars' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Sidecars) * 131928 - - // Field (0) 'Sidecars' - if size := len(b.Sidecars); size > 6 { - err = ssz.ErrListTooBigFn("--.Sidecars", size, 6) - return - } - for ii := 0; ii < len(b.Sidecars); ii++ { - if dst, err = b.Sidecars[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - return -} - -// UnmarshalSSZ ssz unmarshals the BlobSidecars object -func (b *BlobSidecars) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 4 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Sidecars' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 4 { - return ssz.ErrInvalidVariableOffset - } - - // Field (0) 'Sidecars' - { - buf = tail[o0:] - num, err := ssz.DivideInt2(len(buf), 131928, 6) - if err != nil { - return err - } - b.Sidecars = make([]*BlobSidecar, num) - for ii := 0; ii < num; ii++ { - if b.Sidecars[ii] == nil { - b.Sidecars[ii] = new(BlobSidecar) - } - if err = b.Sidecars[ii].UnmarshalSSZ(buf[ii*131928 : (ii+1)*131928]); err != nil { - return err - } - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the BlobSidecars object -func (b *BlobSidecars) SizeSSZ() (size int) { - size = 4 - - // Field (0) 'Sidecars' - size += len(b.Sidecars) * 131928 - - return -} - -// HashTreeRoot ssz hashes the BlobSidecars object -func (b *BlobSidecars) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) -} - -// HashTreeRootWith ssz hashes the BlobSidecars object with a hasher -func (b *BlobSidecars) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Sidecars' - { - subIndx := hh.Index() - num := uint64(len(b.Sidecars)) - if num > 6 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Sidecars { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 6) - } - - hh.Merkleize(indx) - return -} - // MarshalSSZ ssz marshals the BeaconStateDeneb object func (b *BeaconStateDeneb) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) @@ -3593,3 +3592,874 @@ func (b *BlobIdentifier) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.Merkleize(indx) return } + +// MarshalSSZ ssz marshals the LightClientBootstrapDeneb object +func (l *LightClientBootstrapDeneb) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientBootstrapDeneb object to a target array +func (l *LightClientBootstrapDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(24788) + + // Offset (0) 'Header' + dst = ssz.WriteOffset(dst, offset) + if l.Header == nil { + l.Header = new(LightClientHeaderDeneb) + } + offset += l.Header.SizeSSZ() + + // Field (1) 'CurrentSyncCommittee' + if l.CurrentSyncCommittee == nil { + l.CurrentSyncCommittee = new(SyncCommittee) + } + if dst, err = l.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'CurrentSyncCommitteeBranch' + if size := len(l.CurrentSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5) + return + } + for ii := 0; ii < 5; ii++ { + if size := len(l.CurrentSyncCommitteeBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.CurrentSyncCommitteeBranch[ii]", size, 32) + return + } + dst = append(dst, l.CurrentSyncCommitteeBranch[ii]...) + } + + // Field (0) 'Header' + if dst, err = l.Header.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientBootstrapDeneb object +func (l *LightClientBootstrapDeneb) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 24788 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Header' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 24788 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'CurrentSyncCommittee' + if l.CurrentSyncCommittee == nil { + l.CurrentSyncCommittee = new(SyncCommittee) + } + if err = l.CurrentSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil { + return err + } + + // Field (2) 'CurrentSyncCommitteeBranch' + l.CurrentSyncCommitteeBranch = make([][]byte, 5) + for ii := 0; ii < 5; ii++ { + if cap(l.CurrentSyncCommitteeBranch[ii]) == 0 { + l.CurrentSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24788][ii*32:(ii+1)*32])) + } + l.CurrentSyncCommitteeBranch[ii] = append(l.CurrentSyncCommitteeBranch[ii], buf[24628:24788][ii*32:(ii+1)*32]...) + } + + // Field (0) 'Header' + { + buf = tail[o0:] + if l.Header == nil { + l.Header = new(LightClientHeaderDeneb) + } + if err = l.Header.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientBootstrapDeneb object +func (l *LightClientBootstrapDeneb) SizeSSZ() (size int) { + size = 24788 + + // Field (0) 'Header' + if l.Header == nil { + l.Header = new(LightClientHeaderDeneb) + } + size += l.Header.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientBootstrapDeneb object +func (l *LightClientBootstrapDeneb) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientBootstrapDeneb object with a hasher +func (l *LightClientBootstrapDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Header' + if err = l.Header.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'CurrentSyncCommittee' + if err = l.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'CurrentSyncCommitteeBranch' + { + if size := len(l.CurrentSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 5) + return + } + subIndx := hh.Index() + for _, i := range l.CurrentSyncCommitteeBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientUpdateDeneb object +func (l *LightClientUpdateDeneb) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientUpdateDeneb object to a target array +func (l *LightClientUpdateDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(25152) + + // Offset (0) 'AttestedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + offset += l.AttestedHeader.SizeSSZ() + + // Field (1) 'NextSyncCommittee' + if l.NextSyncCommittee == nil { + l.NextSyncCommittee = new(SyncCommittee) + } + if dst, err = l.NextSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'NextSyncCommitteeBranch' + if size := len(l.NextSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5) + return + } + for ii := 0; ii < 5; ii++ { + if size := len(l.NextSyncCommitteeBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.NextSyncCommitteeBranch[ii]", size, 32) + return + } + dst = append(dst, l.NextSyncCommitteeBranch[ii]...) + } + + // Offset (3) 'FinalizedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + offset += l.FinalizedHeader.SizeSSZ() + + // Field (4) 'FinalityBranch' + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + for ii := 0; ii < 6; ii++ { + if size := len(l.FinalityBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32) + return + } + dst = append(dst, l.FinalityBranch[ii]...) + } + + // Field (5) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (6) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + // Field (0) 'AttestedHeader' + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (3) 'FinalizedHeader' + if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientUpdateDeneb object +func (l *LightClientUpdateDeneb) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 25152 { + return ssz.ErrSize + } + + tail := buf + var o0, o3 uint64 + + // Offset (0) 'AttestedHeader' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 25152 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'NextSyncCommittee' + if l.NextSyncCommittee == nil { + l.NextSyncCommittee = new(SyncCommittee) + } + if err = l.NextSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil { + return err + } + + // Field (2) 'NextSyncCommitteeBranch' + l.NextSyncCommitteeBranch = make([][]byte, 5) + for ii := 0; ii < 5; ii++ { + if cap(l.NextSyncCommitteeBranch[ii]) == 0 { + l.NextSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24788][ii*32:(ii+1)*32])) + } + l.NextSyncCommitteeBranch[ii] = append(l.NextSyncCommitteeBranch[ii], buf[24628:24788][ii*32:(ii+1)*32]...) + } + + // Offset (3) 'FinalizedHeader' + if o3 = ssz.ReadOffset(buf[24788:24792]); o3 > size || o0 > o3 { + return ssz.ErrOffset + } + + // Field (4) 'FinalityBranch' + l.FinalityBranch = make([][]byte, 6) + for ii := 0; ii < 6; ii++ { + if cap(l.FinalityBranch[ii]) == 0 { + l.FinalityBranch[ii] = make([]byte, 0, len(buf[24792:24984][ii*32:(ii+1)*32])) + } + l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[24792:24984][ii*32:(ii+1)*32]...) + } + + // Field (5) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[24984:25144]); err != nil { + return err + } + + // Field (6) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[25144:25152])) + + // Field (0) 'AttestedHeader' + { + buf = tail[o0:o3] + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (3) 'FinalizedHeader' + { + buf = tail[o3:] + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientUpdateDeneb object +func (l *LightClientUpdateDeneb) SizeSSZ() (size int) { + size = 25152 + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + size += l.AttestedHeader.SizeSSZ() + + // Field (3) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + size += l.FinalizedHeader.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientUpdateDeneb object +func (l *LightClientUpdateDeneb) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientUpdateDeneb object with a hasher +func (l *LightClientUpdateDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'NextSyncCommittee' + if err = l.NextSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'NextSyncCommitteeBranch' + { + if size := len(l.NextSyncCommitteeBranch); size != 5 { + err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 5) + return + } + subIndx := hh.Index() + for _, i := range l.NextSyncCommitteeBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (3) 'FinalizedHeader' + if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (4) 'FinalityBranch' + { + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + subIndx := hh.Index() + for _, i := range l.FinalityBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (5) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (6) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientFinalityUpdateDeneb object +func (l *LightClientFinalityUpdateDeneb) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientFinalityUpdateDeneb object to a target array +func (l *LightClientFinalityUpdateDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(368) + + // Offset (0) 'AttestedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + offset += l.AttestedHeader.SizeSSZ() + + // Offset (1) 'FinalizedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + offset += l.FinalizedHeader.SizeSSZ() + + // Field (2) 'FinalityBranch' + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + for ii := 0; ii < 6; ii++ { + if size := len(l.FinalityBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32) + return + } + dst = append(dst, l.FinalityBranch[ii]...) + } + + // Field (3) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (4) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + // Field (0) 'AttestedHeader' + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'FinalizedHeader' + if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientFinalityUpdateDeneb object +func (l *LightClientFinalityUpdateDeneb) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 368 { + return ssz.ErrSize + } + + tail := buf + var o0, o1 uint64 + + // Offset (0) 'AttestedHeader' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 368 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (1) 'FinalizedHeader' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Field (2) 'FinalityBranch' + l.FinalityBranch = make([][]byte, 6) + for ii := 0; ii < 6; ii++ { + if cap(l.FinalityBranch[ii]) == 0 { + l.FinalityBranch[ii] = make([]byte, 0, len(buf[8:200][ii*32:(ii+1)*32])) + } + l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[8:200][ii*32:(ii+1)*32]...) + } + + // Field (3) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[200:360]); err != nil { + return err + } + + // Field (4) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[360:368])) + + // Field (0) 'AttestedHeader' + { + buf = tail[o0:o1] + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (1) 'FinalizedHeader' + { + buf = tail[o1:] + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientFinalityUpdateDeneb object +func (l *LightClientFinalityUpdateDeneb) SizeSSZ() (size int) { + size = 368 + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + size += l.AttestedHeader.SizeSSZ() + + // Field (1) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + size += l.FinalizedHeader.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientFinalityUpdateDeneb object +func (l *LightClientFinalityUpdateDeneb) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientFinalityUpdateDeneb object with a hasher +func (l *LightClientFinalityUpdateDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'FinalizedHeader' + if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'FinalityBranch' + { + if size := len(l.FinalityBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 6) + return + } + subIndx := hh.Index() + for _, i := range l.FinalityBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (3) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (4) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientOptimisticUpdateDeneb object +func (l *LightClientOptimisticUpdateDeneb) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientOptimisticUpdateDeneb object to a target array +func (l *LightClientOptimisticUpdateDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(172) + + // Offset (0) 'AttestedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + offset += l.AttestedHeader.SizeSSZ() + + // Field (1) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + // Field (0) 'AttestedHeader' + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientOptimisticUpdateDeneb object +func (l *LightClientOptimisticUpdateDeneb) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 172 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'AttestedHeader' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 172 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[4:164]); err != nil { + return err + } + + // Field (2) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[164:172])) + + // Field (0) 'AttestedHeader' + { + buf = tail[o0:] + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientOptimisticUpdateDeneb object +func (l *LightClientOptimisticUpdateDeneb) SizeSSZ() (size int) { + size = 172 + + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + size += l.AttestedHeader.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientOptimisticUpdateDeneb object +func (l *LightClientOptimisticUpdateDeneb) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientOptimisticUpdateDeneb object with a hasher +func (l *LightClientOptimisticUpdateDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientHeaderDeneb object +func (l *LightClientHeaderDeneb) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientHeaderDeneb object to a target array +func (l *LightClientHeaderDeneb) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(244) + + // Field (0) 'Beacon' + if l.Beacon == nil { + l.Beacon = new(BeaconBlockHeader) + } + if dst, err = l.Beacon.MarshalSSZTo(dst); err != nil { + return + } + + // Offset (1) 'Execution' + dst = ssz.WriteOffset(dst, offset) + if l.Execution == nil { + l.Execution = new(v1.ExecutionPayloadHeaderDeneb) + } + offset += l.Execution.SizeSSZ() + + // Field (2) 'ExecutionBranch' + if size := len(l.ExecutionBranch); size != 4 { + err = ssz.ErrVectorLengthFn("--.ExecutionBranch", size, 4) + return + } + for ii := 0; ii < 4; ii++ { + if size := len(l.ExecutionBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.ExecutionBranch[ii]", size, 32) + return + } + dst = append(dst, l.ExecutionBranch[ii]...) + } + + // Field (1) 'Execution' + if dst, err = l.Execution.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientHeaderDeneb object +func (l *LightClientHeaderDeneb) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 244 { + return ssz.ErrSize + } + + tail := buf + var o1 uint64 + + // Field (0) 'Beacon' + if l.Beacon == nil { + l.Beacon = new(BeaconBlockHeader) + } + if err = l.Beacon.UnmarshalSSZ(buf[0:112]); err != nil { + return err + } + + // Offset (1) 'Execution' + if o1 = ssz.ReadOffset(buf[112:116]); o1 > size { + return ssz.ErrOffset + } + + if o1 != 244 { + return ssz.ErrInvalidVariableOffset + } + + // Field (2) 'ExecutionBranch' + l.ExecutionBranch = make([][]byte, 4) + for ii := 0; ii < 4; ii++ { + if cap(l.ExecutionBranch[ii]) == 0 { + l.ExecutionBranch[ii] = make([]byte, 0, len(buf[116:244][ii*32:(ii+1)*32])) + } + l.ExecutionBranch[ii] = append(l.ExecutionBranch[ii], buf[116:244][ii*32:(ii+1)*32]...) + } + + // Field (1) 'Execution' + { + buf = tail[o1:] + if l.Execution == nil { + l.Execution = new(v1.ExecutionPayloadHeaderDeneb) + } + if err = l.Execution.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the LightClientHeaderDeneb object +func (l *LightClientHeaderDeneb) SizeSSZ() (size int) { + size = 244 + + // Field (1) 'Execution' + if l.Execution == nil { + l.Execution = new(v1.ExecutionPayloadHeaderDeneb) + } + size += l.Execution.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the LightClientHeaderDeneb object +func (l *LightClientHeaderDeneb) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientHeaderDeneb object with a hasher +func (l *LightClientHeaderDeneb) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Beacon' + if err = l.Beacon.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Execution' + if err = l.Execution.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'ExecutionBranch' + { + if size := len(l.ExecutionBranch); size != 4 { + err = ssz.ErrVectorLengthFn("--.ExecutionBranch", size, 4) + return + } + subIndx := hh.Index() + for _, i := range l.ExecutionBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + hh.Merkleize(indx) + return +} diff --git a/proto/prysm/v1alpha1/eip_7251.pb.go b/proto/prysm/v1alpha1/eip_7251.pb.go index 569c74533b18..fa98c3d00741 100755 --- a/proto/prysm/v1alpha1/eip_7251.pb.go +++ b/proto/prysm/v1alpha1/eip_7251.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/eip_7251.proto package eth @@ -23,17 +23,20 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type PendingBalanceDeposit struct { +type PendingDeposit struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Index github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - Amount uint64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` + PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty" spec-name:"pubkey" ssz-size:"48"` + WithdrawalCredentials []byte `protobuf:"bytes,2,opt,name=withdrawal_credentials,json=withdrawalCredentials,proto3" json:"withdrawal_credentials,omitempty" ssz-size:"32"` + Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,5,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` } -func (x *PendingBalanceDeposit) Reset() { - *x = PendingBalanceDeposit{} +func (x *PendingDeposit) Reset() { + *x = PendingDeposit{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_eip_7251_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -41,13 +44,13 @@ func (x *PendingBalanceDeposit) Reset() { } } -func (x *PendingBalanceDeposit) String() string { +func (x *PendingDeposit) String() string { return protoimpl.X.MessageStringOf(x) } -func (*PendingBalanceDeposit) ProtoMessage() {} +func (*PendingDeposit) ProtoMessage() {} -func (x *PendingBalanceDeposit) ProtoReflect() protoreflect.Message { +func (x *PendingDeposit) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_eip_7251_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -59,25 +62,46 @@ func (x *PendingBalanceDeposit) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use PendingBalanceDeposit.ProtoReflect.Descriptor instead. -func (*PendingBalanceDeposit) Descriptor() ([]byte, []int) { +// Deprecated: Use PendingDeposit.ProtoReflect.Descriptor instead. +func (*PendingDeposit) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_eip_7251_proto_rawDescGZIP(), []int{0} } -func (x *PendingBalanceDeposit) GetIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { +func (x *PendingDeposit) GetPublicKey() []byte { if x != nil { - return x.Index + return x.PublicKey } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) + return nil } -func (x *PendingBalanceDeposit) GetAmount() uint64 { +func (x *PendingDeposit) GetWithdrawalCredentials() []byte { + if x != nil { + return x.WithdrawalCredentials + } + return nil +} + +func (x *PendingDeposit) GetAmount() uint64 { if x != nil { return x.Amount } return 0 } +func (x *PendingDeposit) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +func (x *PendingDeposit) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.Slot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + type PendingPartialWithdrawal struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -204,60 +228,68 @@ var file_proto_prysm_v1alpha1_eip_7251_proto_rawDesc = []byte{ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x12, 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, - 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x22, 0x90, 0x02, 0x0a, 0x18, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, - 0x72, 0x74, 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x12, - 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, - 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, - 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x75, - 0x0a, 0x12, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x11, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, - 0x45, 0x70, 0x6f, 0x63, 0x68, 0x22, 0xfe, 0x01, 0x0a, 0x14, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x72, - 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, - 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x72, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x99, 0x02, 0x0a, 0x0e, 0x50, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x2f, 0x0a, 0x0a, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, + 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3d, 0x0a, + 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, + 0x6c, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, + 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x97, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x42, 0x0c, 0x45, 0x49, 0x50, 0x37, 0x32, 0x35, 0x31, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, - 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, - 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, + 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x22, 0x90, 0x02, 0x0a, 0x18, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, + 0x61, 0x6c, 0x12, 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, + 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, + 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x75, 0x0a, 0x12, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, + 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, + 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x11, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, + 0x62, 0x6c, 0x65, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x22, 0xfe, 0x01, 0x0a, 0x14, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x72, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x72, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, + 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0b, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x97, 0x01, 0x0a, 0x19, 0x6f, 0x72, + 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0c, 0x45, 0x49, 0x50, 0x37, 0x32, 0x35, 0x31, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, + 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -274,7 +306,7 @@ func file_proto_prysm_v1alpha1_eip_7251_proto_rawDescGZIP() []byte { var file_proto_prysm_v1alpha1_eip_7251_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_proto_prysm_v1alpha1_eip_7251_proto_goTypes = []interface{}{ - (*PendingBalanceDeposit)(nil), // 0: ethereum.eth.v1alpha1.PendingBalanceDeposit + (*PendingDeposit)(nil), // 0: ethereum.eth.v1alpha1.PendingDeposit (*PendingPartialWithdrawal)(nil), // 1: ethereum.eth.v1alpha1.PendingPartialWithdrawal (*PendingConsolidation)(nil), // 2: ethereum.eth.v1alpha1.PendingConsolidation } @@ -293,7 +325,7 @@ func file_proto_prysm_v1alpha1_eip_7251_proto_init() { } if !protoimpl.UnsafeEnabled { file_proto_prysm_v1alpha1_eip_7251_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PendingBalanceDeposit); i { + switch v := v.(*PendingDeposit); i { case 0: return &v.state case 1: diff --git a/proto/prysm/v1alpha1/eip_7251.pb.gw.go b/proto/prysm/v1alpha1/eip_7251.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/eip_7251.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/eip_7251.proto b/proto/prysm/v1alpha1/eip_7251.proto index 723743b70181..768be978e9bf 100644 --- a/proto/prysm/v1alpha1/eip_7251.proto +++ b/proto/prysm/v1alpha1/eip_7251.proto @@ -24,28 +24,49 @@ option java_outer_classname = "EIP7251Proto"; option java_package = "org.ethereum.eth.v1alpha1"; option php_namespace = "Ethereum\\Eth\\v1alpha1"; -message PendingBalanceDeposit { - // Validator index for the deposit. - uint64 index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; +message PendingDeposit { + // 48 byte BLS public key of the validator. + bytes public_key = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; - // The amount of the deposit (gwei). - uint64 amount = 2; + // A 32 byte hash of the withdrawal address public key. + bytes withdrawal_credentials = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // The amount of the deposit (gwei). + uint64 amount = 3; + // 96 byte BLS signature from the validator that produced this block. + bytes signature = 4 [ (ethereum.eth.ext.ssz_size) = "96" ]; + uint64 slot = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; } message PendingPartialWithdrawal { - // Validator index for the withdrawal. - uint64 index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator index for the withdrawal. + uint64 index = 1 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; - // The amount of the withdrawal (gwei). - uint64 amount = 2; + // The amount of the withdrawal (gwei). + uint64 amount = 2; - // A partial withdrawal is valid at this epoch or later. - uint64 withdrawable_epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // A partial withdrawal is valid at this epoch or later. + uint64 withdrawable_epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; } message PendingConsolidation { - // Validator from which the funds will be moved. - uint64 source_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - // Validator to which the funds will be moved. - uint64 target_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // Validator from which the funds will be moved. + uint64 source_index = 1 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; + // Validator to which the funds will be moved. + uint64 target_index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/" + "consensus-types/primitives.ValidatorIndex" ]; } diff --git a/proto/prysm/v1alpha1/eip_7521.go b/proto/prysm/v1alpha1/eip_7521.go index 473ab2de9882..92c9453f3f51 100644 --- a/proto/prysm/v1alpha1/eip_7521.go +++ b/proto/prysm/v1alpha1/eip_7521.go @@ -1,5 +1,21 @@ package eth +import "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + +// Copy -- +func (pd *PendingDeposit) Copy() *PendingDeposit { + if pd == nil { + return nil + } + return &PendingDeposit{ + PublicKey: bytesutil.SafeCopyBytes(pd.PublicKey), + WithdrawalCredentials: bytesutil.SafeCopyBytes(pd.WithdrawalCredentials), + Amount: pd.Amount, + Signature: bytesutil.SafeCopyBytes(pd.Signature), + Slot: pd.Slot, + } +} + // Copy -- func (pw *PendingPartialWithdrawal) Copy() *PendingPartialWithdrawal { if pw == nil { diff --git a/proto/prysm/v1alpha1/eip_7521_fuzz_test.go b/proto/prysm/v1alpha1/eip_7521_fuzz_test.go index 5123be544d75..7a0e36c98a3d 100644 --- a/proto/prysm/v1alpha1/eip_7521_fuzz_test.go +++ b/proto/prysm/v1alpha1/eip_7521_fuzz_test.go @@ -7,6 +7,7 @@ import ( ) func TestCopyEip7521Types_Fuzz(t *testing.T) { + fuzzCopies(t, ð.PendingDeposit{}) fuzzCopies(t, ð.PendingPartialWithdrawal{}) fuzzCopies(t, ð.PendingConsolidation{}) } diff --git a/proto/prysm/v1alpha1/electra.ssz.go b/proto/prysm/v1alpha1/electra.ssz.go index 570dbbd6a2ad..1fb5892f8f3c 100644 --- a/proto/prysm/v1alpha1/electra.ssz.go +++ b/proto/prysm/v1alpha1/electra.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 84572d8fa233c45a41477bced891ee355cc1745ae0fad290f110b7f6b5ed12e1 package eth import ( @@ -8,150 +7,110 @@ import ( v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ) -// MarshalSSZ ssz marshals the AttestationElectra object -func (a *AttestationElectra) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(a) +// MarshalSSZ ssz marshals the SignedAggregateAttestationAndProofElectra object +func (s *SignedAggregateAttestationAndProofElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the AttestationElectra object to a target array -func (a *AttestationElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SignedAggregateAttestationAndProofElectra object to a target array +func (s *SignedAggregateAttestationAndProofElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(236) + offset := int(100) - // Offset (0) 'AggregationBits' + // Offset (0) 'Message' dst = ssz.WriteOffset(dst, offset) - offset += len(a.AggregationBits) - - // Field (1) 'Data' - if a.Data == nil { - a.Data = new(AttestationData) - } - if dst, err = a.Data.MarshalSSZTo(dst); err != nil { - return - } - - // Field (2) 'CommitteeBits' - if size := len(a.CommitteeBits); size != 8 { - err = ssz.ErrBytesLengthFn("--.CommitteeBits", size, 8) - return + if s.Message == nil { + s.Message = new(AggregateAttestationAndProofElectra) } - dst = append(dst, a.CommitteeBits...) + offset += s.Message.SizeSSZ() - // Field (3) 'Signature' - if size := len(a.Signature); size != 96 { + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - dst = append(dst, a.Signature...) + dst = append(dst, s.Signature...) - // Field (0) 'AggregationBits' - if size := len(a.AggregationBits); size > 131072 { - err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 131072) + // Field (0) 'Message' + if dst, err = s.Message.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, a.AggregationBits...) return } -// UnmarshalSSZ ssz unmarshals the AttestationElectra object -func (a *AttestationElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the SignedAggregateAttestationAndProofElectra object +func (s *SignedAggregateAttestationAndProofElectra) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 236 { + if size < 100 { return ssz.ErrSize } tail := buf var o0 uint64 - // Offset (0) 'AggregationBits' + // Offset (0) 'Message' if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { return ssz.ErrOffset } - if o0 != 236 { + if o0 != 100 { return ssz.ErrInvalidVariableOffset } - // Field (1) 'Data' - if a.Data == nil { - a.Data = new(AttestationData) - } - if err = a.Data.UnmarshalSSZ(buf[4:132]); err != nil { - return err - } - - // Field (2) 'CommitteeBits' - if cap(a.CommitteeBits) == 0 { - a.CommitteeBits = make([]byte, 0, len(buf[132:140])) - } - a.CommitteeBits = append(a.CommitteeBits, buf[132:140]...) - - // Field (3) 'Signature' - if cap(a.Signature) == 0 { - a.Signature = make([]byte, 0, len(buf[140:236])) + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) } - a.Signature = append(a.Signature, buf[140:236]...) + s.Signature = append(s.Signature, buf[4:100]...) - // Field (0) 'AggregationBits' + // Field (0) 'Message' { buf = tail[o0:] - if err = ssz.ValidateBitlist(buf, 131072); err != nil { - return err + if s.Message == nil { + s.Message = new(AggregateAttestationAndProofElectra) } - if cap(a.AggregationBits) == 0 { - a.AggregationBits = make([]byte, 0, len(buf)) + if err = s.Message.UnmarshalSSZ(buf); err != nil { + return err } - a.AggregationBits = append(a.AggregationBits, buf...) } return err } -// SizeSSZ returns the ssz encoded size in bytes for the AttestationElectra object -func (a *AttestationElectra) SizeSSZ() (size int) { - size = 236 +// SizeSSZ returns the ssz encoded size in bytes for the SignedAggregateAttestationAndProofElectra object +func (s *SignedAggregateAttestationAndProofElectra) SizeSSZ() (size int) { + size = 100 - // Field (0) 'AggregationBits' - size += len(a.AggregationBits) + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(AggregateAttestationAndProofElectra) + } + size += s.Message.SizeSSZ() return } -// HashTreeRoot ssz hashes the AttestationElectra object -func (a *AttestationElectra) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(a) +// HashTreeRoot ssz hashes the SignedAggregateAttestationAndProofElectra object +func (s *SignedAggregateAttestationAndProofElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) } -// HashTreeRootWith ssz hashes the AttestationElectra object with a hasher -func (a *AttestationElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the SignedAggregateAttestationAndProofElectra object with a hasher +func (s *SignedAggregateAttestationAndProofElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'AggregationBits' - if len(a.AggregationBits) == 0 { - err = ssz.ErrEmptyBitlist - return - } - hh.PutBitlist(a.AggregationBits, 131072) - - // Field (1) 'Data' - if err = a.Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'CommitteeBits' - if size := len(a.CommitteeBits); size != 8 { - err = ssz.ErrBytesLengthFn("--.CommitteeBits", size, 8) + // Field (0) 'Message' + if err = s.Message.HashTreeRootWith(hh); err != nil { return } - hh.PutBytes(a.CommitteeBits) - // Field (3) 'Signature' - if size := len(a.Signature); size != 96 { + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - hh.PutBytes(a.Signature) + hh.PutBytes(s.Signature) hh.Merkleize(indx) return @@ -275,483 +234,421 @@ func (a *AggregateAttestationAndProofElectra) HashTreeRootWith(hh *ssz.Hasher) ( return } -// MarshalSSZ ssz marshals the SignedAggregateAttestationAndProofElectra object -func (s *SignedAggregateAttestationAndProofElectra) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) +// MarshalSSZ ssz marshals the AttestationElectra object +func (a *AttestationElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(a) } -// MarshalSSZTo ssz marshals the SignedAggregateAttestationAndProofElectra object to a target array -func (s *SignedAggregateAttestationAndProofElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the AttestationElectra object to a target array +func (a *AttestationElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(100) + offset := int(236) - // Offset (0) 'Message' + // Offset (0) 'AggregationBits' dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(AggregateAttestationAndProofElectra) + offset += len(a.AggregationBits) + + // Field (1) 'Data' + if a.Data == nil { + a.Data = new(AttestationData) + } + if dst, err = a.Data.MarshalSSZTo(dst); err != nil { + return } - offset += s.Message.SizeSSZ() - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { + // Field (2) 'Signature' + if size := len(a.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - dst = append(dst, s.Signature...) + dst = append(dst, a.Signature...) - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { + // Field (3) 'CommitteeBits' + if size := len(a.CommitteeBits); size != 8 { + err = ssz.ErrBytesLengthFn("--.CommitteeBits", size, 8) + return + } + dst = append(dst, a.CommitteeBits...) + + // Field (0) 'AggregationBits' + if size := len(a.AggregationBits); size > 131072 { + err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 131072) return } + dst = append(dst, a.AggregationBits...) return } -// UnmarshalSSZ ssz unmarshals the SignedAggregateAttestationAndProofElectra object -func (s *SignedAggregateAttestationAndProofElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the AttestationElectra object +func (a *AttestationElectra) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 100 { + if size < 236 { return ssz.ErrSize } tail := buf var o0 uint64 - // Offset (0) 'Message' + // Offset (0) 'AggregationBits' if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { return ssz.ErrOffset } - if o0 != 100 { + if o0 != 236 { return ssz.ErrInvalidVariableOffset } - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) + // Field (1) 'Data' + if a.Data == nil { + a.Data = new(AttestationData) + } + if err = a.Data.UnmarshalSSZ(buf[4:132]); err != nil { + return err } - s.Signature = append(s.Signature, buf[4:100]...) - // Field (0) 'Message' + // Field (2) 'Signature' + if cap(a.Signature) == 0 { + a.Signature = make([]byte, 0, len(buf[132:228])) + } + a.Signature = append(a.Signature, buf[132:228]...) + + // Field (3) 'CommitteeBits' + if cap(a.CommitteeBits) == 0 { + a.CommitteeBits = make([]byte, 0, len(buf[228:236])) + } + a.CommitteeBits = append(a.CommitteeBits, buf[228:236]...) + + // Field (0) 'AggregationBits' { buf = tail[o0:] - if s.Message == nil { - s.Message = new(AggregateAttestationAndProofElectra) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { + if err = ssz.ValidateBitlist(buf, 131072); err != nil { return err } + if cap(a.AggregationBits) == 0 { + a.AggregationBits = make([]byte, 0, len(buf)) + } + a.AggregationBits = append(a.AggregationBits, buf...) } return err } -// SizeSSZ returns the ssz encoded size in bytes for the SignedAggregateAttestationAndProofElectra object -func (s *SignedAggregateAttestationAndProofElectra) SizeSSZ() (size int) { - size = 100 +// SizeSSZ returns the ssz encoded size in bytes for the AttestationElectra object +func (a *AttestationElectra) SizeSSZ() (size int) { + size = 236 - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(AggregateAttestationAndProofElectra) - } - size += s.Message.SizeSSZ() + // Field (0) 'AggregationBits' + size += len(a.AggregationBits) return } -// HashTreeRoot ssz hashes the SignedAggregateAttestationAndProofElectra object -func (s *SignedAggregateAttestationAndProofElectra) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) +// HashTreeRoot ssz hashes the AttestationElectra object +func (a *AttestationElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(a) } -// HashTreeRootWith ssz hashes the SignedAggregateAttestationAndProofElectra object with a hasher -func (s *SignedAggregateAttestationAndProofElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the AttestationElectra object with a hasher +func (a *AttestationElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { + // Field (0) 'AggregationBits' + if len(a.AggregationBits) == 0 { + err = ssz.ErrEmptyBitlist return } + hh.PutBitlist(a.AggregationBits, 131072) - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { + // Field (1) 'Data' + if err = a.Data.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'Signature' + if size := len(a.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - hh.PutBytes(s.Signature) + hh.PutBytes(a.Signature) + + // Field (3) 'CommitteeBits' + if size := len(a.CommitteeBits); size != 8 { + err = ssz.ErrBytesLengthFn("--.CommitteeBits", size, 8) + return + } + hh.PutBytes(a.CommitteeBits) hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the AttesterSlashingElectra object -func (a *AttesterSlashingElectra) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(a) +// MarshalSSZ ssz marshals the SignedAggregateAttestationAndProofSingle object +func (s *SignedAggregateAttestationAndProofSingle) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the AttesterSlashingElectra object to a target array -func (a *AttesterSlashingElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SignedAggregateAttestationAndProofSingle object to a target array +func (s *SignedAggregateAttestationAndProofSingle) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(8) - - // Offset (0) 'Attestation_1' - dst = ssz.WriteOffset(dst, offset) - if a.Attestation_1 == nil { - a.Attestation_1 = new(IndexedAttestationElectra) - } - offset += a.Attestation_1.SizeSSZ() - // Offset (1) 'Attestation_2' - dst = ssz.WriteOffset(dst, offset) - if a.Attestation_2 == nil { - a.Attestation_2 = new(IndexedAttestationElectra) + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(AggregateAttestationAndProofSingle) } - offset += a.Attestation_2.SizeSSZ() - - // Field (0) 'Attestation_1' - if dst, err = a.Attestation_1.MarshalSSZTo(dst); err != nil { + if dst, err = s.Message.MarshalSSZTo(dst); err != nil { return } - // Field (1) 'Attestation_2' - if dst, err = a.Attestation_2.MarshalSSZTo(dst); err != nil { + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } + dst = append(dst, s.Signature...) return } -// UnmarshalSSZ ssz unmarshals the AttesterSlashingElectra object -func (a *AttesterSlashingElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the SignedAggregateAttestationAndProofSingle object +func (s *SignedAggregateAttestationAndProofSingle) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 8 { + if size != 440 { return ssz.ErrSize } - tail := buf - var o0, o1 uint64 - - // Offset (0) 'Attestation_1' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 8 { - return ssz.ErrInvalidVariableOffset + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(AggregateAttestationAndProofSingle) } - - // Offset (1) 'Attestation_2' - if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { - return ssz.ErrOffset + if err = s.Message.UnmarshalSSZ(buf[0:344]); err != nil { + return err } - // Field (0) 'Attestation_1' - { - buf = tail[o0:o1] - if a.Attestation_1 == nil { - a.Attestation_1 = new(IndexedAttestationElectra) - } - if err = a.Attestation_1.UnmarshalSSZ(buf); err != nil { - return err - } + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[344:440])) } + s.Signature = append(s.Signature, buf[344:440]...) - // Field (1) 'Attestation_2' - { - buf = tail[o1:] - if a.Attestation_2 == nil { - a.Attestation_2 = new(IndexedAttestationElectra) - } - if err = a.Attestation_2.UnmarshalSSZ(buf); err != nil { - return err - } - } return err } -// SizeSSZ returns the ssz encoded size in bytes for the AttesterSlashingElectra object -func (a *AttesterSlashingElectra) SizeSSZ() (size int) { - size = 8 - - // Field (0) 'Attestation_1' - if a.Attestation_1 == nil { - a.Attestation_1 = new(IndexedAttestationElectra) - } - size += a.Attestation_1.SizeSSZ() - - // Field (1) 'Attestation_2' - if a.Attestation_2 == nil { - a.Attestation_2 = new(IndexedAttestationElectra) - } - size += a.Attestation_2.SizeSSZ() - +// SizeSSZ returns the ssz encoded size in bytes for the SignedAggregateAttestationAndProofSingle object +func (s *SignedAggregateAttestationAndProofSingle) SizeSSZ() (size int) { + size = 440 return } -// HashTreeRoot ssz hashes the AttesterSlashingElectra object -func (a *AttesterSlashingElectra) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(a) +// HashTreeRoot ssz hashes the SignedAggregateAttestationAndProofSingle object +func (s *SignedAggregateAttestationAndProofSingle) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) } -// HashTreeRootWith ssz hashes the AttesterSlashingElectra object with a hasher -func (a *AttesterSlashingElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the SignedAggregateAttestationAndProofSingle object with a hasher +func (s *SignedAggregateAttestationAndProofSingle) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Attestation_1' - if err = a.Attestation_1.HashTreeRootWith(hh); err != nil { + // Field (0) 'Message' + if err = s.Message.HashTreeRootWith(hh); err != nil { return } - // Field (1) 'Attestation_2' - if err = a.Attestation_2.HashTreeRootWith(hh); err != nil { + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } + hh.PutBytes(s.Signature) hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the IndexedAttestationElectra object -func (i *IndexedAttestationElectra) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(i) +// MarshalSSZ ssz marshals the AggregateAttestationAndProofSingle object +func (a *AggregateAttestationAndProofSingle) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(a) } -// MarshalSSZTo ssz marshals the IndexedAttestationElectra object to a target array -func (i *IndexedAttestationElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the AggregateAttestationAndProofSingle object to a target array +func (a *AggregateAttestationAndProofSingle) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(228) - // Offset (0) 'AttestingIndices' - dst = ssz.WriteOffset(dst, offset) - offset += len(i.AttestingIndices) * 8 + // Field (0) 'AggregatorIndex' + dst = ssz.MarshalUint64(dst, uint64(a.AggregatorIndex)) - // Field (1) 'Data' - if i.Data == nil { - i.Data = new(AttestationData) - } - if dst, err = i.Data.MarshalSSZTo(dst); err != nil { - return + // Field (1) 'Aggregate' + if a.Aggregate == nil { + a.Aggregate = new(SingleAttestation) } - - // Field (2) 'Signature' - if size := len(i.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + if dst, err = a.Aggregate.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, i.Signature...) - // Field (0) 'AttestingIndices' - if size := len(i.AttestingIndices); size > 131072 { - err = ssz.ErrListTooBigFn("--.AttestingIndices", size, 131072) + // Field (2) 'SelectionProof' + if size := len(a.SelectionProof); size != 96 { + err = ssz.ErrBytesLengthFn("--.SelectionProof", size, 96) return } - for ii := 0; ii < len(i.AttestingIndices); ii++ { - dst = ssz.MarshalUint64(dst, i.AttestingIndices[ii]) - } + dst = append(dst, a.SelectionProof...) return } -// UnmarshalSSZ ssz unmarshals the IndexedAttestationElectra object -func (i *IndexedAttestationElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the AggregateAttestationAndProofSingle object +func (a *AggregateAttestationAndProofSingle) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 228 { + if size != 344 { return ssz.ErrSize } - tail := buf - var o0 uint64 - - // Offset (0) 'AttestingIndices' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 228 { - return ssz.ErrInvalidVariableOffset - } + // Field (0) 'AggregatorIndex' + a.AggregatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) - // Field (1) 'Data' - if i.Data == nil { - i.Data = new(AttestationData) + // Field (1) 'Aggregate' + if a.Aggregate == nil { + a.Aggregate = new(SingleAttestation) } - if err = i.Data.UnmarshalSSZ(buf[4:132]); err != nil { + if err = a.Aggregate.UnmarshalSSZ(buf[8:248]); err != nil { return err } - // Field (2) 'Signature' - if cap(i.Signature) == 0 { - i.Signature = make([]byte, 0, len(buf[132:228])) + // Field (2) 'SelectionProof' + if cap(a.SelectionProof) == 0 { + a.SelectionProof = make([]byte, 0, len(buf[248:344])) } - i.Signature = append(i.Signature, buf[132:228]...) + a.SelectionProof = append(a.SelectionProof, buf[248:344]...) - // Field (0) 'AttestingIndices' - { - buf = tail[o0:] - num, err := ssz.DivideInt2(len(buf), 8, 131072) - if err != nil { - return err - } - i.AttestingIndices = ssz.ExtendUint64(i.AttestingIndices, num) - for ii := 0; ii < num; ii++ { - i.AttestingIndices[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) - } - } return err } -// SizeSSZ returns the ssz encoded size in bytes for the IndexedAttestationElectra object -func (i *IndexedAttestationElectra) SizeSSZ() (size int) { - size = 228 - - // Field (0) 'AttestingIndices' - size += len(i.AttestingIndices) * 8 - +// SizeSSZ returns the ssz encoded size in bytes for the AggregateAttestationAndProofSingle object +func (a *AggregateAttestationAndProofSingle) SizeSSZ() (size int) { + size = 344 return } -// HashTreeRoot ssz hashes the IndexedAttestationElectra object -func (i *IndexedAttestationElectra) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(i) +// HashTreeRoot ssz hashes the AggregateAttestationAndProofSingle object +func (a *AggregateAttestationAndProofSingle) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(a) } -// HashTreeRootWith ssz hashes the IndexedAttestationElectra object with a hasher -func (i *IndexedAttestationElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the AggregateAttestationAndProofSingle object with a hasher +func (a *AggregateAttestationAndProofSingle) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'AttestingIndices' - { - if size := len(i.AttestingIndices); size > 131072 { - err = ssz.ErrListTooBigFn("--.AttestingIndices", size, 131072) - return - } - subIndx := hh.Index() - for _, i := range i.AttestingIndices { - hh.AppendUint64(i) - } - hh.FillUpTo32() - - numItems := uint64(len(i.AttestingIndices)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(131072, numItems, 8)) - } + // Field (0) 'AggregatorIndex' + hh.PutUint64(uint64(a.AggregatorIndex)) - // Field (1) 'Data' - if err = i.Data.HashTreeRootWith(hh); err != nil { + // Field (1) 'Aggregate' + if err = a.Aggregate.HashTreeRootWith(hh); err != nil { return } - // Field (2) 'Signature' - if size := len(i.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + // Field (2) 'SelectionProof' + if size := len(a.SelectionProof); size != 96 { + err = ssz.ErrBytesLengthFn("--.SelectionProof", size, 96) return } - hh.PutBytes(i.Signature) + hh.PutBytes(a.SelectionProof) hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the SignedBeaconBlockElectra object -func (s *SignedBeaconBlockElectra) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the SingleAttestation object +func (s *SingleAttestation) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the SignedBeaconBlockElectra object to a target array -func (s *SignedBeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SingleAttestation object to a target array +func (s *SingleAttestation) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(100) - // Offset (0) 'Block' - dst = ssz.WriteOffset(dst, offset) - if s.Block == nil { - s.Block = new(BeaconBlockElectra) + // Field (0) 'CommitteeId' + dst = ssz.MarshalUint64(dst, uint64(s.CommitteeId)) + + // Field (1) 'AttesterIndex' + dst = ssz.MarshalUint64(dst, uint64(s.AttesterIndex)) + + // Field (2) 'Data' + if s.Data == nil { + s.Data = new(AttestationData) + } + if dst, err = s.Data.MarshalSSZTo(dst); err != nil { + return } - offset += s.Block.SizeSSZ() - // Field (1) 'Signature' + // Field (3) 'Signature' if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } dst = append(dst, s.Signature...) - // Field (0) 'Block' - if dst, err = s.Block.MarshalSSZTo(dst); err != nil { - return - } - return } -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockElectra object -func (s *SignedBeaconBlockElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the SingleAttestation object +func (s *SingleAttestation) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 100 { + if size != 240 { return ssz.ErrSize } - tail := buf - var o0 uint64 + // Field (0) 'CommitteeId' + s.CommitteeId = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex(ssz.UnmarshallUint64(buf[0:8])) - // Offset (0) 'Block' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } + // Field (1) 'AttesterIndex' + s.AttesterIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - if o0 != 100 { - return ssz.ErrInvalidVariableOffset + // Field (2) 'Data' + if s.Data == nil { + s.Data = new(AttestationData) + } + if err = s.Data.UnmarshalSSZ(buf[16:144]); err != nil { + return err } - // Field (1) 'Signature' + // Field (3) 'Signature' if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) + s.Signature = make([]byte, 0, len(buf[144:240])) } - s.Signature = append(s.Signature, buf[4:100]...) + s.Signature = append(s.Signature, buf[144:240]...) - // Field (0) 'Block' - { - buf = tail[o0:] - if s.Block == nil { - s.Block = new(BeaconBlockElectra) - } - if err = s.Block.UnmarshalSSZ(buf); err != nil { - return err - } - } return err } -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockElectra object -func (s *SignedBeaconBlockElectra) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Block' - if s.Block == nil { - s.Block = new(BeaconBlockElectra) - } - size += s.Block.SizeSSZ() - +// SizeSSZ returns the ssz encoded size in bytes for the SingleAttestation object +func (s *SingleAttestation) SizeSSZ() (size int) { + size = 240 return } -// HashTreeRoot ssz hashes the SignedBeaconBlockElectra object -func (s *SignedBeaconBlockElectra) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the SingleAttestation object +func (s *SingleAttestation) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(s) } -// HashTreeRootWith ssz hashes the SignedBeaconBlockElectra object with a hasher -func (s *SignedBeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the SingleAttestation object with a hasher +func (s *SingleAttestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Block' - if err = s.Block.HashTreeRootWith(hh); err != nil { + // Field (0) 'CommitteeId' + hh.PutUint64(uint64(s.CommitteeId)) + + // Field (1) 'AttesterIndex' + hh.PutUint64(uint64(s.AttesterIndex)) + + // Field (2) 'Data' + if err = s.Data.HashTreeRootWith(hh); err != nil { return } - // Field (1) 'Signature' + // Field (3) 'Signature' if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return @@ -762,876 +659,768 @@ func (s *SignedBeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) return } -// MarshalSSZ ssz marshals the BeaconBlockElectra object -func (b *BeaconBlockElectra) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the BuilderBidElectra object +func (b *BuilderBidElectra) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) } -// MarshalSSZTo ssz marshals the BeaconBlockElectra object to a target array -func (b *BeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the BuilderBidElectra object to a target array +func (b *BuilderBidElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(84) + offset := int(92) - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) + // Offset (0) 'Header' + dst = ssz.WriteOffset(dst, offset) + if b.Header == nil { + b.Header = new(v1.ExecutionPayloadHeaderDeneb) + } + offset += b.Header.SizeSSZ() - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) + // Offset (1) 'BlobKzgCommitments' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.BlobKzgCommitments) * 48 - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) + // Offset (2) 'ExecutionRequests' + dst = ssz.WriteOffset(dst, offset) + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) + } + offset += b.ExecutionRequests.SizeSSZ() + + // Field (3) 'Value' + if size := len(b.Value); size != 32 { + err = ssz.ErrBytesLengthFn("--.Value", size, 32) return } - dst = append(dst, b.ParentRoot...) + dst = append(dst, b.Value...) - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + // Field (4) 'Pubkey' + if size := len(b.Pubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48) return } - dst = append(dst, b.StateRoot...) + dst = append(dst, b.Pubkey...) - // Offset (4) 'Body' - dst = ssz.WriteOffset(dst, offset) - if b.Body == nil { - b.Body = new(BeaconBlockBodyElectra) + // Field (0) 'Header' + if dst, err = b.Header.MarshalSSZTo(dst); err != nil { + return } - offset += b.Body.SizeSSZ() - // Field (4) 'Body' - if dst, err = b.Body.MarshalSSZTo(dst); err != nil { + // Field (1) 'BlobKzgCommitments' + if size := len(b.BlobKzgCommitments); size > 4096 { + err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) + return + } + for ii := 0; ii < len(b.BlobKzgCommitments); ii++ { + if size := len(b.BlobKzgCommitments[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.BlobKzgCommitments[ii]", size, 48) + return + } + dst = append(dst, b.BlobKzgCommitments[ii]...) + } + + // Field (2) 'ExecutionRequests' + if dst, err = b.ExecutionRequests.MarshalSSZTo(dst); err != nil { return } return } -// UnmarshalSSZ ssz unmarshals the BeaconBlockElectra object -func (b *BeaconBlockElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the BuilderBidElectra object +func (b *BuilderBidElectra) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 84 { + if size < 92 { return ssz.ErrSize } tail := buf - var o4 uint64 + var o0, o1, o2 uint64 - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) + // Offset (0) 'Header' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) + if o0 != 92 { + return ssz.ErrInvalidVariableOffset } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) + // Offset (1) 'BlobKzgCommitments' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - // Offset (4) 'Body' - if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { + // Offset (2) 'ExecutionRequests' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { return ssz.ErrOffset } - if o4 != 84 { - return ssz.ErrInvalidVariableOffset + // Field (3) 'Value' + if cap(b.Value) == 0 { + b.Value = make([]byte, 0, len(buf[12:44])) } + b.Value = append(b.Value, buf[12:44]...) - // Field (4) 'Body' + // Field (4) 'Pubkey' + if cap(b.Pubkey) == 0 { + b.Pubkey = make([]byte, 0, len(buf[44:92])) + } + b.Pubkey = append(b.Pubkey, buf[44:92]...) + + // Field (0) 'Header' { - buf = tail[o4:] - if b.Body == nil { - b.Body = new(BeaconBlockBodyElectra) + buf = tail[o0:o1] + if b.Header == nil { + b.Header = new(v1.ExecutionPayloadHeaderDeneb) } - if err = b.Body.UnmarshalSSZ(buf); err != nil { + if err = b.Header.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (1) 'BlobKzgCommitments' + { + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 48, 4096) + if err != nil { + return err + } + b.BlobKzgCommitments = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(b.BlobKzgCommitments[ii]) == 0 { + b.BlobKzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + } + b.BlobKzgCommitments[ii] = append(b.BlobKzgCommitments[ii], buf[ii*48:(ii+1)*48]...) + } + } + + // Field (2) 'ExecutionRequests' + { + buf = tail[o2:] + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) + } + if err = b.ExecutionRequests.UnmarshalSSZ(buf); err != nil { return err } } return err } -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockElectra object -func (b *BeaconBlockElectra) SizeSSZ() (size int) { - size = 84 +// SizeSSZ returns the ssz encoded size in bytes for the BuilderBidElectra object +func (b *BuilderBidElectra) SizeSSZ() (size int) { + size = 92 - // Field (4) 'Body' - if b.Body == nil { - b.Body = new(BeaconBlockBodyElectra) + // Field (0) 'Header' + if b.Header == nil { + b.Header = new(v1.ExecutionPayloadHeaderDeneb) } - size += b.Body.SizeSSZ() + size += b.Header.SizeSSZ() + + // Field (1) 'BlobKzgCommitments' + size += len(b.BlobKzgCommitments) * 48 + + // Field (2) 'ExecutionRequests' + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) + } + size += b.ExecutionRequests.SizeSSZ() return } -// HashTreeRoot ssz hashes the BeaconBlockElectra object -func (b *BeaconBlockElectra) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the BuilderBidElectra object +func (b *BuilderBidElectra) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(b) } -// HashTreeRootWith ssz hashes the BeaconBlockElectra object with a hasher -func (b *BeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the BuilderBidElectra object with a hasher +func (b *BuilderBidElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) + // Field (0) 'Header' + if err = b.Header.HashTreeRootWith(hh); err != nil { + return + } - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) + // Field (1) 'BlobKzgCommitments' + { + if size := len(b.BlobKzgCommitments); size > 4096 { + err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range b.BlobKzgCommitments { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) + numItems := uint64(len(b.BlobKzgCommitments)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + // Field (2) 'ExecutionRequests' + if err = b.ExecutionRequests.HashTreeRootWith(hh); err != nil { return } - hh.PutBytes(b.ParentRoot) - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + // Field (3) 'Value' + if size := len(b.Value); size != 32 { + err = ssz.ErrBytesLengthFn("--.Value", size, 32) return } - hh.PutBytes(b.StateRoot) + hh.PutBytes(b.Value) - // Field (4) 'Body' - if err = b.Body.HashTreeRootWith(hh); err != nil { + // Field (4) 'Pubkey' + if size := len(b.Pubkey); size != 48 { + err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48) return } + hh.PutBytes(b.Pubkey) hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the BeaconBlockBodyElectra object -func (b *BeaconBlockBodyElectra) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the SignedBeaconBlockContentsElectra object +func (s *SignedBeaconBlockContentsElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the BeaconBlockBodyElectra object to a target array -func (b *BeaconBlockBodyElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SignedBeaconBlockContentsElectra object to a target array +func (s *SignedBeaconBlockContentsElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(392) + offset := int(12) - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if s.Block == nil { + s.Block = new(SignedBeaconBlockElectra) } - dst = append(dst, b.RandaoReveal...) + offset += s.Block.SizeSSZ() - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { + // Offset (1) 'KzgProofs' + dst = ssz.WriteOffset(dst, offset) + offset += len(s.KzgProofs) * 48 + + // Offset (2) 'Blobs' + dst = ssz.WriteOffset(dst, offset) + offset += len(s.Blobs) * 131072 + + // Field (0) 'Block' + if dst, err = s.Block.MarshalSSZTo(dst); err != nil { return } - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) + // Field (1) 'KzgProofs' + if size := len(s.KzgProofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) return } - dst = append(dst, b.Graffiti...) - - // Offset (3) 'ProposerSlashings' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.ProposerSlashings) * 416 + for ii := 0; ii < len(s.KzgProofs); ii++ { + if size := len(s.KzgProofs[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgProofs[ii]", size, 48) + return + } + dst = append(dst, s.KzgProofs[ii]...) + } - // Offset (4) 'AttesterSlashings' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - offset += 4 - offset += b.AttesterSlashings[ii].SizeSSZ() + // Field (2) 'Blobs' + if size := len(s.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) + return + } + for ii := 0; ii < len(s.Blobs); ii++ { + if size := len(s.Blobs[ii]); size != 131072 { + err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072) + return + } + dst = append(dst, s.Blobs[ii]...) } - // Offset (5) 'Attestations' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(b.Attestations); ii++ { - offset += 4 - offset += b.Attestations[ii].SizeSSZ() + return +} + +// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockContentsElectra object +func (s *SignedBeaconBlockContentsElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 12 { + return ssz.ErrSize } - // Offset (6) 'Deposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Deposits) * 1240 + tail := buf + var o0, o1, o2 uint64 - // Offset (7) 'VoluntaryExits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.VoluntaryExits) * 112 + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(SyncAggregate) + if o0 != 12 { + return ssz.ErrInvalidVariableOffset } - if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { - return + + // Offset (1) 'KzgProofs' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset } - // Offset (9) 'ExecutionPayload' - dst = ssz.WriteOffset(dst, offset) - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v1.ExecutionPayloadElectra) + // Offset (2) 'Blobs' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { + return ssz.ErrOffset } - offset += b.ExecutionPayload.SizeSSZ() - - // Offset (10) 'BlsToExecutionChanges' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.BlsToExecutionChanges) * 172 - - // Offset (11) 'BlobKzgCommitments' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.BlobKzgCommitments) * 48 - // Field (3) 'ProposerSlashings' - if size := len(b.ProposerSlashings); size > 16 { - err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) - return - } - for ii := 0; ii < len(b.ProposerSlashings); ii++ { - if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { - return + // Field (0) 'Block' + { + buf = tail[o0:o1] + if s.Block == nil { + s.Block = new(SignedBeaconBlockElectra) + } + if err = s.Block.UnmarshalSSZ(buf); err != nil { + return err } } - // Field (4) 'AttesterSlashings' - if size := len(b.AttesterSlashings); size > 1 { - err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 1) - return - } + // Field (1) 'KzgProofs' { - offset = 4 * len(b.AttesterSlashings) - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.AttesterSlashings[ii].SizeSSZ() + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 48, 4096) + if err != nil { + return err } - } - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { - return + s.KzgProofs = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(s.KzgProofs[ii]) == 0 { + s.KzgProofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + } + s.KzgProofs[ii] = append(s.KzgProofs[ii], buf[ii*48:(ii+1)*48]...) } } - // Field (5) 'Attestations' - if size := len(b.Attestations); size > 8 { - err = ssz.ErrListTooBigFn("--.Attestations", size, 8) - return - } + // Field (2) 'Blobs' { - offset = 4 * len(b.Attestations) - for ii := 0; ii < len(b.Attestations); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += b.Attestations[ii].SizeSSZ() + buf = tail[o2:] + num, err := ssz.DivideInt2(len(buf), 131072, 4096) + if err != nil { + return err } - } - for ii := 0; ii < len(b.Attestations); ii++ { - if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { - return + s.Blobs = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(s.Blobs[ii]) == 0 { + s.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072])) + } + s.Blobs[ii] = append(s.Blobs[ii], buf[ii*131072:(ii+1)*131072]...) } } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockContentsElectra object +func (s *SignedBeaconBlockContentsElectra) SizeSSZ() (size int) { + size = 12 + + // Field (0) 'Block' + if s.Block == nil { + s.Block = new(SignedBeaconBlockElectra) + } + size += s.Block.SizeSSZ() - // Field (6) 'Deposits' - if size := len(b.Deposits); size > 16 { - err = ssz.ErrListTooBigFn("--.Deposits", size, 16) + // Field (1) 'KzgProofs' + size += len(s.KzgProofs) * 48 + + // Field (2) 'Blobs' + size += len(s.Blobs) * 131072 + + return +} + +// HashTreeRoot ssz hashes the SignedBeaconBlockContentsElectra object +func (s *SignedBeaconBlockContentsElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedBeaconBlockContentsElectra object with a hasher +func (s *SignedBeaconBlockContentsElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Block' + if err = s.Block.HashTreeRootWith(hh); err != nil { return } - for ii := 0; ii < len(b.Deposits); ii++ { - if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { + + // Field (1) 'KzgProofs' + { + if size := len(s.KzgProofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) return } - } + subIndx := hh.Index() + for _, i := range s.KzgProofs { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } - // Field (7) 'VoluntaryExits' - if size := len(b.VoluntaryExits); size > 16 { - err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) - return + numItems := uint64(len(s.KzgProofs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) } - for ii := 0; ii < len(b.VoluntaryExits); ii++ { - if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { + + // Field (2) 'Blobs' + { + if size := len(s.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) return } + subIndx := hh.Index() + for _, i := range s.Blobs { + if len(i) != 131072 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(s.Blobs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) } - // Field (9) 'ExecutionPayload' - if dst, err = b.ExecutionPayload.MarshalSSZTo(dst); err != nil { - return + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the SignedBeaconBlockElectra object +func (s *SignedBeaconBlockElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedBeaconBlockElectra object to a target array +func (s *SignedBeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(100) + + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if s.Block == nil { + s.Block = new(BeaconBlockElectra) } + offset += s.Block.SizeSSZ() - // Field (10) 'BlsToExecutionChanges' - if size := len(b.BlsToExecutionChanges); size > 16 { - err = ssz.ErrListTooBigFn("--.BlsToExecutionChanges", size, 16) + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - for ii := 0; ii < len(b.BlsToExecutionChanges); ii++ { - if dst, err = b.BlsToExecutionChanges[ii].MarshalSSZTo(dst); err != nil { - return - } - } + dst = append(dst, s.Signature...) - // Field (11) 'BlobKzgCommitments' - if size := len(b.BlobKzgCommitments); size > 4096 { - err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) + // Field (0) 'Block' + if dst, err = s.Block.MarshalSSZTo(dst); err != nil { return } - for ii := 0; ii < len(b.BlobKzgCommitments); ii++ { - if size := len(b.BlobKzgCommitments[ii]); size != 48 { - err = ssz.ErrBytesLengthFn("--.BlobKzgCommitments[ii]", size, 48) - return - } - dst = append(dst, b.BlobKzgCommitments[ii]...) - } return } -// UnmarshalSSZ ssz unmarshals the BeaconBlockBodyElectra object -func (b *BeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockElectra object +func (s *SignedBeaconBlockElectra) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 392 { + if size < 100 { return ssz.ErrSize } tail := buf - var o3, o4, o5, o6, o7, o9, o10, o11 uint64 + var o0 uint64 - // Field (0) 'RandaoReveal' - if cap(b.RandaoReveal) == 0 { - b.RandaoReveal = make([]byte, 0, len(buf[0:96])) + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset } - b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) - // Field (1) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(Eth1Data) - } - if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { - return err + if o0 != 100 { + return ssz.ErrInvalidVariableOffset } - // Field (2) 'Graffiti' - if cap(b.Graffiti) == 0 { - b.Graffiti = make([]byte, 0, len(buf[168:200])) + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) } - b.Graffiti = append(b.Graffiti, buf[168:200]...) + s.Signature = append(s.Signature, buf[4:100]...) - // Offset (3) 'ProposerSlashings' - if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { - return ssz.ErrOffset + // Field (0) 'Block' + { + buf = tail[o0:] + if s.Block == nil { + s.Block = new(BeaconBlockElectra) + } + if err = s.Block.UnmarshalSSZ(buf); err != nil { + return err + } } + return err +} - if o3 != 392 { - return ssz.ErrInvalidVariableOffset - } +// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockElectra object +func (s *SignedBeaconBlockElectra) SizeSSZ() (size int) { + size = 100 - // Offset (4) 'AttesterSlashings' - if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { - return ssz.ErrOffset + // Field (0) 'Block' + if s.Block == nil { + s.Block = new(BeaconBlockElectra) } + size += s.Block.SizeSSZ() - // Offset (5) 'Attestations' - if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { - return ssz.ErrOffset - } + return +} - // Offset (6) 'Deposits' - if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { - return ssz.ErrOffset - } +// HashTreeRoot ssz hashes the SignedBeaconBlockElectra object +func (s *SignedBeaconBlockElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} - // Offset (7) 'VoluntaryExits' - if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { - return ssz.ErrOffset - } +// HashTreeRootWith ssz hashes the SignedBeaconBlockElectra object with a hasher +func (s *SignedBeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() - // Field (8) 'SyncAggregate' - if b.SyncAggregate == nil { - b.SyncAggregate = new(SyncAggregate) - } - if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { - return err + // Field (0) 'Block' + if err = s.Block.HashTreeRootWith(hh); err != nil { + return } - // Offset (9) 'ExecutionPayload' - if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { - return ssz.ErrOffset + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return } + hh.PutBytes(s.Signature) - // Offset (10) 'BlsToExecutionChanges' - if o10 = ssz.ReadOffset(buf[384:388]); o10 > size || o9 > o10 { - return ssz.ErrOffset + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the BeaconBlockContentsElectra object +func (b *BeaconBlockContentsElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BeaconBlockContentsElectra object to a target array +func (b *BeaconBlockContentsElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(12) + + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if b.Block == nil { + b.Block = new(BeaconBlockElectra) } + offset += b.Block.SizeSSZ() - // Offset (11) 'BlobKzgCommitments' - if o11 = ssz.ReadOffset(buf[388:392]); o11 > size || o10 > o11 { - return ssz.ErrOffset + // Offset (1) 'KzgProofs' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.KzgProofs) * 48 + + // Offset (2) 'Blobs' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Blobs) * 131072 + + // Field (0) 'Block' + if dst, err = b.Block.MarshalSSZTo(dst); err != nil { + return } - // Field (3) 'ProposerSlashings' - { - buf = tail[o3:o4] - num, err := ssz.DivideInt2(len(buf), 416, 16) - if err != nil { - return err - } - b.ProposerSlashings = make([]*ProposerSlashing, num) - for ii := 0; ii < num; ii++ { - if b.ProposerSlashings[ii] == nil { - b.ProposerSlashings[ii] = new(ProposerSlashing) - } - if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { - return err - } + // Field (1) 'KzgProofs' + if size := len(b.KzgProofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) + return + } + for ii := 0; ii < len(b.KzgProofs); ii++ { + if size := len(b.KzgProofs[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgProofs[ii]", size, 48) + return } + dst = append(dst, b.KzgProofs[ii]...) } - // Field (4) 'AttesterSlashings' - { - buf = tail[o4:o5] - num, err := ssz.DecodeDynamicLength(buf, 1) - if err != nil { - return err - } - b.AttesterSlashings = make([]*AttesterSlashingElectra, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.AttesterSlashings[indx] == nil { - b.AttesterSlashings[indx] = new(AttesterSlashingElectra) - } - if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err + // Field (2) 'Blobs' + if size := len(b.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) + return + } + for ii := 0; ii < len(b.Blobs); ii++ { + if size := len(b.Blobs[ii]); size != 131072 { + err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072) + return } + dst = append(dst, b.Blobs[ii]...) } - // Field (5) 'Attestations' - { - buf = tail[o5:o6] - num, err := ssz.DecodeDynamicLength(buf, 8) - if err != nil { - return err - } - b.Attestations = make([]*AttestationElectra, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if b.Attestations[indx] == nil { - b.Attestations[indx] = new(AttestationElectra) - } - if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { - return err - } - return nil - }) - if err != nil { - return err - } + return +} + +// UnmarshalSSZ ssz unmarshals the BeaconBlockContentsElectra object +func (b *BeaconBlockContentsElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 12 { + return ssz.ErrSize } - // Field (6) 'Deposits' - { - buf = tail[o6:o7] - num, err := ssz.DivideInt2(len(buf), 1240, 16) - if err != nil { - return err - } - b.Deposits = make([]*Deposit, num) - for ii := 0; ii < num; ii++ { - if b.Deposits[ii] == nil { - b.Deposits[ii] = new(Deposit) - } - if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { - return err - } - } + tail := buf + var o0, o1, o2 uint64 + + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset } - // Field (7) 'VoluntaryExits' - { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 112, 16) - if err != nil { - return err - } - b.VoluntaryExits = make([]*SignedVoluntaryExit, num) - for ii := 0; ii < num; ii++ { - if b.VoluntaryExits[ii] == nil { - b.VoluntaryExits[ii] = new(SignedVoluntaryExit) - } - if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { - return err - } - } + if o0 != 12 { + return ssz.ErrInvalidVariableOffset } - // Field (9) 'ExecutionPayload' + // Offset (1) 'KzgProofs' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Offset (2) 'Blobs' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { + return ssz.ErrOffset + } + + // Field (0) 'Block' { - buf = tail[o9:o10] - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v1.ExecutionPayloadElectra) + buf = tail[o0:o1] + if b.Block == nil { + b.Block = new(BeaconBlockElectra) } - if err = b.ExecutionPayload.UnmarshalSSZ(buf); err != nil { + if err = b.Block.UnmarshalSSZ(buf); err != nil { return err } } - // Field (10) 'BlsToExecutionChanges' + // Field (1) 'KzgProofs' { - buf = tail[o10:o11] - num, err := ssz.DivideInt2(len(buf), 172, 16) + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 48, 4096) if err != nil { return err } - b.BlsToExecutionChanges = make([]*SignedBLSToExecutionChange, num) + b.KzgProofs = make([][]byte, num) for ii := 0; ii < num; ii++ { - if b.BlsToExecutionChanges[ii] == nil { - b.BlsToExecutionChanges[ii] = new(SignedBLSToExecutionChange) - } - if err = b.BlsToExecutionChanges[ii].UnmarshalSSZ(buf[ii*172 : (ii+1)*172]); err != nil { - return err + if cap(b.KzgProofs[ii]) == 0 { + b.KzgProofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) } + b.KzgProofs[ii] = append(b.KzgProofs[ii], buf[ii*48:(ii+1)*48]...) } } - // Field (11) 'BlobKzgCommitments' + // Field (2) 'Blobs' { - buf = tail[o11:] - num, err := ssz.DivideInt2(len(buf), 48, 4096) + buf = tail[o2:] + num, err := ssz.DivideInt2(len(buf), 131072, 4096) if err != nil { return err } - b.BlobKzgCommitments = make([][]byte, num) + b.Blobs = make([][]byte, num) for ii := 0; ii < num; ii++ { - if cap(b.BlobKzgCommitments[ii]) == 0 { - b.BlobKzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + if cap(b.Blobs[ii]) == 0 { + b.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072])) } - b.BlobKzgCommitments[ii] = append(b.BlobKzgCommitments[ii], buf[ii*48:(ii+1)*48]...) + b.Blobs[ii] = append(b.Blobs[ii], buf[ii*131072:(ii+1)*131072]...) } } return err } -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyElectra object -func (b *BeaconBlockBodyElectra) SizeSSZ() (size int) { - size = 392 - - // Field (3) 'ProposerSlashings' - size += len(b.ProposerSlashings) * 416 - - // Field (4) 'AttesterSlashings' - for ii := 0; ii < len(b.AttesterSlashings); ii++ { - size += 4 - size += b.AttesterSlashings[ii].SizeSSZ() - } - - // Field (5) 'Attestations' - for ii := 0; ii < len(b.Attestations); ii++ { - size += 4 - size += b.Attestations[ii].SizeSSZ() - } - - // Field (6) 'Deposits' - size += len(b.Deposits) * 1240 - - // Field (7) 'VoluntaryExits' - size += len(b.VoluntaryExits) * 112 +// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockContentsElectra object +func (b *BeaconBlockContentsElectra) SizeSSZ() (size int) { + size = 12 - // Field (9) 'ExecutionPayload' - if b.ExecutionPayload == nil { - b.ExecutionPayload = new(v1.ExecutionPayloadElectra) + // Field (0) 'Block' + if b.Block == nil { + b.Block = new(BeaconBlockElectra) } - size += b.ExecutionPayload.SizeSSZ() + size += b.Block.SizeSSZ() - // Field (10) 'BlsToExecutionChanges' - size += len(b.BlsToExecutionChanges) * 172 + // Field (1) 'KzgProofs' + size += len(b.KzgProofs) * 48 - // Field (11) 'BlobKzgCommitments' - size += len(b.BlobKzgCommitments) * 48 + // Field (2) 'Blobs' + size += len(b.Blobs) * 131072 return } -// HashTreeRoot ssz hashes the BeaconBlockBodyElectra object -func (b *BeaconBlockBodyElectra) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the BeaconBlockContentsElectra object +func (b *BeaconBlockContentsElectra) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(b) } -// HashTreeRootWith ssz hashes the BeaconBlockBodyElectra object with a hasher -func (b *BeaconBlockBodyElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the BeaconBlockContentsElectra object with a hasher +func (b *BeaconBlockContentsElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'RandaoReveal' - if size := len(b.RandaoReveal); size != 96 { - err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) - return - } - hh.PutBytes(b.RandaoReveal) - - // Field (1) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } - - // Field (2) 'Graffiti' - if size := len(b.Graffiti); size != 32 { - err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) + // Field (0) 'Block' + if err = b.Block.HashTreeRootWith(hh); err != nil { return } - hh.PutBytes(b.Graffiti) - // Field (3) 'ProposerSlashings' + // Field (1) 'KzgProofs' { - subIndx := hh.Index() - num := uint64(len(b.ProposerSlashings)) - if num > 16 { - err = ssz.ErrIncorrectListSize + if size := len(b.KzgProofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) return } - for _, elem := range b.ProposerSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (4) 'AttesterSlashings' - { subIndx := hh.Index() - num := uint64(len(b.AttesterSlashings)) - if num > 1 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.AttesterSlashings { - if err = elem.HashTreeRootWith(hh); err != nil { + for _, i := range b.KzgProofs { + if len(i) != 48 { + err = ssz.ErrBytesLength return } + hh.PutBytes(i) } - hh.MerkleizeWithMixin(subIndx, num, 1) + + numItems := uint64(len(b.KzgProofs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) } - // Field (5) 'Attestations' + // Field (2) 'Blobs' { - subIndx := hh.Index() - num := uint64(len(b.Attestations)) - if num > 8 { - err = ssz.ErrIncorrectListSize + if size := len(b.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) return } - for _, elem := range b.Attestations { - if err = elem.HashTreeRootWith(hh); err != nil { + subIndx := hh.Index() + for _, i := range b.Blobs { + if len(i) != 131072 { + err = ssz.ErrBytesLength return } + hh.PutBytes(i) } - hh.MerkleizeWithMixin(subIndx, num, 8) + + numItems := uint64(len(b.Blobs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) } - // Field (6) 'Deposits' - { - subIndx := hh.Index() - num := uint64(len(b.Deposits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Deposits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (7) 'VoluntaryExits' - { - subIndx := hh.Index() - num := uint64(len(b.VoluntaryExits)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.VoluntaryExits { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (8) 'SyncAggregate' - if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { - return - } - - // Field (9) 'ExecutionPayload' - if err = b.ExecutionPayload.HashTreeRootWith(hh); err != nil { - return - } - - // Field (10) 'BlsToExecutionChanges' - { - subIndx := hh.Index() - num := uint64(len(b.BlsToExecutionChanges)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.BlsToExecutionChanges { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (11) 'BlobKzgCommitments' - { - if size := len(b.BlobKzgCommitments); size > 4096 { - err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) - return - } - subIndx := hh.Index() - for _, i := range b.BlobKzgCommitments { - if len(i) != 48 { - err = ssz.ErrBytesLength - return - } - hh.PutBytes(i) - } - - numItems := uint64(len(b.BlobKzgCommitments)) - hh.MerkleizeWithMixin(subIndx, numItems, 4096) - } - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedBlindedBeaconBlockElectra object -func (s *SignedBlindedBeaconBlockElectra) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBlindedBeaconBlockElectra object to a target array -func (s *SignedBlindedBeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Message' - dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(BlindedBeaconBlockElectra) - } - offset += s.Message.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBlindedBeaconBlockElectra object -func (s *SignedBlindedBeaconBlockElectra) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Message' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Message' - { - buf = tail[o0:] - if s.Message == nil { - s.Message = new(BlindedBeaconBlockElectra) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBlindedBeaconBlockElectra object -func (s *SignedBlindedBeaconBlockElectra) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(BlindedBeaconBlockElectra) - } - size += s.Message.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBlindedBeaconBlockElectra object -func (s *SignedBlindedBeaconBlockElectra) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBlindedBeaconBlockElectra object with a hasher -func (s *SignedBlindedBeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the BlindedBeaconBlockElectra object -func (b *BlindedBeaconBlockElectra) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the BeaconBlockElectra object +func (b *BeaconBlockElectra) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) } -// MarshalSSZTo ssz marshals the BlindedBeaconBlockElectra object to a target array -func (b *BlindedBeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the BeaconBlockElectra object to a target array +func (b *BeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf offset := int(84) @@ -1658,7 +1447,7 @@ func (b *BlindedBeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err er // Offset (4) 'Body' dst = ssz.WriteOffset(dst, offset) if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyElectra) + b.Body = new(BeaconBlockBodyElectra) } offset += b.Body.SizeSSZ() @@ -1670,8 +1459,8 @@ func (b *BlindedBeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err er return } -// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockElectra object -func (b *BlindedBeaconBlockElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the BeaconBlockElectra object +func (b *BeaconBlockElectra) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) if size < 84 { @@ -1712,7 +1501,7 @@ func (b *BlindedBeaconBlockElectra) UnmarshalSSZ(buf []byte) error { { buf = tail[o4:] if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyElectra) + b.Body = new(BeaconBlockBodyElectra) } if err = b.Body.UnmarshalSSZ(buf); err != nil { return err @@ -1721,26 +1510,26 @@ func (b *BlindedBeaconBlockElectra) UnmarshalSSZ(buf []byte) error { return err } -// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockElectra object -func (b *BlindedBeaconBlockElectra) SizeSSZ() (size int) { +// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockElectra object +func (b *BeaconBlockElectra) SizeSSZ() (size int) { size = 84 // Field (4) 'Body' if b.Body == nil { - b.Body = new(BlindedBeaconBlockBodyElectra) + b.Body = new(BeaconBlockBodyElectra) } size += b.Body.SizeSSZ() return } -// HashTreeRoot ssz hashes the BlindedBeaconBlockElectra object -func (b *BlindedBeaconBlockElectra) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the BeaconBlockElectra object +func (b *BeaconBlockElectra) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(b) } -// HashTreeRootWith ssz hashes the BlindedBeaconBlockElectra object with a hasher -func (b *BlindedBeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the BeaconBlockElectra object with a hasher +func (b *BeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field (0) 'Slot' @@ -1772,15 +1561,15 @@ func (b *BlindedBeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) return } -// MarshalSSZ ssz marshals the BlindedBeaconBlockBodyElectra object -func (b *BlindedBeaconBlockBodyElectra) MarshalSSZ() ([]byte, error) { +// MarshalSSZ ssz marshals the BeaconBlockBodyElectra object +func (b *BeaconBlockBodyElectra) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) } -// MarshalSSZTo ssz marshals the BlindedBeaconBlockBodyElectra object to a target array -func (b *BlindedBeaconBlockBodyElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the BeaconBlockBodyElectra object to a target array +func (b *BeaconBlockBodyElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(392) + offset := int(396) // Field (0) 'RandaoReveal' if size := len(b.RandaoReveal); size != 96 { @@ -1838,12 +1627,12 @@ func (b *BlindedBeaconBlockBodyElectra) MarshalSSZTo(buf []byte) (dst []byte, er return } - // Offset (9) 'ExecutionPayloadHeader' + // Offset (9) 'ExecutionPayload' dst = ssz.WriteOffset(dst, offset) - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderElectra) + if b.ExecutionPayload == nil { + b.ExecutionPayload = new(v1.ExecutionPayloadDeneb) } - offset += b.ExecutionPayloadHeader.SizeSSZ() + offset += b.ExecutionPayload.SizeSSZ() // Offset (10) 'BlsToExecutionChanges' dst = ssz.WriteOffset(dst, offset) @@ -1853,6 +1642,13 @@ func (b *BlindedBeaconBlockBodyElectra) MarshalSSZTo(buf []byte) (dst []byte, er dst = ssz.WriteOffset(dst, offset) offset += len(b.BlobKzgCommitments) * 48 + // Offset (12) 'ExecutionRequests' + dst = ssz.WriteOffset(dst, offset) + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) + } + offset += b.ExecutionRequests.SizeSSZ() + // Field (3) 'ProposerSlashings' if size := len(b.ProposerSlashings); size > 16 { err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) @@ -1922,8 +1718,8 @@ func (b *BlindedBeaconBlockBodyElectra) MarshalSSZTo(buf []byte) (dst []byte, er } } - // Field (9) 'ExecutionPayloadHeader' - if dst, err = b.ExecutionPayloadHeader.MarshalSSZTo(dst); err != nil { + // Field (9) 'ExecutionPayload' + if dst, err = b.ExecutionPayload.MarshalSSZTo(dst); err != nil { return } @@ -1951,19 +1747,24 @@ func (b *BlindedBeaconBlockBodyElectra) MarshalSSZTo(buf []byte) (dst []byte, er dst = append(dst, b.BlobKzgCommitments[ii]...) } + // Field (12) 'ExecutionRequests' + if dst, err = b.ExecutionRequests.MarshalSSZTo(dst); err != nil { + return + } + return } -// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockBodyElectra object -func (b *BlindedBeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the BeaconBlockBodyElectra object +func (b *BeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 392 { + if size < 396 { return ssz.ErrSize } tail := buf - var o3, o4, o5, o6, o7, o9, o10, o11 uint64 + var o3, o4, o5, o6, o7, o9, o10, o11, o12 uint64 // Field (0) 'RandaoReveal' if cap(b.RandaoReveal) == 0 { @@ -1990,7 +1791,7 @@ func (b *BlindedBeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - if o3 != 392 { + if o3 != 396 { return ssz.ErrInvalidVariableOffset } @@ -2022,7 +1823,7 @@ func (b *BlindedBeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { return err } - // Offset (9) 'ExecutionPayloadHeader' + // Offset (9) 'ExecutionPayload' if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { return ssz.ErrOffset } @@ -2037,6 +1838,11 @@ func (b *BlindedBeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } + // Offset (12) 'ExecutionRequests' + if o12 = ssz.ReadOffset(buf[392:396]); o12 > size || o11 > o12 { + return ssz.ErrOffset + } + // Field (3) 'ProposerSlashings' { buf = tail[o3:o4] @@ -2135,13 +1941,13 @@ func (b *BlindedBeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { } } - // Field (9) 'ExecutionPayloadHeader' + // Field (9) 'ExecutionPayload' { buf = tail[o9:o10] - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderElectra) + if b.ExecutionPayload == nil { + b.ExecutionPayload = new(v1.ExecutionPayloadDeneb) } - if err = b.ExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { + if err = b.ExecutionPayload.UnmarshalSSZ(buf); err != nil { return err } } @@ -2166,7 +1972,7 @@ func (b *BlindedBeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { // Field (11) 'BlobKzgCommitments' { - buf = tail[o11:] + buf = tail[o11:o12] num, err := ssz.DivideInt2(len(buf), 48, 4096) if err != nil { return err @@ -2179,13 +1985,24 @@ func (b *BlindedBeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { b.BlobKzgCommitments[ii] = append(b.BlobKzgCommitments[ii], buf[ii*48:(ii+1)*48]...) } } + + // Field (12) 'ExecutionRequests' + { + buf = tail[o12:] + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) + } + if err = b.ExecutionRequests.UnmarshalSSZ(buf); err != nil { + return err + } + } return err } -// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockBodyElectra object -func (b *BlindedBeaconBlockBodyElectra) SizeSSZ() (size int) { - size = 392 - +// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyElectra object +func (b *BeaconBlockBodyElectra) SizeSSZ() (size int) { + size = 396 + // Field (3) 'ProposerSlashings' size += len(b.ProposerSlashings) * 416 @@ -2207,11 +2024,11 @@ func (b *BlindedBeaconBlockBodyElectra) SizeSSZ() (size int) { // Field (7) 'VoluntaryExits' size += len(b.VoluntaryExits) * 112 - // Field (9) 'ExecutionPayloadHeader' - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderElectra) + // Field (9) 'ExecutionPayload' + if b.ExecutionPayload == nil { + b.ExecutionPayload = new(v1.ExecutionPayloadDeneb) } - size += b.ExecutionPayloadHeader.SizeSSZ() + size += b.ExecutionPayload.SizeSSZ() // Field (10) 'BlsToExecutionChanges' size += len(b.BlsToExecutionChanges) * 172 @@ -2219,16 +2036,22 @@ func (b *BlindedBeaconBlockBodyElectra) SizeSSZ() (size int) { // Field (11) 'BlobKzgCommitments' size += len(b.BlobKzgCommitments) * 48 + // Field (12) 'ExecutionRequests' + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) + } + size += b.ExecutionRequests.SizeSSZ() + return } -// HashTreeRoot ssz hashes the BlindedBeaconBlockBodyElectra object -func (b *BlindedBeaconBlockBodyElectra) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the BeaconBlockBodyElectra object +func (b *BeaconBlockBodyElectra) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(b) } -// HashTreeRootWith ssz hashes the BlindedBeaconBlockBodyElectra object with a hasher -func (b *BlindedBeaconBlockBodyElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the BeaconBlockBodyElectra object with a hasher +func (b *BeaconBlockBodyElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() // Field (0) 'RandaoReveal' @@ -2335,8 +2158,8 @@ func (b *BlindedBeaconBlockBodyElectra) HashTreeRootWith(hh *ssz.Hasher) (err er return } - // Field (9) 'ExecutionPayloadHeader' - if err = b.ExecutionPayloadHeader.HashTreeRootWith(hh); err != nil { + // Field (9) 'ExecutionPayload' + if err = b.ExecutionPayload.HashTreeRootWith(hh); err != nil { return } @@ -2375,948 +2198,2700 @@ func (b *BlindedBeaconBlockBodyElectra) HashTreeRootWith(hh *ssz.Hasher) (err er hh.MerkleizeWithMixin(subIndx, numItems, 4096) } + // Field (12) 'ExecutionRequests' + if err = b.ExecutionRequests.HashTreeRootWith(hh); err != nil { + return + } + hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the BeaconStateElectra object -func (b *BeaconStateElectra) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the SignedBlindedBeaconBlockElectra object +func (s *SignedBlindedBeaconBlockElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the BeaconStateElectra object to a target array -func (b *BeaconStateElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SignedBlindedBeaconBlockElectra object to a target array +func (s *SignedBlindedBeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(2736713) + offset := int(100) - // Field (0) 'GenesisTime' - dst = ssz.MarshalUint64(dst, b.GenesisTime) + // Offset (0) 'Message' + dst = ssz.WriteOffset(dst, offset) + if s.Message == nil { + s.Message = new(BlindedBeaconBlockElectra) + } + offset += s.Message.SizeSSZ() - // Field (1) 'GenesisValidatorsRoot' - if size := len(b.GenesisValidatorsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.GenesisValidatorsRoot", size, 32) + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - dst = append(dst, b.GenesisValidatorsRoot...) - - // Field (2) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) + dst = append(dst, s.Signature...) - // Field (3) 'Fork' - if b.Fork == nil { - b.Fork = new(Fork) - } - if dst, err = b.Fork.MarshalSSZTo(dst); err != nil { + // Field (0) 'Message' + if dst, err = s.Message.MarshalSSZTo(dst); err != nil { return } - // Field (4) 'LatestBlockHeader' - if b.LatestBlockHeader == nil { - b.LatestBlockHeader = new(BeaconBlockHeader) - } - if dst, err = b.LatestBlockHeader.MarshalSSZTo(dst); err != nil { - return + return +} + +// UnmarshalSSZ ssz unmarshals the SignedBlindedBeaconBlockElectra object +func (s *SignedBlindedBeaconBlockElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 100 { + return ssz.ErrSize } - // Field (5) 'BlockRoots' - if size := len(b.BlockRoots); size != 8192 { - err = ssz.ErrVectorLengthFn("--.BlockRoots", size, 8192) - return + tail := buf + var o0 uint64 + + // Offset (0) 'Message' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset } - for ii := 0; ii < 8192; ii++ { - if size := len(b.BlockRoots[ii]); size != 32 { - err = ssz.ErrBytesLengthFn("--.BlockRoots[ii]", size, 32) - return - } - dst = append(dst, b.BlockRoots[ii]...) + + if o0 != 100 { + return ssz.ErrInvalidVariableOffset } - // Field (6) 'StateRoots' - if size := len(b.StateRoots); size != 8192 { - err = ssz.ErrVectorLengthFn("--.StateRoots", size, 8192) - return + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) } - for ii := 0; ii < 8192; ii++ { - if size := len(b.StateRoots[ii]); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoots[ii]", size, 32) - return + s.Signature = append(s.Signature, buf[4:100]...) + + // Field (0) 'Message' + { + buf = tail[o0:] + if s.Message == nil { + s.Message = new(BlindedBeaconBlockElectra) + } + if err = s.Message.UnmarshalSSZ(buf); err != nil { + return err } - dst = append(dst, b.StateRoots[ii]...) } + return err +} - // Offset (7) 'HistoricalRoots' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.HistoricalRoots) * 32 +// SizeSSZ returns the ssz encoded size in bytes for the SignedBlindedBeaconBlockElectra object +func (s *SignedBlindedBeaconBlockElectra) SizeSSZ() (size int) { + size = 100 - // Field (8) 'Eth1Data' - if b.Eth1Data == nil { - b.Eth1Data = new(Eth1Data) - } - if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { - return + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(BlindedBeaconBlockElectra) } + size += s.Message.SizeSSZ() - // Offset (9) 'Eth1DataVotes' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Eth1DataVotes) * 72 - - // Field (10) 'Eth1DepositIndex' - dst = ssz.MarshalUint64(dst, b.Eth1DepositIndex) + return +} - // Offset (11) 'Validators' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Validators) * 121 +// HashTreeRoot ssz hashes the SignedBlindedBeaconBlockElectra object +func (s *SignedBlindedBeaconBlockElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} - // Offset (12) 'Balances' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.Balances) * 8 +// HashTreeRootWith ssz hashes the SignedBlindedBeaconBlockElectra object with a hasher +func (s *SignedBlindedBeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() - // Field (13) 'RandaoMixes' - if size := len(b.RandaoMixes); size != 65536 { - err = ssz.ErrVectorLengthFn("--.RandaoMixes", size, 65536) + // Field (0) 'Message' + if err = s.Message.HashTreeRootWith(hh); err != nil { return } - for ii := 0; ii < 65536; ii++ { - if size := len(b.RandaoMixes[ii]); size != 32 { - err = ssz.ErrBytesLengthFn("--.RandaoMixes[ii]", size, 32) - return - } - dst = append(dst, b.RandaoMixes[ii]...) - } - // Field (14) 'Slashings' - if size := len(b.Slashings); size != 8192 { - err = ssz.ErrVectorLengthFn("--.Slashings", size, 8192) + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - for ii := 0; ii < 8192; ii++ { - dst = ssz.MarshalUint64(dst, b.Slashings[ii]) - } + hh.PutBytes(s.Signature) - // Offset (15) 'PreviousEpochParticipation' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.PreviousEpochParticipation) + hh.Merkleize(indx) + return +} - // Offset (16) 'CurrentEpochParticipation' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.CurrentEpochParticipation) +// MarshalSSZ ssz marshals the BlindedBeaconBlockElectra object +func (b *BlindedBeaconBlockElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} - // Field (17) 'JustificationBits' - if size := len(b.JustificationBits); size != 1 { - err = ssz.ErrBytesLengthFn("--.JustificationBits", size, 1) - return - } - dst = append(dst, b.JustificationBits...) +// MarshalSSZTo ssz marshals the BlindedBeaconBlockElectra object to a target array +func (b *BlindedBeaconBlockElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(84) - // Field (18) 'PreviousJustifiedCheckpoint' - if b.PreviousJustifiedCheckpoint == nil { - b.PreviousJustifiedCheckpoint = new(Checkpoint) - } - if dst, err = b.PreviousJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { - return - } + // Field (0) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - // Field (19) 'CurrentJustifiedCheckpoint' - if b.CurrentJustifiedCheckpoint == nil { - b.CurrentJustifiedCheckpoint = new(Checkpoint) - } - if dst, err = b.CurrentJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { + // Field (1) 'ProposerIndex' + dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) + + // Field (2) 'ParentRoot' + if size := len(b.ParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) return } + dst = append(dst, b.ParentRoot...) - // Field (20) 'FinalizedCheckpoint' - if b.FinalizedCheckpoint == nil { - b.FinalizedCheckpoint = new(Checkpoint) - } - if dst, err = b.FinalizedCheckpoint.MarshalSSZTo(dst); err != nil { + // Field (3) 'StateRoot' + if size := len(b.StateRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) return } + dst = append(dst, b.StateRoot...) - // Offset (21) 'InactivityScores' + // Offset (4) 'Body' dst = ssz.WriteOffset(dst, offset) - offset += len(b.InactivityScores) * 8 - - // Field (22) 'CurrentSyncCommittee' - if b.CurrentSyncCommittee == nil { - b.CurrentSyncCommittee = new(SyncCommittee) - } - if dst, err = b.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil { - return + if b.Body == nil { + b.Body = new(BlindedBeaconBlockBodyElectra) } + offset += b.Body.SizeSSZ() - // Field (23) 'NextSyncCommittee' - if b.NextSyncCommittee == nil { - b.NextSyncCommittee = new(SyncCommittee) - } - if dst, err = b.NextSyncCommittee.MarshalSSZTo(dst); err != nil { + // Field (4) 'Body' + if dst, err = b.Body.MarshalSSZTo(dst); err != nil { return } - // Offset (24) 'LatestExecutionPayloadHeader' - dst = ssz.WriteOffset(dst, offset) - if b.LatestExecutionPayloadHeader == nil { - b.LatestExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderElectra) + return +} + +// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockElectra object +func (b *BlindedBeaconBlockElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 84 { + return ssz.ErrSize } - offset += b.LatestExecutionPayloadHeader.SizeSSZ() - // Field (25) 'NextWithdrawalIndex' - dst = ssz.MarshalUint64(dst, b.NextWithdrawalIndex) + tail := buf + var o4 uint64 - // Field (26) 'NextWithdrawalValidatorIndex' - dst = ssz.MarshalUint64(dst, uint64(b.NextWithdrawalValidatorIndex)) + // Field (0) 'Slot' + b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - // Offset (27) 'HistoricalSummaries' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.HistoricalSummaries) * 64 + // Field (1) 'ProposerIndex' + b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - // Field (28) 'DepositRequestsStartIndex' - dst = ssz.MarshalUint64(dst, b.DepositRequestsStartIndex) + // Field (2) 'ParentRoot' + if cap(b.ParentRoot) == 0 { + b.ParentRoot = make([]byte, 0, len(buf[16:48])) + } + b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - // Field (29) 'DepositBalanceToConsume' - dst = ssz.MarshalUint64(dst, uint64(b.DepositBalanceToConsume)) + // Field (3) 'StateRoot' + if cap(b.StateRoot) == 0 { + b.StateRoot = make([]byte, 0, len(buf[48:80])) + } + b.StateRoot = append(b.StateRoot, buf[48:80]...) - // Field (30) 'ExitBalanceToConsume' - dst = ssz.MarshalUint64(dst, uint64(b.ExitBalanceToConsume)) + // Offset (4) 'Body' + if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { + return ssz.ErrOffset + } - // Field (31) 'EarliestExitEpoch' - dst = ssz.MarshalUint64(dst, uint64(b.EarliestExitEpoch)) + if o4 != 84 { + return ssz.ErrInvalidVariableOffset + } - // Field (32) 'ConsolidationBalanceToConsume' - dst = ssz.MarshalUint64(dst, uint64(b.ConsolidationBalanceToConsume)) + // Field (4) 'Body' + { + buf = tail[o4:] + if b.Body == nil { + b.Body = new(BlindedBeaconBlockBodyElectra) + } + if err = b.Body.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} - // Field (33) 'EarliestConsolidationEpoch' - dst = ssz.MarshalUint64(dst, uint64(b.EarliestConsolidationEpoch)) +// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockElectra object +func (b *BlindedBeaconBlockElectra) SizeSSZ() (size int) { + size = 84 - // Offset (34) 'PendingBalanceDeposits' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.PendingBalanceDeposits) * 16 + // Field (4) 'Body' + if b.Body == nil { + b.Body = new(BlindedBeaconBlockBodyElectra) + } + size += b.Body.SizeSSZ() - // Offset (35) 'PendingPartialWithdrawals' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.PendingPartialWithdrawals) * 24 + return +} - // Offset (36) 'PendingConsolidations' - dst = ssz.WriteOffset(dst, offset) - offset += len(b.PendingConsolidations) * 16 +// HashTreeRoot ssz hashes the BlindedBeaconBlockElectra object +func (b *BlindedBeaconBlockElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) +} - // Field (7) 'HistoricalRoots' - if size := len(b.HistoricalRoots); size > 16777216 { - err = ssz.ErrListTooBigFn("--.HistoricalRoots", size, 16777216) +// HashTreeRootWith ssz hashes the BlindedBeaconBlockElectra object with a hasher +func (b *BlindedBeaconBlockElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Slot' + hh.PutUint64(uint64(b.Slot)) + + // Field (1) 'ProposerIndex' + hh.PutUint64(uint64(b.ProposerIndex)) + + // Field (2) 'ParentRoot' + if size := len(b.ParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) return } - for ii := 0; ii < len(b.HistoricalRoots); ii++ { - if size := len(b.HistoricalRoots[ii]); size != 32 { - err = ssz.ErrBytesLengthFn("--.HistoricalRoots[ii]", size, 32) - return - } - dst = append(dst, b.HistoricalRoots[ii]...) - } + hh.PutBytes(b.ParentRoot) - // Field (9) 'Eth1DataVotes' - if size := len(b.Eth1DataVotes); size > 2048 { - err = ssz.ErrListTooBigFn("--.Eth1DataVotes", size, 2048) + // Field (3) 'StateRoot' + if size := len(b.StateRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) return } - for ii := 0; ii < len(b.Eth1DataVotes); ii++ { - if dst, err = b.Eth1DataVotes[ii].MarshalSSZTo(dst); err != nil { - return - } - } + hh.PutBytes(b.StateRoot) - // Field (11) 'Validators' - if size := len(b.Validators); size > 1099511627776 { - err = ssz.ErrListTooBigFn("--.Validators", size, 1099511627776) + // Field (4) 'Body' + if err = b.Body.HashTreeRootWith(hh); err != nil { return } - for ii := 0; ii < len(b.Validators); ii++ { - if dst, err = b.Validators[ii].MarshalSSZTo(dst); err != nil { - return - } - } - // Field (12) 'Balances' - if size := len(b.Balances); size > 1099511627776 { - err = ssz.ErrListTooBigFn("--.Balances", size, 1099511627776) + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the BlindedBeaconBlockBodyElectra object +func (b *BlindedBeaconBlockBodyElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BlindedBeaconBlockBodyElectra object to a target array +func (b *BlindedBeaconBlockBodyElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(396) + + // Field (0) 'RandaoReveal' + if size := len(b.RandaoReveal); size != 96 { + err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) return } - for ii := 0; ii < len(b.Balances); ii++ { - dst = ssz.MarshalUint64(dst, b.Balances[ii]) - } + dst = append(dst, b.RandaoReveal...) - // Field (15) 'PreviousEpochParticipation' - if size := len(b.PreviousEpochParticipation); size > 1099511627776 { - err = ssz.ErrBytesLengthFn("--.PreviousEpochParticipation", size, 1099511627776) + // Field (1) 'Eth1Data' + if b.Eth1Data == nil { + b.Eth1Data = new(Eth1Data) + } + if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, b.PreviousEpochParticipation...) - // Field (16) 'CurrentEpochParticipation' - if size := len(b.CurrentEpochParticipation); size > 1099511627776 { - err = ssz.ErrBytesLengthFn("--.CurrentEpochParticipation", size, 1099511627776) + // Field (2) 'Graffiti' + if size := len(b.Graffiti); size != 32 { + err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) return } - dst = append(dst, b.CurrentEpochParticipation...) + dst = append(dst, b.Graffiti...) - // Field (21) 'InactivityScores' - if size := len(b.InactivityScores); size > 1099511627776 { - err = ssz.ErrListTooBigFn("--.InactivityScores", size, 1099511627776) - return + // Offset (3) 'ProposerSlashings' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.ProposerSlashings) * 416 + + // Offset (4) 'AttesterSlashings' + dst = ssz.WriteOffset(dst, offset) + for ii := 0; ii < len(b.AttesterSlashings); ii++ { + offset += 4 + offset += b.AttesterSlashings[ii].SizeSSZ() } - for ii := 0; ii < len(b.InactivityScores); ii++ { - dst = ssz.MarshalUint64(dst, b.InactivityScores[ii]) + + // Offset (5) 'Attestations' + dst = ssz.WriteOffset(dst, offset) + for ii := 0; ii < len(b.Attestations); ii++ { + offset += 4 + offset += b.Attestations[ii].SizeSSZ() } - // Field (24) 'LatestExecutionPayloadHeader' - if dst, err = b.LatestExecutionPayloadHeader.MarshalSSZTo(dst); err != nil { + // Offset (6) 'Deposits' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Deposits) * 1240 + + // Offset (7) 'VoluntaryExits' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.VoluntaryExits) * 112 + + // Field (8) 'SyncAggregate' + if b.SyncAggregate == nil { + b.SyncAggregate = new(SyncAggregate) + } + if dst, err = b.SyncAggregate.MarshalSSZTo(dst); err != nil { return } - // Field (27) 'HistoricalSummaries' - if size := len(b.HistoricalSummaries); size > 16777216 { - err = ssz.ErrListTooBigFn("--.HistoricalSummaries", size, 16777216) - return + // Offset (9) 'ExecutionPayloadHeader' + dst = ssz.WriteOffset(dst, offset) + if b.ExecutionPayloadHeader == nil { + b.ExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderDeneb) } - for ii := 0; ii < len(b.HistoricalSummaries); ii++ { - if dst, err = b.HistoricalSummaries[ii].MarshalSSZTo(dst); err != nil { - return - } + offset += b.ExecutionPayloadHeader.SizeSSZ() + + // Offset (10) 'BlsToExecutionChanges' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.BlsToExecutionChanges) * 172 + + // Offset (11) 'BlobKzgCommitments' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.BlobKzgCommitments) * 48 + + // Offset (12) 'ExecutionRequests' + dst = ssz.WriteOffset(dst, offset) + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) } + offset += b.ExecutionRequests.SizeSSZ() - // Field (34) 'PendingBalanceDeposits' - if size := len(b.PendingBalanceDeposits); size > 134217728 { - err = ssz.ErrListTooBigFn("--.PendingBalanceDeposits", size, 134217728) + // Field (3) 'ProposerSlashings' + if size := len(b.ProposerSlashings); size > 16 { + err = ssz.ErrListTooBigFn("--.ProposerSlashings", size, 16) return } - for ii := 0; ii < len(b.PendingBalanceDeposits); ii++ { - if dst, err = b.PendingBalanceDeposits[ii].MarshalSSZTo(dst); err != nil { + for ii := 0; ii < len(b.ProposerSlashings); ii++ { + if dst, err = b.ProposerSlashings[ii].MarshalSSZTo(dst); err != nil { return } } - // Field (35) 'PendingPartialWithdrawals' - if size := len(b.PendingPartialWithdrawals); size > 134217728 { - err = ssz.ErrListTooBigFn("--.PendingPartialWithdrawals", size, 134217728) + // Field (4) 'AttesterSlashings' + if size := len(b.AttesterSlashings); size > 1 { + err = ssz.ErrListTooBigFn("--.AttesterSlashings", size, 1) return } - for ii := 0; ii < len(b.PendingPartialWithdrawals); ii++ { - if dst, err = b.PendingPartialWithdrawals[ii].MarshalSSZTo(dst); err != nil { + { + offset = 4 * len(b.AttesterSlashings) + for ii := 0; ii < len(b.AttesterSlashings); ii++ { + dst = ssz.WriteOffset(dst, offset) + offset += b.AttesterSlashings[ii].SizeSSZ() + } + } + for ii := 0; ii < len(b.AttesterSlashings); ii++ { + if dst, err = b.AttesterSlashings[ii].MarshalSSZTo(dst); err != nil { return } } - // Field (36) 'PendingConsolidations' - if size := len(b.PendingConsolidations); size > 262144 { - err = ssz.ErrListTooBigFn("--.PendingConsolidations", size, 262144) - return + // Field (5) 'Attestations' + if size := len(b.Attestations); size > 8 { + err = ssz.ErrListTooBigFn("--.Attestations", size, 8) + return } - for ii := 0; ii < len(b.PendingConsolidations); ii++ { - if dst, err = b.PendingConsolidations[ii].MarshalSSZTo(dst); err != nil { + { + offset = 4 * len(b.Attestations) + for ii := 0; ii < len(b.Attestations); ii++ { + dst = ssz.WriteOffset(dst, offset) + offset += b.Attestations[ii].SizeSSZ() + } + } + for ii := 0; ii < len(b.Attestations); ii++ { + if dst, err = b.Attestations[ii].MarshalSSZTo(dst); err != nil { return } } - return -} - -// UnmarshalSSZ ssz unmarshals the BeaconStateElectra object -func (b *BeaconStateElectra) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 2736713 { - return ssz.ErrSize + // Field (6) 'Deposits' + if size := len(b.Deposits); size > 16 { + err = ssz.ErrListTooBigFn("--.Deposits", size, 16) + return } - - tail := buf - var o7, o9, o11, o12, o15, o16, o21, o24, o27, o34, o35, o36 uint64 - - // Field (0) 'GenesisTime' - b.GenesisTime = ssz.UnmarshallUint64(buf[0:8]) - - // Field (1) 'GenesisValidatorsRoot' - if cap(b.GenesisValidatorsRoot) == 0 { - b.GenesisValidatorsRoot = make([]byte, 0, len(buf[8:40])) + for ii := 0; ii < len(b.Deposits); ii++ { + if dst, err = b.Deposits[ii].MarshalSSZTo(dst); err != nil { + return + } } - b.GenesisValidatorsRoot = append(b.GenesisValidatorsRoot, buf[8:40]...) - - // Field (2) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[40:48])) - // Field (3) 'Fork' - if b.Fork == nil { - b.Fork = new(Fork) + // Field (7) 'VoluntaryExits' + if size := len(b.VoluntaryExits); size > 16 { + err = ssz.ErrListTooBigFn("--.VoluntaryExits", size, 16) + return } - if err = b.Fork.UnmarshalSSZ(buf[48:64]); err != nil { - return err + for ii := 0; ii < len(b.VoluntaryExits); ii++ { + if dst, err = b.VoluntaryExits[ii].MarshalSSZTo(dst); err != nil { + return + } } - // Field (4) 'LatestBlockHeader' - if b.LatestBlockHeader == nil { - b.LatestBlockHeader = new(BeaconBlockHeader) - } - if err = b.LatestBlockHeader.UnmarshalSSZ(buf[64:176]); err != nil { - return err + // Field (9) 'ExecutionPayloadHeader' + if dst, err = b.ExecutionPayloadHeader.MarshalSSZTo(dst); err != nil { + return } - // Field (5) 'BlockRoots' - b.BlockRoots = make([][]byte, 8192) - for ii := 0; ii < 8192; ii++ { - if cap(b.BlockRoots[ii]) == 0 { - b.BlockRoots[ii] = make([]byte, 0, len(buf[176:262320][ii*32:(ii+1)*32])) + // Field (10) 'BlsToExecutionChanges' + if size := len(b.BlsToExecutionChanges); size > 16 { + err = ssz.ErrListTooBigFn("--.BlsToExecutionChanges", size, 16) + return + } + for ii := 0; ii < len(b.BlsToExecutionChanges); ii++ { + if dst, err = b.BlsToExecutionChanges[ii].MarshalSSZTo(dst); err != nil { + return } - b.BlockRoots[ii] = append(b.BlockRoots[ii], buf[176:262320][ii*32:(ii+1)*32]...) } - // Field (6) 'StateRoots' - b.StateRoots = make([][]byte, 8192) - for ii := 0; ii < 8192; ii++ { - if cap(b.StateRoots[ii]) == 0 { - b.StateRoots[ii] = make([]byte, 0, len(buf[262320:524464][ii*32:(ii+1)*32])) + // Field (11) 'BlobKzgCommitments' + if size := len(b.BlobKzgCommitments); size > 4096 { + err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) + return + } + for ii := 0; ii < len(b.BlobKzgCommitments); ii++ { + if size := len(b.BlobKzgCommitments[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.BlobKzgCommitments[ii]", size, 48) + return } - b.StateRoots[ii] = append(b.StateRoots[ii], buf[262320:524464][ii*32:(ii+1)*32]...) + dst = append(dst, b.BlobKzgCommitments[ii]...) } - // Offset (7) 'HistoricalRoots' - if o7 = ssz.ReadOffset(buf[524464:524468]); o7 > size { - return ssz.ErrOffset + // Field (12) 'ExecutionRequests' + if dst, err = b.ExecutionRequests.MarshalSSZTo(dst); err != nil { + return } - if o7 != 2736713 { - return ssz.ErrInvalidVariableOffset + return +} + +// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockBodyElectra object +func (b *BlindedBeaconBlockBodyElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 396 { + return ssz.ErrSize } - // Field (8) 'Eth1Data' + tail := buf + var o3, o4, o5, o6, o7, o9, o10, o11, o12 uint64 + + // Field (0) 'RandaoReveal' + if cap(b.RandaoReveal) == 0 { + b.RandaoReveal = make([]byte, 0, len(buf[0:96])) + } + b.RandaoReveal = append(b.RandaoReveal, buf[0:96]...) + + // Field (1) 'Eth1Data' if b.Eth1Data == nil { b.Eth1Data = new(Eth1Data) } - if err = b.Eth1Data.UnmarshalSSZ(buf[524468:524540]); err != nil { + if err = b.Eth1Data.UnmarshalSSZ(buf[96:168]); err != nil { return err } - // Offset (9) 'Eth1DataVotes' - if o9 = ssz.ReadOffset(buf[524540:524544]); o9 > size || o7 > o9 { - return ssz.ErrOffset - } - - // Field (10) 'Eth1DepositIndex' - b.Eth1DepositIndex = ssz.UnmarshallUint64(buf[524544:524552]) - - // Offset (11) 'Validators' - if o11 = ssz.ReadOffset(buf[524552:524556]); o11 > size || o9 > o11 { - return ssz.ErrOffset + // Field (2) 'Graffiti' + if cap(b.Graffiti) == 0 { + b.Graffiti = make([]byte, 0, len(buf[168:200])) } + b.Graffiti = append(b.Graffiti, buf[168:200]...) - // Offset (12) 'Balances' - if o12 = ssz.ReadOffset(buf[524556:524560]); o12 > size || o11 > o12 { + // Offset (3) 'ProposerSlashings' + if o3 = ssz.ReadOffset(buf[200:204]); o3 > size { return ssz.ErrOffset } - // Field (13) 'RandaoMixes' - b.RandaoMixes = make([][]byte, 65536) - for ii := 0; ii < 65536; ii++ { - if cap(b.RandaoMixes[ii]) == 0 { - b.RandaoMixes[ii] = make([]byte, 0, len(buf[524560:2621712][ii*32:(ii+1)*32])) - } - b.RandaoMixes[ii] = append(b.RandaoMixes[ii], buf[524560:2621712][ii*32:(ii+1)*32]...) - } - - // Field (14) 'Slashings' - b.Slashings = ssz.ExtendUint64(b.Slashings, 8192) - for ii := 0; ii < 8192; ii++ { - b.Slashings[ii] = ssz.UnmarshallUint64(buf[2621712:2687248][ii*8 : (ii+1)*8]) + if o3 != 396 { + return ssz.ErrInvalidVariableOffset } - // Offset (15) 'PreviousEpochParticipation' - if o15 = ssz.ReadOffset(buf[2687248:2687252]); o15 > size || o12 > o15 { + // Offset (4) 'AttesterSlashings' + if o4 = ssz.ReadOffset(buf[204:208]); o4 > size || o3 > o4 { return ssz.ErrOffset } - // Offset (16) 'CurrentEpochParticipation' - if o16 = ssz.ReadOffset(buf[2687252:2687256]); o16 > size || o15 > o16 { + // Offset (5) 'Attestations' + if o5 = ssz.ReadOffset(buf[208:212]); o5 > size || o4 > o5 { return ssz.ErrOffset } - // Field (17) 'JustificationBits' - if cap(b.JustificationBits) == 0 { - b.JustificationBits = make([]byte, 0, len(buf[2687256:2687257])) - } - b.JustificationBits = append(b.JustificationBits, buf[2687256:2687257]...) - - // Field (18) 'PreviousJustifiedCheckpoint' - if b.PreviousJustifiedCheckpoint == nil { - b.PreviousJustifiedCheckpoint = new(Checkpoint) - } - if err = b.PreviousJustifiedCheckpoint.UnmarshalSSZ(buf[2687257:2687297]); err != nil { - return err - } - - // Field (19) 'CurrentJustifiedCheckpoint' - if b.CurrentJustifiedCheckpoint == nil { - b.CurrentJustifiedCheckpoint = new(Checkpoint) - } - if err = b.CurrentJustifiedCheckpoint.UnmarshalSSZ(buf[2687297:2687337]); err != nil { - return err - } - - // Field (20) 'FinalizedCheckpoint' - if b.FinalizedCheckpoint == nil { - b.FinalizedCheckpoint = new(Checkpoint) - } - if err = b.FinalizedCheckpoint.UnmarshalSSZ(buf[2687337:2687377]); err != nil { - return err - } - - // Offset (21) 'InactivityScores' - if o21 = ssz.ReadOffset(buf[2687377:2687381]); o21 > size || o16 > o21 { + // Offset (6) 'Deposits' + if o6 = ssz.ReadOffset(buf[212:216]); o6 > size || o5 > o6 { return ssz.ErrOffset } - // Field (22) 'CurrentSyncCommittee' - if b.CurrentSyncCommittee == nil { - b.CurrentSyncCommittee = new(SyncCommittee) - } - if err = b.CurrentSyncCommittee.UnmarshalSSZ(buf[2687381:2712005]); err != nil { - return err + // Offset (7) 'VoluntaryExits' + if o7 = ssz.ReadOffset(buf[216:220]); o7 > size || o6 > o7 { + return ssz.ErrOffset } - // Field (23) 'NextSyncCommittee' - if b.NextSyncCommittee == nil { - b.NextSyncCommittee = new(SyncCommittee) + // Field (8) 'SyncAggregate' + if b.SyncAggregate == nil { + b.SyncAggregate = new(SyncAggregate) } - if err = b.NextSyncCommittee.UnmarshalSSZ(buf[2712005:2736629]); err != nil { + if err = b.SyncAggregate.UnmarshalSSZ(buf[220:380]); err != nil { return err } - // Offset (24) 'LatestExecutionPayloadHeader' - if o24 = ssz.ReadOffset(buf[2736629:2736633]); o24 > size || o21 > o24 { + // Offset (9) 'ExecutionPayloadHeader' + if o9 = ssz.ReadOffset(buf[380:384]); o9 > size || o7 > o9 { return ssz.ErrOffset } - // Field (25) 'NextWithdrawalIndex' - b.NextWithdrawalIndex = ssz.UnmarshallUint64(buf[2736633:2736641]) - - // Field (26) 'NextWithdrawalValidatorIndex' - b.NextWithdrawalValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[2736641:2736649])) - - // Offset (27) 'HistoricalSummaries' - if o27 = ssz.ReadOffset(buf[2736649:2736653]); o27 > size || o24 > o27 { + // Offset (10) 'BlsToExecutionChanges' + if o10 = ssz.ReadOffset(buf[384:388]); o10 > size || o9 > o10 { return ssz.ErrOffset } - // Field (28) 'DepositRequestsStartIndex' - b.DepositRequestsStartIndex = ssz.UnmarshallUint64(buf[2736653:2736661]) - - // Field (29) 'DepositBalanceToConsume' - b.DepositBalanceToConsume = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736661:2736669])) - - // Field (30) 'ExitBalanceToConsume' - b.ExitBalanceToConsume = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736669:2736677])) - - // Field (31) 'EarliestExitEpoch' - b.EarliestExitEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736677:2736685])) - - // Field (32) 'ConsolidationBalanceToConsume' - b.ConsolidationBalanceToConsume = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736685:2736693])) - - // Field (33) 'EarliestConsolidationEpoch' - b.EarliestConsolidationEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736693:2736701])) - - // Offset (34) 'PendingBalanceDeposits' - if o34 = ssz.ReadOffset(buf[2736701:2736705]); o34 > size || o27 > o34 { + // Offset (11) 'BlobKzgCommitments' + if o11 = ssz.ReadOffset(buf[388:392]); o11 > size || o10 > o11 { return ssz.ErrOffset } - // Offset (35) 'PendingPartialWithdrawals' - if o35 = ssz.ReadOffset(buf[2736705:2736709]); o35 > size || o34 > o35 { + // Offset (12) 'ExecutionRequests' + if o12 = ssz.ReadOffset(buf[392:396]); o12 > size || o11 > o12 { return ssz.ErrOffset } - // Offset (36) 'PendingConsolidations' - if o36 = ssz.ReadOffset(buf[2736709:2736713]); o36 > size || o35 > o36 { - return ssz.ErrOffset - } - - // Field (7) 'HistoricalRoots' + // Field (3) 'ProposerSlashings' { - buf = tail[o7:o9] - num, err := ssz.DivideInt2(len(buf), 32, 16777216) + buf = tail[o3:o4] + num, err := ssz.DivideInt2(len(buf), 416, 16) if err != nil { return err } - b.HistoricalRoots = make([][]byte, num) + b.ProposerSlashings = make([]*ProposerSlashing, num) for ii := 0; ii < num; ii++ { - if cap(b.HistoricalRoots[ii]) == 0 { - b.HistoricalRoots[ii] = make([]byte, 0, len(buf[ii*32:(ii+1)*32])) + if b.ProposerSlashings[ii] == nil { + b.ProposerSlashings[ii] = new(ProposerSlashing) + } + if err = b.ProposerSlashings[ii].UnmarshalSSZ(buf[ii*416 : (ii+1)*416]); err != nil { + return err } - b.HistoricalRoots[ii] = append(b.HistoricalRoots[ii], buf[ii*32:(ii+1)*32]...) } } - // Field (9) 'Eth1DataVotes' + // Field (4) 'AttesterSlashings' { - buf = tail[o9:o11] - num, err := ssz.DivideInt2(len(buf), 72, 2048) + buf = tail[o4:o5] + num, err := ssz.DecodeDynamicLength(buf, 1) if err != nil { return err } - b.Eth1DataVotes = make([]*Eth1Data, num) - for ii := 0; ii < num; ii++ { - if b.Eth1DataVotes[ii] == nil { - b.Eth1DataVotes[ii] = new(Eth1Data) + b.AttesterSlashings = make([]*AttesterSlashingElectra, num) + err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { + if b.AttesterSlashings[indx] == nil { + b.AttesterSlashings[indx] = new(AttesterSlashingElectra) } - if err = b.Eth1DataVotes[ii].UnmarshalSSZ(buf[ii*72 : (ii+1)*72]); err != nil { + if err = b.AttesterSlashings[indx].UnmarshalSSZ(buf); err != nil { return err } + return nil + }) + if err != nil { + return err } } - // Field (11) 'Validators' + // Field (5) 'Attestations' { - buf = tail[o11:o12] - num, err := ssz.DivideInt2(len(buf), 121, 1099511627776) + buf = tail[o5:o6] + num, err := ssz.DecodeDynamicLength(buf, 8) if err != nil { return err } - b.Validators = make([]*Validator, num) - for ii := 0; ii < num; ii++ { - if b.Validators[ii] == nil { - b.Validators[ii] = new(Validator) + b.Attestations = make([]*AttestationElectra, num) + err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { + if b.Attestations[indx] == nil { + b.Attestations[indx] = new(AttestationElectra) } - if err = b.Validators[ii].UnmarshalSSZ(buf[ii*121 : (ii+1)*121]); err != nil { + if err = b.Attestations[indx].UnmarshalSSZ(buf); err != nil { return err } + return nil + }) + if err != nil { + return err } } - // Field (12) 'Balances' + // Field (6) 'Deposits' { - buf = tail[o12:o15] - num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) + buf = tail[o6:o7] + num, err := ssz.DivideInt2(len(buf), 1240, 16) if err != nil { return err } - b.Balances = ssz.ExtendUint64(b.Balances, num) + b.Deposits = make([]*Deposit, num) for ii := 0; ii < num; ii++ { - b.Balances[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) - } - } - - // Field (15) 'PreviousEpochParticipation' - { - buf = tail[o15:o16] - if len(buf) > 1099511627776 { - return ssz.ErrBytesLength - } - if cap(b.PreviousEpochParticipation) == 0 { - b.PreviousEpochParticipation = make([]byte, 0, len(buf)) - } - b.PreviousEpochParticipation = append(b.PreviousEpochParticipation, buf...) - } - - // Field (16) 'CurrentEpochParticipation' - { - buf = tail[o16:o21] - if len(buf) > 1099511627776 { - return ssz.ErrBytesLength - } - if cap(b.CurrentEpochParticipation) == 0 { - b.CurrentEpochParticipation = make([]byte, 0, len(buf)) + if b.Deposits[ii] == nil { + b.Deposits[ii] = new(Deposit) + } + if err = b.Deposits[ii].UnmarshalSSZ(buf[ii*1240 : (ii+1)*1240]); err != nil { + return err + } } - b.CurrentEpochParticipation = append(b.CurrentEpochParticipation, buf...) } - // Field (21) 'InactivityScores' + // Field (7) 'VoluntaryExits' { - buf = tail[o21:o24] - num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) + buf = tail[o7:o9] + num, err := ssz.DivideInt2(len(buf), 112, 16) if err != nil { return err } - b.InactivityScores = ssz.ExtendUint64(b.InactivityScores, num) + b.VoluntaryExits = make([]*SignedVoluntaryExit, num) for ii := 0; ii < num; ii++ { - b.InactivityScores[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) + if b.VoluntaryExits[ii] == nil { + b.VoluntaryExits[ii] = new(SignedVoluntaryExit) + } + if err = b.VoluntaryExits[ii].UnmarshalSSZ(buf[ii*112 : (ii+1)*112]); err != nil { + return err + } } } - // Field (24) 'LatestExecutionPayloadHeader' + // Field (9) 'ExecutionPayloadHeader' { - buf = tail[o24:o27] - if b.LatestExecutionPayloadHeader == nil { - b.LatestExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderElectra) + buf = tail[o9:o10] + if b.ExecutionPayloadHeader == nil { + b.ExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderDeneb) } - if err = b.LatestExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { + if err = b.ExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { return err } } - // Field (27) 'HistoricalSummaries' + // Field (10) 'BlsToExecutionChanges' { - buf = tail[o27:o34] - num, err := ssz.DivideInt2(len(buf), 64, 16777216) + buf = tail[o10:o11] + num, err := ssz.DivideInt2(len(buf), 172, 16) if err != nil { return err } - b.HistoricalSummaries = make([]*HistoricalSummary, num) + b.BlsToExecutionChanges = make([]*SignedBLSToExecutionChange, num) for ii := 0; ii < num; ii++ { - if b.HistoricalSummaries[ii] == nil { - b.HistoricalSummaries[ii] = new(HistoricalSummary) + if b.BlsToExecutionChanges[ii] == nil { + b.BlsToExecutionChanges[ii] = new(SignedBLSToExecutionChange) } - if err = b.HistoricalSummaries[ii].UnmarshalSSZ(buf[ii*64 : (ii+1)*64]); err != nil { + if err = b.BlsToExecutionChanges[ii].UnmarshalSSZ(buf[ii*172 : (ii+1)*172]); err != nil { return err } } } - // Field (34) 'PendingBalanceDeposits' + // Field (11) 'BlobKzgCommitments' { - buf = tail[o34:o35] - num, err := ssz.DivideInt2(len(buf), 16, 134217728) + buf = tail[o11:o12] + num, err := ssz.DivideInt2(len(buf), 48, 4096) if err != nil { return err } - b.PendingBalanceDeposits = make([]*PendingBalanceDeposit, num) + b.BlobKzgCommitments = make([][]byte, num) for ii := 0; ii < num; ii++ { - if b.PendingBalanceDeposits[ii] == nil { - b.PendingBalanceDeposits[ii] = new(PendingBalanceDeposit) - } - if err = b.PendingBalanceDeposits[ii].UnmarshalSSZ(buf[ii*16 : (ii+1)*16]); err != nil { - return err + if cap(b.BlobKzgCommitments[ii]) == 0 { + b.BlobKzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) } + b.BlobKzgCommitments[ii] = append(b.BlobKzgCommitments[ii], buf[ii*48:(ii+1)*48]...) } } - // Field (35) 'PendingPartialWithdrawals' + // Field (12) 'ExecutionRequests' { - buf = tail[o35:o36] - num, err := ssz.DivideInt2(len(buf), 24, 134217728) - if err != nil { - return err - } - b.PendingPartialWithdrawals = make([]*PendingPartialWithdrawal, num) - for ii := 0; ii < num; ii++ { - if b.PendingPartialWithdrawals[ii] == nil { - b.PendingPartialWithdrawals[ii] = new(PendingPartialWithdrawal) - } - if err = b.PendingPartialWithdrawals[ii].UnmarshalSSZ(buf[ii*24 : (ii+1)*24]); err != nil { - return err - } + buf = tail[o12:] + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) } - } - - // Field (36) 'PendingConsolidations' - { - buf = tail[o36:] - num, err := ssz.DivideInt2(len(buf), 16, 262144) - if err != nil { + if err = b.ExecutionRequests.UnmarshalSSZ(buf); err != nil { return err } - b.PendingConsolidations = make([]*PendingConsolidation, num) - for ii := 0; ii < num; ii++ { - if b.PendingConsolidations[ii] == nil { - b.PendingConsolidations[ii] = new(PendingConsolidation) - } - if err = b.PendingConsolidations[ii].UnmarshalSSZ(buf[ii*16 : (ii+1)*16]); err != nil { - return err - } - } } return err } -// SizeSSZ returns the ssz encoded size in bytes for the BeaconStateElectra object -func (b *BeaconStateElectra) SizeSSZ() (size int) { - size = 2736713 - - // Field (7) 'HistoricalRoots' - size += len(b.HistoricalRoots) * 32 - - // Field (9) 'Eth1DataVotes' - size += len(b.Eth1DataVotes) * 72 +// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockBodyElectra object +func (b *BlindedBeaconBlockBodyElectra) SizeSSZ() (size int) { + size = 396 - // Field (11) 'Validators' - size += len(b.Validators) * 121 + // Field (3) 'ProposerSlashings' + size += len(b.ProposerSlashings) * 416 - // Field (12) 'Balances' - size += len(b.Balances) * 8 + // Field (4) 'AttesterSlashings' + for ii := 0; ii < len(b.AttesterSlashings); ii++ { + size += 4 + size += b.AttesterSlashings[ii].SizeSSZ() + } - // Field (15) 'PreviousEpochParticipation' - size += len(b.PreviousEpochParticipation) + // Field (5) 'Attestations' + for ii := 0; ii < len(b.Attestations); ii++ { + size += 4 + size += b.Attestations[ii].SizeSSZ() + } - // Field (16) 'CurrentEpochParticipation' - size += len(b.CurrentEpochParticipation) + // Field (6) 'Deposits' + size += len(b.Deposits) * 1240 - // Field (21) 'InactivityScores' - size += len(b.InactivityScores) * 8 + // Field (7) 'VoluntaryExits' + size += len(b.VoluntaryExits) * 112 - // Field (24) 'LatestExecutionPayloadHeader' - if b.LatestExecutionPayloadHeader == nil { - b.LatestExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderElectra) + // Field (9) 'ExecutionPayloadHeader' + if b.ExecutionPayloadHeader == nil { + b.ExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderDeneb) } - size += b.LatestExecutionPayloadHeader.SizeSSZ() - - // Field (27) 'HistoricalSummaries' - size += len(b.HistoricalSummaries) * 64 + size += b.ExecutionPayloadHeader.SizeSSZ() - // Field (34) 'PendingBalanceDeposits' - size += len(b.PendingBalanceDeposits) * 16 + // Field (10) 'BlsToExecutionChanges' + size += len(b.BlsToExecutionChanges) * 172 - // Field (35) 'PendingPartialWithdrawals' - size += len(b.PendingPartialWithdrawals) * 24 + // Field (11) 'BlobKzgCommitments' + size += len(b.BlobKzgCommitments) * 48 - // Field (36) 'PendingConsolidations' - size += len(b.PendingConsolidations) * 16 + // Field (12) 'ExecutionRequests' + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(v1.ExecutionRequests) + } + size += b.ExecutionRequests.SizeSSZ() return } -// HashTreeRoot ssz hashes the BeaconStateElectra object -func (b *BeaconStateElectra) HashTreeRoot() ([32]byte, error) { +// HashTreeRoot ssz hashes the BlindedBeaconBlockBodyElectra object +func (b *BlindedBeaconBlockBodyElectra) HashTreeRoot() ([32]byte, error) { return ssz.HashWithDefaultHasher(b) } -// HashTreeRootWith ssz hashes the BeaconStateElectra object with a hasher -func (b *BeaconStateElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the BlindedBeaconBlockBodyElectra object with a hasher +func (b *BlindedBeaconBlockBodyElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'GenesisTime' - hh.PutUint64(b.GenesisTime) - - // Field (1) 'GenesisValidatorsRoot' - if size := len(b.GenesisValidatorsRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.GenesisValidatorsRoot", size, 32) + // Field (0) 'RandaoReveal' + if size := len(b.RandaoReveal); size != 96 { + err = ssz.ErrBytesLengthFn("--.RandaoReveal", size, 96) return } - hh.PutBytes(b.GenesisValidatorsRoot) - - // Field (2) 'Slot' - hh.PutUint64(uint64(b.Slot)) + hh.PutBytes(b.RandaoReveal) - // Field (3) 'Fork' - if err = b.Fork.HashTreeRootWith(hh); err != nil { + // Field (1) 'Eth1Data' + if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { return } - // Field (4) 'LatestBlockHeader' - if err = b.LatestBlockHeader.HashTreeRootWith(hh); err != nil { - return + // Field (2) 'Graffiti' + if size := len(b.Graffiti); size != 32 { + err = ssz.ErrBytesLengthFn("--.Graffiti", size, 32) + return + } + hh.PutBytes(b.Graffiti) + + // Field (3) 'ProposerSlashings' + { + subIndx := hh.Index() + num := uint64(len(b.ProposerSlashings)) + if num > 16 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.ProposerSlashings { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 16) + } + + // Field (4) 'AttesterSlashings' + { + subIndx := hh.Index() + num := uint64(len(b.AttesterSlashings)) + if num > 1 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.AttesterSlashings { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 1) + } + + // Field (5) 'Attestations' + { + subIndx := hh.Index() + num := uint64(len(b.Attestations)) + if num > 8 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.Attestations { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 8) + } + + // Field (6) 'Deposits' + { + subIndx := hh.Index() + num := uint64(len(b.Deposits)) + if num > 16 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.Deposits { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 16) + } + + // Field (7) 'VoluntaryExits' + { + subIndx := hh.Index() + num := uint64(len(b.VoluntaryExits)) + if num > 16 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.VoluntaryExits { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 16) + } + + // Field (8) 'SyncAggregate' + if err = b.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (9) 'ExecutionPayloadHeader' + if err = b.ExecutionPayloadHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (10) 'BlsToExecutionChanges' + { + subIndx := hh.Index() + num := uint64(len(b.BlsToExecutionChanges)) + if num > 16 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.BlsToExecutionChanges { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 16) + } + + // Field (11) 'BlobKzgCommitments' + { + if size := len(b.BlobKzgCommitments); size > 4096 { + err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range b.BlobKzgCommitments { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(b.BlobKzgCommitments)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + // Field (12) 'ExecutionRequests' + if err = b.ExecutionRequests.HashTreeRootWith(hh); err != nil { + return + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the AttesterSlashingElectra object +func (a *AttesterSlashingElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(a) +} + +// MarshalSSZTo ssz marshals the AttesterSlashingElectra object to a target array +func (a *AttesterSlashingElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(8) + + // Offset (0) 'Attestation_1' + dst = ssz.WriteOffset(dst, offset) + if a.Attestation_1 == nil { + a.Attestation_1 = new(IndexedAttestationElectra) + } + offset += a.Attestation_1.SizeSSZ() + + // Offset (1) 'Attestation_2' + dst = ssz.WriteOffset(dst, offset) + if a.Attestation_2 == nil { + a.Attestation_2 = new(IndexedAttestationElectra) + } + offset += a.Attestation_2.SizeSSZ() + + // Field (0) 'Attestation_1' + if dst, err = a.Attestation_1.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'Attestation_2' + if dst, err = a.Attestation_2.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the AttesterSlashingElectra object +func (a *AttesterSlashingElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 8 { + return ssz.ErrSize + } + + tail := buf + var o0, o1 uint64 + + // Offset (0) 'Attestation_1' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 8 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (1) 'Attestation_2' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Field (0) 'Attestation_1' + { + buf = tail[o0:o1] + if a.Attestation_1 == nil { + a.Attestation_1 = new(IndexedAttestationElectra) + } + if err = a.Attestation_1.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (1) 'Attestation_2' + { + buf = tail[o1:] + if a.Attestation_2 == nil { + a.Attestation_2 = new(IndexedAttestationElectra) + } + if err = a.Attestation_2.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the AttesterSlashingElectra object +func (a *AttesterSlashingElectra) SizeSSZ() (size int) { + size = 8 + + // Field (0) 'Attestation_1' + if a.Attestation_1 == nil { + a.Attestation_1 = new(IndexedAttestationElectra) + } + size += a.Attestation_1.SizeSSZ() + + // Field (1) 'Attestation_2' + if a.Attestation_2 == nil { + a.Attestation_2 = new(IndexedAttestationElectra) + } + size += a.Attestation_2.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the AttesterSlashingElectra object +func (a *AttesterSlashingElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(a) +} + +// HashTreeRootWith ssz hashes the AttesterSlashingElectra object with a hasher +func (a *AttesterSlashingElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Attestation_1' + if err = a.Attestation_1.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Attestation_2' + if err = a.Attestation_2.HashTreeRootWith(hh); err != nil { + return + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the IndexedAttestationElectra object +func (i *IndexedAttestationElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(i) +} + +// MarshalSSZTo ssz marshals the IndexedAttestationElectra object to a target array +func (i *IndexedAttestationElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(228) + + // Offset (0) 'AttestingIndices' + dst = ssz.WriteOffset(dst, offset) + offset += len(i.AttestingIndices) * 8 + + // Field (1) 'Data' + if i.Data == nil { + i.Data = new(AttestationData) + } + if dst, err = i.Data.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'Signature' + if size := len(i.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, i.Signature...) + + // Field (0) 'AttestingIndices' + if size := len(i.AttestingIndices); size > 131072 { + err = ssz.ErrListTooBigFn("--.AttestingIndices", size, 131072) + return + } + for ii := 0; ii < len(i.AttestingIndices); ii++ { + dst = ssz.MarshalUint64(dst, i.AttestingIndices[ii]) + } + + return +} + +// UnmarshalSSZ ssz unmarshals the IndexedAttestationElectra object +func (i *IndexedAttestationElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 228 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'AttestingIndices' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 228 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'Data' + if i.Data == nil { + i.Data = new(AttestationData) + } + if err = i.Data.UnmarshalSSZ(buf[4:132]); err != nil { + return err + } + + // Field (2) 'Signature' + if cap(i.Signature) == 0 { + i.Signature = make([]byte, 0, len(buf[132:228])) + } + i.Signature = append(i.Signature, buf[132:228]...) + + // Field (0) 'AttestingIndices' + { + buf = tail[o0:] + num, err := ssz.DivideInt2(len(buf), 8, 131072) + if err != nil { + return err + } + i.AttestingIndices = ssz.ExtendUint64(i.AttestingIndices, num) + for ii := 0; ii < num; ii++ { + i.AttestingIndices[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the IndexedAttestationElectra object +func (i *IndexedAttestationElectra) SizeSSZ() (size int) { + size = 228 + + // Field (0) 'AttestingIndices' + size += len(i.AttestingIndices) * 8 + + return +} + +// HashTreeRoot ssz hashes the IndexedAttestationElectra object +func (i *IndexedAttestationElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(i) +} + +// HashTreeRootWith ssz hashes the IndexedAttestationElectra object with a hasher +func (i *IndexedAttestationElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestingIndices' + { + if size := len(i.AttestingIndices); size > 131072 { + err = ssz.ErrListTooBigFn("--.AttestingIndices", size, 131072) + return + } + subIndx := hh.Index() + for _, i := range i.AttestingIndices { + hh.AppendUint64(i) + } + hh.FillUpTo32() + + numItems := uint64(len(i.AttestingIndices)) + hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(131072, numItems, 8)) + } + + // Field (1) 'Data' + if err = i.Data.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'Signature' + if size := len(i.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(i.Signature) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the BeaconStateElectra object +func (b *BeaconStateElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BeaconStateElectra object to a target array +func (b *BeaconStateElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(2736713) + + // Field (0) 'GenesisTime' + dst = ssz.MarshalUint64(dst, b.GenesisTime) + + // Field (1) 'GenesisValidatorsRoot' + if size := len(b.GenesisValidatorsRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.GenesisValidatorsRoot", size, 32) + return + } + dst = append(dst, b.GenesisValidatorsRoot...) + + // Field (2) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(b.Slot)) + + // Field (3) 'Fork' + if b.Fork == nil { + b.Fork = new(Fork) + } + if dst, err = b.Fork.MarshalSSZTo(dst); err != nil { + return + } + + // Field (4) 'LatestBlockHeader' + if b.LatestBlockHeader == nil { + b.LatestBlockHeader = new(BeaconBlockHeader) + } + if dst, err = b.LatestBlockHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (5) 'BlockRoots' + if size := len(b.BlockRoots); size != 8192 { + err = ssz.ErrVectorLengthFn("--.BlockRoots", size, 8192) + return + } + for ii := 0; ii < 8192; ii++ { + if size := len(b.BlockRoots[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockRoots[ii]", size, 32) + return + } + dst = append(dst, b.BlockRoots[ii]...) + } + + // Field (6) 'StateRoots' + if size := len(b.StateRoots); size != 8192 { + err = ssz.ErrVectorLengthFn("--.StateRoots", size, 8192) + return + } + for ii := 0; ii < 8192; ii++ { + if size := len(b.StateRoots[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.StateRoots[ii]", size, 32) + return + } + dst = append(dst, b.StateRoots[ii]...) + } + + // Offset (7) 'HistoricalRoots' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.HistoricalRoots) * 32 + + // Field (8) 'Eth1Data' + if b.Eth1Data == nil { + b.Eth1Data = new(Eth1Data) + } + if dst, err = b.Eth1Data.MarshalSSZTo(dst); err != nil { + return + } + + // Offset (9) 'Eth1DataVotes' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Eth1DataVotes) * 72 + + // Field (10) 'Eth1DepositIndex' + dst = ssz.MarshalUint64(dst, b.Eth1DepositIndex) + + // Offset (11) 'Validators' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Validators) * 121 + + // Offset (12) 'Balances' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Balances) * 8 + + // Field (13) 'RandaoMixes' + if size := len(b.RandaoMixes); size != 65536 { + err = ssz.ErrVectorLengthFn("--.RandaoMixes", size, 65536) + return + } + for ii := 0; ii < 65536; ii++ { + if size := len(b.RandaoMixes[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.RandaoMixes[ii]", size, 32) + return + } + dst = append(dst, b.RandaoMixes[ii]...) + } + + // Field (14) 'Slashings' + if size := len(b.Slashings); size != 8192 { + err = ssz.ErrVectorLengthFn("--.Slashings", size, 8192) + return + } + for ii := 0; ii < 8192; ii++ { + dst = ssz.MarshalUint64(dst, b.Slashings[ii]) + } + + // Offset (15) 'PreviousEpochParticipation' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.PreviousEpochParticipation) + + // Offset (16) 'CurrentEpochParticipation' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.CurrentEpochParticipation) + + // Field (17) 'JustificationBits' + if size := len(b.JustificationBits); size != 1 { + err = ssz.ErrBytesLengthFn("--.JustificationBits", size, 1) + return + } + dst = append(dst, b.JustificationBits...) + + // Field (18) 'PreviousJustifiedCheckpoint' + if b.PreviousJustifiedCheckpoint == nil { + b.PreviousJustifiedCheckpoint = new(Checkpoint) + } + if dst, err = b.PreviousJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { + return + } + + // Field (19) 'CurrentJustifiedCheckpoint' + if b.CurrentJustifiedCheckpoint == nil { + b.CurrentJustifiedCheckpoint = new(Checkpoint) + } + if dst, err = b.CurrentJustifiedCheckpoint.MarshalSSZTo(dst); err != nil { + return + } + + // Field (20) 'FinalizedCheckpoint' + if b.FinalizedCheckpoint == nil { + b.FinalizedCheckpoint = new(Checkpoint) + } + if dst, err = b.FinalizedCheckpoint.MarshalSSZTo(dst); err != nil { + return + } + + // Offset (21) 'InactivityScores' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.InactivityScores) * 8 + + // Field (22) 'CurrentSyncCommittee' + if b.CurrentSyncCommittee == nil { + b.CurrentSyncCommittee = new(SyncCommittee) + } + if dst, err = b.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Field (23) 'NextSyncCommittee' + if b.NextSyncCommittee == nil { + b.NextSyncCommittee = new(SyncCommittee) + } + if dst, err = b.NextSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Offset (24) 'LatestExecutionPayloadHeader' + dst = ssz.WriteOffset(dst, offset) + if b.LatestExecutionPayloadHeader == nil { + b.LatestExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderDeneb) + } + offset += b.LatestExecutionPayloadHeader.SizeSSZ() + + // Field (25) 'NextWithdrawalIndex' + dst = ssz.MarshalUint64(dst, b.NextWithdrawalIndex) + + // Field (26) 'NextWithdrawalValidatorIndex' + dst = ssz.MarshalUint64(dst, uint64(b.NextWithdrawalValidatorIndex)) + + // Offset (27) 'HistoricalSummaries' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.HistoricalSummaries) * 64 + + // Field (28) 'DepositRequestsStartIndex' + dst = ssz.MarshalUint64(dst, b.DepositRequestsStartIndex) + + // Field (29) 'DepositBalanceToConsume' + dst = ssz.MarshalUint64(dst, uint64(b.DepositBalanceToConsume)) + + // Field (30) 'ExitBalanceToConsume' + dst = ssz.MarshalUint64(dst, uint64(b.ExitBalanceToConsume)) + + // Field (31) 'EarliestExitEpoch' + dst = ssz.MarshalUint64(dst, uint64(b.EarliestExitEpoch)) + + // Field (32) 'ConsolidationBalanceToConsume' + dst = ssz.MarshalUint64(dst, uint64(b.ConsolidationBalanceToConsume)) + + // Field (33) 'EarliestConsolidationEpoch' + dst = ssz.MarshalUint64(dst, uint64(b.EarliestConsolidationEpoch)) + + // Offset (34) 'PendingDeposits' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.PendingDeposits) * 192 + + // Offset (35) 'PendingPartialWithdrawals' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.PendingPartialWithdrawals) * 24 + + // Offset (36) 'PendingConsolidations' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.PendingConsolidations) * 16 + + // Field (7) 'HistoricalRoots' + if size := len(b.HistoricalRoots); size > 16777216 { + err = ssz.ErrListTooBigFn("--.HistoricalRoots", size, 16777216) + return + } + for ii := 0; ii < len(b.HistoricalRoots); ii++ { + if size := len(b.HistoricalRoots[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.HistoricalRoots[ii]", size, 32) + return + } + dst = append(dst, b.HistoricalRoots[ii]...) + } + + // Field (9) 'Eth1DataVotes' + if size := len(b.Eth1DataVotes); size > 2048 { + err = ssz.ErrListTooBigFn("--.Eth1DataVotes", size, 2048) + return + } + for ii := 0; ii < len(b.Eth1DataVotes); ii++ { + if dst, err = b.Eth1DataVotes[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (11) 'Validators' + if size := len(b.Validators); size > 1099511627776 { + err = ssz.ErrListTooBigFn("--.Validators", size, 1099511627776) + return + } + for ii := 0; ii < len(b.Validators); ii++ { + if dst, err = b.Validators[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (12) 'Balances' + if size := len(b.Balances); size > 1099511627776 { + err = ssz.ErrListTooBigFn("--.Balances", size, 1099511627776) + return + } + for ii := 0; ii < len(b.Balances); ii++ { + dst = ssz.MarshalUint64(dst, b.Balances[ii]) + } + + // Field (15) 'PreviousEpochParticipation' + if size := len(b.PreviousEpochParticipation); size > 1099511627776 { + err = ssz.ErrBytesLengthFn("--.PreviousEpochParticipation", size, 1099511627776) + return + } + dst = append(dst, b.PreviousEpochParticipation...) + + // Field (16) 'CurrentEpochParticipation' + if size := len(b.CurrentEpochParticipation); size > 1099511627776 { + err = ssz.ErrBytesLengthFn("--.CurrentEpochParticipation", size, 1099511627776) + return + } + dst = append(dst, b.CurrentEpochParticipation...) + + // Field (21) 'InactivityScores' + if size := len(b.InactivityScores); size > 1099511627776 { + err = ssz.ErrListTooBigFn("--.InactivityScores", size, 1099511627776) + return + } + for ii := 0; ii < len(b.InactivityScores); ii++ { + dst = ssz.MarshalUint64(dst, b.InactivityScores[ii]) + } + + // Field (24) 'LatestExecutionPayloadHeader' + if dst, err = b.LatestExecutionPayloadHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (27) 'HistoricalSummaries' + if size := len(b.HistoricalSummaries); size > 16777216 { + err = ssz.ErrListTooBigFn("--.HistoricalSummaries", size, 16777216) + return + } + for ii := 0; ii < len(b.HistoricalSummaries); ii++ { + if dst, err = b.HistoricalSummaries[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (34) 'PendingDeposits' + if size := len(b.PendingDeposits); size > 134217728 { + err = ssz.ErrListTooBigFn("--.PendingDeposits", size, 134217728) + return + } + for ii := 0; ii < len(b.PendingDeposits); ii++ { + if dst, err = b.PendingDeposits[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (35) 'PendingPartialWithdrawals' + if size := len(b.PendingPartialWithdrawals); size > 134217728 { + err = ssz.ErrListTooBigFn("--.PendingPartialWithdrawals", size, 134217728) + return + } + for ii := 0; ii < len(b.PendingPartialWithdrawals); ii++ { + if dst, err = b.PendingPartialWithdrawals[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (36) 'PendingConsolidations' + if size := len(b.PendingConsolidations); size > 262144 { + err = ssz.ErrListTooBigFn("--.PendingConsolidations", size, 262144) + return + } + for ii := 0; ii < len(b.PendingConsolidations); ii++ { + if dst, err = b.PendingConsolidations[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + return +} + +// UnmarshalSSZ ssz unmarshals the BeaconStateElectra object +func (b *BeaconStateElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 2736713 { + return ssz.ErrSize + } + + tail := buf + var o7, o9, o11, o12, o15, o16, o21, o24, o27, o34, o35, o36 uint64 + + // Field (0) 'GenesisTime' + b.GenesisTime = ssz.UnmarshallUint64(buf[0:8]) + + // Field (1) 'GenesisValidatorsRoot' + if cap(b.GenesisValidatorsRoot) == 0 { + b.GenesisValidatorsRoot = make([]byte, 0, len(buf[8:40])) + } + b.GenesisValidatorsRoot = append(b.GenesisValidatorsRoot, buf[8:40]...) + + // Field (2) 'Slot' + b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[40:48])) + + // Field (3) 'Fork' + if b.Fork == nil { + b.Fork = new(Fork) + } + if err = b.Fork.UnmarshalSSZ(buf[48:64]); err != nil { + return err + } + + // Field (4) 'LatestBlockHeader' + if b.LatestBlockHeader == nil { + b.LatestBlockHeader = new(BeaconBlockHeader) + } + if err = b.LatestBlockHeader.UnmarshalSSZ(buf[64:176]); err != nil { + return err + } + + // Field (5) 'BlockRoots' + b.BlockRoots = make([][]byte, 8192) + for ii := 0; ii < 8192; ii++ { + if cap(b.BlockRoots[ii]) == 0 { + b.BlockRoots[ii] = make([]byte, 0, len(buf[176:262320][ii*32:(ii+1)*32])) + } + b.BlockRoots[ii] = append(b.BlockRoots[ii], buf[176:262320][ii*32:(ii+1)*32]...) + } + + // Field (6) 'StateRoots' + b.StateRoots = make([][]byte, 8192) + for ii := 0; ii < 8192; ii++ { + if cap(b.StateRoots[ii]) == 0 { + b.StateRoots[ii] = make([]byte, 0, len(buf[262320:524464][ii*32:(ii+1)*32])) + } + b.StateRoots[ii] = append(b.StateRoots[ii], buf[262320:524464][ii*32:(ii+1)*32]...) + } + + // Offset (7) 'HistoricalRoots' + if o7 = ssz.ReadOffset(buf[524464:524468]); o7 > size { + return ssz.ErrOffset + } + + if o7 != 2736713 { + return ssz.ErrInvalidVariableOffset + } + + // Field (8) 'Eth1Data' + if b.Eth1Data == nil { + b.Eth1Data = new(Eth1Data) + } + if err = b.Eth1Data.UnmarshalSSZ(buf[524468:524540]); err != nil { + return err + } + + // Offset (9) 'Eth1DataVotes' + if o9 = ssz.ReadOffset(buf[524540:524544]); o9 > size || o7 > o9 { + return ssz.ErrOffset + } + + // Field (10) 'Eth1DepositIndex' + b.Eth1DepositIndex = ssz.UnmarshallUint64(buf[524544:524552]) + + // Offset (11) 'Validators' + if o11 = ssz.ReadOffset(buf[524552:524556]); o11 > size || o9 > o11 { + return ssz.ErrOffset + } + + // Offset (12) 'Balances' + if o12 = ssz.ReadOffset(buf[524556:524560]); o12 > size || o11 > o12 { + return ssz.ErrOffset + } + + // Field (13) 'RandaoMixes' + b.RandaoMixes = make([][]byte, 65536) + for ii := 0; ii < 65536; ii++ { + if cap(b.RandaoMixes[ii]) == 0 { + b.RandaoMixes[ii] = make([]byte, 0, len(buf[524560:2621712][ii*32:(ii+1)*32])) + } + b.RandaoMixes[ii] = append(b.RandaoMixes[ii], buf[524560:2621712][ii*32:(ii+1)*32]...) + } + + // Field (14) 'Slashings' + b.Slashings = ssz.ExtendUint64(b.Slashings, 8192) + for ii := 0; ii < 8192; ii++ { + b.Slashings[ii] = ssz.UnmarshallUint64(buf[2621712:2687248][ii*8 : (ii+1)*8]) + } + + // Offset (15) 'PreviousEpochParticipation' + if o15 = ssz.ReadOffset(buf[2687248:2687252]); o15 > size || o12 > o15 { + return ssz.ErrOffset + } + + // Offset (16) 'CurrentEpochParticipation' + if o16 = ssz.ReadOffset(buf[2687252:2687256]); o16 > size || o15 > o16 { + return ssz.ErrOffset + } + + // Field (17) 'JustificationBits' + if cap(b.JustificationBits) == 0 { + b.JustificationBits = make([]byte, 0, len(buf[2687256:2687257])) + } + b.JustificationBits = append(b.JustificationBits, buf[2687256:2687257]...) + + // Field (18) 'PreviousJustifiedCheckpoint' + if b.PreviousJustifiedCheckpoint == nil { + b.PreviousJustifiedCheckpoint = new(Checkpoint) + } + if err = b.PreviousJustifiedCheckpoint.UnmarshalSSZ(buf[2687257:2687297]); err != nil { + return err + } + + // Field (19) 'CurrentJustifiedCheckpoint' + if b.CurrentJustifiedCheckpoint == nil { + b.CurrentJustifiedCheckpoint = new(Checkpoint) + } + if err = b.CurrentJustifiedCheckpoint.UnmarshalSSZ(buf[2687297:2687337]); err != nil { + return err + } + + // Field (20) 'FinalizedCheckpoint' + if b.FinalizedCheckpoint == nil { + b.FinalizedCheckpoint = new(Checkpoint) + } + if err = b.FinalizedCheckpoint.UnmarshalSSZ(buf[2687337:2687377]); err != nil { + return err + } + + // Offset (21) 'InactivityScores' + if o21 = ssz.ReadOffset(buf[2687377:2687381]); o21 > size || o16 > o21 { + return ssz.ErrOffset + } + + // Field (22) 'CurrentSyncCommittee' + if b.CurrentSyncCommittee == nil { + b.CurrentSyncCommittee = new(SyncCommittee) + } + if err = b.CurrentSyncCommittee.UnmarshalSSZ(buf[2687381:2712005]); err != nil { + return err + } + + // Field (23) 'NextSyncCommittee' + if b.NextSyncCommittee == nil { + b.NextSyncCommittee = new(SyncCommittee) + } + if err = b.NextSyncCommittee.UnmarshalSSZ(buf[2712005:2736629]); err != nil { + return err + } + + // Offset (24) 'LatestExecutionPayloadHeader' + if o24 = ssz.ReadOffset(buf[2736629:2736633]); o24 > size || o21 > o24 { + return ssz.ErrOffset + } + + // Field (25) 'NextWithdrawalIndex' + b.NextWithdrawalIndex = ssz.UnmarshallUint64(buf[2736633:2736641]) + + // Field (26) 'NextWithdrawalValidatorIndex' + b.NextWithdrawalValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[2736641:2736649])) + + // Offset (27) 'HistoricalSummaries' + if o27 = ssz.ReadOffset(buf[2736649:2736653]); o27 > size || o24 > o27 { + return ssz.ErrOffset + } + + // Field (28) 'DepositRequestsStartIndex' + b.DepositRequestsStartIndex = ssz.UnmarshallUint64(buf[2736653:2736661]) + + // Field (29) 'DepositBalanceToConsume' + b.DepositBalanceToConsume = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736661:2736669])) + + // Field (30) 'ExitBalanceToConsume' + b.ExitBalanceToConsume = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736669:2736677])) + + // Field (31) 'EarliestExitEpoch' + b.EarliestExitEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736677:2736685])) + + // Field (32) 'ConsolidationBalanceToConsume' + b.ConsolidationBalanceToConsume = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736685:2736693])) + + // Field (33) 'EarliestConsolidationEpoch' + b.EarliestConsolidationEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736693:2736701])) + + // Offset (34) 'PendingDeposits' + if o34 = ssz.ReadOffset(buf[2736701:2736705]); o34 > size || o27 > o34 { + return ssz.ErrOffset + } + + // Offset (35) 'PendingPartialWithdrawals' + if o35 = ssz.ReadOffset(buf[2736705:2736709]); o35 > size || o34 > o35 { + return ssz.ErrOffset + } + + // Offset (36) 'PendingConsolidations' + if o36 = ssz.ReadOffset(buf[2736709:2736713]); o36 > size || o35 > o36 { + return ssz.ErrOffset + } + + // Field (7) 'HistoricalRoots' + { + buf = tail[o7:o9] + num, err := ssz.DivideInt2(len(buf), 32, 16777216) + if err != nil { + return err + } + b.HistoricalRoots = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(b.HistoricalRoots[ii]) == 0 { + b.HistoricalRoots[ii] = make([]byte, 0, len(buf[ii*32:(ii+1)*32])) + } + b.HistoricalRoots[ii] = append(b.HistoricalRoots[ii], buf[ii*32:(ii+1)*32]...) + } + } + + // Field (9) 'Eth1DataVotes' + { + buf = tail[o9:o11] + num, err := ssz.DivideInt2(len(buf), 72, 2048) + if err != nil { + return err + } + b.Eth1DataVotes = make([]*Eth1Data, num) + for ii := 0; ii < num; ii++ { + if b.Eth1DataVotes[ii] == nil { + b.Eth1DataVotes[ii] = new(Eth1Data) + } + if err = b.Eth1DataVotes[ii].UnmarshalSSZ(buf[ii*72 : (ii+1)*72]); err != nil { + return err + } + } + } + + // Field (11) 'Validators' + { + buf = tail[o11:o12] + num, err := ssz.DivideInt2(len(buf), 121, 1099511627776) + if err != nil { + return err + } + b.Validators = make([]*Validator, num) + for ii := 0; ii < num; ii++ { + if b.Validators[ii] == nil { + b.Validators[ii] = new(Validator) + } + if err = b.Validators[ii].UnmarshalSSZ(buf[ii*121 : (ii+1)*121]); err != nil { + return err + } + } + } + + // Field (12) 'Balances' + { + buf = tail[o12:o15] + num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) + if err != nil { + return err + } + b.Balances = ssz.ExtendUint64(b.Balances, num) + for ii := 0; ii < num; ii++ { + b.Balances[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) + } + } + + // Field (15) 'PreviousEpochParticipation' + { + buf = tail[o15:o16] + if len(buf) > 1099511627776 { + return ssz.ErrBytesLength + } + if cap(b.PreviousEpochParticipation) == 0 { + b.PreviousEpochParticipation = make([]byte, 0, len(buf)) + } + b.PreviousEpochParticipation = append(b.PreviousEpochParticipation, buf...) + } + + // Field (16) 'CurrentEpochParticipation' + { + buf = tail[o16:o21] + if len(buf) > 1099511627776 { + return ssz.ErrBytesLength + } + if cap(b.CurrentEpochParticipation) == 0 { + b.CurrentEpochParticipation = make([]byte, 0, len(buf)) + } + b.CurrentEpochParticipation = append(b.CurrentEpochParticipation, buf...) + } + + // Field (21) 'InactivityScores' + { + buf = tail[o21:o24] + num, err := ssz.DivideInt2(len(buf), 8, 1099511627776) + if err != nil { + return err + } + b.InactivityScores = ssz.ExtendUint64(b.InactivityScores, num) + for ii := 0; ii < num; ii++ { + b.InactivityScores[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) + } + } + + // Field (24) 'LatestExecutionPayloadHeader' + { + buf = tail[o24:o27] + if b.LatestExecutionPayloadHeader == nil { + b.LatestExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderDeneb) + } + if err = b.LatestExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (27) 'HistoricalSummaries' + { + buf = tail[o27:o34] + num, err := ssz.DivideInt2(len(buf), 64, 16777216) + if err != nil { + return err + } + b.HistoricalSummaries = make([]*HistoricalSummary, num) + for ii := 0; ii < num; ii++ { + if b.HistoricalSummaries[ii] == nil { + b.HistoricalSummaries[ii] = new(HistoricalSummary) + } + if err = b.HistoricalSummaries[ii].UnmarshalSSZ(buf[ii*64 : (ii+1)*64]); err != nil { + return err + } + } + } + + // Field (34) 'PendingDeposits' + { + buf = tail[o34:o35] + num, err := ssz.DivideInt2(len(buf), 192, 134217728) + if err != nil { + return err + } + b.PendingDeposits = make([]*PendingDeposit, num) + for ii := 0; ii < num; ii++ { + if b.PendingDeposits[ii] == nil { + b.PendingDeposits[ii] = new(PendingDeposit) + } + if err = b.PendingDeposits[ii].UnmarshalSSZ(buf[ii*192 : (ii+1)*192]); err != nil { + return err + } + } + } + + // Field (35) 'PendingPartialWithdrawals' + { + buf = tail[o35:o36] + num, err := ssz.DivideInt2(len(buf), 24, 134217728) + if err != nil { + return err + } + b.PendingPartialWithdrawals = make([]*PendingPartialWithdrawal, num) + for ii := 0; ii < num; ii++ { + if b.PendingPartialWithdrawals[ii] == nil { + b.PendingPartialWithdrawals[ii] = new(PendingPartialWithdrawal) + } + if err = b.PendingPartialWithdrawals[ii].UnmarshalSSZ(buf[ii*24 : (ii+1)*24]); err != nil { + return err + } + } + } + + // Field (36) 'PendingConsolidations' + { + buf = tail[o36:] + num, err := ssz.DivideInt2(len(buf), 16, 262144) + if err != nil { + return err + } + b.PendingConsolidations = make([]*PendingConsolidation, num) + for ii := 0; ii < num; ii++ { + if b.PendingConsolidations[ii] == nil { + b.PendingConsolidations[ii] = new(PendingConsolidation) + } + if err = b.PendingConsolidations[ii].UnmarshalSSZ(buf[ii*16 : (ii+1)*16]); err != nil { + return err + } + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the BeaconStateElectra object +func (b *BeaconStateElectra) SizeSSZ() (size int) { + size = 2736713 + + // Field (7) 'HistoricalRoots' + size += len(b.HistoricalRoots) * 32 + + // Field (9) 'Eth1DataVotes' + size += len(b.Eth1DataVotes) * 72 + + // Field (11) 'Validators' + size += len(b.Validators) * 121 + + // Field (12) 'Balances' + size += len(b.Balances) * 8 + + // Field (15) 'PreviousEpochParticipation' + size += len(b.PreviousEpochParticipation) + + // Field (16) 'CurrentEpochParticipation' + size += len(b.CurrentEpochParticipation) + + // Field (21) 'InactivityScores' + size += len(b.InactivityScores) * 8 + + // Field (24) 'LatestExecutionPayloadHeader' + if b.LatestExecutionPayloadHeader == nil { + b.LatestExecutionPayloadHeader = new(v1.ExecutionPayloadHeaderDeneb) + } + size += b.LatestExecutionPayloadHeader.SizeSSZ() + + // Field (27) 'HistoricalSummaries' + size += len(b.HistoricalSummaries) * 64 + + // Field (34) 'PendingDeposits' + size += len(b.PendingDeposits) * 192 + + // Field (35) 'PendingPartialWithdrawals' + size += len(b.PendingPartialWithdrawals) * 24 + + // Field (36) 'PendingConsolidations' + size += len(b.PendingConsolidations) * 16 + + return +} + +// HashTreeRoot ssz hashes the BeaconStateElectra object +func (b *BeaconStateElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) +} + +// HashTreeRootWith ssz hashes the BeaconStateElectra object with a hasher +func (b *BeaconStateElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'GenesisTime' + hh.PutUint64(b.GenesisTime) + + // Field (1) 'GenesisValidatorsRoot' + if size := len(b.GenesisValidatorsRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.GenesisValidatorsRoot", size, 32) + return + } + hh.PutBytes(b.GenesisValidatorsRoot) + + // Field (2) 'Slot' + hh.PutUint64(uint64(b.Slot)) + + // Field (3) 'Fork' + if err = b.Fork.HashTreeRootWith(hh); err != nil { + return + } + + // Field (4) 'LatestBlockHeader' + if err = b.LatestBlockHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (5) 'BlockRoots' + { + if size := len(b.BlockRoots); size != 8192 { + err = ssz.ErrVectorLengthFn("--.BlockRoots", size, 8192) + return + } + subIndx := hh.Index() + for _, i := range b.BlockRoots { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (6) 'StateRoots' + { + if size := len(b.StateRoots); size != 8192 { + err = ssz.ErrVectorLengthFn("--.StateRoots", size, 8192) + return + } + subIndx := hh.Index() + for _, i := range b.StateRoots { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (7) 'HistoricalRoots' + { + if size := len(b.HistoricalRoots); size > 16777216 { + err = ssz.ErrListTooBigFn("--.HistoricalRoots", size, 16777216) + return + } + subIndx := hh.Index() + for _, i := range b.HistoricalRoots { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + + numItems := uint64(len(b.HistoricalRoots)) + hh.MerkleizeWithMixin(subIndx, numItems, 16777216) + } + + // Field (8) 'Eth1Data' + if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { + return + } + + // Field (9) 'Eth1DataVotes' + { + subIndx := hh.Index() + num := uint64(len(b.Eth1DataVotes)) + if num > 2048 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.Eth1DataVotes { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 2048) + } + + // Field (10) 'Eth1DepositIndex' + hh.PutUint64(b.Eth1DepositIndex) + + // Field (11) 'Validators' + { + subIndx := hh.Index() + num := uint64(len(b.Validators)) + if num > 1099511627776 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.Validators { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 1099511627776) + } + + // Field (12) 'Balances' + { + if size := len(b.Balances); size > 1099511627776 { + err = ssz.ErrListTooBigFn("--.Balances", size, 1099511627776) + return + } + subIndx := hh.Index() + for _, i := range b.Balances { + hh.AppendUint64(i) + } + hh.FillUpTo32() + + numItems := uint64(len(b.Balances)) + hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(1099511627776, numItems, 8)) + } + + // Field (13) 'RandaoMixes' + { + if size := len(b.RandaoMixes); size != 65536 { + err = ssz.ErrVectorLengthFn("--.RandaoMixes", size, 65536) + return + } + subIndx := hh.Index() + for _, i := range b.RandaoMixes { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (14) 'Slashings' + { + if size := len(b.Slashings); size != 8192 { + err = ssz.ErrVectorLengthFn("--.Slashings", size, 8192) + return + } + subIndx := hh.Index() + for _, i := range b.Slashings { + hh.AppendUint64(i) + } + hh.Merkleize(subIndx) + } + + // Field (15) 'PreviousEpochParticipation' + { + elemIndx := hh.Index() + byteLen := uint64(len(b.PreviousEpochParticipation)) + if byteLen > 1099511627776 { + err = ssz.ErrIncorrectListSize + return + } + hh.PutBytes(b.PreviousEpochParticipation) + hh.MerkleizeWithMixin(elemIndx, byteLen, (1099511627776+31)/32) + } + + // Field (16) 'CurrentEpochParticipation' + { + elemIndx := hh.Index() + byteLen := uint64(len(b.CurrentEpochParticipation)) + if byteLen > 1099511627776 { + err = ssz.ErrIncorrectListSize + return + } + hh.PutBytes(b.CurrentEpochParticipation) + hh.MerkleizeWithMixin(elemIndx, byteLen, (1099511627776+31)/32) + } + + // Field (17) 'JustificationBits' + if size := len(b.JustificationBits); size != 1 { + err = ssz.ErrBytesLengthFn("--.JustificationBits", size, 1) + return + } + hh.PutBytes(b.JustificationBits) + + // Field (18) 'PreviousJustifiedCheckpoint' + if err = b.PreviousJustifiedCheckpoint.HashTreeRootWith(hh); err != nil { + return + } + + // Field (19) 'CurrentJustifiedCheckpoint' + if err = b.CurrentJustifiedCheckpoint.HashTreeRootWith(hh); err != nil { + return + } + + // Field (20) 'FinalizedCheckpoint' + if err = b.FinalizedCheckpoint.HashTreeRootWith(hh); err != nil { + return + } + + // Field (21) 'InactivityScores' + { + if size := len(b.InactivityScores); size > 1099511627776 { + err = ssz.ErrListTooBigFn("--.InactivityScores", size, 1099511627776) + return + } + subIndx := hh.Index() + for _, i := range b.InactivityScores { + hh.AppendUint64(i) + } + hh.FillUpTo32() + + numItems := uint64(len(b.InactivityScores)) + hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(1099511627776, numItems, 8)) + } + + // Field (22) 'CurrentSyncCommittee' + if err = b.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } + + // Field (23) 'NextSyncCommittee' + if err = b.NextSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } + + // Field (24) 'LatestExecutionPayloadHeader' + if err = b.LatestExecutionPayloadHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (25) 'NextWithdrawalIndex' + hh.PutUint64(b.NextWithdrawalIndex) + + // Field (26) 'NextWithdrawalValidatorIndex' + hh.PutUint64(uint64(b.NextWithdrawalValidatorIndex)) + + // Field (27) 'HistoricalSummaries' + { + subIndx := hh.Index() + num := uint64(len(b.HistoricalSummaries)) + if num > 16777216 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.HistoricalSummaries { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 16777216) + } + + // Field (28) 'DepositRequestsStartIndex' + hh.PutUint64(b.DepositRequestsStartIndex) + + // Field (29) 'DepositBalanceToConsume' + hh.PutUint64(uint64(b.DepositBalanceToConsume)) + + // Field (30) 'ExitBalanceToConsume' + hh.PutUint64(uint64(b.ExitBalanceToConsume)) + + // Field (31) 'EarliestExitEpoch' + hh.PutUint64(uint64(b.EarliestExitEpoch)) + + // Field (32) 'ConsolidationBalanceToConsume' + hh.PutUint64(uint64(b.ConsolidationBalanceToConsume)) + + // Field (33) 'EarliestConsolidationEpoch' + hh.PutUint64(uint64(b.EarliestConsolidationEpoch)) + + // Field (34) 'PendingDeposits' + { + subIndx := hh.Index() + num := uint64(len(b.PendingDeposits)) + if num > 134217728 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.PendingDeposits { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 134217728) + } + + // Field (35) 'PendingPartialWithdrawals' + { + subIndx := hh.Index() + num := uint64(len(b.PendingPartialWithdrawals)) + if num > 134217728 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.PendingPartialWithdrawals { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 134217728) + } + + // Field (36) 'PendingConsolidations' + { + subIndx := hh.Index() + num := uint64(len(b.PendingConsolidations)) + if num > 262144 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range b.PendingConsolidations { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 262144) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the PendingDeposit object +func (p *PendingDeposit) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(p) +} + +// MarshalSSZTo ssz marshals the PendingDeposit object to a target array +func (p *PendingDeposit) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'PublicKey' + if size := len(p.PublicKey); size != 48 { + err = ssz.ErrBytesLengthFn("--.PublicKey", size, 48) + return + } + dst = append(dst, p.PublicKey...) + + // Field (1) 'WithdrawalCredentials' + if size := len(p.WithdrawalCredentials); size != 32 { + err = ssz.ErrBytesLengthFn("--.WithdrawalCredentials", size, 32) + return + } + dst = append(dst, p.WithdrawalCredentials...) + + // Field (2) 'Amount' + dst = ssz.MarshalUint64(dst, p.Amount) + + // Field (3) 'Signature' + if size := len(p.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, p.Signature...) + + // Field (4) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(p.Slot)) + + return +} + +// UnmarshalSSZ ssz unmarshals the PendingDeposit object +func (p *PendingDeposit) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 192 { + return ssz.ErrSize + } + + // Field (0) 'PublicKey' + if cap(p.PublicKey) == 0 { + p.PublicKey = make([]byte, 0, len(buf[0:48])) + } + p.PublicKey = append(p.PublicKey, buf[0:48]...) + + // Field (1) 'WithdrawalCredentials' + if cap(p.WithdrawalCredentials) == 0 { + p.WithdrawalCredentials = make([]byte, 0, len(buf[48:80])) + } + p.WithdrawalCredentials = append(p.WithdrawalCredentials, buf[48:80]...) + + // Field (2) 'Amount' + p.Amount = ssz.UnmarshallUint64(buf[80:88]) + + // Field (3) 'Signature' + if cap(p.Signature) == 0 { + p.Signature = make([]byte, 0, len(buf[88:184])) + } + p.Signature = append(p.Signature, buf[88:184]...) + + // Field (4) 'Slot' + p.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[184:192])) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the PendingDeposit object +func (p *PendingDeposit) SizeSSZ() (size int) { + size = 192 + return +} + +// HashTreeRoot ssz hashes the PendingDeposit object +func (p *PendingDeposit) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(p) +} + +// HashTreeRootWith ssz hashes the PendingDeposit object with a hasher +func (p *PendingDeposit) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'PublicKey' + if size := len(p.PublicKey); size != 48 { + err = ssz.ErrBytesLengthFn("--.PublicKey", size, 48) + return + } + hh.PutBytes(p.PublicKey) + + // Field (1) 'WithdrawalCredentials' + if size := len(p.WithdrawalCredentials); size != 32 { + err = ssz.ErrBytesLengthFn("--.WithdrawalCredentials", size, 32) + return + } + hh.PutBytes(p.WithdrawalCredentials) + + // Field (2) 'Amount' + hh.PutUint64(p.Amount) + + // Field (3) 'Signature' + if size := len(p.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(p.Signature) + + // Field (4) 'Slot' + hh.PutUint64(uint64(p.Slot)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the PendingPartialWithdrawal object +func (p *PendingPartialWithdrawal) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(p) +} + +// MarshalSSZTo ssz marshals the PendingPartialWithdrawal object to a target array +func (p *PendingPartialWithdrawal) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Index' + dst = ssz.MarshalUint64(dst, uint64(p.Index)) + + // Field (1) 'Amount' + dst = ssz.MarshalUint64(dst, p.Amount) + + // Field (2) 'WithdrawableEpoch' + dst = ssz.MarshalUint64(dst, uint64(p.WithdrawableEpoch)) + + return +} + +// UnmarshalSSZ ssz unmarshals the PendingPartialWithdrawal object +func (p *PendingPartialWithdrawal) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 24 { + return ssz.ErrSize + } + + // Field (0) 'Index' + p.Index = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'Amount' + p.Amount = ssz.UnmarshallUint64(buf[8:16]) + + // Field (2) 'WithdrawableEpoch' + p.WithdrawableEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[16:24])) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the PendingPartialWithdrawal object +func (p *PendingPartialWithdrawal) SizeSSZ() (size int) { + size = 24 + return +} + +// HashTreeRoot ssz hashes the PendingPartialWithdrawal object +func (p *PendingPartialWithdrawal) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(p) +} + +// HashTreeRootWith ssz hashes the PendingPartialWithdrawal object with a hasher +func (p *PendingPartialWithdrawal) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Index' + hh.PutUint64(uint64(p.Index)) + + // Field (1) 'Amount' + hh.PutUint64(p.Amount) + + // Field (2) 'WithdrawableEpoch' + hh.PutUint64(uint64(p.WithdrawableEpoch)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the PendingConsolidation object +func (p *PendingConsolidation) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(p) +} + +// MarshalSSZTo ssz marshals the PendingConsolidation object to a target array +func (p *PendingConsolidation) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'SourceIndex' + dst = ssz.MarshalUint64(dst, uint64(p.SourceIndex)) + + // Field (1) 'TargetIndex' + dst = ssz.MarshalUint64(dst, uint64(p.TargetIndex)) + + return +} + +// UnmarshalSSZ ssz unmarshals the PendingConsolidation object +func (p *PendingConsolidation) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 16 { + return ssz.ErrSize + } + + // Field (0) 'SourceIndex' + p.SourceIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'TargetIndex' + p.TargetIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the PendingConsolidation object +func (p *PendingConsolidation) SizeSSZ() (size int) { + size = 16 + return +} + +// HashTreeRoot ssz hashes the PendingConsolidation object +func (p *PendingConsolidation) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(p) +} + +// HashTreeRootWith ssz hashes the PendingConsolidation object with a hasher +func (p *PendingConsolidation) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'SourceIndex' + hh.PutUint64(uint64(p.SourceIndex)) + + // Field (1) 'TargetIndex' + hh.PutUint64(uint64(p.TargetIndex)) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientBootstrapElectra object +func (l *LightClientBootstrapElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientBootstrapElectra object to a target array +func (l *LightClientBootstrapElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(24820) + + // Offset (0) 'Header' + dst = ssz.WriteOffset(dst, offset) + if l.Header == nil { + l.Header = new(LightClientHeaderDeneb) + } + offset += l.Header.SizeSSZ() + + // Field (1) 'CurrentSyncCommittee' + if l.CurrentSyncCommittee == nil { + l.CurrentSyncCommittee = new(SyncCommittee) + } + if dst, err = l.CurrentSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'CurrentSyncCommitteeBranch' + if size := len(l.CurrentSyncCommitteeBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 6) + return + } + for ii := 0; ii < 6; ii++ { + if size := len(l.CurrentSyncCommitteeBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.CurrentSyncCommitteeBranch[ii]", size, 32) + return + } + dst = append(dst, l.CurrentSyncCommitteeBranch[ii]...) + } + + // Field (0) 'Header' + if dst, err = l.Header.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientBootstrapElectra object +func (l *LightClientBootstrapElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 24820 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Header' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 24820 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'CurrentSyncCommittee' + if l.CurrentSyncCommittee == nil { + l.CurrentSyncCommittee = new(SyncCommittee) + } + if err = l.CurrentSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil { + return err } - // Field (5) 'BlockRoots' - { - if size := len(b.BlockRoots); size != 8192 { - err = ssz.ErrVectorLengthFn("--.BlockRoots", size, 8192) - return - } - subIndx := hh.Index() - for _, i := range b.BlockRoots { - if len(i) != 32 { - err = ssz.ErrBytesLength - return - } - hh.Append(i) + // Field (2) 'CurrentSyncCommitteeBranch' + l.CurrentSyncCommitteeBranch = make([][]byte, 6) + for ii := 0; ii < 6; ii++ { + if cap(l.CurrentSyncCommitteeBranch[ii]) == 0 { + l.CurrentSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24820][ii*32:(ii+1)*32])) } - hh.Merkleize(subIndx) + l.CurrentSyncCommitteeBranch[ii] = append(l.CurrentSyncCommitteeBranch[ii], buf[24628:24820][ii*32:(ii+1)*32]...) } - // Field (6) 'StateRoots' + // Field (0) 'Header' { - if size := len(b.StateRoots); size != 8192 { - err = ssz.ErrVectorLengthFn("--.StateRoots", size, 8192) - return + buf = tail[o0:] + if l.Header == nil { + l.Header = new(LightClientHeaderDeneb) } - subIndx := hh.Index() - for _, i := range b.StateRoots { - if len(i) != 32 { - err = ssz.ErrBytesLength - return - } - hh.Append(i) + if err = l.Header.UnmarshalSSZ(buf); err != nil { + return err } - hh.Merkleize(subIndx) } + return err +} - // Field (7) 'HistoricalRoots' - { - if size := len(b.HistoricalRoots); size > 16777216 { - err = ssz.ErrListTooBigFn("--.HistoricalRoots", size, 16777216) - return - } - subIndx := hh.Index() - for _, i := range b.HistoricalRoots { - if len(i) != 32 { - err = ssz.ErrBytesLength - return - } - hh.Append(i) - } +// SizeSSZ returns the ssz encoded size in bytes for the LightClientBootstrapElectra object +func (l *LightClientBootstrapElectra) SizeSSZ() (size int) { + size = 24820 - numItems := uint64(len(b.HistoricalRoots)) - hh.MerkleizeWithMixin(subIndx, numItems, 16777216) + // Field (0) 'Header' + if l.Header == nil { + l.Header = new(LightClientHeaderDeneb) } + size += l.Header.SizeSSZ() - // Field (8) 'Eth1Data' - if err = b.Eth1Data.HashTreeRootWith(hh); err != nil { - return - } + return +} - // Field (9) 'Eth1DataVotes' - { - subIndx := hh.Index() - num := uint64(len(b.Eth1DataVotes)) - if num > 2048 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Eth1DataVotes { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 2048) - } +// HashTreeRoot ssz hashes the LightClientBootstrapElectra object +func (l *LightClientBootstrapElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} - // Field (10) 'Eth1DepositIndex' - hh.PutUint64(b.Eth1DepositIndex) +// HashTreeRootWith ssz hashes the LightClientBootstrapElectra object with a hasher +func (l *LightClientBootstrapElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() - // Field (11) 'Validators' - { - subIndx := hh.Index() - num := uint64(len(b.Validators)) - if num > 1099511627776 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.Validators { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 1099511627776) + // Field (0) 'Header' + if err = l.Header.HashTreeRootWith(hh); err != nil { + return } - // Field (12) 'Balances' - { - if size := len(b.Balances); size > 1099511627776 { - err = ssz.ErrListTooBigFn("--.Balances", size, 1099511627776) - return - } - subIndx := hh.Index() - for _, i := range b.Balances { - hh.AppendUint64(i) - } - hh.FillUpTo32() - - numItems := uint64(len(b.Balances)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(1099511627776, numItems, 8)) + // Field (1) 'CurrentSyncCommittee' + if err = l.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil { + return } - // Field (13) 'RandaoMixes' + // Field (2) 'CurrentSyncCommitteeBranch' { - if size := len(b.RandaoMixes); size != 65536 { - err = ssz.ErrVectorLengthFn("--.RandaoMixes", size, 65536) + if size := len(l.CurrentSyncCommitteeBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.CurrentSyncCommitteeBranch", size, 6) return } subIndx := hh.Index() - for _, i := range b.RandaoMixes { + for _, i := range l.CurrentSyncCommitteeBranch { if len(i) != 32 { err = ssz.ErrBytesLength return @@ -3326,372 +4901,504 @@ func (b *BeaconStateElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.Merkleize(subIndx) } - // Field (14) 'Slashings' - { - if size := len(b.Slashings); size != 8192 { - err = ssz.ErrVectorLengthFn("--.Slashings", size, 8192) - return - } - subIndx := hh.Index() - for _, i := range b.Slashings { - hh.AppendUint64(i) - } - hh.Merkleize(subIndx) + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the LightClientUpdateElectra object +func (l *LightClientUpdateElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) +} + +// MarshalSSZTo ssz marshals the LightClientUpdateElectra object to a target array +func (l *LightClientUpdateElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(25216) + + // Offset (0) 'AttestedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) } + offset += l.AttestedHeader.SizeSSZ() - // Field (15) 'PreviousEpochParticipation' - { - elemIndx := hh.Index() - byteLen := uint64(len(b.PreviousEpochParticipation)) - if byteLen > 1099511627776 { - err = ssz.ErrIncorrectListSize + // Field (1) 'NextSyncCommittee' + if l.NextSyncCommittee == nil { + l.NextSyncCommittee = new(SyncCommittee) + } + if dst, err = l.NextSyncCommittee.MarshalSSZTo(dst); err != nil { + return + } + + // Field (2) 'NextSyncCommitteeBranch' + if size := len(l.NextSyncCommitteeBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 6) + return + } + for ii := 0; ii < 6; ii++ { + if size := len(l.NextSyncCommitteeBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.NextSyncCommitteeBranch[ii]", size, 32) return } - hh.PutBytes(b.PreviousEpochParticipation) - hh.MerkleizeWithMixin(elemIndx, byteLen, (1099511627776+31)/32) + dst = append(dst, l.NextSyncCommitteeBranch[ii]...) } - // Field (16) 'CurrentEpochParticipation' - { - elemIndx := hh.Index() - byteLen := uint64(len(b.CurrentEpochParticipation)) - if byteLen > 1099511627776 { - err = ssz.ErrIncorrectListSize + // Offset (3) 'FinalizedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + offset += l.FinalizedHeader.SizeSSZ() + + // Field (4) 'FinalityBranch' + if size := len(l.FinalityBranch); size != 7 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 7) + return + } + for ii := 0; ii < 7; ii++ { + if size := len(l.FinalityBranch[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32) return } - hh.PutBytes(b.CurrentEpochParticipation) - hh.MerkleizeWithMixin(elemIndx, byteLen, (1099511627776+31)/32) + dst = append(dst, l.FinalityBranch[ii]...) } - // Field (17) 'JustificationBits' - if size := len(b.JustificationBits); size != 1 { - err = ssz.ErrBytesLengthFn("--.JustificationBits", size, 1) + // Field (5) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { return } - hh.PutBytes(b.JustificationBits) - // Field (18) 'PreviousJustifiedCheckpoint' - if err = b.PreviousJustifiedCheckpoint.HashTreeRootWith(hh); err != nil { + // Field (6) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) + + // Field (0) 'AttestedHeader' + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { return } - // Field (19) 'CurrentJustifiedCheckpoint' - if err = b.CurrentJustifiedCheckpoint.HashTreeRootWith(hh); err != nil { + // Field (3) 'FinalizedHeader' + if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil { return } - // Field (20) 'FinalizedCheckpoint' - if err = b.FinalizedCheckpoint.HashTreeRootWith(hh); err != nil { - return + return +} + +// UnmarshalSSZ ssz unmarshals the LightClientUpdateElectra object +func (l *LightClientUpdateElectra) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 25216 { + return ssz.ErrSize } - // Field (21) 'InactivityScores' - { - if size := len(b.InactivityScores); size > 1099511627776 { - err = ssz.ErrListTooBigFn("--.InactivityScores", size, 1099511627776) - return - } - subIndx := hh.Index() - for _, i := range b.InactivityScores { - hh.AppendUint64(i) - } - hh.FillUpTo32() + tail := buf + var o0, o3 uint64 - numItems := uint64(len(b.InactivityScores)) - hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(1099511627776, numItems, 8)) + // Offset (0) 'AttestedHeader' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset } - // Field (22) 'CurrentSyncCommittee' - if err = b.CurrentSyncCommittee.HashTreeRootWith(hh); err != nil { - return + if o0 != 25216 { + return ssz.ErrInvalidVariableOffset } - // Field (23) 'NextSyncCommittee' - if err = b.NextSyncCommittee.HashTreeRootWith(hh); err != nil { - return + // Field (1) 'NextSyncCommittee' + if l.NextSyncCommittee == nil { + l.NextSyncCommittee = new(SyncCommittee) + } + if err = l.NextSyncCommittee.UnmarshalSSZ(buf[4:24628]); err != nil { + return err } - // Field (24) 'LatestExecutionPayloadHeader' - if err = b.LatestExecutionPayloadHeader.HashTreeRootWith(hh); err != nil { - return + // Field (2) 'NextSyncCommitteeBranch' + l.NextSyncCommitteeBranch = make([][]byte, 6) + for ii := 0; ii < 6; ii++ { + if cap(l.NextSyncCommitteeBranch[ii]) == 0 { + l.NextSyncCommitteeBranch[ii] = make([]byte, 0, len(buf[24628:24820][ii*32:(ii+1)*32])) + } + l.NextSyncCommitteeBranch[ii] = append(l.NextSyncCommitteeBranch[ii], buf[24628:24820][ii*32:(ii+1)*32]...) } - // Field (25) 'NextWithdrawalIndex' - hh.PutUint64(b.NextWithdrawalIndex) + // Offset (3) 'FinalizedHeader' + if o3 = ssz.ReadOffset(buf[24820:24824]); o3 > size || o0 > o3 { + return ssz.ErrOffset + } - // Field (26) 'NextWithdrawalValidatorIndex' - hh.PutUint64(uint64(b.NextWithdrawalValidatorIndex)) + // Field (4) 'FinalityBranch' + l.FinalityBranch = make([][]byte, 7) + for ii := 0; ii < 7; ii++ { + if cap(l.FinalityBranch[ii]) == 0 { + l.FinalityBranch[ii] = make([]byte, 0, len(buf[24824:25048][ii*32:(ii+1)*32])) + } + l.FinalityBranch[ii] = append(l.FinalityBranch[ii], buf[24824:25048][ii*32:(ii+1)*32]...) + } - // Field (27) 'HistoricalSummaries' + // Field (5) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[25048:25208]); err != nil { + return err + } + + // Field (6) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[25208:25216])) + + // Field (0) 'AttestedHeader' { - subIndx := hh.Index() - num := uint64(len(b.HistoricalSummaries)) - if num > 16777216 { - err = ssz.ErrIncorrectListSize - return + buf = tail[o0:o3] + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) } - for _, elem := range b.HistoricalSummaries { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } + if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil { + return err } - hh.MerkleizeWithMixin(subIndx, num, 16777216) } - // Field (28) 'DepositRequestsStartIndex' - hh.PutUint64(b.DepositRequestsStartIndex) + // Field (3) 'FinalizedHeader' + { + buf = tail[o3:] + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} - // Field (29) 'DepositBalanceToConsume' - hh.PutUint64(uint64(b.DepositBalanceToConsume)) +// SizeSSZ returns the ssz encoded size in bytes for the LightClientUpdateElectra object +func (l *LightClientUpdateElectra) SizeSSZ() (size int) { + size = 25216 - // Field (30) 'ExitBalanceToConsume' - hh.PutUint64(uint64(b.ExitBalanceToConsume)) + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + size += l.AttestedHeader.SizeSSZ() - // Field (31) 'EarliestExitEpoch' - hh.PutUint64(uint64(b.EarliestExitEpoch)) + // Field (3) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + size += l.FinalizedHeader.SizeSSZ() - // Field (32) 'ConsolidationBalanceToConsume' - hh.PutUint64(uint64(b.ConsolidationBalanceToConsume)) + return +} + +// HashTreeRoot ssz hashes the LightClientUpdateElectra object +func (l *LightClientUpdateElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) +} + +// HashTreeRootWith ssz hashes the LightClientUpdateElectra object with a hasher +func (l *LightClientUpdateElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } - // Field (33) 'EarliestConsolidationEpoch' - hh.PutUint64(uint64(b.EarliestConsolidationEpoch)) + // Field (1) 'NextSyncCommittee' + if err = l.NextSyncCommittee.HashTreeRootWith(hh); err != nil { + return + } - // Field (34) 'PendingBalanceDeposits' + // Field (2) 'NextSyncCommitteeBranch' { - subIndx := hh.Index() - num := uint64(len(b.PendingBalanceDeposits)) - if num > 134217728 { - err = ssz.ErrIncorrectListSize + if size := len(l.NextSyncCommitteeBranch); size != 6 { + err = ssz.ErrVectorLengthFn("--.NextSyncCommitteeBranch", size, 6) return } - for _, elem := range b.PendingBalanceDeposits { - if err = elem.HashTreeRootWith(hh); err != nil { + subIndx := hh.Index() + for _, i := range l.NextSyncCommitteeBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength return } + hh.Append(i) } - hh.MerkleizeWithMixin(subIndx, num, 134217728) + hh.Merkleize(subIndx) } - // Field (35) 'PendingPartialWithdrawals' - { - subIndx := hh.Index() - num := uint64(len(b.PendingPartialWithdrawals)) - if num > 134217728 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range b.PendingPartialWithdrawals { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 134217728) + // Field (3) 'FinalizedHeader' + if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil { + return } - // Field (36) 'PendingConsolidations' + // Field (4) 'FinalityBranch' { - subIndx := hh.Index() - num := uint64(len(b.PendingConsolidations)) - if num > 262144 { - err = ssz.ErrIncorrectListSize + if size := len(l.FinalityBranch); size != 7 { + err = ssz.ErrVectorLengthFn("--.FinalityBranch", size, 7) return } - for _, elem := range b.PendingConsolidations { - if err = elem.HashTreeRootWith(hh); err != nil { + subIndx := hh.Index() + for _, i := range l.FinalityBranch { + if len(i) != 32 { + err = ssz.ErrBytesLength return } + hh.Append(i) } - hh.MerkleizeWithMixin(subIndx, num, 262144) + hh.Merkleize(subIndx) } - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the PendingBalanceDeposit object -func (p *PendingBalanceDeposit) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(p) -} - -// MarshalSSZTo ssz marshals the PendingBalanceDeposit object to a target array -func (p *PendingBalanceDeposit) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Index' - dst = ssz.MarshalUint64(dst, uint64(p.Index)) - - // Field (1) 'Amount' - dst = ssz.MarshalUint64(dst, p.Amount) - - return -} - -// UnmarshalSSZ ssz unmarshals the PendingBalanceDeposit object -func (p *PendingBalanceDeposit) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 16 { - return ssz.ErrSize + // Field (5) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return } - // Field (0) 'Index' - p.Index = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'Amount' - p.Amount = ssz.UnmarshallUint64(buf[8:16]) - - return err -} + // Field (6) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) -// SizeSSZ returns the ssz encoded size in bytes for the PendingBalanceDeposit object -func (p *PendingBalanceDeposit) SizeSSZ() (size int) { - size = 16 + hh.Merkleize(indx) return } -// HashTreeRoot ssz hashes the PendingBalanceDeposit object -func (p *PendingBalanceDeposit) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(p) +// MarshalSSZ ssz marshals the LightClientFinalityUpdateElectra object +func (l *LightClientFinalityUpdateElectra) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(l) } -// HashTreeRootWith ssz hashes the PendingBalanceDeposit object with a hasher -func (p *PendingBalanceDeposit) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() +// MarshalSSZTo ssz marshals the LightClientFinalityUpdateElectra object to a target array +func (l *LightClientFinalityUpdateElectra) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(180) - // Field (0) 'Index' - hh.PutUint64(uint64(p.Index)) + // Offset (0) 'AttestedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + offset += l.AttestedHeader.SizeSSZ() - // Field (1) 'Amount' - hh.PutUint64(p.Amount) + // Offset (1) 'FinalizedHeader' + dst = ssz.WriteOffset(dst, offset) + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + offset += l.FinalizedHeader.SizeSSZ() - hh.Merkleize(indx) - return -} + // Offset (2) 'FinalityBranch' + dst = ssz.WriteOffset(dst, offset) + for ii := 0; ii < len(l.FinalityBranch); ii++ { + offset += 4 + offset += len(l.FinalityBranch[ii]) + } -// MarshalSSZ ssz marshals the PendingPartialWithdrawal object -func (p *PendingPartialWithdrawal) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(p) -} + // Field (3) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if dst, err = l.SyncAggregate.MarshalSSZTo(dst); err != nil { + return + } -// MarshalSSZTo ssz marshals the PendingPartialWithdrawal object to a target array -func (p *PendingPartialWithdrawal) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf + // Field (4) 'SignatureSlot' + dst = ssz.MarshalUint64(dst, uint64(l.SignatureSlot)) - // Field (0) 'Index' - dst = ssz.MarshalUint64(dst, uint64(p.Index)) + // Field (0) 'AttestedHeader' + if dst, err = l.AttestedHeader.MarshalSSZTo(dst); err != nil { + return + } - // Field (1) 'Amount' - dst = ssz.MarshalUint64(dst, p.Amount) + // Field (1) 'FinalizedHeader' + if dst, err = l.FinalizedHeader.MarshalSSZTo(dst); err != nil { + return + } - // Field (2) 'WithdrawableEpoch' - dst = ssz.MarshalUint64(dst, uint64(p.WithdrawableEpoch)) + // Field (2) 'FinalityBranch' + if size := len(l.FinalityBranch); size > 7 { + err = ssz.ErrListTooBigFn("--.FinalityBranch", size, 7) + return + } + { + offset = 4 * len(l.FinalityBranch) + for ii := 0; ii < len(l.FinalityBranch); ii++ { + dst = ssz.WriteOffset(dst, offset) + offset += len(l.FinalityBranch[ii]) + } + } + for ii := 0; ii < len(l.FinalityBranch); ii++ { + if size := len(l.FinalityBranch[ii]); size > 32 { + err = ssz.ErrBytesLengthFn("--.FinalityBranch[ii]", size, 32) + return + } + dst = append(dst, l.FinalityBranch[ii]...) + } return } -// UnmarshalSSZ ssz unmarshals the PendingPartialWithdrawal object -func (p *PendingPartialWithdrawal) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the LightClientFinalityUpdateElectra object +func (l *LightClientFinalityUpdateElectra) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 24 { + if size < 180 { return ssz.ErrSize } - // Field (0) 'Index' - p.Index = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'Amount' - p.Amount = ssz.UnmarshallUint64(buf[8:16]) - - // Field (2) 'WithdrawableEpoch' - p.WithdrawableEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[16:24])) + tail := buf + var o0, o1, o2 uint64 - return err -} + // Offset (0) 'AttestedHeader' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } -// SizeSSZ returns the ssz encoded size in bytes for the PendingPartialWithdrawal object -func (p *PendingPartialWithdrawal) SizeSSZ() (size int) { - size = 24 - return -} + if o0 != 180 { + return ssz.ErrInvalidVariableOffset + } -// HashTreeRoot ssz hashes the PendingPartialWithdrawal object -func (p *PendingPartialWithdrawal) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(p) -} + // Offset (1) 'FinalizedHeader' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } -// HashTreeRootWith ssz hashes the PendingPartialWithdrawal object with a hasher -func (p *PendingPartialWithdrawal) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() + // Offset (2) 'FinalityBranch' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { + return ssz.ErrOffset + } - // Field (0) 'Index' - hh.PutUint64(uint64(p.Index)) + // Field (3) 'SyncAggregate' + if l.SyncAggregate == nil { + l.SyncAggregate = new(SyncAggregate) + } + if err = l.SyncAggregate.UnmarshalSSZ(buf[12:172]); err != nil { + return err + } - // Field (1) 'Amount' - hh.PutUint64(p.Amount) + // Field (4) 'SignatureSlot' + l.SignatureSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[172:180])) - // Field (2) 'WithdrawableEpoch' - hh.PutUint64(uint64(p.WithdrawableEpoch)) + // Field (0) 'AttestedHeader' + { + buf = tail[o0:o1] + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) + } + if err = l.AttestedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } - hh.Merkleize(indx) - return -} + // Field (1) 'FinalizedHeader' + { + buf = tail[o1:o2] + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + if err = l.FinalizedHeader.UnmarshalSSZ(buf); err != nil { + return err + } + } -// MarshalSSZ ssz marshals the PendingConsolidation object -func (p *PendingConsolidation) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(p) + // Field (2) 'FinalityBranch' + { + buf = tail[o2:] + num, err := ssz.DecodeDynamicLength(buf, 7) + if err != nil { + return err + } + l.FinalityBranch = make([][]byte, num) + err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { + if len(buf) > 32 { + return ssz.ErrBytesLength + } + if cap(l.FinalityBranch[indx]) == 0 { + l.FinalityBranch[indx] = make([]byte, 0, len(buf)) + } + l.FinalityBranch[indx] = append(l.FinalityBranch[indx], buf...) + return nil + }) + if err != nil { + return err + } + } + return err } -// MarshalSSZTo ssz marshals the PendingConsolidation object to a target array -func (p *PendingConsolidation) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'SourceIndex' - dst = ssz.MarshalUint64(dst, uint64(p.SourceIndex)) - - // Field (1) 'TargetIndex' - dst = ssz.MarshalUint64(dst, uint64(p.TargetIndex)) - - return -} +// SizeSSZ returns the ssz encoded size in bytes for the LightClientFinalityUpdateElectra object +func (l *LightClientFinalityUpdateElectra) SizeSSZ() (size int) { + size = 180 -// UnmarshalSSZ ssz unmarshals the PendingConsolidation object -func (p *PendingConsolidation) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 16 { - return ssz.ErrSize + // Field (0) 'AttestedHeader' + if l.AttestedHeader == nil { + l.AttestedHeader = new(LightClientHeaderDeneb) } + size += l.AttestedHeader.SizeSSZ() - // Field (0) 'SourceIndex' - p.SourceIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'TargetIndex' - p.TargetIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) + // Field (1) 'FinalizedHeader' + if l.FinalizedHeader == nil { + l.FinalizedHeader = new(LightClientHeaderDeneb) + } + size += l.FinalizedHeader.SizeSSZ() - return err -} + // Field (2) 'FinalityBranch' + for ii := 0; ii < len(l.FinalityBranch); ii++ { + size += 4 + size += len(l.FinalityBranch[ii]) + } -// SizeSSZ returns the ssz encoded size in bytes for the PendingConsolidation object -func (p *PendingConsolidation) SizeSSZ() (size int) { - size = 16 return } -// HashTreeRoot ssz hashes the PendingConsolidation object -func (p *PendingConsolidation) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(p) +// HashTreeRoot ssz hashes the LightClientFinalityUpdateElectra object +func (l *LightClientFinalityUpdateElectra) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(l) } -// HashTreeRootWith ssz hashes the PendingConsolidation object with a hasher -func (p *PendingConsolidation) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the LightClientFinalityUpdateElectra object with a hasher +func (l *LightClientFinalityUpdateElectra) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'SourceIndex' - hh.PutUint64(uint64(p.SourceIndex)) + // Field (0) 'AttestedHeader' + if err = l.AttestedHeader.HashTreeRootWith(hh); err != nil { + return + } - // Field (1) 'TargetIndex' - hh.PutUint64(uint64(p.TargetIndex)) + // Field (1) 'FinalizedHeader' + if err = l.FinalizedHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'FinalityBranch' + { + subIndx := hh.Index() + num := uint64(len(l.FinalityBranch)) + if num > 7 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range l.FinalityBranch { + { + elemIndx := hh.Index() + byteLen := uint64(len(elem)) + if byteLen > 32 { + err = ssz.ErrIncorrectListSize + return + } + hh.AppendBytes32(elem) + hh.MerkleizeWithMixin(elemIndx, byteLen, (32+31)/32) + } + } + hh.MerkleizeWithMixin(subIndx, num, 7) + } + + // Field (3) 'SyncAggregate' + if err = l.SyncAggregate.HashTreeRootWith(hh); err != nil { + return + } + + // Field (4) 'SignatureSlot' + hh.PutUint64(uint64(l.SignatureSlot)) hh.Merkleize(indx) return diff --git a/proto/prysm/v1alpha1/finalized_block_root_container.pb.go b/proto/prysm/v1alpha1/finalized_block_root_container.pb.go index f0913dd3425d..5ba76d8b12e7 100755 --- a/proto/prysm/v1alpha1/finalized_block_root_container.pb.go +++ b/proto/prysm/v1alpha1/finalized_block_root_container.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/finalized_block_root_container.proto package eth diff --git a/proto/prysm/v1alpha1/finalized_block_root_container.pb.gw.go b/proto/prysm/v1alpha1/finalized_block_root_container.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/finalized_block_root_container.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/finalized_block_root_container.proto b/proto/prysm/v1alpha1/finalized_block_root_container.proto index 02d9839d3227..b89de16d92c7 100644 --- a/proto/prysm/v1alpha1/finalized_block_root_container.proto +++ b/proto/prysm/v1alpha1/finalized_block_root_container.proto @@ -10,6 +10,6 @@ option java_package = "org.ethereum.eth.v1alpha1"; option php_namespace = "Ethereum\\Eth\\v1alpha1"; message FinalizedBlockRootContainer { - bytes parent_root = 1; - bytes child_root = 2; + bytes parent_root = 1; + bytes child_root = 2; } diff --git a/proto/prysm/v1alpha1/fulu.ssz.go b/proto/prysm/v1alpha1/fulu.ssz.go new file mode 100644 index 000000000000..03407bc38f39 --- /dev/null +++ b/proto/prysm/v1alpha1/fulu.ssz.go @@ -0,0 +1,1160 @@ +// Code generated by fastssz. DO NOT EDIT. +package eth + +import ( + ssz "github.com/prysmaticlabs/fastssz" + github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" +) + +// MarshalSSZ ssz marshals the SignedBeaconBlockContentsFulu object +func (s *SignedBeaconBlockContentsFulu) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedBeaconBlockContentsFulu object to a target array +func (s *SignedBeaconBlockContentsFulu) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(12) + + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if s.Block == nil { + s.Block = new(SignedBeaconBlockFulu) + } + offset += s.Block.SizeSSZ() + + // Offset (1) 'KzgProofs' + dst = ssz.WriteOffset(dst, offset) + offset += len(s.KzgProofs) * 48 + + // Offset (2) 'Blobs' + dst = ssz.WriteOffset(dst, offset) + offset += len(s.Blobs) * 131072 + + // Field (0) 'Block' + if dst, err = s.Block.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'KzgProofs' + if size := len(s.KzgProofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) + return + } + for ii := 0; ii < len(s.KzgProofs); ii++ { + if size := len(s.KzgProofs[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgProofs[ii]", size, 48) + return + } + dst = append(dst, s.KzgProofs[ii]...) + } + + // Field (2) 'Blobs' + if size := len(s.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) + return + } + for ii := 0; ii < len(s.Blobs); ii++ { + if size := len(s.Blobs[ii]); size != 131072 { + err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072) + return + } + dst = append(dst, s.Blobs[ii]...) + } + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockContentsFulu object +func (s *SignedBeaconBlockContentsFulu) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 12 { + return ssz.ErrSize + } + + tail := buf + var o0, o1, o2 uint64 + + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 12 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (1) 'KzgProofs' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Offset (2) 'Blobs' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { + return ssz.ErrOffset + } + + // Field (0) 'Block' + { + buf = tail[o0:o1] + if s.Block == nil { + s.Block = new(SignedBeaconBlockFulu) + } + if err = s.Block.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (1) 'KzgProofs' + { + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 48, 4096) + if err != nil { + return err + } + s.KzgProofs = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(s.KzgProofs[ii]) == 0 { + s.KzgProofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + } + s.KzgProofs[ii] = append(s.KzgProofs[ii], buf[ii*48:(ii+1)*48]...) + } + } + + // Field (2) 'Blobs' + { + buf = tail[o2:] + num, err := ssz.DivideInt2(len(buf), 131072, 4096) + if err != nil { + return err + } + s.Blobs = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(s.Blobs[ii]) == 0 { + s.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072])) + } + s.Blobs[ii] = append(s.Blobs[ii], buf[ii*131072:(ii+1)*131072]...) + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockContentsFulu object +func (s *SignedBeaconBlockContentsFulu) SizeSSZ() (size int) { + size = 12 + + // Field (0) 'Block' + if s.Block == nil { + s.Block = new(SignedBeaconBlockFulu) + } + size += s.Block.SizeSSZ() + + // Field (1) 'KzgProofs' + size += len(s.KzgProofs) * 48 + + // Field (2) 'Blobs' + size += len(s.Blobs) * 131072 + + return +} + +// HashTreeRoot ssz hashes the SignedBeaconBlockContentsFulu object +func (s *SignedBeaconBlockContentsFulu) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedBeaconBlockContentsFulu object with a hasher +func (s *SignedBeaconBlockContentsFulu) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Block' + if err = s.Block.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'KzgProofs' + { + if size := len(s.KzgProofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range s.KzgProofs { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(s.KzgProofs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + // Field (2) 'Blobs' + { + if size := len(s.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range s.Blobs { + if len(i) != 131072 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(s.Blobs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the SignedBeaconBlockFulu object +func (s *SignedBeaconBlockFulu) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedBeaconBlockFulu object to a target array +func (s *SignedBeaconBlockFulu) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(100) + + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if s.Block == nil { + s.Block = new(BeaconBlockElectra) + } + offset += s.Block.SizeSSZ() + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + // Field (0) 'Block' + if dst, err = s.Block.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockFulu object +func (s *SignedBeaconBlockFulu) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 100 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 100 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) + } + s.Signature = append(s.Signature, buf[4:100]...) + + // Field (0) 'Block' + { + buf = tail[o0:] + if s.Block == nil { + s.Block = new(BeaconBlockElectra) + } + if err = s.Block.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockFulu object +func (s *SignedBeaconBlockFulu) SizeSSZ() (size int) { + size = 100 + + // Field (0) 'Block' + if s.Block == nil { + s.Block = new(BeaconBlockElectra) + } + size += s.Block.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the SignedBeaconBlockFulu object +func (s *SignedBeaconBlockFulu) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedBeaconBlockFulu object with a hasher +func (s *SignedBeaconBlockFulu) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Block' + if err = s.Block.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(s.Signature) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the BeaconBlockContentsFulu object +func (b *BeaconBlockContentsFulu) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BeaconBlockContentsFulu object to a target array +func (b *BeaconBlockContentsFulu) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(12) + + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if b.Block == nil { + b.Block = new(BeaconBlockElectra) + } + offset += b.Block.SizeSSZ() + + // Offset (1) 'KzgProofs' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.KzgProofs) * 48 + + // Offset (2) 'Blobs' + dst = ssz.WriteOffset(dst, offset) + offset += len(b.Blobs) * 131072 + + // Field (0) 'Block' + if dst, err = b.Block.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'KzgProofs' + if size := len(b.KzgProofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) + return + } + for ii := 0; ii < len(b.KzgProofs); ii++ { + if size := len(b.KzgProofs[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgProofs[ii]", size, 48) + return + } + dst = append(dst, b.KzgProofs[ii]...) + } + + // Field (2) 'Blobs' + if size := len(b.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) + return + } + for ii := 0; ii < len(b.Blobs); ii++ { + if size := len(b.Blobs[ii]); size != 131072 { + err = ssz.ErrBytesLengthFn("--.Blobs[ii]", size, 131072) + return + } + dst = append(dst, b.Blobs[ii]...) + } + + return +} + +// UnmarshalSSZ ssz unmarshals the BeaconBlockContentsFulu object +func (b *BeaconBlockContentsFulu) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 12 { + return ssz.ErrSize + } + + tail := buf + var o0, o1, o2 uint64 + + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 12 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (1) 'KzgProofs' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Offset (2) 'Blobs' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { + return ssz.ErrOffset + } + + // Field (0) 'Block' + { + buf = tail[o0:o1] + if b.Block == nil { + b.Block = new(BeaconBlockElectra) + } + if err = b.Block.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (1) 'KzgProofs' + { + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 48, 4096) + if err != nil { + return err + } + b.KzgProofs = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(b.KzgProofs[ii]) == 0 { + b.KzgProofs[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + } + b.KzgProofs[ii] = append(b.KzgProofs[ii], buf[ii*48:(ii+1)*48]...) + } + } + + // Field (2) 'Blobs' + { + buf = tail[o2:] + num, err := ssz.DivideInt2(len(buf), 131072, 4096) + if err != nil { + return err + } + b.Blobs = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(b.Blobs[ii]) == 0 { + b.Blobs[ii] = make([]byte, 0, len(buf[ii*131072:(ii+1)*131072])) + } + b.Blobs[ii] = append(b.Blobs[ii], buf[ii*131072:(ii+1)*131072]...) + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockContentsFulu object +func (b *BeaconBlockContentsFulu) SizeSSZ() (size int) { + size = 12 + + // Field (0) 'Block' + if b.Block == nil { + b.Block = new(BeaconBlockElectra) + } + size += b.Block.SizeSSZ() + + // Field (1) 'KzgProofs' + size += len(b.KzgProofs) * 48 + + // Field (2) 'Blobs' + size += len(b.Blobs) * 131072 + + return +} + +// HashTreeRoot ssz hashes the BeaconBlockContentsFulu object +func (b *BeaconBlockContentsFulu) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) +} + +// HashTreeRootWith ssz hashes the BeaconBlockContentsFulu object with a hasher +func (b *BeaconBlockContentsFulu) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Block' + if err = b.Block.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'KzgProofs' + { + if size := len(b.KzgProofs); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProofs", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range b.KzgProofs { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(b.KzgProofs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + // Field (2) 'Blobs' + { + if size := len(b.Blobs); size > 4096 { + err = ssz.ErrListTooBigFn("--.Blobs", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range b.Blobs { + if len(i) != 131072 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(b.Blobs)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the SignedBlindedBeaconBlockFulu object +func (s *SignedBlindedBeaconBlockFulu) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedBlindedBeaconBlockFulu object to a target array +func (s *SignedBlindedBeaconBlockFulu) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(100) + + // Offset (0) 'Message' + dst = ssz.WriteOffset(dst, offset) + if s.Message == nil { + s.Message = new(BlindedBeaconBlockFulu) + } + offset += s.Message.SizeSSZ() + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + // Field (0) 'Message' + if dst, err = s.Message.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedBlindedBeaconBlockFulu object +func (s *SignedBlindedBeaconBlockFulu) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 100 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Message' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 100 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) + } + s.Signature = append(s.Signature, buf[4:100]...) + + // Field (0) 'Message' + { + buf = tail[o0:] + if s.Message == nil { + s.Message = new(BlindedBeaconBlockFulu) + } + if err = s.Message.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedBlindedBeaconBlockFulu object +func (s *SignedBlindedBeaconBlockFulu) SizeSSZ() (size int) { + size = 100 + + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(BlindedBeaconBlockFulu) + } + size += s.Message.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the SignedBlindedBeaconBlockFulu object +func (s *SignedBlindedBeaconBlockFulu) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedBlindedBeaconBlockFulu object with a hasher +func (s *SignedBlindedBeaconBlockFulu) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Message' + if err = s.Message.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(s.Signature) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the BlindedBeaconBlockFulu object +func (b *BlindedBeaconBlockFulu) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BlindedBeaconBlockFulu object to a target array +func (b *BlindedBeaconBlockFulu) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(84) + + // Field (0) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(b.Slot)) + + // Field (1) 'ProposerIndex' + dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) + + // Field (2) 'ParentRoot' + if size := len(b.ParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) + return + } + dst = append(dst, b.ParentRoot...) + + // Field (3) 'StateRoot' + if size := len(b.StateRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + return + } + dst = append(dst, b.StateRoot...) + + // Offset (4) 'Body' + dst = ssz.WriteOffset(dst, offset) + if b.Body == nil { + b.Body = new(BlindedBeaconBlockBodyElectra) + } + offset += b.Body.SizeSSZ() + + // Field (4) 'Body' + if dst, err = b.Body.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the BlindedBeaconBlockFulu object +func (b *BlindedBeaconBlockFulu) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 84 { + return ssz.ErrSize + } + + tail := buf + var o4 uint64 + + // Field (0) 'Slot' + b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'ProposerIndex' + b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) + + // Field (2) 'ParentRoot' + if cap(b.ParentRoot) == 0 { + b.ParentRoot = make([]byte, 0, len(buf[16:48])) + } + b.ParentRoot = append(b.ParentRoot, buf[16:48]...) + + // Field (3) 'StateRoot' + if cap(b.StateRoot) == 0 { + b.StateRoot = make([]byte, 0, len(buf[48:80])) + } + b.StateRoot = append(b.StateRoot, buf[48:80]...) + + // Offset (4) 'Body' + if o4 = ssz.ReadOffset(buf[80:84]); o4 > size { + return ssz.ErrOffset + } + + if o4 != 84 { + return ssz.ErrInvalidVariableOffset + } + + // Field (4) 'Body' + { + buf = tail[o4:] + if b.Body == nil { + b.Body = new(BlindedBeaconBlockBodyElectra) + } + if err = b.Body.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockFulu object +func (b *BlindedBeaconBlockFulu) SizeSSZ() (size int) { + size = 84 + + // Field (4) 'Body' + if b.Body == nil { + b.Body = new(BlindedBeaconBlockBodyElectra) + } + size += b.Body.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the BlindedBeaconBlockFulu object +func (b *BlindedBeaconBlockFulu) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) +} + +// HashTreeRootWith ssz hashes the BlindedBeaconBlockFulu object with a hasher +func (b *BlindedBeaconBlockFulu) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Slot' + hh.PutUint64(uint64(b.Slot)) + + // Field (1) 'ProposerIndex' + hh.PutUint64(uint64(b.ProposerIndex)) + + // Field (2) 'ParentRoot' + if size := len(b.ParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) + return + } + hh.PutBytes(b.ParentRoot) + + // Field (3) 'StateRoot' + if size := len(b.StateRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + return + } + hh.PutBytes(b.StateRoot) + + // Field (4) 'Body' + if err = b.Body.HashTreeRootWith(hh); err != nil { + return + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the DataColumnSidecar object +func (d *DataColumnSidecar) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(d) +} + +// MarshalSSZTo ssz marshals the DataColumnSidecar object to a target array +func (d *DataColumnSidecar) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(356) + + // Field (0) 'ColumnIndex' + dst = ssz.MarshalUint64(dst, d.ColumnIndex) + + // Offset (1) 'DataColumn' + dst = ssz.WriteOffset(dst, offset) + offset += len(d.DataColumn) * 2048 + + // Offset (2) 'KzgCommitments' + dst = ssz.WriteOffset(dst, offset) + offset += len(d.KzgCommitments) * 48 + + // Offset (3) 'KzgProof' + dst = ssz.WriteOffset(dst, offset) + offset += len(d.KzgProof) * 48 + + // Field (4) 'SignedBlockHeader' + if d.SignedBlockHeader == nil { + d.SignedBlockHeader = new(SignedBeaconBlockHeader) + } + if dst, err = d.SignedBlockHeader.MarshalSSZTo(dst); err != nil { + return + } + + // Field (5) 'KzgCommitmentsInclusionProof' + if size := len(d.KzgCommitmentsInclusionProof); size != 4 { + err = ssz.ErrVectorLengthFn("--.KzgCommitmentsInclusionProof", size, 4) + return + } + for ii := 0; ii < 4; ii++ { + if size := len(d.KzgCommitmentsInclusionProof[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.KzgCommitmentsInclusionProof[ii]", size, 32) + return + } + dst = append(dst, d.KzgCommitmentsInclusionProof[ii]...) + } + + // Field (1) 'DataColumn' + if size := len(d.DataColumn); size > 4096 { + err = ssz.ErrListTooBigFn("--.DataColumn", size, 4096) + return + } + for ii := 0; ii < len(d.DataColumn); ii++ { + if size := len(d.DataColumn[ii]); size != 2048 { + err = ssz.ErrBytesLengthFn("--.DataColumn[ii]", size, 2048) + return + } + dst = append(dst, d.DataColumn[ii]...) + } + + // Field (2) 'KzgCommitments' + if size := len(d.KzgCommitments); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgCommitments", size, 4096) + return + } + for ii := 0; ii < len(d.KzgCommitments); ii++ { + if size := len(d.KzgCommitments[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgCommitments[ii]", size, 48) + return + } + dst = append(dst, d.KzgCommitments[ii]...) + } + + // Field (3) 'KzgProof' + if size := len(d.KzgProof); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProof", size, 4096) + return + } + for ii := 0; ii < len(d.KzgProof); ii++ { + if size := len(d.KzgProof[ii]); size != 48 { + err = ssz.ErrBytesLengthFn("--.KzgProof[ii]", size, 48) + return + } + dst = append(dst, d.KzgProof[ii]...) + } + + return +} + +// UnmarshalSSZ ssz unmarshals the DataColumnSidecar object +func (d *DataColumnSidecar) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 356 { + return ssz.ErrSize + } + + tail := buf + var o1, o2, o3 uint64 + + // Field (0) 'ColumnIndex' + d.ColumnIndex = ssz.UnmarshallUint64(buf[0:8]) + + // Offset (1) 'DataColumn' + if o1 = ssz.ReadOffset(buf[8:12]); o1 > size { + return ssz.ErrOffset + } + + if o1 != 356 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (2) 'KzgCommitments' + if o2 = ssz.ReadOffset(buf[12:16]); o2 > size || o1 > o2 { + return ssz.ErrOffset + } + + // Offset (3) 'KzgProof' + if o3 = ssz.ReadOffset(buf[16:20]); o3 > size || o2 > o3 { + return ssz.ErrOffset + } + + // Field (4) 'SignedBlockHeader' + if d.SignedBlockHeader == nil { + d.SignedBlockHeader = new(SignedBeaconBlockHeader) + } + if err = d.SignedBlockHeader.UnmarshalSSZ(buf[20:228]); err != nil { + return err + } + + // Field (5) 'KzgCommitmentsInclusionProof' + d.KzgCommitmentsInclusionProof = make([][]byte, 4) + for ii := 0; ii < 4; ii++ { + if cap(d.KzgCommitmentsInclusionProof[ii]) == 0 { + d.KzgCommitmentsInclusionProof[ii] = make([]byte, 0, len(buf[228:356][ii*32:(ii+1)*32])) + } + d.KzgCommitmentsInclusionProof[ii] = append(d.KzgCommitmentsInclusionProof[ii], buf[228:356][ii*32:(ii+1)*32]...) + } + + // Field (1) 'DataColumn' + { + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 2048, 4096) + if err != nil { + return err + } + d.DataColumn = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(d.DataColumn[ii]) == 0 { + d.DataColumn[ii] = make([]byte, 0, len(buf[ii*2048:(ii+1)*2048])) + } + d.DataColumn[ii] = append(d.DataColumn[ii], buf[ii*2048:(ii+1)*2048]...) + } + } + + // Field (2) 'KzgCommitments' + { + buf = tail[o2:o3] + num, err := ssz.DivideInt2(len(buf), 48, 4096) + if err != nil { + return err + } + d.KzgCommitments = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(d.KzgCommitments[ii]) == 0 { + d.KzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + } + d.KzgCommitments[ii] = append(d.KzgCommitments[ii], buf[ii*48:(ii+1)*48]...) + } + } + + // Field (3) 'KzgProof' + { + buf = tail[o3:] + num, err := ssz.DivideInt2(len(buf), 48, 4096) + if err != nil { + return err + } + d.KzgProof = make([][]byte, num) + for ii := 0; ii < num; ii++ { + if cap(d.KzgProof[ii]) == 0 { + d.KzgProof[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48])) + } + d.KzgProof[ii] = append(d.KzgProof[ii], buf[ii*48:(ii+1)*48]...) + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the DataColumnSidecar object +func (d *DataColumnSidecar) SizeSSZ() (size int) { + size = 356 + + // Field (1) 'DataColumn' + size += len(d.DataColumn) * 2048 + + // Field (2) 'KzgCommitments' + size += len(d.KzgCommitments) * 48 + + // Field (3) 'KzgProof' + size += len(d.KzgProof) * 48 + + return +} + +// HashTreeRoot ssz hashes the DataColumnSidecar object +func (d *DataColumnSidecar) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(d) +} + +// HashTreeRootWith ssz hashes the DataColumnSidecar object with a hasher +func (d *DataColumnSidecar) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'ColumnIndex' + hh.PutUint64(d.ColumnIndex) + + // Field (1) 'DataColumn' + { + if size := len(d.DataColumn); size > 4096 { + err = ssz.ErrListTooBigFn("--.DataColumn", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range d.DataColumn { + if len(i) != 2048 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(d.DataColumn)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + // Field (2) 'KzgCommitments' + { + if size := len(d.KzgCommitments); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgCommitments", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range d.KzgCommitments { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(d.KzgCommitments)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + // Field (3) 'KzgProof' + { + if size := len(d.KzgProof); size > 4096 { + err = ssz.ErrListTooBigFn("--.KzgProof", size, 4096) + return + } + subIndx := hh.Index() + for _, i := range d.KzgProof { + if len(i) != 48 { + err = ssz.ErrBytesLength + return + } + hh.PutBytes(i) + } + + numItems := uint64(len(d.KzgProof)) + hh.MerkleizeWithMixin(subIndx, numItems, 4096) + } + + // Field (4) 'SignedBlockHeader' + if err = d.SignedBlockHeader.HashTreeRootWith(hh); err != nil { + return + } + + // Field (5) 'KzgCommitmentsInclusionProof' + { + if size := len(d.KzgCommitmentsInclusionProof); size != 4 { + err = ssz.ErrVectorLengthFn("--.KzgCommitmentsInclusionProof", size, 4) + return + } + subIndx := hh.Index() + for _, i := range d.KzgCommitmentsInclusionProof { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the DataColumnIdentifier object +func (d *DataColumnIdentifier) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(d) +} + +// MarshalSSZTo ssz marshals the DataColumnIdentifier object to a target array +func (d *DataColumnIdentifier) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'BlockRoot' + if size := len(d.BlockRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) + return + } + dst = append(dst, d.BlockRoot...) + + // Field (1) 'ColumnIndex' + dst = ssz.MarshalUint64(dst, d.ColumnIndex) + + return +} + +// UnmarshalSSZ ssz unmarshals the DataColumnIdentifier object +func (d *DataColumnIdentifier) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 40 { + return ssz.ErrSize + } + + // Field (0) 'BlockRoot' + if cap(d.BlockRoot) == 0 { + d.BlockRoot = make([]byte, 0, len(buf[0:32])) + } + d.BlockRoot = append(d.BlockRoot, buf[0:32]...) + + // Field (1) 'ColumnIndex' + d.ColumnIndex = ssz.UnmarshallUint64(buf[32:40]) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the DataColumnIdentifier object +func (d *DataColumnIdentifier) SizeSSZ() (size int) { + size = 40 + return +} + +// HashTreeRoot ssz hashes the DataColumnIdentifier object +func (d *DataColumnIdentifier) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(d) +} + +// HashTreeRootWith ssz hashes the DataColumnIdentifier object with a hasher +func (d *DataColumnIdentifier) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'BlockRoot' + if size := len(d.BlockRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BlockRoot", size, 32) + return + } + hh.PutBytes(d.BlockRoot) + + // Field (1) 'ColumnIndex' + hh.PutUint64(d.ColumnIndex) + + hh.Merkleize(indx) + return +} diff --git a/proto/prysm/v1alpha1/health.pb.go b/proto/prysm/v1alpha1/health.pb.go index 7223d9cf95e2..08f0190eab94 100755 --- a/proto/prysm/v1alpha1/health.pb.go +++ b/proto/prysm/v1alpha1/health.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/health.proto package eth diff --git a/proto/prysm/v1alpha1/health.pb.gw.go b/proto/prysm/v1alpha1/health.pb.gw.go deleted file mode 100755 index 099b72831001..000000000000 --- a/proto/prysm/v1alpha1/health.pb.gw.go +++ /dev/null @@ -1,138 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: proto/prysm/v1alpha1/health.proto - -/* -Package eth is a reverse proxy. - -It translates gRPC into RESTful JSON APIs. -*/ -package eth - -import ( - "context" - "io" - "net/http" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/emptypb" -) - -// Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join -var _ = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) -var _ = emptypb.Empty{} - -func request_Health_StreamBeaconLogs_0(ctx context.Context, marshaler runtime.Marshaler, client HealthClient, req *http.Request, pathParams map[string]string) (Health_StreamBeaconLogsClient, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - stream, err := client.StreamBeaconLogs(ctx, &protoReq) - if err != nil { - return nil, metadata, err - } - header, err := stream.Header() - if err != nil { - return nil, metadata, err - } - metadata.HeaderMD = header - return stream, metadata, nil - -} - -// RegisterHealthHandlerServer registers the http handlers for service Health to "mux". -// UnaryRPC :call HealthServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterHealthHandlerFromEndpoint instead. -func RegisterHealthHandlerServer(ctx context.Context, mux *runtime.ServeMux, server HealthServer) error { - - mux.Handle("GET", pattern_Health_StreamBeaconLogs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") - _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - }) - - return nil -} - -// RegisterHealthHandlerFromEndpoint is same as RegisterHealthHandler but -// automatically dials to "endpoint" and closes the connection when "ctx" gets done. -func RegisterHealthHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) - if err != nil { - return err - } - defer func() { - if err != nil { - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - return - } - go func() { - <-ctx.Done() - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - }() - }() - - return RegisterHealthHandler(ctx, mux, conn) -} - -// RegisterHealthHandler registers the http handlers for service Health to "mux". -// The handlers forward requests to the grpc endpoint over "conn". -func RegisterHealthHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { - return RegisterHealthHandlerClient(ctx, mux, NewHealthClient(conn)) -} - -// RegisterHealthHandlerClient registers the http handlers for service Health -// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "HealthClient". -// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "HealthClient" -// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "HealthClient" to call the correct interceptors. -func RegisterHealthHandlerClient(ctx context.Context, mux *runtime.ServeMux, client HealthClient) error { - - mux.Handle("GET", pattern_Health_StreamBeaconLogs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Health/StreamBeaconLogs") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Health_StreamBeaconLogs_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Health_StreamBeaconLogs_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Health_StreamBeaconLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "health", "logs", "stream"}, "")) -) - -var ( - forward_Health_StreamBeaconLogs_0 = runtime.ForwardResponseStream -) diff --git a/proto/prysm/v1alpha1/health.proto b/proto/prysm/v1alpha1/health.proto index fc0783cd43c2..d68bcd87e716 100644 --- a/proto/prysm/v1alpha1/health.proto +++ b/proto/prysm/v1alpha1/health.proto @@ -17,13 +17,11 @@ option php_namespace = "Ethereum\\Eth\\v1alpha1"; // The health service is able to return important metadata about a beacon node // such being able to stream logs via gRPC. service Health { - rpc StreamBeaconLogs(google.protobuf.Empty) returns (stream LogsResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/health/logs/stream" - }; - } + rpc StreamBeaconLogs(google.protobuf.Empty) returns (stream LogsResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/health/logs/stream" + }; + } } -message LogsResponse { - repeated string logs = 1; -} +message LogsResponse { repeated string logs = 1; } diff --git a/proto/prysm/v1alpha1/light_client.pb.go b/proto/prysm/v1alpha1/light_client.pb.go new file mode 100755 index 000000000000..e45951bf2dac --- /dev/null +++ b/proto/prysm/v1alpha1/light_client.pb.go @@ -0,0 +1,2127 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.7 +// source: proto/prysm/v1alpha1/light_client.proto + +package eth + +import ( + reflect "reflect" + sync "sync" + + github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + _ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type LightClientBootstrapAltair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Header *LightClientHeaderAltair `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` + CurrentSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=current_sync_committee_branch,json=currentSyncCommitteeBranch,proto3" json:"current_sync_committee_branch,omitempty" ssz-size:"5,32"` +} + +func (x *LightClientBootstrapAltair) Reset() { + *x = LightClientBootstrapAltair{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientBootstrapAltair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientBootstrapAltair) ProtoMessage() {} + +func (x *LightClientBootstrapAltair) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientBootstrapAltair.ProtoReflect.Descriptor instead. +func (*LightClientBootstrapAltair) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{0} +} + +func (x *LightClientBootstrapAltair) GetHeader() *LightClientHeaderAltair { + if x != nil { + return x.Header + } + return nil +} + +func (x *LightClientBootstrapAltair) GetCurrentSyncCommittee() *SyncCommittee { + if x != nil { + return x.CurrentSyncCommittee + } + return nil +} + +func (x *LightClientBootstrapAltair) GetCurrentSyncCommitteeBranch() [][]byte { + if x != nil { + return x.CurrentSyncCommitteeBranch + } + return nil +} + +type LightClientUpdateAltair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderAltair `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + NextSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` + NextSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=next_sync_committee_branch,json=nextSyncCommitteeBranch,proto3" json:"next_sync_committee_branch,omitempty" ssz-size:"5,32"` + FinalizedHeader *LightClientHeaderAltair `protobuf:"bytes,4,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,5,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"6,32"` + SyncAggregate *SyncAggregate `protobuf:"bytes,6,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,7,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientUpdateAltair) Reset() { + *x = LightClientUpdateAltair{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientUpdateAltair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientUpdateAltair) ProtoMessage() {} + +func (x *LightClientUpdateAltair) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientUpdateAltair.ProtoReflect.Descriptor instead. +func (*LightClientUpdateAltair) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{1} +} + +func (x *LightClientUpdateAltair) GetAttestedHeader() *LightClientHeaderAltair { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientUpdateAltair) GetNextSyncCommittee() *SyncCommittee { + if x != nil { + return x.NextSyncCommittee + } + return nil +} + +func (x *LightClientUpdateAltair) GetNextSyncCommitteeBranch() [][]byte { + if x != nil { + return x.NextSyncCommitteeBranch + } + return nil +} + +func (x *LightClientUpdateAltair) GetFinalizedHeader() *LightClientHeaderAltair { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientUpdateAltair) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientUpdateAltair) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientUpdateAltair) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientFinalityUpdateAltair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderAltair `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + FinalizedHeader *LightClientHeaderAltair `protobuf:"bytes,2,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,3,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"6,32"` + SyncAggregate *SyncAggregate `protobuf:"bytes,4,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,5,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientFinalityUpdateAltair) Reset() { + *x = LightClientFinalityUpdateAltair{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientFinalityUpdateAltair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientFinalityUpdateAltair) ProtoMessage() {} + +func (x *LightClientFinalityUpdateAltair) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientFinalityUpdateAltair.ProtoReflect.Descriptor instead. +func (*LightClientFinalityUpdateAltair) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{2} +} + +func (x *LightClientFinalityUpdateAltair) GetAttestedHeader() *LightClientHeaderAltair { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientFinalityUpdateAltair) GetFinalizedHeader() *LightClientHeaderAltair { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientFinalityUpdateAltair) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientFinalityUpdateAltair) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientFinalityUpdateAltair) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientOptimisticUpdateAltair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderAltair `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + SyncAggregate *SyncAggregate `protobuf:"bytes,2,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,3,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientOptimisticUpdateAltair) Reset() { + *x = LightClientOptimisticUpdateAltair{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientOptimisticUpdateAltair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientOptimisticUpdateAltair) ProtoMessage() {} + +func (x *LightClientOptimisticUpdateAltair) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientOptimisticUpdateAltair.ProtoReflect.Descriptor instead. +func (*LightClientOptimisticUpdateAltair) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{3} +} + +func (x *LightClientOptimisticUpdateAltair) GetAttestedHeader() *LightClientHeaderAltair { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientOptimisticUpdateAltair) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientOptimisticUpdateAltair) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientHeaderAltair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Beacon *BeaconBlockHeader `protobuf:"bytes,1,opt,name=beacon,proto3" json:"beacon,omitempty"` +} + +func (x *LightClientHeaderAltair) Reset() { + *x = LightClientHeaderAltair{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientHeaderAltair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientHeaderAltair) ProtoMessage() {} + +func (x *LightClientHeaderAltair) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientHeaderAltair.ProtoReflect.Descriptor instead. +func (*LightClientHeaderAltair) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{4} +} + +func (x *LightClientHeaderAltair) GetBeacon() *BeaconBlockHeader { + if x != nil { + return x.Beacon + } + return nil +} + +type LightClientBootstrapCapella struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Header *LightClientHeaderCapella `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` + CurrentSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=current_sync_committee_branch,json=currentSyncCommitteeBranch,proto3" json:"current_sync_committee_branch,omitempty" ssz-size:"5,32"` +} + +func (x *LightClientBootstrapCapella) Reset() { + *x = LightClientBootstrapCapella{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientBootstrapCapella) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientBootstrapCapella) ProtoMessage() {} + +func (x *LightClientBootstrapCapella) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientBootstrapCapella.ProtoReflect.Descriptor instead. +func (*LightClientBootstrapCapella) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{5} +} + +func (x *LightClientBootstrapCapella) GetHeader() *LightClientHeaderCapella { + if x != nil { + return x.Header + } + return nil +} + +func (x *LightClientBootstrapCapella) GetCurrentSyncCommittee() *SyncCommittee { + if x != nil { + return x.CurrentSyncCommittee + } + return nil +} + +func (x *LightClientBootstrapCapella) GetCurrentSyncCommitteeBranch() [][]byte { + if x != nil { + return x.CurrentSyncCommitteeBranch + } + return nil +} + +type LightClientUpdateCapella struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderCapella `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + NextSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` + NextSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=next_sync_committee_branch,json=nextSyncCommitteeBranch,proto3" json:"next_sync_committee_branch,omitempty" ssz-size:"5,32"` + FinalizedHeader *LightClientHeaderCapella `protobuf:"bytes,4,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,5,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"6,32"` + SyncAggregate *SyncAggregate `protobuf:"bytes,6,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,7,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientUpdateCapella) Reset() { + *x = LightClientUpdateCapella{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientUpdateCapella) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientUpdateCapella) ProtoMessage() {} + +func (x *LightClientUpdateCapella) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientUpdateCapella.ProtoReflect.Descriptor instead. +func (*LightClientUpdateCapella) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{6} +} + +func (x *LightClientUpdateCapella) GetAttestedHeader() *LightClientHeaderCapella { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientUpdateCapella) GetNextSyncCommittee() *SyncCommittee { + if x != nil { + return x.NextSyncCommittee + } + return nil +} + +func (x *LightClientUpdateCapella) GetNextSyncCommitteeBranch() [][]byte { + if x != nil { + return x.NextSyncCommitteeBranch + } + return nil +} + +func (x *LightClientUpdateCapella) GetFinalizedHeader() *LightClientHeaderCapella { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientUpdateCapella) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientUpdateCapella) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientUpdateCapella) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientFinalityUpdateCapella struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderCapella `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + FinalizedHeader *LightClientHeaderCapella `protobuf:"bytes,2,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,3,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"6,32"` + SyncAggregate *SyncAggregate `protobuf:"bytes,4,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,5,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientFinalityUpdateCapella) Reset() { + *x = LightClientFinalityUpdateCapella{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientFinalityUpdateCapella) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientFinalityUpdateCapella) ProtoMessage() {} + +func (x *LightClientFinalityUpdateCapella) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientFinalityUpdateCapella.ProtoReflect.Descriptor instead. +func (*LightClientFinalityUpdateCapella) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{7} +} + +func (x *LightClientFinalityUpdateCapella) GetAttestedHeader() *LightClientHeaderCapella { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientFinalityUpdateCapella) GetFinalizedHeader() *LightClientHeaderCapella { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientFinalityUpdateCapella) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientFinalityUpdateCapella) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientFinalityUpdateCapella) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientOptimisticUpdateCapella struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderCapella `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + SyncAggregate *SyncAggregate `protobuf:"bytes,2,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,3,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientOptimisticUpdateCapella) Reset() { + *x = LightClientOptimisticUpdateCapella{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientOptimisticUpdateCapella) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientOptimisticUpdateCapella) ProtoMessage() {} + +func (x *LightClientOptimisticUpdateCapella) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientOptimisticUpdateCapella.ProtoReflect.Descriptor instead. +func (*LightClientOptimisticUpdateCapella) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{8} +} + +func (x *LightClientOptimisticUpdateCapella) GetAttestedHeader() *LightClientHeaderCapella { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientOptimisticUpdateCapella) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientOptimisticUpdateCapella) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientHeaderCapella struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Beacon *BeaconBlockHeader `protobuf:"bytes,1,opt,name=beacon,proto3" json:"beacon,omitempty"` + Execution *v1.ExecutionPayloadHeaderCapella `protobuf:"bytes,2,opt,name=execution,proto3" json:"execution,omitempty"` + ExecutionBranch [][]byte `protobuf:"bytes,3,rep,name=execution_branch,json=executionBranch,proto3" json:"execution_branch,omitempty" ssz-size:"4,32"` +} + +func (x *LightClientHeaderCapella) Reset() { + *x = LightClientHeaderCapella{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientHeaderCapella) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientHeaderCapella) ProtoMessage() {} + +func (x *LightClientHeaderCapella) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientHeaderCapella.ProtoReflect.Descriptor instead. +func (*LightClientHeaderCapella) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{9} +} + +func (x *LightClientHeaderCapella) GetBeacon() *BeaconBlockHeader { + if x != nil { + return x.Beacon + } + return nil +} + +func (x *LightClientHeaderCapella) GetExecution() *v1.ExecutionPayloadHeaderCapella { + if x != nil { + return x.Execution + } + return nil +} + +func (x *LightClientHeaderCapella) GetExecutionBranch() [][]byte { + if x != nil { + return x.ExecutionBranch + } + return nil +} + +type LightClientBootstrapDeneb struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Header *LightClientHeaderDeneb `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` + CurrentSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=current_sync_committee_branch,json=currentSyncCommitteeBranch,proto3" json:"current_sync_committee_branch,omitempty" ssz-size:"5,32"` +} + +func (x *LightClientBootstrapDeneb) Reset() { + *x = LightClientBootstrapDeneb{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientBootstrapDeneb) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientBootstrapDeneb) ProtoMessage() {} + +func (x *LightClientBootstrapDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientBootstrapDeneb.ProtoReflect.Descriptor instead. +func (*LightClientBootstrapDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{10} +} + +func (x *LightClientBootstrapDeneb) GetHeader() *LightClientHeaderDeneb { + if x != nil { + return x.Header + } + return nil +} + +func (x *LightClientBootstrapDeneb) GetCurrentSyncCommittee() *SyncCommittee { + if x != nil { + return x.CurrentSyncCommittee + } + return nil +} + +func (x *LightClientBootstrapDeneb) GetCurrentSyncCommitteeBranch() [][]byte { + if x != nil { + return x.CurrentSyncCommitteeBranch + } + return nil +} + +type LightClientUpdateDeneb struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderDeneb `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + NextSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` + NextSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=next_sync_committee_branch,json=nextSyncCommitteeBranch,proto3" json:"next_sync_committee_branch,omitempty" ssz-size:"5,32"` + FinalizedHeader *LightClientHeaderDeneb `protobuf:"bytes,4,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,5,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"6,32"` + SyncAggregate *SyncAggregate `protobuf:"bytes,6,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,7,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientUpdateDeneb) Reset() { + *x = LightClientUpdateDeneb{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientUpdateDeneb) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientUpdateDeneb) ProtoMessage() {} + +func (x *LightClientUpdateDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientUpdateDeneb.ProtoReflect.Descriptor instead. +func (*LightClientUpdateDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{11} +} + +func (x *LightClientUpdateDeneb) GetAttestedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientUpdateDeneb) GetNextSyncCommittee() *SyncCommittee { + if x != nil { + return x.NextSyncCommittee + } + return nil +} + +func (x *LightClientUpdateDeneb) GetNextSyncCommitteeBranch() [][]byte { + if x != nil { + return x.NextSyncCommitteeBranch + } + return nil +} + +func (x *LightClientUpdateDeneb) GetFinalizedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientUpdateDeneb) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientUpdateDeneb) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientUpdateDeneb) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientFinalityUpdateDeneb struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderDeneb `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + FinalizedHeader *LightClientHeaderDeneb `protobuf:"bytes,2,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,3,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"6,32"` + SyncAggregate *SyncAggregate `protobuf:"bytes,4,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,5,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientFinalityUpdateDeneb) Reset() { + *x = LightClientFinalityUpdateDeneb{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientFinalityUpdateDeneb) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientFinalityUpdateDeneb) ProtoMessage() {} + +func (x *LightClientFinalityUpdateDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientFinalityUpdateDeneb.ProtoReflect.Descriptor instead. +func (*LightClientFinalityUpdateDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{12} +} + +func (x *LightClientFinalityUpdateDeneb) GetAttestedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientFinalityUpdateDeneb) GetFinalizedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientFinalityUpdateDeneb) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientFinalityUpdateDeneb) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientFinalityUpdateDeneb) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientOptimisticUpdateDeneb struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderDeneb `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + SyncAggregate *SyncAggregate `protobuf:"bytes,2,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,3,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientOptimisticUpdateDeneb) Reset() { + *x = LightClientOptimisticUpdateDeneb{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientOptimisticUpdateDeneb) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientOptimisticUpdateDeneb) ProtoMessage() {} + +func (x *LightClientOptimisticUpdateDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientOptimisticUpdateDeneb.ProtoReflect.Descriptor instead. +func (*LightClientOptimisticUpdateDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{13} +} + +func (x *LightClientOptimisticUpdateDeneb) GetAttestedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientOptimisticUpdateDeneb) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientOptimisticUpdateDeneb) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientHeaderDeneb struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Beacon *BeaconBlockHeader `protobuf:"bytes,1,opt,name=beacon,proto3" json:"beacon,omitempty"` + Execution *v1.ExecutionPayloadHeaderDeneb `protobuf:"bytes,2,opt,name=execution,proto3" json:"execution,omitempty"` + ExecutionBranch [][]byte `protobuf:"bytes,3,rep,name=execution_branch,json=executionBranch,proto3" json:"execution_branch,omitempty" ssz-size:"4,32"` +} + +func (x *LightClientHeaderDeneb) Reset() { + *x = LightClientHeaderDeneb{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientHeaderDeneb) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientHeaderDeneb) ProtoMessage() {} + +func (x *LightClientHeaderDeneb) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientHeaderDeneb.ProtoReflect.Descriptor instead. +func (*LightClientHeaderDeneb) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{14} +} + +func (x *LightClientHeaderDeneb) GetBeacon() *BeaconBlockHeader { + if x != nil { + return x.Beacon + } + return nil +} + +func (x *LightClientHeaderDeneb) GetExecution() *v1.ExecutionPayloadHeaderDeneb { + if x != nil { + return x.Execution + } + return nil +} + +func (x *LightClientHeaderDeneb) GetExecutionBranch() [][]byte { + if x != nil { + return x.ExecutionBranch + } + return nil +} + +type LightClientBootstrapElectra struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Header *LightClientHeaderDeneb `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + CurrentSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=current_sync_committee,json=currentSyncCommittee,proto3" json:"current_sync_committee,omitempty"` + CurrentSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=current_sync_committee_branch,json=currentSyncCommitteeBranch,proto3" json:"current_sync_committee_branch,omitempty" ssz-size:"6,32"` +} + +func (x *LightClientBootstrapElectra) Reset() { + *x = LightClientBootstrapElectra{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientBootstrapElectra) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientBootstrapElectra) ProtoMessage() {} + +func (x *LightClientBootstrapElectra) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientBootstrapElectra.ProtoReflect.Descriptor instead. +func (*LightClientBootstrapElectra) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{15} +} + +func (x *LightClientBootstrapElectra) GetHeader() *LightClientHeaderDeneb { + if x != nil { + return x.Header + } + return nil +} + +func (x *LightClientBootstrapElectra) GetCurrentSyncCommittee() *SyncCommittee { + if x != nil { + return x.CurrentSyncCommittee + } + return nil +} + +func (x *LightClientBootstrapElectra) GetCurrentSyncCommitteeBranch() [][]byte { + if x != nil { + return x.CurrentSyncCommitteeBranch + } + return nil +} + +type LightClientUpdateElectra struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderDeneb `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + NextSyncCommittee *SyncCommittee `protobuf:"bytes,2,opt,name=next_sync_committee,json=nextSyncCommittee,proto3" json:"next_sync_committee,omitempty"` + NextSyncCommitteeBranch [][]byte `protobuf:"bytes,3,rep,name=next_sync_committee_branch,json=nextSyncCommitteeBranch,proto3" json:"next_sync_committee_branch,omitempty" ssz-size:"6,32"` + FinalizedHeader *LightClientHeaderDeneb `protobuf:"bytes,4,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,5,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-size:"7,32"` + SyncAggregate *SyncAggregate `protobuf:"bytes,6,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,7,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientUpdateElectra) Reset() { + *x = LightClientUpdateElectra{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientUpdateElectra) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientUpdateElectra) ProtoMessage() {} + +func (x *LightClientUpdateElectra) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientUpdateElectra.ProtoReflect.Descriptor instead. +func (*LightClientUpdateElectra) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{16} +} + +func (x *LightClientUpdateElectra) GetAttestedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientUpdateElectra) GetNextSyncCommittee() *SyncCommittee { + if x != nil { + return x.NextSyncCommittee + } + return nil +} + +func (x *LightClientUpdateElectra) GetNextSyncCommitteeBranch() [][]byte { + if x != nil { + return x.NextSyncCommitteeBranch + } + return nil +} + +func (x *LightClientUpdateElectra) GetFinalizedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientUpdateElectra) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientUpdateElectra) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientUpdateElectra) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +type LightClientFinalityUpdateElectra struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AttestedHeader *LightClientHeaderDeneb `protobuf:"bytes,1,opt,name=attested_header,json=attestedHeader,proto3" json:"attested_header,omitempty"` + FinalizedHeader *LightClientHeaderDeneb `protobuf:"bytes,2,opt,name=finalized_header,json=finalizedHeader,proto3" json:"finalized_header,omitempty"` + FinalityBranch [][]byte `protobuf:"bytes,3,rep,name=finality_branch,json=finalityBranch,proto3" json:"finality_branch,omitempty" ssz-max:"7,32"` + SyncAggregate *SyncAggregate `protobuf:"bytes,4,opt,name=sync_aggregate,json=syncAggregate,proto3" json:"sync_aggregate,omitempty"` + SignatureSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,5,opt,name=signature_slot,json=signatureSlot,proto3" json:"signature_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` +} + +func (x *LightClientFinalityUpdateElectra) Reset() { + *x = LightClientFinalityUpdateElectra{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LightClientFinalityUpdateElectra) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LightClientFinalityUpdateElectra) ProtoMessage() {} + +func (x *LightClientFinalityUpdateElectra) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_light_client_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LightClientFinalityUpdateElectra.ProtoReflect.Descriptor instead. +func (*LightClientFinalityUpdateElectra) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP(), []int{17} +} + +func (x *LightClientFinalityUpdateElectra) GetAttestedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.AttestedHeader + } + return nil +} + +func (x *LightClientFinalityUpdateElectra) GetFinalizedHeader() *LightClientHeaderDeneb { + if x != nil { + return x.FinalizedHeader + } + return nil +} + +func (x *LightClientFinalityUpdateElectra) GetFinalityBranch() [][]byte { + if x != nil { + return x.FinalityBranch + } + return nil +} + +func (x *LightClientFinalityUpdateElectra) GetSyncAggregate() *SyncAggregate { + if x != nil { + return x.SyncAggregate + } + return nil +} + +func (x *LightClientFinalityUpdateElectra) GetSignatureSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.SignatureSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +var File_proto_prysm_v1alpha1_light_client_proto protoreflect.FileDescriptor + +var file_proto_prysm_v1alpha1_light_client_proto_rawDesc = []byte{ + 0x0a, 0x27, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8d, 0x02, 0x0a, 0x1a, 0x4c, 0x69, 0x67, 0x68, + 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, + 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x46, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, + 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5a, + 0x0a, 0x16, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, + 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x4b, 0x0a, 0x1d, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x35, 0x2c, 0x33, 0x32, 0x52, 0x1a, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0xd8, 0x04, 0x0a, 0x17, 0x4c, 0x69, 0x67, 0x68, + 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x6c, 0x74, + 0x61, 0x69, 0x72, 0x12, 0x57, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x0e, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x13, + 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, + 0x11, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x12, 0x45, 0x0a, 0x1a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x35, 0x2c, 0x33, 0x32, + 0x52, 0x17, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x59, 0x0a, 0x10, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, + 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x6c, 0x74, + 0x61, 0x69, 0x72, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, + 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, + 0xb5, 0x18, 0x04, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, + 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, + 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, + 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, + 0x6f, 0x74, 0x22, 0xc3, 0x03, 0x0a, 0x1f, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x57, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, + 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x59, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x0f, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0e, 0x66, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x4b, 0x0a, + 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, + 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, + 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, + 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x22, 0xb7, 0x02, 0x0a, 0x21, 0x4c, 0x69, 0x67, + 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, + 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x57, + 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, + 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, + 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, + 0x6f, 0x74, 0x22, 0x5b, 0x0a, 0x17, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x40, 0x0a, + 0x06, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x22, + 0x8f, 0x02, 0x0a, 0x1b, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x42, + 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, + 0x47, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, + 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x16, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x12, 0x4b, 0x0a, 0x1d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, + 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, + 0x04, 0x35, 0x2c, 0x33, 0x32, 0x52, 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, + 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x22, 0xdb, 0x04, 0x0a, 0x18, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x58, + 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x13, 0x6e, 0x65, 0x78, 0x74, + 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, + 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x11, 0x6e, 0x65, 0x78, + 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x45, + 0x0a, 0x1a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x35, 0x2c, 0x33, 0x32, 0x52, 0x17, 0x6e, 0x65, + 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x5a, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, + 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x31, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, + 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, + 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, + 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x22, + 0xc6, 0x03, 0x0a, 0x20, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x46, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x70, + 0x65, 0x6c, 0x6c, 0x61, 0x12, 0x58, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, + 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x0e, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5a, + 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x0f, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0e, 0x66, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x4b, 0x0a, + 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, + 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, + 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, + 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x22, 0xb9, 0x02, 0x0a, 0x22, 0x4c, 0x69, 0x67, + 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, + 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x12, + 0x58, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, + 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, + 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, + 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x53, 0x6c, 0x6f, 0x74, 0x22, 0xe2, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, + 0x61, 0x12, 0x40, 0x0a, 0x06, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x62, 0x65, 0x61, + 0x63, 0x6f, 0x6e, 0x12, 0x4f, 0x0a, 0x09, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x43, 0x61, 0x70, 0x65, 0x6c, 0x6c, 0x61, 0x52, 0x09, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, + 0x8a, 0xb5, 0x18, 0x04, 0x34, 0x2c, 0x33, 0x32, 0x52, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x8b, 0x02, 0x0a, 0x19, 0x4c, 0x69, + 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, + 0x61, 0x70, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x45, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x5a, + 0x0a, 0x16, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, + 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x4b, 0x0a, 0x1d, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x35, 0x2c, 0x33, 0x32, 0x52, 0x1a, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0xd5, 0x04, 0x0a, 0x16, 0x4c, 0x69, 0x67, 0x68, + 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6e, + 0x65, 0x62, 0x12, 0x56, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x13, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x11, 0x6e, + 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, + 0x12, 0x45, 0x0a, 0x1a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x35, 0x2c, 0x33, 0x32, 0x52, 0x17, + 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x58, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, + 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x31, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, + 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, + 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, + 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x22, + 0xc0, 0x03, 0x0a, 0x1e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x46, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6e, + 0x65, 0x62, 0x12, 0x56, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x58, 0x0a, 0x10, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, + 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, + 0x6e, 0x65, 0x62, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, + 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, + 0xb5, 0x18, 0x04, 0x36, 0x2c, 0x33, 0x32, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, + 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, + 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, + 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, + 0x6f, 0x74, 0x22, 0xb5, 0x02, 0x0a, 0x20, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x56, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, + 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, + 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x22, 0xde, 0x01, 0x0a, 0x16, 0x4c, + 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x44, 0x65, 0x6e, 0x65, 0x62, 0x12, 0x40, 0x0a, 0x06, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, + 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, + 0x06, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x12, 0x4d, 0x0a, 0x09, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x09, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x10, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, + 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x34, 0x2c, 0x33, 0x32, 0x52, 0x0f, 0x65, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x8d, 0x02, 0x0a, 0x1b, + 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, + 0x74, 0x72, 0x61, 0x70, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x45, 0x0a, 0x06, 0x68, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x16, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, + 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x4b, + 0x0a, 0x1d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x36, 0x2c, 0x33, 0x32, 0x52, + 0x1a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0xd7, 0x04, 0x0a, 0x18, + 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x56, 0x0a, 0x0f, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, + 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x54, 0x0a, 0x13, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x52, 0x11, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x45, 0x0a, 0x1a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, + 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x62, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, + 0x36, 0x2c, 0x33, 0x32, 0x52, 0x17, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x58, 0x0a, + 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, + 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x37, 0x2c, 0x33, 0x32, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x4b, 0x0a, 0x0e, 0x73, 0x79, + 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, 0x79, 0x6e, 0x63, 0x41, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x42, + 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, + 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, + 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x22, 0xc2, 0x03, 0x0a, 0x20, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x56, 0x0a, 0x0f, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, + 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, + 0x65, 0x62, 0x52, 0x0e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x12, 0x58, 0x0a, 0x10, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x44, 0x65, 0x6e, 0x65, 0x62, 0x52, 0x0f, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x0f, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x37, 0x2c, 0x33, 0x32, 0x52, + 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, + 0x4b, 0x0a, 0x0e, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x53, 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x73, + 0x79, 0x6e, 0x63, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x6c, 0x0a, 0x0e, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0d, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x42, 0x99, 0x01, 0x0a, 0x19, 0x6f, + 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, + 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, + 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_prysm_v1alpha1_light_client_proto_rawDescOnce sync.Once + file_proto_prysm_v1alpha1_light_client_proto_rawDescData = file_proto_prysm_v1alpha1_light_client_proto_rawDesc +) + +func file_proto_prysm_v1alpha1_light_client_proto_rawDescGZIP() []byte { + file_proto_prysm_v1alpha1_light_client_proto_rawDescOnce.Do(func() { + file_proto_prysm_v1alpha1_light_client_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_prysm_v1alpha1_light_client_proto_rawDescData) + }) + return file_proto_prysm_v1alpha1_light_client_proto_rawDescData +} + +var file_proto_prysm_v1alpha1_light_client_proto_msgTypes = make([]protoimpl.MessageInfo, 18) +var file_proto_prysm_v1alpha1_light_client_proto_goTypes = []interface{}{ + (*LightClientBootstrapAltair)(nil), // 0: ethereum.eth.v1alpha1.LightClientBootstrapAltair + (*LightClientUpdateAltair)(nil), // 1: ethereum.eth.v1alpha1.LightClientUpdateAltair + (*LightClientFinalityUpdateAltair)(nil), // 2: ethereum.eth.v1alpha1.LightClientFinalityUpdateAltair + (*LightClientOptimisticUpdateAltair)(nil), // 3: ethereum.eth.v1alpha1.LightClientOptimisticUpdateAltair + (*LightClientHeaderAltair)(nil), // 4: ethereum.eth.v1alpha1.LightClientHeaderAltair + (*LightClientBootstrapCapella)(nil), // 5: ethereum.eth.v1alpha1.LightClientBootstrapCapella + (*LightClientUpdateCapella)(nil), // 6: ethereum.eth.v1alpha1.LightClientUpdateCapella + (*LightClientFinalityUpdateCapella)(nil), // 7: ethereum.eth.v1alpha1.LightClientFinalityUpdateCapella + (*LightClientOptimisticUpdateCapella)(nil), // 8: ethereum.eth.v1alpha1.LightClientOptimisticUpdateCapella + (*LightClientHeaderCapella)(nil), // 9: ethereum.eth.v1alpha1.LightClientHeaderCapella + (*LightClientBootstrapDeneb)(nil), // 10: ethereum.eth.v1alpha1.LightClientBootstrapDeneb + (*LightClientUpdateDeneb)(nil), // 11: ethereum.eth.v1alpha1.LightClientUpdateDeneb + (*LightClientFinalityUpdateDeneb)(nil), // 12: ethereum.eth.v1alpha1.LightClientFinalityUpdateDeneb + (*LightClientOptimisticUpdateDeneb)(nil), // 13: ethereum.eth.v1alpha1.LightClientOptimisticUpdateDeneb + (*LightClientHeaderDeneb)(nil), // 14: ethereum.eth.v1alpha1.LightClientHeaderDeneb + (*LightClientBootstrapElectra)(nil), // 15: ethereum.eth.v1alpha1.LightClientBootstrapElectra + (*LightClientUpdateElectra)(nil), // 16: ethereum.eth.v1alpha1.LightClientUpdateElectra + (*LightClientFinalityUpdateElectra)(nil), // 17: ethereum.eth.v1alpha1.LightClientFinalityUpdateElectra + (*SyncCommittee)(nil), // 18: ethereum.eth.v1alpha1.SyncCommittee + (*SyncAggregate)(nil), // 19: ethereum.eth.v1alpha1.SyncAggregate + (*BeaconBlockHeader)(nil), // 20: ethereum.eth.v1alpha1.BeaconBlockHeader + (*v1.ExecutionPayloadHeaderCapella)(nil), // 21: ethereum.engine.v1.ExecutionPayloadHeaderCapella + (*v1.ExecutionPayloadHeaderDeneb)(nil), // 22: ethereum.engine.v1.ExecutionPayloadHeaderDeneb +} +var file_proto_prysm_v1alpha1_light_client_proto_depIdxs = []int32{ + 4, // 0: ethereum.eth.v1alpha1.LightClientBootstrapAltair.header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderAltair + 18, // 1: ethereum.eth.v1alpha1.LightClientBootstrapAltair.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 4, // 2: ethereum.eth.v1alpha1.LightClientUpdateAltair.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderAltair + 18, // 3: ethereum.eth.v1alpha1.LightClientUpdateAltair.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 4, // 4: ethereum.eth.v1alpha1.LightClientUpdateAltair.finalized_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderAltair + 19, // 5: ethereum.eth.v1alpha1.LightClientUpdateAltair.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 4, // 6: ethereum.eth.v1alpha1.LightClientFinalityUpdateAltair.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderAltair + 4, // 7: ethereum.eth.v1alpha1.LightClientFinalityUpdateAltair.finalized_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderAltair + 19, // 8: ethereum.eth.v1alpha1.LightClientFinalityUpdateAltair.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 4, // 9: ethereum.eth.v1alpha1.LightClientOptimisticUpdateAltair.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderAltair + 19, // 10: ethereum.eth.v1alpha1.LightClientOptimisticUpdateAltair.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 20, // 11: ethereum.eth.v1alpha1.LightClientHeaderAltair.beacon:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader + 9, // 12: ethereum.eth.v1alpha1.LightClientBootstrapCapella.header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderCapella + 18, // 13: ethereum.eth.v1alpha1.LightClientBootstrapCapella.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 9, // 14: ethereum.eth.v1alpha1.LightClientUpdateCapella.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderCapella + 18, // 15: ethereum.eth.v1alpha1.LightClientUpdateCapella.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 9, // 16: ethereum.eth.v1alpha1.LightClientUpdateCapella.finalized_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderCapella + 19, // 17: ethereum.eth.v1alpha1.LightClientUpdateCapella.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 9, // 18: ethereum.eth.v1alpha1.LightClientFinalityUpdateCapella.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderCapella + 9, // 19: ethereum.eth.v1alpha1.LightClientFinalityUpdateCapella.finalized_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderCapella + 19, // 20: ethereum.eth.v1alpha1.LightClientFinalityUpdateCapella.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 9, // 21: ethereum.eth.v1alpha1.LightClientOptimisticUpdateCapella.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderCapella + 19, // 22: ethereum.eth.v1alpha1.LightClientOptimisticUpdateCapella.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 20, // 23: ethereum.eth.v1alpha1.LightClientHeaderCapella.beacon:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader + 21, // 24: ethereum.eth.v1alpha1.LightClientHeaderCapella.execution:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderCapella + 14, // 25: ethereum.eth.v1alpha1.LightClientBootstrapDeneb.header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 18, // 26: ethereum.eth.v1alpha1.LightClientBootstrapDeneb.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 14, // 27: ethereum.eth.v1alpha1.LightClientUpdateDeneb.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 18, // 28: ethereum.eth.v1alpha1.LightClientUpdateDeneb.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 14, // 29: ethereum.eth.v1alpha1.LightClientUpdateDeneb.finalized_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 19, // 30: ethereum.eth.v1alpha1.LightClientUpdateDeneb.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 14, // 31: ethereum.eth.v1alpha1.LightClientFinalityUpdateDeneb.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 14, // 32: ethereum.eth.v1alpha1.LightClientFinalityUpdateDeneb.finalized_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 19, // 33: ethereum.eth.v1alpha1.LightClientFinalityUpdateDeneb.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 14, // 34: ethereum.eth.v1alpha1.LightClientOptimisticUpdateDeneb.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 19, // 35: ethereum.eth.v1alpha1.LightClientOptimisticUpdateDeneb.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 20, // 36: ethereum.eth.v1alpha1.LightClientHeaderDeneb.beacon:type_name -> ethereum.eth.v1alpha1.BeaconBlockHeader + 22, // 37: ethereum.eth.v1alpha1.LightClientHeaderDeneb.execution:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderDeneb + 14, // 38: ethereum.eth.v1alpha1.LightClientBootstrapElectra.header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 18, // 39: ethereum.eth.v1alpha1.LightClientBootstrapElectra.current_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 14, // 40: ethereum.eth.v1alpha1.LightClientUpdateElectra.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 18, // 41: ethereum.eth.v1alpha1.LightClientUpdateElectra.next_sync_committee:type_name -> ethereum.eth.v1alpha1.SyncCommittee + 14, // 42: ethereum.eth.v1alpha1.LightClientUpdateElectra.finalized_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 19, // 43: ethereum.eth.v1alpha1.LightClientUpdateElectra.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 14, // 44: ethereum.eth.v1alpha1.LightClientFinalityUpdateElectra.attested_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 14, // 45: ethereum.eth.v1alpha1.LightClientFinalityUpdateElectra.finalized_header:type_name -> ethereum.eth.v1alpha1.LightClientHeaderDeneb + 19, // 46: ethereum.eth.v1alpha1.LightClientFinalityUpdateElectra.sync_aggregate:type_name -> ethereum.eth.v1alpha1.SyncAggregate + 47, // [47:47] is the sub-list for method output_type + 47, // [47:47] is the sub-list for method input_type + 47, // [47:47] is the sub-list for extension type_name + 47, // [47:47] is the sub-list for extension extendee + 0, // [0:47] is the sub-list for field type_name +} + +func init() { file_proto_prysm_v1alpha1_light_client_proto_init() } +func file_proto_prysm_v1alpha1_light_client_proto_init() { + if File_proto_prysm_v1alpha1_light_client_proto != nil { + return + } + file_proto_prysm_v1alpha1_beacon_block_proto_init() + file_proto_prysm_v1alpha1_beacon_state_proto_init() + if !protoimpl.UnsafeEnabled { + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientBootstrapAltair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientUpdateAltair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientFinalityUpdateAltair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientOptimisticUpdateAltair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientHeaderAltair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientBootstrapCapella); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientUpdateCapella); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientFinalityUpdateCapella); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientOptimisticUpdateCapella); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientHeaderCapella); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientBootstrapDeneb); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientUpdateDeneb); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientFinalityUpdateDeneb); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientOptimisticUpdateDeneb); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientHeaderDeneb); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientBootstrapElectra); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientUpdateElectra); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_light_client_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LightClientFinalityUpdateElectra); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_prysm_v1alpha1_light_client_proto_rawDesc, + NumEnums: 0, + NumMessages: 18, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_prysm_v1alpha1_light_client_proto_goTypes, + DependencyIndexes: file_proto_prysm_v1alpha1_light_client_proto_depIdxs, + MessageInfos: file_proto_prysm_v1alpha1_light_client_proto_msgTypes, + }.Build() + File_proto_prysm_v1alpha1_light_client_proto = out.File + file_proto_prysm_v1alpha1_light_client_proto_rawDesc = nil + file_proto_prysm_v1alpha1_light_client_proto_goTypes = nil + file_proto_prysm_v1alpha1_light_client_proto_depIdxs = nil +} diff --git a/proto/prysm/v1alpha1/light_client.proto b/proto/prysm/v1alpha1/light_client.proto new file mode 100644 index 000000000000..dfadfe987c7d --- /dev/null +++ b/proto/prysm/v1alpha1/light_client.proto @@ -0,0 +1,213 @@ +// Copyright 2024 Prysmatic Labs. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +syntax = "proto3"; + +package ethereum.eth.v1alpha1; + +import "proto/eth/ext/options.proto"; +import "proto/prysm/v1alpha1/beacon_block.proto"; +import "proto/engine/v1/execution_engine.proto"; +import "proto/prysm/v1alpha1/beacon_state.proto"; + +option csharp_namespace = "Ethereum.Eth.V1alpha1"; +option go_package = "github.com/prysmaticlabs/prysm/v5/proto/eth/v1alpha1;eth"; +option java_multiple_files = true; +option java_outer_classname = "LightClientProto"; +option java_package = "org.ethereum.eth.v1alpha1"; +option php_namespace = "Ethereum\\Eth\\v1alpha1"; + +// ---------------------------------------------------------------------------- +// Altair & Bellatrix +// ---------------------------------------------------------------------------- + +message LightClientBootstrapAltair { + LightClientHeaderAltair header = 1; + SyncCommittee current_sync_committee = 2; + repeated bytes current_sync_committee_branch = 3 + [ (ethereum.eth.ext.ssz_size) = "5,32" ]; +} + +message LightClientUpdateAltair { + LightClientHeaderAltair attested_header = 1; + SyncCommittee next_sync_committee = 2; + repeated bytes next_sync_committee_branch = 3 + [ (ethereum.eth.ext.ssz_size) = "5,32" ]; + LightClientHeaderAltair finalized_header = 4; + repeated bytes finality_branch = 5 [ (ethereum.eth.ext.ssz_size) = "6,32" ]; + SyncAggregate sync_aggregate = 6; + uint64 signature_slot = 7 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientFinalityUpdateAltair { + LightClientHeaderAltair attested_header = 1; + LightClientHeaderAltair finalized_header = 2; + repeated bytes finality_branch = 3 [ (ethereum.eth.ext.ssz_size) = "6,32" ]; + SyncAggregate sync_aggregate = 4; + uint64 signature_slot = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientOptimisticUpdateAltair { + LightClientHeaderAltair attested_header = 1; + SyncAggregate sync_aggregate = 2; + uint64 signature_slot = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientHeaderAltair { BeaconBlockHeader beacon = 1; } + +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + +message LightClientBootstrapCapella { + LightClientHeaderCapella header = 1; + SyncCommittee current_sync_committee = 2; + repeated bytes current_sync_committee_branch = 3 + [ (ethereum.eth.ext.ssz_size) = "5,32" ]; +} + +message LightClientUpdateCapella { + LightClientHeaderCapella attested_header = 1; + SyncCommittee next_sync_committee = 2; + repeated bytes next_sync_committee_branch = 3 + [ (ethereum.eth.ext.ssz_size) = "5,32" ]; + LightClientHeaderCapella finalized_header = 4; + repeated bytes finality_branch = 5 [ (ethereum.eth.ext.ssz_size) = "6,32" ]; + SyncAggregate sync_aggregate = 6; + uint64 signature_slot = 7 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientFinalityUpdateCapella { + LightClientHeaderCapella attested_header = 1; + LightClientHeaderCapella finalized_header = 2; + repeated bytes finality_branch = 3 [ (ethereum.eth.ext.ssz_size) = "6,32" ]; + SyncAggregate sync_aggregate = 4; + uint64 signature_slot = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientOptimisticUpdateCapella { + LightClientHeaderCapella attested_header = 1; + SyncAggregate sync_aggregate = 2; + uint64 signature_slot = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientHeaderCapella { + BeaconBlockHeader beacon = 1; + ethereum.engine.v1.ExecutionPayloadHeaderCapella execution = 2; + repeated bytes execution_branch = 3 [ (ethereum.eth.ext.ssz_size) = "4,32" ]; +} + +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + +message LightClientBootstrapDeneb { + LightClientHeaderDeneb header = 1; + SyncCommittee current_sync_committee = 2; + repeated bytes current_sync_committee_branch = 3 + [ (ethereum.eth.ext.ssz_size) = "5,32" ]; +} + +message LightClientUpdateDeneb { + LightClientHeaderDeneb attested_header = 1; + SyncCommittee next_sync_committee = 2; + repeated bytes next_sync_committee_branch = 3 + [ (ethereum.eth.ext.ssz_size) = "5,32" ]; + LightClientHeaderDeneb finalized_header = 4; + repeated bytes finality_branch = 5 [ (ethereum.eth.ext.ssz_size) = "6,32" ]; + SyncAggregate sync_aggregate = 6; + uint64 signature_slot = 7 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientFinalityUpdateDeneb { + LightClientHeaderDeneb attested_header = 1; + LightClientHeaderDeneb finalized_header = 2; + repeated bytes finality_branch = 3 [ (ethereum.eth.ext.ssz_size) = "6,32" ]; + SyncAggregate sync_aggregate = 4; + uint64 signature_slot = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientOptimisticUpdateDeneb { + LightClientHeaderDeneb attested_header = 1; + SyncAggregate sync_aggregate = 2; + uint64 signature_slot = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientHeaderDeneb { + BeaconBlockHeader beacon = 1; + ethereum.engine.v1.ExecutionPayloadHeaderDeneb execution = 2; + repeated bytes execution_branch = 3 [ (ethereum.eth.ext.ssz_size) = "4,32" ]; +} + +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +message LightClientBootstrapElectra { + LightClientHeaderDeneb header = 1; + SyncCommittee current_sync_committee = 2; + repeated bytes current_sync_committee_branch = 3 + [ (ethereum.eth.ext.ssz_size) = "6,32" ]; +} + +message LightClientUpdateElectra { + LightClientHeaderDeneb attested_header = 1; + SyncCommittee next_sync_committee = 2; + repeated bytes next_sync_committee_branch = 3 + [ (ethereum.eth.ext.ssz_size) = "6,32" ]; + LightClientHeaderDeneb finalized_header = 4; + repeated bytes finality_branch = 5 [ (ethereum.eth.ext.ssz_size) = "7,32" ]; + SyncAggregate sync_aggregate = 6; + uint64 signature_slot = 7 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} + +message LightClientFinalityUpdateElectra { + LightClientHeaderDeneb attested_header = 1; + LightClientHeaderDeneb finalized_header = 2; + repeated bytes finality_branch = 3 [ (ethereum.eth.ext.ssz_max) = "7,32" ]; + SyncAggregate sync_aggregate = 4; + uint64 signature_slot = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; +} \ No newline at end of file diff --git a/proto/prysm/v1alpha1/metadata/metadata_interfaces.go b/proto/prysm/v1alpha1/metadata/metadata_interfaces.go index 1135e32c6a00..b3b2b8ec0f0f 100644 --- a/proto/prysm/v1alpha1/metadata/metadata_interfaces.go +++ b/proto/prysm/v1alpha1/metadata/metadata_interfaces.go @@ -10,6 +10,7 @@ import ( type Metadata interface { SequenceNumber() uint64 AttnetsBitfield() bitfield.Bitvector64 + SyncnetsBitfield() bitfield.Bitvector4 InnerObject() interface{} IsNil() bool Copy() Metadata diff --git a/proto/prysm/v1alpha1/node.pb.go b/proto/prysm/v1alpha1/node.pb.go index ac175b8329c1..a4ef0f7e8e05 100755 --- a/proto/prysm/v1alpha1/node.pb.go +++ b/proto/prysm/v1alpha1/node.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/node.proto package eth diff --git a/proto/prysm/v1alpha1/node.pb.gw.go b/proto/prysm/v1alpha1/node.pb.gw.go deleted file mode 100755 index 104633765f54..000000000000 --- a/proto/prysm/v1alpha1/node.pb.gw.go +++ /dev/null @@ -1,711 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: proto/prysm/v1alpha1/node.proto - -/* -Package eth is a reverse proxy. - -It translates gRPC into RESTful JSON APIs. -*/ -package eth - -import ( - "context" - "io" - "net/http" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/emptypb" -) - -// Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join -var _ = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) -var _ = emptypb.Empty{} - -func request_Node_GetSyncStatus_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetSyncStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_GetSyncStatus_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetSyncStatus(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Node_GetGenesis_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetGenesis(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_GetGenesis_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetGenesis(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Node_GetVersion_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetVersion(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_GetVersion_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetVersion(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_Node_GetHealth_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_Node_GetHealth_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq HealthRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Node_GetHealth_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetHealth(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_GetHealth_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq HealthRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Node_GetHealth_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetHealth(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Node_ListImplementedServices_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.ListImplementedServices(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_ListImplementedServices_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.ListImplementedServices(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Node_GetHost_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetHost(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_GetHost_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetHost(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_Node_GetPeer_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_Node_GetPeer_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq PeerRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Node_GetPeer_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetPeer(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_GetPeer_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq PeerRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Node_GetPeer_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetPeer(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Node_ListPeers_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.ListPeers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_ListPeers_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.ListPeers(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Node_GetETH1ConnectionStatus_0(ctx context.Context, marshaler runtime.Marshaler, client NodeClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetETH1ConnectionStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Node_GetETH1ConnectionStatus_0(ctx context.Context, marshaler runtime.Marshaler, server NodeServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetETH1ConnectionStatus(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterNodeHandlerServer registers the http handlers for service Node to "mux". -// UnaryRPC :call NodeServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterNodeHandlerFromEndpoint instead. -func RegisterNodeHandlerServer(ctx context.Context, mux *runtime.ServeMux, server NodeServer) error { - - mux.Handle("GET", pattern_Node_GetSyncStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetSyncStatus") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_GetSyncStatus_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetSyncStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetGenesis_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetGenesis") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_GetGenesis_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetGenesis_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetVersion") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_GetVersion_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetVersion_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetHealth_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetHealth") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_GetHealth_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetHealth_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_ListImplementedServices_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/ListImplementedServices") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_ListImplementedServices_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_ListImplementedServices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetHost_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetHost") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_GetHost_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetHost_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetPeer_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetPeer") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_GetPeer_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetPeer_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_ListPeers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/ListPeers") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_ListPeers_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_ListPeers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetETH1ConnectionStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetETH1ConnectionStatus") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Node_GetETH1ConnectionStatus_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetETH1ConnectionStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -// RegisterNodeHandlerFromEndpoint is same as RegisterNodeHandler but -// automatically dials to "endpoint" and closes the connection when "ctx" gets done. -func RegisterNodeHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) - if err != nil { - return err - } - defer func() { - if err != nil { - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - return - } - go func() { - <-ctx.Done() - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - }() - }() - - return RegisterNodeHandler(ctx, mux, conn) -} - -// RegisterNodeHandler registers the http handlers for service Node to "mux". -// The handlers forward requests to the grpc endpoint over "conn". -func RegisterNodeHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { - return RegisterNodeHandlerClient(ctx, mux, NewNodeClient(conn)) -} - -// RegisterNodeHandlerClient registers the http handlers for service Node -// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "NodeClient". -// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "NodeClient" -// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "NodeClient" to call the correct interceptors. -func RegisterNodeHandlerClient(ctx context.Context, mux *runtime.ServeMux, client NodeClient) error { - - mux.Handle("GET", pattern_Node_GetSyncStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetSyncStatus") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_GetSyncStatus_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetSyncStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetGenesis_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetGenesis") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_GetGenesis_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetGenesis_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetVersion") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_GetVersion_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetVersion_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetHealth_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetHealth") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_GetHealth_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetHealth_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_ListImplementedServices_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/ListImplementedServices") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_ListImplementedServices_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_ListImplementedServices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetHost_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetHost") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_GetHost_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetHost_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetPeer_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetPeer") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_GetPeer_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetPeer_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_ListPeers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/ListPeers") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_ListPeers_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_ListPeers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Node_GetETH1ConnectionStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.Node/GetETH1ConnectionStatus") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Node_GetETH1ConnectionStatus_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Node_GetETH1ConnectionStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Node_GetSyncStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "node", "syncing"}, "")) - - pattern_Node_GetGenesis_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "node", "genesis"}, "")) - - pattern_Node_GetVersion_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "node", "version"}, "")) - - pattern_Node_GetHealth_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "node", "health"}, "")) - - pattern_Node_ListImplementedServices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "node", "services"}, "")) - - pattern_Node_GetHost_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "node", "p2p"}, "")) - - pattern_Node_GetPeer_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "node", "peer"}, "")) - - pattern_Node_ListPeers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "node", "peers"}, "")) - - pattern_Node_GetETH1ConnectionStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "node", "eth1", "connections"}, "")) -) - -var ( - forward_Node_GetSyncStatus_0 = runtime.ForwardResponseMessage - - forward_Node_GetGenesis_0 = runtime.ForwardResponseMessage - - forward_Node_GetVersion_0 = runtime.ForwardResponseMessage - - forward_Node_GetHealth_0 = runtime.ForwardResponseMessage - - forward_Node_ListImplementedServices_0 = runtime.ForwardResponseMessage - - forward_Node_GetHost_0 = runtime.ForwardResponseMessage - - forward_Node_GetPeer_0 = runtime.ForwardResponseMessage - - forward_Node_ListPeers_0 = runtime.ForwardResponseMessage - - forward_Node_GetETH1ConnectionStatus_0 = runtime.ForwardResponseMessage -) diff --git a/proto/prysm/v1alpha1/node.proto b/proto/prysm/v1alpha1/node.proto index a0f8a510b654..2ebca48c2c05 100644 --- a/proto/prysm/v1alpha1/node.proto +++ b/proto/prysm/v1alpha1/node.proto @@ -33,145 +33,143 @@ option php_namespace = "Ethereum\\Eth\\v1alpha1"; // Node service provides general information about the node itself, the services // it supports, chain information and node version. service Node { - // Retrieve the current network sync status of the node. - rpc GetSyncStatus(google.protobuf.Empty) returns (SyncStatus) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/syncing" - }; - } - - // Retrieve information about the genesis of Ethereum proof of stake. - rpc GetGenesis(google.protobuf.Empty) returns (Genesis) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/genesis" - }; - } - - // Retrieve information about the running Ethereum Beacon Node. - rpc GetVersion(google.protobuf.Empty) returns (Version) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/version" - }; - } - - // Retrieve the current health of the node. - rpc GetHealth(HealthRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/health" - }; - } - - // Retrieve the list of services implemented and enabled by this node. - // - // Any service not present in this list may return UNIMPLEMENTED or - // PERMISSION_DENIED. The server may also support fetching services by grpc - // reflection. - rpc ListImplementedServices(google.protobuf.Empty) returns (ImplementedServices) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/services" - }; - } - - // Retrieves the peer data of the local peer. - rpc GetHost(google.protobuf.Empty) returns (HostData) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/p2p" - }; - } - - // Retrieve the peer corresponding to the provided peer id. - rpc GetPeer(PeerRequest) returns (Peer) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/peer" - }; - } - - // Retrieve the list of peers currently connected to this node. - rpc ListPeers(google.protobuf.Empty) returns (Peers) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/peers" - }; - } - - // // Retrieve the status of the ETH1 connections. - rpc GetETH1ConnectionStatus(google.protobuf.Empty) returns (ETH1ConnectionStatus) { - option (google.api.http) = { - get: "/eth/v1alpha1/node/eth1/connections" - }; - } + // Retrieve the current network sync status of the node. + rpc GetSyncStatus(google.protobuf.Empty) returns (SyncStatus) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/syncing" + }; + } + + // Retrieve information about the genesis of Ethereum proof of stake. + rpc GetGenesis(google.protobuf.Empty) returns (Genesis) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/genesis" + }; + } + + // Retrieve information about the running Ethereum Beacon Node. + rpc GetVersion(google.protobuf.Empty) returns (Version) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/version" + }; + } + + // Retrieve the current health of the node. + rpc GetHealth(HealthRequest) returns (google.protobuf.Empty) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/health" + }; + } + + // Retrieve the list of services implemented and enabled by this node. + // + // Any service not present in this list may return UNIMPLEMENTED or + // PERMISSION_DENIED. The server may also support fetching services by grpc + // reflection. + rpc ListImplementedServices(google.protobuf.Empty) + returns (ImplementedServices) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/services" + }; + } + + // Retrieves the peer data of the local peer. + rpc GetHost(google.protobuf.Empty) returns (HostData) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/p2p" + }; + } + + // Retrieve the peer corresponding to the provided peer id. + rpc GetPeer(PeerRequest) returns (Peer) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/peer" + }; + } + + // Retrieve the list of peers currently connected to this node. + rpc ListPeers(google.protobuf.Empty) returns (Peers) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/peers" + }; + } + + // // Retrieve the status of the ETH1 connections. + rpc GetETH1ConnectionStatus(google.protobuf.Empty) + returns (ETH1ConnectionStatus) { + option (google.api.http) = { + get : "/eth/v1alpha1/node/eth1/connections" + }; + } } -message HealthRequest { - uint64 syncing_status = 1; -} +message HealthRequest { uint64 syncing_status = 1; } // Information about the current network sync status of the node. message SyncStatus { - // Whether or not the node is currently syncing. - bool syncing = 1; + // Whether or not the node is currently syncing. + bool syncing = 1; } // Information about the genesis of Ethereum proof of stake. message Genesis { - // UTC time specified in the chain start event in the deposit contract. - google.protobuf.Timestamp genesis_time = 1; + // UTC time specified in the chain start event in the deposit contract. + google.protobuf.Timestamp genesis_time = 1; - // Address of the deposit contract in the Ethereum 1 chain. - bytes deposit_contract_address = 2; + // Address of the deposit contract in the Ethereum 1 chain. + bytes deposit_contract_address = 2; - // Root of the genesis validators deposits; used for domain separation - // when signing data structures for this chain. - bytes genesis_validators_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // Root of the genesis validators deposits; used for domain separation + // when signing data structures for this chain. + bytes genesis_validators_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; } // Information about the node version. message Version { - // A string that uniquely identifies the node and its version. - string version = 1; + // A string that uniquely identifies the node and its version. + string version = 1; - // Additional metadata that the node would like to provide. This field may - // be used to list any meaningful data to the client. - string metadata = 2; + // Additional metadata that the node would like to provide. This field may + // be used to list any meaningful data to the client. + string metadata = 2; } -message ImplementedServices { - repeated string services = 1; -} +message ImplementedServices { repeated string services = 1; } message PeerRequest { - // Peer id of the peer requested. - string peer_id = 1; + // Peer id of the peer requested. + string peer_id = 1; } // Peers is a list of peer messages. -message Peers { - repeated Peer peers = 1; -} +message Peers { repeated Peer peers = 1; } // Peer provides details of a peer on the network. message Peer { - // The address of the peer, as a full multiaddr, for example: - // /ip4/37.221.192.134/tcp/13000/p2p/16Uiu2HAm8maLMjag1TAUM52zPfmLbVMGFdwUAWgoHu1HDQLR6e17 - string address = 1; - // The direction of the connection (inbound/outbound). - PeerDirection direction = 2; - // The connection state of the peer at the moment of the request. (e.g. Connecting) - ConnectionState connection_state = 3; - // The peer id of the peer. - string peer_id = 4; - // The latest ENR of the peer that's in the record. - string enr = 5; + // The address of the peer, as a full multiaddr, for example: + // /ip4/37.221.192.134/tcp/13000/p2p/16Uiu2HAm8maLMjag1TAUM52zPfmLbVMGFdwUAWgoHu1HDQLR6e17 + string address = 1; + // The direction of the connection (inbound/outbound). + PeerDirection direction = 2; + // The connection state of the peer at the moment of the request. (e.g. + // Connecting) + ConnectionState connection_state = 3; + // The peer id of the peer. + string peer_id = 4; + // The latest ENR of the peer that's in the record. + string enr = 5; } // P2P Data on the local host. message HostData { - // All the multiaddress of the peer, specified as a full multiaddr, for example: - // /ip4/37.221.192.134/tcp/13000/p2p/16Uiu2HAm8maLMjag1TAUM52zPfmLbVMGFdwUAWgoHu1HDQLR6e17 - repeated string addresses = 1; - // The peer id of the peer. - string peer_id = 2; - // The latest ENR of the local peer. - string enr = 3; + // All the multiaddress of the peer, specified as a full multiaddr, for + // example: + // /ip4/37.221.192.134/tcp/13000/p2p/16Uiu2HAm8maLMjag1TAUM52zPfmLbVMGFdwUAWgoHu1HDQLR6e17 + repeated string addresses = 1; + // The peer id of the peer. + string peer_id = 2; + // The latest ENR of the local peer. + string enr = 3; } // PeerDirection states the direction of the connection to a peer. @@ -183,24 +181,24 @@ enum PeerDirection { // ConnectionState states the current status of the peer. enum ConnectionState { - DISCONNECTED = 0; - DISCONNECTING = 1; - CONNECTED = 2; - CONNECTING = 3; + DISCONNECTED = 0; + DISCONNECTING = 1; + CONNECTED = 2; + CONNECTING = 3; } // ETH1ConnectionStatus states the current address and error of the ETH1 API -// endpoint. It also provides the addresses and errors for any fallback URLs. +// endpoint. It also provides the addresses and errors for any fallback URLs. message ETH1ConnectionStatus { - // Current ETH1 HTTP endpoint. - string current_address = 1; + // Current ETH1 HTTP endpoint. + string current_address = 1; - // Current error (if any) of the current connection. - string current_connection_error = 2; + // Current error (if any) of the current connection. + string current_connection_error = 2; - // A list of all provider URLs. - repeated string addresses = 3; + // A list of all provider URLs. + repeated string addresses = 3; - // Current error (if any) of the HTTP connections. - repeated string connection_errors = 4; + // Current error (if any) of the HTTP connections. + repeated string connection_errors = 4; } diff --git a/proto/prysm/v1alpha1/non-core.ssz.go b/proto/prysm/v1alpha1/non-core.ssz.go index 2c720bc17b34..58e5e30d402d 100644 --- a/proto/prysm/v1alpha1/non-core.ssz.go +++ b/proto/prysm/v1alpha1/non-core.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 6fe6b8a92c8bbb2fc95fc59fca0b73d1c787c00ec01137d73193b5b251e40c12 package eth import ( @@ -8,6 +7,89 @@ import ( v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ) +// MarshalSSZ ssz marshals the SignedValidatorRegistrationV1 object +func (s *SignedValidatorRegistrationV1) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedValidatorRegistrationV1 object to a target array +func (s *SignedValidatorRegistrationV1) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(ValidatorRegistrationV1) + } + if dst, err = s.Message.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedValidatorRegistrationV1 object +func (s *SignedValidatorRegistrationV1) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 180 { + return ssz.ErrSize + } + + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(ValidatorRegistrationV1) + } + if err = s.Message.UnmarshalSSZ(buf[0:84]); err != nil { + return err + } + + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[84:180])) + } + s.Signature = append(s.Signature, buf[84:180]...) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedValidatorRegistrationV1 object +func (s *SignedValidatorRegistrationV1) SizeSSZ() (size int) { + size = 180 + return +} + +// HashTreeRoot ssz hashes the SignedValidatorRegistrationV1 object +func (s *SignedValidatorRegistrationV1) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedValidatorRegistrationV1 object with a hasher +func (s *SignedValidatorRegistrationV1) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Message' + if err = s.Message.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(s.Signature) + + hh.Merkleize(indx) + return +} + // MarshalSSZ ssz marshals the ValidatorRegistrationV1 object func (v *ValidatorRegistrationV1) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(v) @@ -108,89 +190,6 @@ func (v *ValidatorRegistrationV1) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the SignedValidatorRegistrationV1 object -func (s *SignedValidatorRegistrationV1) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedValidatorRegistrationV1 object to a target array -func (s *SignedValidatorRegistrationV1) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(ValidatorRegistrationV1) - } - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedValidatorRegistrationV1 object -func (s *SignedValidatorRegistrationV1) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 180 { - return ssz.ErrSize - } - - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(ValidatorRegistrationV1) - } - if err = s.Message.UnmarshalSSZ(buf[0:84]); err != nil { - return err - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[84:180])) - } - s.Signature = append(s.Signature, buf[84:180]...) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedValidatorRegistrationV1 object -func (s *SignedValidatorRegistrationV1) SizeSSZ() (size int) { - size = 180 - return -} - -// HashTreeRoot ssz hashes the SignedValidatorRegistrationV1 object -func (s *SignedValidatorRegistrationV1) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedValidatorRegistrationV1 object with a hasher -func (s *SignedValidatorRegistrationV1) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - // MarshalSSZ ssz marshals the BuilderBid object func (b *BuilderBid) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) @@ -551,6 +550,106 @@ func (m *MetaDataV1) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } +// MarshalSSZ ssz marshals the MetaDataV2 object +func (m *MetaDataV2) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(m) +} + +// MarshalSSZTo ssz marshals the MetaDataV2 object to a target array +func (m *MetaDataV2) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'SeqNumber' + dst = ssz.MarshalUint64(dst, m.SeqNumber) + + // Field (1) 'Attnets' + if size := len(m.Attnets); size != 8 { + err = ssz.ErrBytesLengthFn("--.Attnets", size, 8) + return + } + dst = append(dst, m.Attnets...) + + // Field (2) 'Syncnets' + if size := len(m.Syncnets); size != 1 { + err = ssz.ErrBytesLengthFn("--.Syncnets", size, 1) + return + } + dst = append(dst, m.Syncnets...) + + // Field (3) 'CustodySubnetCount' + dst = ssz.MarshalUint64(dst, m.CustodySubnetCount) + + return +} + +// UnmarshalSSZ ssz unmarshals the MetaDataV2 object +func (m *MetaDataV2) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 25 { + return ssz.ErrSize + } + + // Field (0) 'SeqNumber' + m.SeqNumber = ssz.UnmarshallUint64(buf[0:8]) + + // Field (1) 'Attnets' + if cap(m.Attnets) == 0 { + m.Attnets = make([]byte, 0, len(buf[8:16])) + } + m.Attnets = append(m.Attnets, buf[8:16]...) + + // Field (2) 'Syncnets' + if cap(m.Syncnets) == 0 { + m.Syncnets = make([]byte, 0, len(buf[16:17])) + } + m.Syncnets = append(m.Syncnets, buf[16:17]...) + + // Field (3) 'CustodySubnetCount' + m.CustodySubnetCount = ssz.UnmarshallUint64(buf[17:25]) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the MetaDataV2 object +func (m *MetaDataV2) SizeSSZ() (size int) { + size = 25 + return +} + +// HashTreeRoot ssz hashes the MetaDataV2 object +func (m *MetaDataV2) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(m) +} + +// HashTreeRootWith ssz hashes the MetaDataV2 object with a hasher +func (m *MetaDataV2) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'SeqNumber' + hh.PutUint64(m.SeqNumber) + + // Field (1) 'Attnets' + if size := len(m.Attnets); size != 8 { + err = ssz.ErrBytesLengthFn("--.Attnets", size, 8) + return + } + hh.PutBytes(m.Attnets) + + // Field (2) 'Syncnets' + if size := len(m.Syncnets); size != 1 { + err = ssz.ErrBytesLengthFn("--.Syncnets", size, 1) + return + } + hh.PutBytes(m.Syncnets) + + // Field (3) 'CustodySubnetCount' + hh.PutUint64(m.CustodySubnetCount) + + hh.Merkleize(indx) + return +} + // MarshalSSZ ssz marshals the BlobSidecarsByRangeRequest object func (b *BlobSidecarsByRangeRequest) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) @@ -611,6 +710,124 @@ func (b *BlobSidecarsByRangeRequest) HashTreeRootWith(hh *ssz.Hasher) (err error return } +// MarshalSSZ ssz marshals the DataColumnSidecarsByRangeRequest object +func (d *DataColumnSidecarsByRangeRequest) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(d) +} + +// MarshalSSZTo ssz marshals the DataColumnSidecarsByRangeRequest object to a target array +func (d *DataColumnSidecarsByRangeRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(20) + + // Field (0) 'StartSlot' + dst = ssz.MarshalUint64(dst, uint64(d.StartSlot)) + + // Field (1) 'Count' + dst = ssz.MarshalUint64(dst, d.Count) + + // Offset (2) 'Columns' + dst = ssz.WriteOffset(dst, offset) + offset += len(d.Columns) * 8 + + // Field (2) 'Columns' + if size := len(d.Columns); size > 128 { + err = ssz.ErrListTooBigFn("--.Columns", size, 128) + return + } + for ii := 0; ii < len(d.Columns); ii++ { + dst = ssz.MarshalUint64(dst, d.Columns[ii]) + } + + return +} + +// UnmarshalSSZ ssz unmarshals the DataColumnSidecarsByRangeRequest object +func (d *DataColumnSidecarsByRangeRequest) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 20 { + return ssz.ErrSize + } + + tail := buf + var o2 uint64 + + // Field (0) 'StartSlot' + d.StartSlot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'Count' + d.Count = ssz.UnmarshallUint64(buf[8:16]) + + // Offset (2) 'Columns' + if o2 = ssz.ReadOffset(buf[16:20]); o2 > size { + return ssz.ErrOffset + } + + if o2 != 20 { + return ssz.ErrInvalidVariableOffset + } + + // Field (2) 'Columns' + { + buf = tail[o2:] + num, err := ssz.DivideInt2(len(buf), 8, 128) + if err != nil { + return err + } + d.Columns = ssz.ExtendUint64(d.Columns, num) + for ii := 0; ii < num; ii++ { + d.Columns[ii] = ssz.UnmarshallUint64(buf[ii*8 : (ii+1)*8]) + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the DataColumnSidecarsByRangeRequest object +func (d *DataColumnSidecarsByRangeRequest) SizeSSZ() (size int) { + size = 20 + + // Field (2) 'Columns' + size += len(d.Columns) * 8 + + return +} + +// HashTreeRoot ssz hashes the DataColumnSidecarsByRangeRequest object +func (d *DataColumnSidecarsByRangeRequest) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(d) +} + +// HashTreeRootWith ssz hashes the DataColumnSidecarsByRangeRequest object with a hasher +func (d *DataColumnSidecarsByRangeRequest) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'StartSlot' + hh.PutUint64(uint64(d.StartSlot)) + + // Field (1) 'Count' + hh.PutUint64(d.Count) + + // Field (2) 'Columns' + { + if size := len(d.Columns); size > 128 { + err = ssz.ErrListTooBigFn("--.Columns", size, 128) + return + } + subIndx := hh.Index() + for _, i := range d.Columns { + hh.AppendUint64(i) + } + hh.FillUpTo32() + + numItems := uint64(len(d.Columns)) + hh.MerkleizeWithMixin(subIndx, numItems, ssz.CalculateLimit(128, numItems, 8)) + } + + hh.Merkleize(indx) + return +} + // MarshalSSZ ssz marshals the DepositSnapshot object func (d *DepositSnapshot) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(d) diff --git a/proto/prysm/v1alpha1/p2p_messages.pb.go b/proto/prysm/v1alpha1/p2p_messages.pb.go index 5afd437c2f71..c6bd08c16251 100755 --- a/proto/prysm/v1alpha1/p2p_messages.pb.go +++ b/proto/prysm/v1alpha1/p2p_messages.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/p2p_messages.proto package eth @@ -348,6 +348,77 @@ func (x *MetaDataV1) GetSyncnets() github_com_prysmaticlabs_go_bitfield.Bitvecto return github_com_prysmaticlabs_go_bitfield.Bitvector4(nil) } +type MetaDataV2 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SeqNumber uint64 `protobuf:"varint,1,opt,name=seq_number,json=seqNumber,proto3" json:"seq_number,omitempty"` + Attnets github_com_prysmaticlabs_go_bitfield.Bitvector64 `protobuf:"bytes,2,opt,name=attnets,proto3" json:"attnets,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector64" ssz-size:"8"` + Syncnets github_com_prysmaticlabs_go_bitfield.Bitvector4 `protobuf:"bytes,3,opt,name=syncnets,proto3" json:"syncnets,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector4" ssz-size:"1"` + CustodySubnetCount uint64 `protobuf:"varint,4,opt,name=custody_subnet_count,json=custodySubnetCount,proto3" json:"custody_subnet_count,omitempty"` +} + +func (x *MetaDataV2) Reset() { + *x = MetaDataV2{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MetaDataV2) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetaDataV2) ProtoMessage() {} + +func (x *MetaDataV2) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetaDataV2.ProtoReflect.Descriptor instead. +func (*MetaDataV2) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_p2p_messages_proto_rawDescGZIP(), []int{5} +} + +func (x *MetaDataV2) GetSeqNumber() uint64 { + if x != nil { + return x.SeqNumber + } + return 0 +} + +func (x *MetaDataV2) GetAttnets() github_com_prysmaticlabs_go_bitfield.Bitvector64 { + if x != nil { + return x.Attnets + } + return github_com_prysmaticlabs_go_bitfield.Bitvector64(nil) +} + +func (x *MetaDataV2) GetSyncnets() github_com_prysmaticlabs_go_bitfield.Bitvector4 { + if x != nil { + return x.Syncnets + } + return github_com_prysmaticlabs_go_bitfield.Bitvector4(nil) +} + +func (x *MetaDataV2) GetCustodySubnetCount() uint64 { + if x != nil { + return x.CustodySubnetCount + } + return 0 +} + type BlobSidecarsByRangeRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -360,7 +431,7 @@ type BlobSidecarsByRangeRequest struct { func (x *BlobSidecarsByRangeRequest) Reset() { *x = BlobSidecarsByRangeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -373,7 +444,7 @@ func (x *BlobSidecarsByRangeRequest) String() string { func (*BlobSidecarsByRangeRequest) ProtoMessage() {} func (x *BlobSidecarsByRangeRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[5] + mi := &file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -386,7 +457,7 @@ func (x *BlobSidecarsByRangeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BlobSidecarsByRangeRequest.ProtoReflect.Descriptor instead. func (*BlobSidecarsByRangeRequest) Descriptor() ([]byte, []int) { - return file_proto_prysm_v1alpha1_p2p_messages_proto_rawDescGZIP(), []int{5} + return file_proto_prysm_v1alpha1_p2p_messages_proto_rawDescGZIP(), []int{6} } func (x *BlobSidecarsByRangeRequest) GetStartSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { @@ -403,6 +474,69 @@ func (x *BlobSidecarsByRangeRequest) GetCount() uint64 { return 0 } +type DataColumnSidecarsByRangeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StartSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=start_slot,json=startSlot,proto3" json:"start_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + Count uint64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` + Columns []uint64 `protobuf:"varint,3,rep,packed,name=columns,proto3" json:"columns,omitempty" ssz-max:"128"` +} + +func (x *DataColumnSidecarsByRangeRequest) Reset() { + *x = DataColumnSidecarsByRangeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DataColumnSidecarsByRangeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DataColumnSidecarsByRangeRequest) ProtoMessage() {} + +func (x *DataColumnSidecarsByRangeRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DataColumnSidecarsByRangeRequest.ProtoReflect.Descriptor instead. +func (*DataColumnSidecarsByRangeRequest) Descriptor() ([]byte, []int) { + return file_proto_prysm_v1alpha1_p2p_messages_proto_rawDescGZIP(), []int{7} +} + +func (x *DataColumnSidecarsByRangeRequest) GetStartSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { + if x != nil { + return x.StartSlot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +func (x *DataColumnSidecarsByRangeRequest) GetCount() uint64 { + if x != nil { + return x.Count + } + return 0 +} + +func (x *DataColumnSidecarsByRangeRequest) GetColumns() []uint64 { + if x != nil { + return x.Columns + } + return nil +} + var File_proto_prysm_v1alpha1_p2p_messages_proto protoreflect.FileDescriptor var file_proto_prysm_v1alpha1_p2p_messages_proto_rawDesc = []byte{ @@ -482,27 +616,56 @@ var file_proto_prysm_v1alpha1_p2p_messages_proto_rawDesc = []byte{ 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x34, 0x8a, - 0xb5, 0x18, 0x01, 0x31, 0x52, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x6e, 0x65, 0x74, 0x73, 0x22, 0x98, - 0x01, 0x0a, 0x1a, 0x42, 0x6c, 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x42, - 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x64, 0x0a, - 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, - 0x6c, 0x6f, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, - 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x50, 0x32, 0x50, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, - 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0xb5, 0x18, 0x01, 0x31, 0x52, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x6e, 0x65, 0x74, 0x73, 0x22, 0x88, + 0x02, 0x0a, 0x0a, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x56, 0x32, 0x12, 0x1d, 0x0a, + 0x0a, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x09, 0x73, 0x65, 0x71, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x07, + 0x61, 0x74, 0x74, 0x6e, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x39, 0x82, + 0xb5, 0x18, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, + 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x36, 0x34, 0x8a, 0xb5, 0x18, 0x01, 0x38, 0x52, 0x07, 0x61, 0x74, 0x74, 0x6e, 0x65, 0x74, + 0x73, 0x12, 0x54, 0x0a, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x6e, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, + 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x34, 0x8a, 0xb5, 0x18, 0x01, 0x31, 0x52, 0x08, 0x73, + 0x79, 0x6e, 0x63, 0x6e, 0x65, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x75, 0x73, 0x74, 0x6f, + 0x64, 0x79, 0x5f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x64, 0x79, 0x53, 0x75, + 0x62, 0x6e, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x1a, 0x42, 0x6c, + 0x6f, 0x62, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x42, 0x79, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x64, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, + 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, + 0x6c, 0x6f, 0x74, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc1, 0x01, 0x0a, 0x20, 0x44, 0x61, 0x74, 0x61, 0x43, 0x6f, 0x6c, + 0x75, 0x6d, 0x6e, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x73, 0x42, 0x79, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x64, 0x0a, 0x0a, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, + 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, + 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x53, 0x6c, 0x6f, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, + 0x07, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x50, 0x32, 0x50, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, + 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -517,14 +680,16 @@ func file_proto_prysm_v1alpha1_p2p_messages_proto_rawDescGZIP() []byte { return file_proto_prysm_v1alpha1_p2p_messages_proto_rawDescData } -var file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_proto_prysm_v1alpha1_p2p_messages_proto_goTypes = []interface{}{ - (*Status)(nil), // 0: ethereum.eth.v1alpha1.Status - (*BeaconBlocksByRangeRequest)(nil), // 1: ethereum.eth.v1alpha1.BeaconBlocksByRangeRequest - (*ENRForkID)(nil), // 2: ethereum.eth.v1alpha1.ENRForkID - (*MetaDataV0)(nil), // 3: ethereum.eth.v1alpha1.MetaDataV0 - (*MetaDataV1)(nil), // 4: ethereum.eth.v1alpha1.MetaDataV1 - (*BlobSidecarsByRangeRequest)(nil), // 5: ethereum.eth.v1alpha1.BlobSidecarsByRangeRequest + (*Status)(nil), // 0: ethereum.eth.v1alpha1.Status + (*BeaconBlocksByRangeRequest)(nil), // 1: ethereum.eth.v1alpha1.BeaconBlocksByRangeRequest + (*ENRForkID)(nil), // 2: ethereum.eth.v1alpha1.ENRForkID + (*MetaDataV0)(nil), // 3: ethereum.eth.v1alpha1.MetaDataV0 + (*MetaDataV1)(nil), // 4: ethereum.eth.v1alpha1.MetaDataV1 + (*MetaDataV2)(nil), // 5: ethereum.eth.v1alpha1.MetaDataV2 + (*BlobSidecarsByRangeRequest)(nil), // 6: ethereum.eth.v1alpha1.BlobSidecarsByRangeRequest + (*DataColumnSidecarsByRangeRequest)(nil), // 7: ethereum.eth.v1alpha1.DataColumnSidecarsByRangeRequest } var file_proto_prysm_v1alpha1_p2p_messages_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type @@ -601,6 +766,18 @@ func file_proto_prysm_v1alpha1_p2p_messages_proto_init() { } } file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetaDataV2); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlobSidecarsByRangeRequest); i { case 0: return &v.state @@ -612,6 +789,18 @@ func file_proto_prysm_v1alpha1_p2p_messages_proto_init() { return nil } } + file_proto_prysm_v1alpha1_p2p_messages_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DataColumnSidecarsByRangeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -619,7 +808,7 @@ func file_proto_prysm_v1alpha1_p2p_messages_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_prysm_v1alpha1_p2p_messages_proto_rawDesc, NumEnums: 0, - NumMessages: 6, + NumMessages: 8, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/prysm/v1alpha1/p2p_messages.pb.gw.go b/proto/prysm/v1alpha1/p2p_messages.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/p2p_messages.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/p2p_messages.proto b/proto/prysm/v1alpha1/p2p_messages.proto index 8ba1d36c88cd..86028667c93f 100644 --- a/proto/prysm/v1alpha1/p2p_messages.proto +++ b/proto/prysm/v1alpha1/p2p_messages.proto @@ -13,23 +13,35 @@ option java_package = "org.ethereum.eth.v1alpha1"; option php_namespace = "Ethereum\\Eth\\v1alpha1"; message Status { - bytes fork_digest = 1 [(ethereum.eth.ext.ssz_size) = "4"]; - bytes finalized_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 finalized_epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - bytes head_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 head_slot = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + bytes fork_digest = 1 [ (ethereum.eth.ext.ssz_size) = "4" ]; + bytes finalized_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 finalized_epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + bytes head_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 head_slot = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; } message BeaconBlocksByRangeRequest { - uint64 start_slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 start_slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; uint64 count = 2; uint64 step = 3; } message ENRForkID { - bytes current_fork_digest = 1 [(ethereum.eth.ext.ssz_size) = "4"]; - bytes next_fork_version = 2 [(ethereum.eth.ext.ssz_size) = "4"]; - uint64 next_fork_epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + bytes current_fork_digest = 1 [ (ethereum.eth.ext.ssz_size) = "4" ]; + bytes next_fork_version = 2 [ (ethereum.eth.ext.ssz_size) = "4" ]; + uint64 next_fork_epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; } /* @@ -42,7 +54,11 @@ message ENRForkID { */ message MetaDataV0 { uint64 seq_number = 1; - bytes attnets = 2 [(ethereum.eth.ext.ssz_size) = "8", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector64"]; + bytes attnets = 2 [ + (ethereum.eth.ext.ssz_size) = "8", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector64" + ]; } /* @@ -51,12 +67,46 @@ message MetaDataV0 { ( seq_number: uint64 attnets: Bitvector[ATTESTATION_SUBNET_COUNT] + syncnets: Bitvector[SYNC_COMMITTEE_SUBNET_COUNT] ) */ message MetaDataV1 { uint64 seq_number = 1; - bytes attnets = 2 [(ethereum.eth.ext.ssz_size) = "8", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector64"]; - bytes syncnets = 3 [(ethereum.eth.ext.ssz_size) = "1", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitvector4"]; + bytes attnets = 2 [ + (ethereum.eth.ext.ssz_size) = "8", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector64" + ]; + bytes syncnets = 3 [ + (ethereum.eth.ext.ssz_size) = "1", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector4" + ]; +} + +/* + Spec Definition: + MetaData + ( + seq_number: uint64 + attnets: Bitvector[ATTESTATION_SUBNET_COUNT] + syncnets: Bitvector[SYNC_COMMITTEE_SUBNET_COUNT] + custody_subnet_count: uint64 + ) +*/ +message MetaDataV2 { + uint64 seq_number = 1; + bytes attnets = 2 [ + (ethereum.eth.ext.ssz_size) = "8", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector64" + ]; + bytes syncnets = 3 [ + (ethereum.eth.ext.ssz_size) = "1", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector4" + ]; + uint64 custody_subnet_count = 4; } /* @@ -67,6 +117,26 @@ message MetaDataV1 { ) */ message BlobSidecarsByRangeRequest { - uint64 start_slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 start_slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; uint64 count = 2; } + +/* +Spec Definition: +( + start_slot: Slot + count: uint64 + columns: List[ColumnIndex] +) + */ +message DataColumnSidecarsByRangeRequest { + uint64 start_slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + uint64 count = 2; + repeated uint64 columns = 3 [ (ethereum.eth.ext.ssz_max) = "128" ]; +} \ No newline at end of file diff --git a/proto/prysm/v1alpha1/phase0.ssz.go b/proto/prysm/v1alpha1/phase0.ssz.go index d9d2b40cb253..e95995f0e610 100644 --- a/proto/prysm/v1alpha1/phase0.ssz.go +++ b/proto/prysm/v1alpha1/phase0.ssz.go @@ -1,5 +1,4 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 0858b1e553b943e9cbdba001604002341da98f82976954a2eafa7a97632f485c package eth import ( @@ -7,130 +6,110 @@ import ( github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ) -// MarshalSSZ ssz marshals the Attestation object -func (a *Attestation) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(a) +// MarshalSSZ ssz marshals the SignedAggregateAttestationAndProof object +func (s *SignedAggregateAttestationAndProof) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the Attestation object to a target array -func (a *Attestation) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SignedAggregateAttestationAndProof object to a target array +func (s *SignedAggregateAttestationAndProof) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(228) + offset := int(100) - // Offset (0) 'AggregationBits' + // Offset (0) 'Message' dst = ssz.WriteOffset(dst, offset) - offset += len(a.AggregationBits) - - // Field (1) 'Data' - if a.Data == nil { - a.Data = new(AttestationData) - } - if dst, err = a.Data.MarshalSSZTo(dst); err != nil { - return + if s.Message == nil { + s.Message = new(AggregateAttestationAndProof) } + offset += s.Message.SizeSSZ() - // Field (2) 'Signature' - if size := len(a.Signature); size != 96 { + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - dst = append(dst, a.Signature...) + dst = append(dst, s.Signature...) - // Field (0) 'AggregationBits' - if size := len(a.AggregationBits); size > 2048 { - err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 2048) + // Field (0) 'Message' + if dst, err = s.Message.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, a.AggregationBits...) return } -// UnmarshalSSZ ssz unmarshals the Attestation object -func (a *Attestation) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the SignedAggregateAttestationAndProof object +func (s *SignedAggregateAttestationAndProof) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 228 { + if size < 100 { return ssz.ErrSize } tail := buf var o0 uint64 - // Offset (0) 'AggregationBits' + // Offset (0) 'Message' if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { return ssz.ErrOffset } - if o0 != 228 { + if o0 != 100 { return ssz.ErrInvalidVariableOffset } - // Field (1) 'Data' - if a.Data == nil { - a.Data = new(AttestationData) - } - if err = a.Data.UnmarshalSSZ(buf[4:132]); err != nil { - return err - } - - // Field (2) 'Signature' - if cap(a.Signature) == 0 { - a.Signature = make([]byte, 0, len(buf[132:228])) + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) } - a.Signature = append(a.Signature, buf[132:228]...) + s.Signature = append(s.Signature, buf[4:100]...) - // Field (0) 'AggregationBits' + // Field (0) 'Message' { buf = tail[o0:] - if err = ssz.ValidateBitlist(buf, 2048); err != nil { - return err + if s.Message == nil { + s.Message = new(AggregateAttestationAndProof) } - if cap(a.AggregationBits) == 0 { - a.AggregationBits = make([]byte, 0, len(buf)) + if err = s.Message.UnmarshalSSZ(buf); err != nil { + return err } - a.AggregationBits = append(a.AggregationBits, buf...) } return err } -// SizeSSZ returns the ssz encoded size in bytes for the Attestation object -func (a *Attestation) SizeSSZ() (size int) { - size = 228 +// SizeSSZ returns the ssz encoded size in bytes for the SignedAggregateAttestationAndProof object +func (s *SignedAggregateAttestationAndProof) SizeSSZ() (size int) { + size = 100 - // Field (0) 'AggregationBits' - size += len(a.AggregationBits) + // Field (0) 'Message' + if s.Message == nil { + s.Message = new(AggregateAttestationAndProof) + } + size += s.Message.SizeSSZ() return } -// HashTreeRoot ssz hashes the Attestation object -func (a *Attestation) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(a) +// HashTreeRoot ssz hashes the SignedAggregateAttestationAndProof object +func (s *SignedAggregateAttestationAndProof) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) } -// HashTreeRootWith ssz hashes the Attestation object with a hasher -func (a *Attestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the SignedAggregateAttestationAndProof object with a hasher +func (s *SignedAggregateAttestationAndProof) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'AggregationBits' - if len(a.AggregationBits) == 0 { - err = ssz.ErrEmptyBitlist - return - } - hh.PutBitlist(a.AggregationBits, 2048) - - // Field (1) 'Data' - if err = a.Data.HashTreeRootWith(hh); err != nil { + // Field (0) 'Message' + if err = s.Message.HashTreeRootWith(hh); err != nil { return } - // Field (2) 'Signature' - if size := len(a.Signature); size != 96 { + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - hh.PutBytes(a.Signature) + hh.PutBytes(s.Signature) hh.Merkleize(indx) return @@ -254,110 +233,130 @@ func (a *AggregateAttestationAndProof) HashTreeRootWith(hh *ssz.Hasher) (err err return } -// MarshalSSZ ssz marshals the SignedAggregateAttestationAndProof object -func (s *SignedAggregateAttestationAndProof) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) +// MarshalSSZ ssz marshals the Attestation object +func (a *Attestation) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(a) } -// MarshalSSZTo ssz marshals the SignedAggregateAttestationAndProof object to a target array -func (s *SignedAggregateAttestationAndProof) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the Attestation object to a target array +func (a *Attestation) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(100) + offset := int(228) - // Offset (0) 'Message' + // Offset (0) 'AggregationBits' dst = ssz.WriteOffset(dst, offset) - if s.Message == nil { - s.Message = new(AggregateAttestationAndProof) + offset += len(a.AggregationBits) + + // Field (1) 'Data' + if a.Data == nil { + a.Data = new(AttestationData) + } + if dst, err = a.Data.MarshalSSZTo(dst); err != nil { + return } - offset += s.Message.SizeSSZ() - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { + // Field (2) 'Signature' + if size := len(a.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - dst = append(dst, s.Signature...) + dst = append(dst, a.Signature...) - // Field (0) 'Message' - if dst, err = s.Message.MarshalSSZTo(dst); err != nil { + // Field (0) 'AggregationBits' + if size := len(a.AggregationBits); size > 2048 { + err = ssz.ErrBytesLengthFn("--.AggregationBits", size, 2048) return } + dst = append(dst, a.AggregationBits...) return } -// UnmarshalSSZ ssz unmarshals the SignedAggregateAttestationAndProof object -func (s *SignedAggregateAttestationAndProof) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the Attestation object +func (a *Attestation) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 100 { + if size < 228 { return ssz.ErrSize } tail := buf var o0 uint64 - // Offset (0) 'Message' + // Offset (0) 'AggregationBits' if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { return ssz.ErrOffset } - if o0 != 100 { + if o0 != 228 { return ssz.ErrInvalidVariableOffset } - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) + // Field (1) 'Data' + if a.Data == nil { + a.Data = new(AttestationData) + } + if err = a.Data.UnmarshalSSZ(buf[4:132]); err != nil { + return err } - s.Signature = append(s.Signature, buf[4:100]...) - // Field (0) 'Message' + // Field (2) 'Signature' + if cap(a.Signature) == 0 { + a.Signature = make([]byte, 0, len(buf[132:228])) + } + a.Signature = append(a.Signature, buf[132:228]...) + + // Field (0) 'AggregationBits' { buf = tail[o0:] - if s.Message == nil { - s.Message = new(AggregateAttestationAndProof) - } - if err = s.Message.UnmarshalSSZ(buf); err != nil { + if err = ssz.ValidateBitlist(buf, 2048); err != nil { return err } + if cap(a.AggregationBits) == 0 { + a.AggregationBits = make([]byte, 0, len(buf)) + } + a.AggregationBits = append(a.AggregationBits, buf...) } return err } -// SizeSSZ returns the ssz encoded size in bytes for the SignedAggregateAttestationAndProof object -func (s *SignedAggregateAttestationAndProof) SizeSSZ() (size int) { - size = 100 +// SizeSSZ returns the ssz encoded size in bytes for the Attestation object +func (a *Attestation) SizeSSZ() (size int) { + size = 228 - // Field (0) 'Message' - if s.Message == nil { - s.Message = new(AggregateAttestationAndProof) - } - size += s.Message.SizeSSZ() + // Field (0) 'AggregationBits' + size += len(a.AggregationBits) return } -// HashTreeRoot ssz hashes the SignedAggregateAttestationAndProof object -func (s *SignedAggregateAttestationAndProof) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) +// HashTreeRoot ssz hashes the Attestation object +func (a *Attestation) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(a) } -// HashTreeRootWith ssz hashes the SignedAggregateAttestationAndProof object with a hasher -func (s *SignedAggregateAttestationAndProof) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the Attestation object with a hasher +func (a *Attestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Message' - if err = s.Message.HashTreeRootWith(hh); err != nil { + // Field (0) 'AggregationBits' + if len(a.AggregationBits) == 0 { + err = ssz.ErrEmptyBitlist return } + hh.PutBitlist(a.AggregationBits, 2048) - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { + // Field (1) 'Data' + if err = a.Data.HashTreeRootWith(hh); err != nil { + return + } + + // Field (2) 'Signature' + if size := len(a.Signature); size != 96 { err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } - hh.PutBytes(s.Signature) + hh.PutBytes(a.Signature) hh.Merkleize(indx) return @@ -556,28 +555,137 @@ func (c *Checkpoint) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the BeaconBlock object -func (b *BeaconBlock) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the SignedBeaconBlock object +func (s *SignedBeaconBlock) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the BeaconBlock object to a target array -func (b *BeaconBlock) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SignedBeaconBlock object to a target array +func (s *SignedBeaconBlock) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(84) - - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) + offset := int(100) - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return + // Offset (0) 'Block' + dst = ssz.WriteOffset(dst, offset) + if s.Block == nil { + s.Block = new(BeaconBlock) } - dst = append(dst, b.ParentRoot...) + offset += s.Block.SizeSSZ() + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + // Field (0) 'Block' + if dst, err = s.Block.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedBeaconBlock object +func (s *SignedBeaconBlock) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 100 { + return ssz.ErrSize + } + + tail := buf + var o0 uint64 + + // Offset (0) 'Block' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 100 { + return ssz.ErrInvalidVariableOffset + } + + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[4:100])) + } + s.Signature = append(s.Signature, buf[4:100]...) + + // Field (0) 'Block' + { + buf = tail[o0:] + if s.Block == nil { + s.Block = new(BeaconBlock) + } + if err = s.Block.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlock object +func (s *SignedBeaconBlock) SizeSSZ() (size int) { + size = 100 + + // Field (0) 'Block' + if s.Block == nil { + s.Block = new(BeaconBlock) + } + size += s.Block.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the SignedBeaconBlock object +func (s *SignedBeaconBlock) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedBeaconBlock object with a hasher +func (s *SignedBeaconBlock) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Block' + if err = s.Block.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(s.Signature) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the BeaconBlock object +func (b *BeaconBlock) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) +} + +// MarshalSSZTo ssz marshals the BeaconBlock object to a target array +func (b *BeaconBlock) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(84) + + // Field (0) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(b.Slot)) + + // Field (1) 'ProposerIndex' + dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) + + // Field (2) 'ParentRoot' + if size := len(b.ParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) + return + } + dst = append(dst, b.ParentRoot...) // Field (3) 'StateRoot' if size := len(b.StateRoot); size != 32 { @@ -703,115 +811,6 @@ func (b *BeaconBlock) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the SignedBeaconBlock object -func (s *SignedBeaconBlock) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedBeaconBlock object to a target array -func (s *SignedBeaconBlock) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(100) - - // Offset (0) 'Block' - dst = ssz.WriteOffset(dst, offset) - if s.Block == nil { - s.Block = new(BeaconBlock) - } - offset += s.Block.SizeSSZ() - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - // Field (0) 'Block' - if dst, err = s.Block.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlock object -func (s *SignedBeaconBlock) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 100 { - return ssz.ErrSize - } - - tail := buf - var o0 uint64 - - // Offset (0) 'Block' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 100 { - return ssz.ErrInvalidVariableOffset - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[4:100])) - } - s.Signature = append(s.Signature, buf[4:100]...) - - // Field (0) 'Block' - { - buf = tail[o0:] - if s.Block == nil { - s.Block = new(BeaconBlock) - } - if err = s.Block.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlock object -func (s *SignedBeaconBlock) SizeSSZ() (size int) { - size = 100 - - // Field (0) 'Block' - if s.Block == nil { - s.Block = new(BeaconBlock) - } - size += s.Block.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the SignedBeaconBlock object -func (s *SignedBeaconBlock) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} - -// HashTreeRootWith ssz hashes the SignedBeaconBlock object with a hasher -func (s *SignedBeaconBlock) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() - - // Field (0) 'Block' - if err = s.Block.HashTreeRootWith(hh); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - hh.PutBytes(s.Signature) - - hh.Merkleize(indx) - return -} - // MarshalSSZ ssz marshals the BeaconBlockBody object func (b *BeaconBlockBody) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(b) @@ -1242,458 +1241,204 @@ func (b *BeaconBlockBody) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the ProposerSlashing object -func (p *ProposerSlashing) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(p) +// MarshalSSZ ssz marshals the SignedBeaconBlockHeader object +func (s *SignedBeaconBlockHeader) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) } -// MarshalSSZTo ssz marshals the ProposerSlashing object to a target array -func (p *ProposerSlashing) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the SignedBeaconBlockHeader object to a target array +func (s *SignedBeaconBlockHeader) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - // Field (0) 'Header_1' - if p.Header_1 == nil { - p.Header_1 = new(SignedBeaconBlockHeader) + // Field (0) 'Header' + if s.Header == nil { + s.Header = new(BeaconBlockHeader) } - if dst, err = p.Header_1.MarshalSSZTo(dst); err != nil { + if dst, err = s.Header.MarshalSSZTo(dst); err != nil { return } - // Field (1) 'Header_2' - if p.Header_2 == nil { - p.Header_2 = new(SignedBeaconBlockHeader) - } - if dst, err = p.Header_2.MarshalSSZTo(dst); err != nil { + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } + dst = append(dst, s.Signature...) return } -// UnmarshalSSZ ssz unmarshals the ProposerSlashing object -func (p *ProposerSlashing) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockHeader object +func (s *SignedBeaconBlockHeader) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 416 { + if size != 208 { return ssz.ErrSize } - // Field (0) 'Header_1' - if p.Header_1 == nil { - p.Header_1 = new(SignedBeaconBlockHeader) + // Field (0) 'Header' + if s.Header == nil { + s.Header = new(BeaconBlockHeader) } - if err = p.Header_1.UnmarshalSSZ(buf[0:208]); err != nil { + if err = s.Header.UnmarshalSSZ(buf[0:112]); err != nil { return err } - // Field (1) 'Header_2' - if p.Header_2 == nil { - p.Header_2 = new(SignedBeaconBlockHeader) - } - if err = p.Header_2.UnmarshalSSZ(buf[208:416]); err != nil { - return err + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[112:208])) } + s.Signature = append(s.Signature, buf[112:208]...) return err } -// SizeSSZ returns the ssz encoded size in bytes for the ProposerSlashing object -func (p *ProposerSlashing) SizeSSZ() (size int) { - size = 416 +// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockHeader object +func (s *SignedBeaconBlockHeader) SizeSSZ() (size int) { + size = 208 return } -// HashTreeRoot ssz hashes the ProposerSlashing object -func (p *ProposerSlashing) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(p) +// HashTreeRoot ssz hashes the SignedBeaconBlockHeader object +func (s *SignedBeaconBlockHeader) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) } -// HashTreeRootWith ssz hashes the ProposerSlashing object with a hasher -func (p *ProposerSlashing) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the SignedBeaconBlockHeader object with a hasher +func (s *SignedBeaconBlockHeader) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Header_1' - if err = p.Header_1.HashTreeRootWith(hh); err != nil { + // Field (0) 'Header' + if err = s.Header.HashTreeRootWith(hh); err != nil { return } - // Field (1) 'Header_2' - if err = p.Header_2.HashTreeRootWith(hh); err != nil { + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) return } + hh.PutBytes(s.Signature) hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the AttesterSlashing object -func (a *AttesterSlashing) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(a) +// MarshalSSZ ssz marshals the BeaconBlockHeader object +func (b *BeaconBlockHeader) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(b) } -// MarshalSSZTo ssz marshals the AttesterSlashing object to a target array -func (a *AttesterSlashing) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the BeaconBlockHeader object to a target array +func (b *BeaconBlockHeader) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(8) - - // Offset (0) 'Attestation_1' - dst = ssz.WriteOffset(dst, offset) - if a.Attestation_1 == nil { - a.Attestation_1 = new(IndexedAttestation) - } - offset += a.Attestation_1.SizeSSZ() - - // Offset (1) 'Attestation_2' - dst = ssz.WriteOffset(dst, offset) - if a.Attestation_2 == nil { - a.Attestation_2 = new(IndexedAttestation) - } - offset += a.Attestation_2.SizeSSZ() - // Field (0) 'Attestation_1' - if dst, err = a.Attestation_1.MarshalSSZTo(dst); err != nil { - return - } - - // Field (1) 'Attestation_2' - if dst, err = a.Attestation_2.MarshalSSZTo(dst); err != nil { - return - } - - return -} - -// UnmarshalSSZ ssz unmarshals the AttesterSlashing object -func (a *AttesterSlashing) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 8 { - return ssz.ErrSize - } - - tail := buf - var o0, o1 uint64 - - // Offset (0) 'Attestation_1' - if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { - return ssz.ErrOffset - } - - if o0 != 8 { - return ssz.ErrInvalidVariableOffset - } - - // Offset (1) 'Attestation_2' - if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { - return ssz.ErrOffset - } - - // Field (0) 'Attestation_1' - { - buf = tail[o0:o1] - if a.Attestation_1 == nil { - a.Attestation_1 = new(IndexedAttestation) - } - if err = a.Attestation_1.UnmarshalSSZ(buf); err != nil { - return err - } - } - - // Field (1) 'Attestation_2' - { - buf = tail[o1:] - if a.Attestation_2 == nil { - a.Attestation_2 = new(IndexedAttestation) - } - if err = a.Attestation_2.UnmarshalSSZ(buf); err != nil { - return err - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the AttesterSlashing object -func (a *AttesterSlashing) SizeSSZ() (size int) { - size = 8 - - // Field (0) 'Attestation_1' - if a.Attestation_1 == nil { - a.Attestation_1 = new(IndexedAttestation) - } - size += a.Attestation_1.SizeSSZ() - - // Field (1) 'Attestation_2' - if a.Attestation_2 == nil { - a.Attestation_2 = new(IndexedAttestation) - } - size += a.Attestation_2.SizeSSZ() - - return -} - -// HashTreeRoot ssz hashes the AttesterSlashing object -func (a *AttesterSlashing) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(a) -} - -// HashTreeRootWith ssz hashes the AttesterSlashing object with a hasher -func (a *AttesterSlashing) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() + // Field (0) 'Slot' + dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - // Field (0) 'Attestation_1' - if err = a.Attestation_1.HashTreeRootWith(hh); err != nil { - return - } + // Field (1) 'ProposerIndex' + dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - // Field (1) 'Attestation_2' - if err = a.Attestation_2.HashTreeRootWith(hh); err != nil { + // Field (2) 'ParentRoot' + if size := len(b.ParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) return } + dst = append(dst, b.ParentRoot...) - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the Deposit object -func (d *Deposit) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(d) -} - -// MarshalSSZTo ssz marshals the Deposit object to a target array -func (d *Deposit) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Proof' - if size := len(d.Proof); size != 33 { - err = ssz.ErrVectorLengthFn("--.Proof", size, 33) + // Field (3) 'StateRoot' + if size := len(b.StateRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) return } - for ii := 0; ii < 33; ii++ { - if size := len(d.Proof[ii]); size != 32 { - err = ssz.ErrBytesLengthFn("--.Proof[ii]", size, 32) - return - } - dst = append(dst, d.Proof[ii]...) - } + dst = append(dst, b.StateRoot...) - // Field (1) 'Data' - if d.Data == nil { - d.Data = new(Deposit_Data) - } - if dst, err = d.Data.MarshalSSZTo(dst); err != nil { + // Field (4) 'BodyRoot' + if size := len(b.BodyRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BodyRoot", size, 32) return } + dst = append(dst, b.BodyRoot...) return } -// UnmarshalSSZ ssz unmarshals the Deposit object -func (d *Deposit) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the BeaconBlockHeader object +func (b *BeaconBlockHeader) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 1240 { + if size != 112 { return ssz.ErrSize } - // Field (0) 'Proof' - d.Proof = make([][]byte, 33) - for ii := 0; ii < 33; ii++ { - if cap(d.Proof[ii]) == 0 { - d.Proof[ii] = make([]byte, 0, len(buf[0:1056][ii*32:(ii+1)*32])) - } - d.Proof[ii] = append(d.Proof[ii], buf[0:1056][ii*32:(ii+1)*32]...) - } - - // Field (1) 'Data' - if d.Data == nil { - d.Data = new(Deposit_Data) - } - if err = d.Data.UnmarshalSSZ(buf[1056:1240]); err != nil { - return err - } - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the Deposit object -func (d *Deposit) SizeSSZ() (size int) { - size = 1240 - return -} - -// HashTreeRoot ssz hashes the Deposit object -func (d *Deposit) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(d) -} + // Field (0) 'Slot' + b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) -// HashTreeRootWith ssz hashes the Deposit object with a hasher -func (d *Deposit) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() + // Field (1) 'ProposerIndex' + b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - // Field (0) 'Proof' - { - if size := len(d.Proof); size != 33 { - err = ssz.ErrVectorLengthFn("--.Proof", size, 33) - return - } - subIndx := hh.Index() - for _, i := range d.Proof { - if len(i) != 32 { - err = ssz.ErrBytesLength - return - } - hh.Append(i) - } - hh.Merkleize(subIndx) + // Field (2) 'ParentRoot' + if cap(b.ParentRoot) == 0 { + b.ParentRoot = make([]byte, 0, len(buf[16:48])) } + b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - // Field (1) 'Data' - if err = d.Data.HashTreeRootWith(hh); err != nil { - return + // Field (3) 'StateRoot' + if cap(b.StateRoot) == 0 { + b.StateRoot = make([]byte, 0, len(buf[48:80])) } + b.StateRoot = append(b.StateRoot, buf[48:80]...) - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the VoluntaryExit object -func (v *VoluntaryExit) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(v) -} - -// MarshalSSZTo ssz marshals the VoluntaryExit object to a target array -func (v *VoluntaryExit) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Epoch' - dst = ssz.MarshalUint64(dst, uint64(v.Epoch)) - - // Field (1) 'ValidatorIndex' - dst = ssz.MarshalUint64(dst, uint64(v.ValidatorIndex)) - - return -} - -// UnmarshalSSZ ssz unmarshals the VoluntaryExit object -func (v *VoluntaryExit) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 16 { - return ssz.ErrSize + // Field (4) 'BodyRoot' + if cap(b.BodyRoot) == 0 { + b.BodyRoot = make([]byte, 0, len(buf[80:112])) } - - // Field (0) 'Epoch' - v.Epoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ValidatorIndex' - v.ValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) + b.BodyRoot = append(b.BodyRoot, buf[80:112]...) return err } -// SizeSSZ returns the ssz encoded size in bytes for the VoluntaryExit object -func (v *VoluntaryExit) SizeSSZ() (size int) { - size = 16 +// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockHeader object +func (b *BeaconBlockHeader) SizeSSZ() (size int) { + size = 112 return } -// HashTreeRoot ssz hashes the VoluntaryExit object -func (v *VoluntaryExit) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(v) +// HashTreeRoot ssz hashes the BeaconBlockHeader object +func (b *BeaconBlockHeader) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(b) } -// HashTreeRootWith ssz hashes the VoluntaryExit object with a hasher -func (v *VoluntaryExit) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the BeaconBlockHeader object with a hasher +func (b *BeaconBlockHeader) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Epoch' - hh.PutUint64(uint64(v.Epoch)) - - // Field (1) 'ValidatorIndex' - hh.PutUint64(uint64(v.ValidatorIndex)) - - hh.Merkleize(indx) - return -} - -// MarshalSSZ ssz marshals the SignedVoluntaryExit object -func (s *SignedVoluntaryExit) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) -} - -// MarshalSSZTo ssz marshals the SignedVoluntaryExit object to a target array -func (s *SignedVoluntaryExit) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - - // Field (0) 'Exit' - if s.Exit == nil { - s.Exit = new(VoluntaryExit) - } - if dst, err = s.Exit.MarshalSSZTo(dst); err != nil { - return - } - - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) - return - } - dst = append(dst, s.Signature...) - - return -} - -// UnmarshalSSZ ssz unmarshals the SignedVoluntaryExit object -func (s *SignedVoluntaryExit) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size != 112 { - return ssz.ErrSize - } - - // Field (0) 'Exit' - if s.Exit == nil { - s.Exit = new(VoluntaryExit) - } - if err = s.Exit.UnmarshalSSZ(buf[0:16]); err != nil { - return err - } - - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[16:112])) - } - s.Signature = append(s.Signature, buf[16:112]...) - - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the SignedVoluntaryExit object -func (s *SignedVoluntaryExit) SizeSSZ() (size int) { - size = 112 - return -} + // Field (0) 'Slot' + hh.PutUint64(uint64(b.Slot)) -// HashTreeRoot ssz hashes the SignedVoluntaryExit object -func (s *SignedVoluntaryExit) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) -} + // Field (1) 'ProposerIndex' + hh.PutUint64(uint64(b.ProposerIndex)) -// HashTreeRootWith ssz hashes the SignedVoluntaryExit object with a hasher -func (s *SignedVoluntaryExit) HashTreeRootWith(hh *ssz.Hasher) (err error) { - indx := hh.Index() + // Field (2) 'ParentRoot' + if size := len(b.ParentRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) + return + } + hh.PutBytes(b.ParentRoot) - // Field (0) 'Exit' - if err = s.Exit.HashTreeRootWith(hh); err != nil { + // Field (3) 'StateRoot' + if size := len(b.StateRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) return } + hh.PutBytes(b.StateRoot) - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + // Field (4) 'BodyRoot' + if size := len(b.BodyRoot); size != 32 { + err = ssz.ErrBytesLengthFn("--.BodyRoot", size, 32) return } - hh.PutBytes(s.Signature) + hh.PutBytes(b.BodyRoot) hh.Merkleize(indx) return @@ -1790,204 +1535,213 @@ func (e *Eth1Data) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } -// MarshalSSZ ssz marshals the BeaconBlockHeader object -func (b *BeaconBlockHeader) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(b) +// MarshalSSZ ssz marshals the ProposerSlashing object +func (p *ProposerSlashing) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(p) } -// MarshalSSZTo ssz marshals the BeaconBlockHeader object to a target array -func (b *BeaconBlockHeader) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the ProposerSlashing object to a target array +func (p *ProposerSlashing) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - // Field (0) 'Slot' - dst = ssz.MarshalUint64(dst, uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - dst = ssz.MarshalUint64(dst, uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return + // Field (0) 'Header_1' + if p.Header_1 == nil { + p.Header_1 = new(SignedBeaconBlockHeader) } - dst = append(dst, b.ParentRoot...) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + if dst, err = p.Header_1.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, b.StateRoot...) - // Field (4) 'BodyRoot' - if size := len(b.BodyRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.BodyRoot", size, 32) + // Field (1) 'Header_2' + if p.Header_2 == nil { + p.Header_2 = new(SignedBeaconBlockHeader) + } + if dst, err = p.Header_2.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, b.BodyRoot...) return } -// UnmarshalSSZ ssz unmarshals the BeaconBlockHeader object -func (b *BeaconBlockHeader) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the ProposerSlashing object +func (p *ProposerSlashing) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 112 { + if size != 416 { return ssz.ErrSize } - // Field (0) 'Slot' - b.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[0:8])) - - // Field (1) 'ProposerIndex' - b.ProposerIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) - - // Field (2) 'ParentRoot' - if cap(b.ParentRoot) == 0 { - b.ParentRoot = make([]byte, 0, len(buf[16:48])) + // Field (0) 'Header_1' + if p.Header_1 == nil { + p.Header_1 = new(SignedBeaconBlockHeader) } - b.ParentRoot = append(b.ParentRoot, buf[16:48]...) - - // Field (3) 'StateRoot' - if cap(b.StateRoot) == 0 { - b.StateRoot = make([]byte, 0, len(buf[48:80])) + if err = p.Header_1.UnmarshalSSZ(buf[0:208]); err != nil { + return err } - b.StateRoot = append(b.StateRoot, buf[48:80]...) - // Field (4) 'BodyRoot' - if cap(b.BodyRoot) == 0 { - b.BodyRoot = make([]byte, 0, len(buf[80:112])) + // Field (1) 'Header_2' + if p.Header_2 == nil { + p.Header_2 = new(SignedBeaconBlockHeader) + } + if err = p.Header_2.UnmarshalSSZ(buf[208:416]); err != nil { + return err } - b.BodyRoot = append(b.BodyRoot, buf[80:112]...) return err } -// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockHeader object -func (b *BeaconBlockHeader) SizeSSZ() (size int) { - size = 112 +// SizeSSZ returns the ssz encoded size in bytes for the ProposerSlashing object +func (p *ProposerSlashing) SizeSSZ() (size int) { + size = 416 return } -// HashTreeRoot ssz hashes the BeaconBlockHeader object -func (b *BeaconBlockHeader) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(b) +// HashTreeRoot ssz hashes the ProposerSlashing object +func (p *ProposerSlashing) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(p) } -// HashTreeRootWith ssz hashes the BeaconBlockHeader object with a hasher -func (b *BeaconBlockHeader) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the ProposerSlashing object with a hasher +func (p *ProposerSlashing) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - // Field (0) 'Slot' - hh.PutUint64(uint64(b.Slot)) - - // Field (1) 'ProposerIndex' - hh.PutUint64(uint64(b.ProposerIndex)) - - // Field (2) 'ParentRoot' - if size := len(b.ParentRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.ParentRoot", size, 32) - return - } - hh.PutBytes(b.ParentRoot) - - // Field (3) 'StateRoot' - if size := len(b.StateRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32) + // Field (0) 'Header_1' + if err = p.Header_1.HashTreeRootWith(hh); err != nil { return } - hh.PutBytes(b.StateRoot) - // Field (4) 'BodyRoot' - if size := len(b.BodyRoot); size != 32 { - err = ssz.ErrBytesLengthFn("--.BodyRoot", size, 32) + // Field (1) 'Header_2' + if err = p.Header_2.HashTreeRootWith(hh); err != nil { return } - hh.PutBytes(b.BodyRoot) hh.Merkleize(indx) return } -// MarshalSSZ ssz marshals the SignedBeaconBlockHeader object -func (s *SignedBeaconBlockHeader) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(s) +// MarshalSSZ ssz marshals the AttesterSlashing object +func (a *AttesterSlashing) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(a) } -// MarshalSSZTo ssz marshals the SignedBeaconBlockHeader object to a target array -func (s *SignedBeaconBlockHeader) MarshalSSZTo(buf []byte) (dst []byte, err error) { +// MarshalSSZTo ssz marshals the AttesterSlashing object to a target array +func (a *AttesterSlashing) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf + offset := int(8) - // Field (0) 'Header' - if s.Header == nil { - s.Header = new(BeaconBlockHeader) + // Offset (0) 'Attestation_1' + dst = ssz.WriteOffset(dst, offset) + if a.Attestation_1 == nil { + a.Attestation_1 = new(IndexedAttestation) } - if dst, err = s.Header.MarshalSSZTo(dst); err != nil { + offset += a.Attestation_1.SizeSSZ() + + // Offset (1) 'Attestation_2' + dst = ssz.WriteOffset(dst, offset) + if a.Attestation_2 == nil { + a.Attestation_2 = new(IndexedAttestation) + } + offset += a.Attestation_2.SizeSSZ() + + // Field (0) 'Attestation_1' + if dst, err = a.Attestation_1.MarshalSSZTo(dst); err != nil { return } - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + // Field (1) 'Attestation_2' + if dst, err = a.Attestation_2.MarshalSSZTo(dst); err != nil { return } - dst = append(dst, s.Signature...) return } -// UnmarshalSSZ ssz unmarshals the SignedBeaconBlockHeader object -func (s *SignedBeaconBlockHeader) UnmarshalSSZ(buf []byte) error { +// UnmarshalSSZ ssz unmarshals the AttesterSlashing object +func (a *AttesterSlashing) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 208 { + if size < 8 { return ssz.ErrSize } - // Field (0) 'Header' - if s.Header == nil { - s.Header = new(BeaconBlockHeader) + tail := buf + var o0, o1 uint64 + + // Offset (0) 'Attestation_1' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset } - if err = s.Header.UnmarshalSSZ(buf[0:112]); err != nil { - return err + + if o0 != 8 { + return ssz.ErrInvalidVariableOffset } - // Field (1) 'Signature' - if cap(s.Signature) == 0 { - s.Signature = make([]byte, 0, len(buf[112:208])) + // Offset (1) 'Attestation_2' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Field (0) 'Attestation_1' + { + buf = tail[o0:o1] + if a.Attestation_1 == nil { + a.Attestation_1 = new(IndexedAttestation) + } + if err = a.Attestation_1.UnmarshalSSZ(buf); err != nil { + return err + } } - s.Signature = append(s.Signature, buf[112:208]...) + // Field (1) 'Attestation_2' + { + buf = tail[o1:] + if a.Attestation_2 == nil { + a.Attestation_2 = new(IndexedAttestation) + } + if err = a.Attestation_2.UnmarshalSSZ(buf); err != nil { + return err + } + } return err } -// SizeSSZ returns the ssz encoded size in bytes for the SignedBeaconBlockHeader object -func (s *SignedBeaconBlockHeader) SizeSSZ() (size int) { - size = 208 +// SizeSSZ returns the ssz encoded size in bytes for the AttesterSlashing object +func (a *AttesterSlashing) SizeSSZ() (size int) { + size = 8 + + // Field (0) 'Attestation_1' + if a.Attestation_1 == nil { + a.Attestation_1 = new(IndexedAttestation) + } + size += a.Attestation_1.SizeSSZ() + + // Field (1) 'Attestation_2' + if a.Attestation_2 == nil { + a.Attestation_2 = new(IndexedAttestation) + } + size += a.Attestation_2.SizeSSZ() + return } -// HashTreeRoot ssz hashes the SignedBeaconBlockHeader object -func (s *SignedBeaconBlockHeader) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(s) +// HashTreeRoot ssz hashes the AttesterSlashing object +func (a *AttesterSlashing) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(a) } -// HashTreeRootWith ssz hashes the SignedBeaconBlockHeader object with a hasher -func (s *SignedBeaconBlockHeader) HashTreeRootWith(hh *ssz.Hasher) (err error) { +// HashTreeRootWith ssz hashes the AttesterSlashing object with a hasher +func (a *AttesterSlashing) HashTreeRootWith(hh *ssz.Hasher) (err error) { indx := hh.Index() - - // Field (0) 'Header' - if err = s.Header.HashTreeRootWith(hh); err != nil { + + // Field (0) 'Attestation_1' + if err = a.Attestation_1.HashTreeRootWith(hh); err != nil { return } - // Field (1) 'Signature' - if size := len(s.Signature); size != 96 { - err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + // Field (1) 'Attestation_2' + if err = a.Attestation_2.HashTreeRootWith(hh); err != nil { return } - hh.PutBytes(s.Signature) hh.Merkleize(indx) return @@ -2134,6 +1888,251 @@ func (i *IndexedAttestation) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } +// MarshalSSZ ssz marshals the Deposit object +func (d *Deposit) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(d) +} + +// MarshalSSZTo ssz marshals the Deposit object to a target array +func (d *Deposit) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Proof' + if size := len(d.Proof); size != 33 { + err = ssz.ErrVectorLengthFn("--.Proof", size, 33) + return + } + for ii := 0; ii < 33; ii++ { + if size := len(d.Proof[ii]); size != 32 { + err = ssz.ErrBytesLengthFn("--.Proof[ii]", size, 32) + return + } + dst = append(dst, d.Proof[ii]...) + } + + // Field (1) 'Data' + if d.Data == nil { + d.Data = new(Deposit_Data) + } + if dst, err = d.Data.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the Deposit object +func (d *Deposit) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 1240 { + return ssz.ErrSize + } + + // Field (0) 'Proof' + d.Proof = make([][]byte, 33) + for ii := 0; ii < 33; ii++ { + if cap(d.Proof[ii]) == 0 { + d.Proof[ii] = make([]byte, 0, len(buf[0:1056][ii*32:(ii+1)*32])) + } + d.Proof[ii] = append(d.Proof[ii], buf[0:1056][ii*32:(ii+1)*32]...) + } + + // Field (1) 'Data' + if d.Data == nil { + d.Data = new(Deposit_Data) + } + if err = d.Data.UnmarshalSSZ(buf[1056:1240]); err != nil { + return err + } + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the Deposit object +func (d *Deposit) SizeSSZ() (size int) { + size = 1240 + return +} + +// HashTreeRoot ssz hashes the Deposit object +func (d *Deposit) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(d) +} + +// HashTreeRootWith ssz hashes the Deposit object with a hasher +func (d *Deposit) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Proof' + { + if size := len(d.Proof); size != 33 { + err = ssz.ErrVectorLengthFn("--.Proof", size, 33) + return + } + subIndx := hh.Index() + for _, i := range d.Proof { + if len(i) != 32 { + err = ssz.ErrBytesLength + return + } + hh.Append(i) + } + hh.Merkleize(subIndx) + } + + // Field (1) 'Data' + if err = d.Data.HashTreeRootWith(hh); err != nil { + return + } + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the SignedVoluntaryExit object +func (s *SignedVoluntaryExit) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(s) +} + +// MarshalSSZTo ssz marshals the SignedVoluntaryExit object to a target array +func (s *SignedVoluntaryExit) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Exit' + if s.Exit == nil { + s.Exit = new(VoluntaryExit) + } + if dst, err = s.Exit.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + dst = append(dst, s.Signature...) + + return +} + +// UnmarshalSSZ ssz unmarshals the SignedVoluntaryExit object +func (s *SignedVoluntaryExit) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 112 { + return ssz.ErrSize + } + + // Field (0) 'Exit' + if s.Exit == nil { + s.Exit = new(VoluntaryExit) + } + if err = s.Exit.UnmarshalSSZ(buf[0:16]); err != nil { + return err + } + + // Field (1) 'Signature' + if cap(s.Signature) == 0 { + s.Signature = make([]byte, 0, len(buf[16:112])) + } + s.Signature = append(s.Signature, buf[16:112]...) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the SignedVoluntaryExit object +func (s *SignedVoluntaryExit) SizeSSZ() (size int) { + size = 112 + return +} + +// HashTreeRoot ssz hashes the SignedVoluntaryExit object +func (s *SignedVoluntaryExit) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(s) +} + +// HashTreeRootWith ssz hashes the SignedVoluntaryExit object with a hasher +func (s *SignedVoluntaryExit) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Exit' + if err = s.Exit.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Signature' + if size := len(s.Signature); size != 96 { + err = ssz.ErrBytesLengthFn("--.Signature", size, 96) + return + } + hh.PutBytes(s.Signature) + + hh.Merkleize(indx) + return +} + +// MarshalSSZ ssz marshals the VoluntaryExit object +func (v *VoluntaryExit) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(v) +} + +// MarshalSSZTo ssz marshals the VoluntaryExit object to a target array +func (v *VoluntaryExit) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + + // Field (0) 'Epoch' + dst = ssz.MarshalUint64(dst, uint64(v.Epoch)) + + // Field (1) 'ValidatorIndex' + dst = ssz.MarshalUint64(dst, uint64(v.ValidatorIndex)) + + return +} + +// UnmarshalSSZ ssz unmarshals the VoluntaryExit object +func (v *VoluntaryExit) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size != 16 { + return ssz.ErrSize + } + + // Field (0) 'Epoch' + v.Epoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[0:8])) + + // Field (1) 'ValidatorIndex' + v.ValidatorIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) + + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the VoluntaryExit object +func (v *VoluntaryExit) SizeSSZ() (size int) { + size = 16 + return +} + +// HashTreeRoot ssz hashes the VoluntaryExit object +func (v *VoluntaryExit) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(v) +} + +// HashTreeRootWith ssz hashes the VoluntaryExit object with a hasher +func (v *VoluntaryExit) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Epoch' + hh.PutUint64(uint64(v.Epoch)) + + // Field (1) 'ValidatorIndex' + hh.PutUint64(uint64(v.ValidatorIndex)) + + hh.Merkleize(indx) + return +} + // MarshalSSZ ssz marshals the Deposit_Data object func (d *Deposit_Data) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(d) @@ -3979,7 +3978,10 @@ func (v *Validator) UnmarshalSSZ(buf []byte) error { v.EffectiveBalance = ssz.UnmarshallUint64(buf[80:88]) // Field (3) 'Slashed' - v.Slashed = ssz.UnmarshalBool(buf[88:89]) + v.Slashed, err = ssz.DecodeBool(buf[88:89]) + if err != nil { + return err + } // Field (4) 'ActivationEligibilityEpoch' v.ActivationEligibilityEpoch = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[89:97])) diff --git a/proto/prysm/v1alpha1/powchain.pb.go b/proto/prysm/v1alpha1/powchain.pb.go index f37a8a10e52f..9292254c2571 100755 --- a/proto/prysm/v1alpha1/powchain.pb.go +++ b/proto/prysm/v1alpha1/powchain.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/powchain.proto package eth diff --git a/proto/prysm/v1alpha1/powchain.pb.gw.go b/proto/prysm/v1alpha1/powchain.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/powchain.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/powchain.proto b/proto/prysm/v1alpha1/powchain.proto index b523f59fd658..0c3868cba5b3 100644 --- a/proto/prysm/v1alpha1/powchain.proto +++ b/proto/prysm/v1alpha1/powchain.proto @@ -17,58 +17,59 @@ option php_namespace = "Ethereum\\Eth\\v1alpha1"; // ETH1ChainData is a container which holds all the relevant eth1 // information message ETH1ChainData { - LatestETH1Data current_eth1_data = 1 ; - ChainStartData chainstart_data = 2; - BeaconState beacon_state = 3; - SparseMerkleTrie trie = 4; - repeated DepositContainer deposit_containers = 5; - DepositSnapshot deposit_snapshot = 6; + LatestETH1Data current_eth1_data = 1; + ChainStartData chainstart_data = 2; + BeaconState beacon_state = 3; + SparseMerkleTrie trie = 4; + repeated DepositContainer deposit_containers = 5; + DepositSnapshot deposit_snapshot = 6; } // DepositSnapshot represents an EIP-4881 deposit snapshot message DepositSnapshot { - repeated bytes finalized = 1 [(ethereum.eth.ext.ssz_size) = "?,32", (ethereum.eth.ext.ssz_max) = "32"]; - bytes deposit_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 deposit_count = 3; - bytes execution_hash = 4 [(ethereum.eth.ext.ssz_size) = "32"]; - uint64 execution_depth = 5; + repeated bytes finalized = 1 [ + (ethereum.eth.ext.ssz_size) = "?,32", + (ethereum.eth.ext.ssz_max) = "32" + ]; + bytes deposit_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 deposit_count = 3; + bytes execution_hash = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; + uint64 execution_depth = 5; } // LatestETH1Data contains the current state of the eth1 chain. message LatestETH1Data { - uint64 block_height = 2; - uint64 block_time = 3; - bytes block_hash = 4; - uint64 last_requested_block = 5; + uint64 block_height = 2; + uint64 block_time = 3; + bytes block_hash = 4; + uint64 last_requested_block = 5; } // ChainStartData contains all the information related to chainstart. message ChainStartData { - bool chainstarted = 1; - uint64 genesis_time = 2; - uint64 genesis_block = 3; - Eth1Data eth1_data = 4; - repeated Deposit chainstart_deposits = 5; + bool chainstarted = 1; + uint64 genesis_time = 2; + uint64 genesis_block = 3; + Eth1Data eth1_data = 4; + repeated Deposit chainstart_deposits = 5; } // SparseMerkleTrie is used to describe the model of our deposit trie. message SparseMerkleTrie { - uint64 depth = 1; - repeated TrieLayer layers = 2; - repeated bytes original_items = 3; + uint64 depth = 1; + repeated TrieLayer layers = 2; + repeated bytes original_items = 3; } // TrieLayer is used to represent each layer in the deposit tree due to // the lack of protobuf support for multi-dimensional arrays.(Ex: 3d,4d,...) -message TrieLayer { - repeated bytes layer = 1; -} +message TrieLayer { repeated bytes layer = 1; } // DepositContainer defines a container that can be used to store // deposit related information for a particular deposit. message DepositContainer { - int64 index = 1; - uint64 eth1_block_height = 2; - Deposit deposit = 3; - bytes deposit_root = 4; + int64 index = 1; + uint64 eth1_block_height = 2; + Deposit deposit = 3; + bytes deposit_root = 4; } diff --git a/proto/prysm/v1alpha1/slasher.pb.go b/proto/prysm/v1alpha1/slasher.pb.go index e7d5be913219..a562753b01ff 100755 --- a/proto/prysm/v1alpha1/slasher.pb.go +++ b/proto/prysm/v1alpha1/slasher.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/slasher.proto package eth diff --git a/proto/prysm/v1alpha1/slasher.pb.gw.go b/proto/prysm/v1alpha1/slasher.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/slasher.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/slasher.proto b/proto/prysm/v1alpha1/slasher.proto index 036f536451db..253b70f955d1 100644 --- a/proto/prysm/v1alpha1/slasher.proto +++ b/proto/prysm/v1alpha1/slasher.proto @@ -26,10 +26,12 @@ option php_namespace = "Ethereum\\Eth\\v1alpha1"; message HighestAttestation { uint64 validator_index = 1; - uint64 highest_source_epoch = 2 - [ (ethereum.eth.ext.cast_type) = - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" ]; - uint64 highest_target_epoch = 3 - [ (ethereum.eth.ext.cast_type) = - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" ]; + uint64 highest_source_epoch = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + uint64 highest_target_epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; } \ No newline at end of file diff --git a/proto/prysm/v1alpha1/sync_committee.pb.go b/proto/prysm/v1alpha1/sync_committee.pb.go index 1a7fe922f799..a6fab83c6617 100755 --- a/proto/prysm/v1alpha1/sync_committee.pb.go +++ b/proto/prysm/v1alpha1/sync_committee.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/sync_committee.proto package eth @@ -95,20 +95,17 @@ func (x *SyncCommitteeMessage) GetSignature() []byte { return nil } -type SyncCommitteeContribution struct { +type SignedContributionAndProof struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` - BlockRoot []byte `protobuf:"bytes,2,opt,name=block_root,json=blockRoot,proto3" json:"block_root,omitempty" ssz-size:"32"` - SubcommitteeIndex uint64 `protobuf:"varint,3,opt,name=subcommittee_index,json=subcommitteeIndex,proto3" json:"subcommittee_index,omitempty"` - AggregationBits github_com_prysmaticlabs_go_bitfield.Bitvector128 `protobuf:"bytes,4,opt,name=aggregation_bits,json=aggregationBits,proto3" json:"aggregation_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector128" ssz-size:"16"` - Signature []byte `protobuf:"bytes,5,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Message *ContributionAndProof `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SyncCommitteeContribution) Reset() { - *x = SyncCommitteeContribution{} +func (x *SignedContributionAndProof) Reset() { + *x = SignedContributionAndProof{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_sync_committee_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -116,13 +113,13 @@ func (x *SyncCommitteeContribution) Reset() { } } -func (x *SyncCommitteeContribution) String() string { +func (x *SignedContributionAndProof) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SyncCommitteeContribution) ProtoMessage() {} +func (*SignedContributionAndProof) ProtoMessage() {} -func (x *SyncCommitteeContribution) ProtoReflect() protoreflect.Message { +func (x *SignedContributionAndProof) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_sync_committee_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -134,40 +131,19 @@ func (x *SyncCommitteeContribution) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SyncCommitteeContribution.ProtoReflect.Descriptor instead. -func (*SyncCommitteeContribution) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedContributionAndProof.ProtoReflect.Descriptor instead. +func (*SignedContributionAndProof) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_sync_committee_proto_rawDescGZIP(), []int{1} } -func (x *SyncCommitteeContribution) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { - if x != nil { - return x.Slot - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) -} - -func (x *SyncCommitteeContribution) GetBlockRoot() []byte { +func (x *SignedContributionAndProof) GetMessage() *ContributionAndProof { if x != nil { - return x.BlockRoot + return x.Message } return nil } -func (x *SyncCommitteeContribution) GetSubcommitteeIndex() uint64 { - if x != nil { - return x.SubcommitteeIndex - } - return 0 -} - -func (x *SyncCommitteeContribution) GetAggregationBits() github_com_prysmaticlabs_go_bitfield.Bitvector128 { - if x != nil { - return x.AggregationBits - } - return github_com_prysmaticlabs_go_bitfield.Bitvector128(nil) -} - -func (x *SyncCommitteeContribution) GetSignature() []byte { +func (x *SignedContributionAndProof) GetSignature() []byte { if x != nil { return x.Signature } @@ -237,17 +213,20 @@ func (x *ContributionAndProof) GetSelectionProof() []byte { return nil } -type SignedContributionAndProof struct { +type SyncCommitteeContribution struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *ContributionAndProof `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,4,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` + BlockRoot []byte `protobuf:"bytes,2,opt,name=block_root,json=blockRoot,proto3" json:"block_root,omitempty" ssz-size:"32"` + SubcommitteeIndex uint64 `protobuf:"varint,3,opt,name=subcommittee_index,json=subcommitteeIndex,proto3" json:"subcommittee_index,omitempty"` + AggregationBits github_com_prysmaticlabs_go_bitfield.Bitvector128 `protobuf:"bytes,4,opt,name=aggregation_bits,json=aggregationBits,proto3" json:"aggregation_bits,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector128" ssz-size:"16"` + Signature []byte `protobuf:"bytes,5,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *SignedContributionAndProof) Reset() { - *x = SignedContributionAndProof{} +func (x *SyncCommitteeContribution) Reset() { + *x = SyncCommitteeContribution{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_sync_committee_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -255,13 +234,13 @@ func (x *SignedContributionAndProof) Reset() { } } -func (x *SignedContributionAndProof) String() string { +func (x *SyncCommitteeContribution) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedContributionAndProof) ProtoMessage() {} +func (*SyncCommitteeContribution) ProtoMessage() {} -func (x *SignedContributionAndProof) ProtoReflect() protoreflect.Message { +func (x *SyncCommitteeContribution) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_sync_committee_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -273,19 +252,40 @@ func (x *SignedContributionAndProof) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedContributionAndProof.ProtoReflect.Descriptor instead. -func (*SignedContributionAndProof) Descriptor() ([]byte, []int) { +// Deprecated: Use SyncCommitteeContribution.ProtoReflect.Descriptor instead. +func (*SyncCommitteeContribution) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_sync_committee_proto_rawDescGZIP(), []int{3} } -func (x *SignedContributionAndProof) GetMessage() *ContributionAndProof { +func (x *SyncCommitteeContribution) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { - return x.Message + return x.Slot + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0) +} + +func (x *SyncCommitteeContribution) GetBlockRoot() []byte { + if x != nil { + return x.BlockRoot } return nil } -func (x *SignedContributionAndProof) GetSignature() []byte { +func (x *SyncCommitteeContribution) GetSubcommitteeIndex() uint64 { + if x != nil { + return x.SubcommitteeIndex + } + return 0 +} + +func (x *SyncCommitteeContribution) GetAggregationBits() github_com_prysmaticlabs_go_bitfield.Bitvector128 { + if x != nil { + return x.AggregationBits + } + return github_com_prysmaticlabs_go_bitfield.Bitvector128(nil) +} + +func (x *SyncCommitteeContribution) GetSignature() []byte { if x != nil { return x.Signature } @@ -320,54 +320,54 @@ var file_proto_prysm_v1alpha1_sync_committee_proto_rawDesc = []byte{ 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xda, 0x02, 0x0a, 0x19, 0x53, - 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, - 0x6c, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, - 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x75, - 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x66, 0x0a, 0x10, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x3b, 0x82, 0xb5, 0x18, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, - 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x31, 0x32, 0x38, 0x8a, 0xb5, 0x18, 0x02, 0x31, 0x36, - 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, - 0x73, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x99, 0x02, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x12, 0x7a, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0f, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x54, 0x0a, 0x0c, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x22, 0x89, 0x01, 0x0a, 0x1a, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x12, 0x45, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x1a, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x45, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, + 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x99, 0x02, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, + 0x7a, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x54, 0x0a, 0x0c, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x2f, 0x0a, 0x0f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, + 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x39, 0x36, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, + 0x6f, 0x66, 0x22, 0xda, 0x02, 0x0a, 0x19, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, + 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, + 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, + 0x6f, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, + 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x12, 0x66, 0x0a, 0x10, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x62, 0x69, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x3b, 0x82, 0xb5, 0x18, + 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x31, + 0x32, 0x38, 0x8a, 0xb5, 0x18, 0x02, 0x31, 0x36, 0x52, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x97, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x12, 0x53, @@ -397,13 +397,13 @@ func file_proto_prysm_v1alpha1_sync_committee_proto_rawDescGZIP() []byte { var file_proto_prysm_v1alpha1_sync_committee_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_proto_prysm_v1alpha1_sync_committee_proto_goTypes = []interface{}{ (*SyncCommitteeMessage)(nil), // 0: ethereum.eth.v1alpha1.SyncCommitteeMessage - (*SyncCommitteeContribution)(nil), // 1: ethereum.eth.v1alpha1.SyncCommitteeContribution + (*SignedContributionAndProof)(nil), // 1: ethereum.eth.v1alpha1.SignedContributionAndProof (*ContributionAndProof)(nil), // 2: ethereum.eth.v1alpha1.ContributionAndProof - (*SignedContributionAndProof)(nil), // 3: ethereum.eth.v1alpha1.SignedContributionAndProof + (*SyncCommitteeContribution)(nil), // 3: ethereum.eth.v1alpha1.SyncCommitteeContribution } var file_proto_prysm_v1alpha1_sync_committee_proto_depIdxs = []int32{ - 1, // 0: ethereum.eth.v1alpha1.ContributionAndProof.contribution:type_name -> ethereum.eth.v1alpha1.SyncCommitteeContribution - 2, // 1: ethereum.eth.v1alpha1.SignedContributionAndProof.message:type_name -> ethereum.eth.v1alpha1.ContributionAndProof + 2, // 0: ethereum.eth.v1alpha1.SignedContributionAndProof.message:type_name -> ethereum.eth.v1alpha1.ContributionAndProof + 3, // 1: ethereum.eth.v1alpha1.ContributionAndProof.contribution:type_name -> ethereum.eth.v1alpha1.SyncCommitteeContribution 2, // [2:2] is the sub-list for method output_type 2, // [2:2] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name @@ -430,7 +430,7 @@ func file_proto_prysm_v1alpha1_sync_committee_proto_init() { } } file_proto_prysm_v1alpha1_sync_committee_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SyncCommitteeContribution); i { + switch v := v.(*SignedContributionAndProof); i { case 0: return &v.state case 1: @@ -454,7 +454,7 @@ func file_proto_prysm_v1alpha1_sync_committee_proto_init() { } } file_proto_prysm_v1alpha1_sync_committee_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedContributionAndProof); i { + switch v := v.(*SyncCommitteeContribution); i { case 0: return &v.state case 1: diff --git a/proto/prysm/v1alpha1/sync_committee.pb.gw.go b/proto/prysm/v1alpha1/sync_committee.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/sync_committee.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/sync_committee.proto b/proto/prysm/v1alpha1/sync_committee.proto index a2bd674f4be7..0f09db806dd2 100644 --- a/proto/prysm/v1alpha1/sync_committee.proto +++ b/proto/prysm/v1alpha1/sync_committee.proto @@ -27,51 +27,69 @@ option php_namespace = "Ethereum\\Eth\\v1alpha1"; // Sync committee object to support light client. message SyncCommitteeMessage { // Slot to which this contribution pertains. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; // 32 byte block root for this signature. - bytes block_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; + bytes block_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Index of the validator that produced this signature. - uint64 validator_index = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + uint64 validator_index = 3 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; // Signature by the validator over the block root of `slot`. - bytes signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; + bytes signature = 4 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -// Aggregated sync committee object to support light client. -message SyncCommitteeContribution { - // Slot to which this contribution pertains. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - - // 32 byte block root for this signature. - bytes block_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The subcommittee this contribution pertains to out of the broader sync committee. - uint64 subcommittee_index = 3; +// Signed aggregated sync committee signature object with selection proof to +// support light client. +message SignedContributionAndProof { + ContributionAndProof message = 1; - // A bit is set if a signature from the validator at the corresponding - // index in the subcommittee is present in the aggregate `signature`. - bytes aggregation_bits = 4 [(ethereum.eth.ext.ssz_size) = "sync_committee_aggregate_bytes.size", (ethereum.eth.ext.cast_type) = "sync_committee_aggregate_bits.type"]; - // Signature by the validator(s) over the block root of `slot`. - bytes signature = 5 [(ethereum.eth.ext.ssz_size) = "96"]; + // Signature of the aggregator that produced `message`. + bytes signature = 4 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -// Aggregated sync committee signature object with selection proof to support light client. +// Aggregated sync committee signature object with selection proof to support +// light client. message ContributionAndProof { // Index of the aggregator that produced this proof. - uint64 aggregator_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + uint64 aggregator_index = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; SyncCommitteeContribution contribution = 2; // The selection proof itself. - bytes selection_proof = 3 [(ethereum.eth.ext.ssz_size) = "96"]; + bytes selection_proof = 3 [ (ethereum.eth.ext.ssz_size) = "96" ]; } -// Signed aggregated sync committee signature object with selection proof to support light client. -message SignedContributionAndProof { - ContributionAndProof message = 1; +// Aggregated sync committee object to support light client. +message SyncCommitteeContribution { + // Slot to which this contribution pertains. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Signature of the aggregator that produced `message`. - bytes signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; + // 32 byte block root for this signature. + bytes block_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // The subcommittee this contribution pertains to out of the broader sync + // committee. + uint64 subcommittee_index = 3; + + // A bit is set if a signature from the validator at the corresponding + // index in the subcommittee is present in the aggregate `signature`. + bytes aggregation_bits = 4 [ + (ethereum.eth.ext.ssz_size) = "sync_committee_aggregate_bytes.size", + (ethereum.eth.ext.cast_type) = "sync_committee_aggregate_bits.type" + ]; + // Signature by the validator(s) over the block root of `slot`. + bytes signature = 5 [ (ethereum.eth.ext.ssz_size) = "96" ]; } diff --git a/proto/prysm/v1alpha1/validator-client/BUILD.bazel b/proto/prysm/v1alpha1/validator-client/BUILD.bazel index bd4607d598bc..df99b795100a 100644 --- a/proto/prysm/v1alpha1/validator-client/BUILD.bazel +++ b/proto/prysm/v1alpha1/validator-client/BUILD.bazel @@ -11,11 +11,6 @@ load("@rules_proto//proto:defs.bzl", "proto_library") load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") -############################################################################## -# OpenAPI (Swagger) V2 -############################################################################## -load("@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2:defs.bzl", "protoc_gen_openapiv2") - proto_library( name = "proto", srcs = [ @@ -25,7 +20,6 @@ proto_library( deps = [ "//proto/eth/ext:proto", "//proto/prysm/v1alpha1:proto", - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_proto", "@com_google_protobuf//:any_proto", "@com_google_protobuf//:descriptor_proto", "@com_google_protobuf//:empty_proto", @@ -49,7 +43,6 @@ go_proto_library( "//proto/eth/ext:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_golang_protobuf//proto:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@googleapis//google/api:annotations_go_proto", "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", @@ -63,35 +56,13 @@ go_proto_library( ], ) -go_proto_library( - name = "go_grpc_gateway_library", - compilers = [ - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-grpc-gateway:go_gen_grpc_gateway", - ], - embed = [":go_proto"], - importpath = "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client", - protos = [":proto"], - visibility = ["//visibility:private"], - deps = [ - "//proto/eth/ext:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto", - "@com_github_prysmaticlabs_go_bitfield//:go_default_library", - "@googleapis//google/api:annotations_go_proto", - "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", - "@io_bazel_rules_go//proto/wkt:empty_go_proto", - "@io_bazel_rules_go//proto/wkt:wrappers_go_proto", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", - ], -) - go_library( name = "go_default_library", srcs = [ "interface.go", ], embed = [ - ":go_grpc_gateway_library", + ":go_proto", ], importpath = "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client", visibility = ["//visibility:public"], @@ -99,9 +70,6 @@ go_library( "//proto/eth/ext:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "@com_github_golang_protobuf//proto:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//protoc-gen-openapiv2/options:options_go_proto", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//utilities:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", # keep "@googleapis//google/api:annotations_go_proto", "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", diff --git a/proto/prysm/v1alpha1/validator-client/keymanager.pb.go b/proto/prysm/v1alpha1/validator-client/keymanager.pb.go index b6e9f1b1542a..a6af696e499f 100755 --- a/proto/prysm/v1alpha1/validator-client/keymanager.pb.go +++ b/proto/prysm/v1alpha1/validator-client/keymanager.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/validator-client/keymanager.proto package validatorpb @@ -107,6 +107,8 @@ type SignRequest struct { // *SignRequest_BlockElectra // *SignRequest_BlindedBlockElectra // *SignRequest_AggregateAttestationAndProofElectra + // *SignRequest_BlockFulu + // *SignRequest_BlindedBlockFulu Object isSignRequest_Object `protobuf_oneof:"object"` SigningSlot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,6,opt,name=signing_slot,json=signingSlot,proto3" json:"signing_slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"` } @@ -311,6 +313,20 @@ func (x *SignRequest) GetAggregateAttestationAndProofElectra() *v1alpha1.Aggrega return nil } +func (x *SignRequest) GetBlockFulu() *v1alpha1.BeaconBlockElectra { + if x, ok := x.GetObject().(*SignRequest_BlockFulu); ok { + return x.BlockFulu + } + return nil +} + +func (x *SignRequest) GetBlindedBlockFulu() *v1alpha1.BlindedBeaconBlockFulu { + if x, ok := x.GetObject().(*SignRequest_BlindedBlockFulu); ok { + return x.BlindedBlockFulu + } + return nil +} + func (x *SignRequest) GetSigningSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot { if x != nil { return x.SigningSlot @@ -402,6 +418,14 @@ type SignRequest_AggregateAttestationAndProofElectra struct { AggregateAttestationAndProofElectra *v1alpha1.AggregateAttestationAndProofElectra `protobuf:"bytes,120,opt,name=aggregate_attestation_and_proof_electra,json=aggregateAttestationAndProofElectra,proto3,oneof"` } +type SignRequest_BlockFulu struct { + BlockFulu *v1alpha1.BeaconBlockElectra `protobuf:"bytes,121,opt,name=block_fulu,json=blockFulu,proto3,oneof"` +} + +type SignRequest_BlindedBlockFulu struct { + BlindedBlockFulu *v1alpha1.BlindedBeaconBlockFulu `protobuf:"bytes,122,opt,name=blinded_block_fulu,json=blindedBlockFulu,proto3,oneof"` +} + func (*SignRequest_Block) isSignRequest_Object() {} func (*SignRequest_AttestationData) isSignRequest_Object() {} @@ -442,6 +466,10 @@ func (*SignRequest_BlindedBlockElectra) isSignRequest_Object() {} func (*SignRequest_AggregateAttestationAndProofElectra) isSignRequest_Object() {} +func (*SignRequest_BlockFulu) isSignRequest_Object() {} + +func (*SignRequest_BlindedBlockFulu) isSignRequest_Object() {} + type SignResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -698,7 +726,7 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbd, 0x10, 0x0a, 0x0b, 0x53, + 0x74, 0x74, 0x65, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe8, 0x11, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x67, @@ -822,85 +850,96 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_rawDesc = []byte 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x48, 0x00, 0x52, 0x23, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x68, 0x0a, 0x0c, 0x73, 0x69, - 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, - 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, - 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, - 0x53, 0x6c, 0x6f, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4a, 0x04, - 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0xb7, 0x01, 0x0a, 0x0c, 0x53, - 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3c, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, - 0x09, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, - 0x44, 0x45, 0x4e, 0x49, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, - 0x45, 0x44, 0x10, 0x03, 0x22, 0xb3, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x23, - 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x4a, 0x0a, 0x0a, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x66, 0x75, 0x6c, 0x75, 0x18, 0x79, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x75, 0x12, 0x5d, 0x0a, 0x12, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, + 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x66, 0x75, 0x6c, 0x75, 0x18, 0x7a, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, + 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x75, 0x6c, + 0x75, 0x48, 0x00, 0x52, 0x10, 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x46, 0x75, 0x6c, 0x75, 0x12, 0x68, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, + 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, + 0x6f, 0x74, 0x52, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x6c, 0x6f, 0x74, 0x42, + 0x08, 0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, + 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0xb7, 0x01, 0x0a, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x08, - 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, - 0x09, 0x5f, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x22, 0xa6, 0x01, 0x0a, 0x0d, 0x42, - 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x63, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, - 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x69, 0x6e, 0x74, 0x36, - 0x34, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6c, - 0x61, 0x79, 0x73, 0x22, 0xe7, 0x02, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, - 0x74, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x22, 0x3c, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x43, 0x43, + 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4e, 0x49, 0x45, + 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x22, + 0xb3, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x65, 0x65, + 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x47, + 0x0a, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, + 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, + 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x67, 0x72, 0x61, + 0x66, 0x66, 0x69, 0x74, 0x69, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x67, 0x72, 0x61, + 0x66, 0x66, 0x69, 0x74, 0x69, 0x22, 0xa6, 0x01, 0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x63, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x52, 0x08, 0x67, 0x61, + 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0xe7, + 0x02, 0x0a, 0x17, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x74, 0x0a, 0x0f, 0x70, 0x72, + 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x50, 0x72, 0x6f, + 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x5c, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5c, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x1a, 0x78, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4b, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0xce, 0x01, - 0x0a, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x73, 0x2e, 0x76, 0x32, 0x42, 0x0f, 0x4b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x3b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xaa, 0x02, 0x1e, 0x45, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x1e, - 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x5c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5c, 0x56, 0x32, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, + 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x78, + 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0xce, 0x01, 0x0a, 0x22, 0x6f, 0x72, 0x67, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x32, 0x42, + 0x0f, 0x4b, 0x65, 0x79, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x53, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x3b, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xaa, 0x02, 0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x1e, 0x45, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x5c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5c, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5c, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -942,6 +981,7 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_goTypes = []inte (*v1alpha1.BeaconBlockElectra)(nil), // 21: ethereum.eth.v1alpha1.BeaconBlockElectra (*v1alpha1.BlindedBeaconBlockElectra)(nil), // 22: ethereum.eth.v1alpha1.BlindedBeaconBlockElectra (*v1alpha1.AggregateAttestationAndProofElectra)(nil), // 23: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + (*v1alpha1.BlindedBeaconBlockFulu)(nil), // 24: ethereum.eth.v1alpha1.BlindedBeaconBlockFulu } var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_depIdxs = []int32{ 7, // 0: ethereum.validator.accounts.v2.SignRequest.block:type_name -> ethereum.eth.v1alpha1.BeaconBlock @@ -961,16 +1001,18 @@ var file_proto_prysm_v1alpha1_validator_client_keymanager_proto_depIdxs = []int3 21, // 14: ethereum.validator.accounts.v2.SignRequest.block_electra:type_name -> ethereum.eth.v1alpha1.BeaconBlockElectra 22, // 15: ethereum.validator.accounts.v2.SignRequest.blinded_block_electra:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockElectra 23, // 16: ethereum.validator.accounts.v2.SignRequest.aggregate_attestation_and_proof_electra:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - 0, // 17: ethereum.validator.accounts.v2.SignResponse.status:type_name -> ethereum.validator.accounts.v2.SignResponse.Status - 4, // 18: ethereum.validator.accounts.v2.ProposerOptionPayload.builder:type_name -> ethereum.validator.accounts.v2.BuilderConfig - 6, // 19: ethereum.validator.accounts.v2.ProposerSettingsPayload.proposer_config:type_name -> ethereum.validator.accounts.v2.ProposerSettingsPayload.ProposerConfigEntry - 3, // 20: ethereum.validator.accounts.v2.ProposerSettingsPayload.default_config:type_name -> ethereum.validator.accounts.v2.ProposerOptionPayload - 3, // 21: ethereum.validator.accounts.v2.ProposerSettingsPayload.ProposerConfigEntry.value:type_name -> ethereum.validator.accounts.v2.ProposerOptionPayload - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 21, // 17: ethereum.validator.accounts.v2.SignRequest.block_fulu:type_name -> ethereum.eth.v1alpha1.BeaconBlockElectra + 24, // 18: ethereum.validator.accounts.v2.SignRequest.blinded_block_fulu:type_name -> ethereum.eth.v1alpha1.BlindedBeaconBlockFulu + 0, // 19: ethereum.validator.accounts.v2.SignResponse.status:type_name -> ethereum.validator.accounts.v2.SignResponse.Status + 4, // 20: ethereum.validator.accounts.v2.ProposerOptionPayload.builder:type_name -> ethereum.validator.accounts.v2.BuilderConfig + 6, // 21: ethereum.validator.accounts.v2.ProposerSettingsPayload.proposer_config:type_name -> ethereum.validator.accounts.v2.ProposerSettingsPayload.ProposerConfigEntry + 3, // 22: ethereum.validator.accounts.v2.ProposerSettingsPayload.default_config:type_name -> ethereum.validator.accounts.v2.ProposerOptionPayload + 3, // 23: ethereum.validator.accounts.v2.ProposerSettingsPayload.ProposerConfigEntry.value:type_name -> ethereum.validator.accounts.v2.ProposerOptionPayload + 24, // [24:24] is the sub-list for method output_type + 24, // [24:24] is the sub-list for method input_type + 24, // [24:24] is the sub-list for extension type_name + 24, // [24:24] is the sub-list for extension extendee + 0, // [0:24] is the sub-list for field type_name } func init() { file_proto_prysm_v1alpha1_validator_client_keymanager_proto_init() } @@ -1061,6 +1103,8 @@ func file_proto_prysm_v1alpha1_validator_client_keymanager_proto_init() { (*SignRequest_BlockElectra)(nil), (*SignRequest_BlindedBlockElectra)(nil), (*SignRequest_AggregateAttestationAndProofElectra)(nil), + (*SignRequest_BlockFulu)(nil), + (*SignRequest_BlindedBlockFulu)(nil), } file_proto_prysm_v1alpha1_validator_client_keymanager_proto_msgTypes[2].OneofWrappers = []interface{}{} type x struct{} diff --git a/proto/prysm/v1alpha1/validator-client/keymanager.pb.gw.go b/proto/prysm/v1alpha1/validator-client/keymanager.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/validator-client/keymanager.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/validator-client/keymanager.proto b/proto/prysm/v1alpha1/validator-client/keymanager.proto index 81769612a17c..f63e49a3f9d4 100644 --- a/proto/prysm/v1alpha1/validator-client/keymanager.proto +++ b/proto/prysm/v1alpha1/validator-client/keymanager.proto @@ -17,75 +17,93 @@ option php_namespace = "Ethereum\\Validator\\Accounts\\V2"; // SignRequest is a message type used by a keymanager // as part of Prysm's accounts v2 implementation. message SignRequest { - // 48 byte public key corresponding to an associated private key - // being requested to sign data. - bytes public_key = 1; - - // Raw bytes signing root the client is requesting to sign. The client is - // expected to determine these raw bytes from the appropriate BLS - // signing domain as well as the signing root of the data structure - // the bytes represent. - bytes signing_root = 2; - - // Signature domain and the beacon chain objects to allow server to verify - // the contents and to prevent slashing. - bytes signature_domain = 3; - // Beacon chain objects. [100-200] - oneof object { - // Phase0 objects. - ethereum.eth.v1alpha1.BeaconBlock block = 101; - ethereum.eth.v1alpha1.AttestationData attestation_data = 102; - ethereum.eth.v1alpha1.AggregateAttestationAndProof aggregate_attestation_and_proof = 103; - ethereum.eth.v1alpha1.VoluntaryExit exit = 104; - uint64 slot = 105 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - uint64 epoch = 106 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Altair objects. - ethereum.eth.v1alpha1.BeaconBlockAltair block_altair = 107; - ethereum.eth.v1alpha1.SyncAggregatorSelectionData sync_aggregator_selection_data = 108; - ethereum.eth.v1alpha1.ContributionAndProof contribution_and_proof = 109; - bytes sync_message_block_root = 110; - - // Bellatrix objects. - ethereum.eth.v1alpha1.BeaconBlockBellatrix block_bellatrix = 111; - ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix blinded_block_bellatrix = 112; - - // Builder objects. - ethereum.eth.v1alpha1.ValidatorRegistrationV1 registration = 113; - - // Capella objects. - ethereum.eth.v1alpha1.BeaconBlockCapella block_capella = 114; - ethereum.eth.v1alpha1.BlindedBeaconBlockCapella blinded_block_capella = 115; - - // Deneb objects. - ethereum.eth.v1alpha1.BeaconBlockDeneb block_deneb = 116; - ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb blinded_block_deneb = 117; - - // Electra objects. - ethereum.eth.v1alpha1.BeaconBlockElectra block_electra = 118; - ethereum.eth.v1alpha1.BlindedBeaconBlockElectra blinded_block_electra = 119; - ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra aggregate_attestation_and_proof_electra = 120; - } - reserved 4, 5; // Reserving old, deleted fields. - uint64 signing_slot = 6 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // 48 byte public key corresponding to an associated private key + // being requested to sign data. + bytes public_key = 1; + + // Raw bytes signing root the client is requesting to sign. The client is + // expected to determine these raw bytes from the appropriate BLS + // signing domain as well as the signing root of the data structure + // the bytes represent. + bytes signing_root = 2; + + // Signature domain and the beacon chain objects to allow server to verify + // the contents and to prevent slashing. + bytes signature_domain = 3; + // Beacon chain objects. [100-200] + oneof object { + // Phase0 objects. + ethereum.eth.v1alpha1.BeaconBlock block = 101; + ethereum.eth.v1alpha1.AttestationData attestation_data = 102; + ethereum.eth.v1alpha1.AggregateAttestationAndProof + aggregate_attestation_and_proof = 103; + ethereum.eth.v1alpha1.VoluntaryExit exit = 104; + uint64 slot = 105 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + uint64 epoch = 106 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Altair objects. + ethereum.eth.v1alpha1.BeaconBlockAltair block_altair = 107; + ethereum.eth.v1alpha1.SyncAggregatorSelectionData + sync_aggregator_selection_data = 108; + ethereum.eth.v1alpha1.ContributionAndProof contribution_and_proof = 109; + bytes sync_message_block_root = 110; + + // Bellatrix objects. + ethereum.eth.v1alpha1.BeaconBlockBellatrix block_bellatrix = 111; + ethereum.eth.v1alpha1.BlindedBeaconBlockBellatrix blinded_block_bellatrix = + 112; + + // Builder objects. + ethereum.eth.v1alpha1.ValidatorRegistrationV1 registration = 113; + + // Capella objects. + ethereum.eth.v1alpha1.BeaconBlockCapella block_capella = 114; + ethereum.eth.v1alpha1.BlindedBeaconBlockCapella blinded_block_capella = 115; + + // Deneb objects. + ethereum.eth.v1alpha1.BeaconBlockDeneb block_deneb = 116; + ethereum.eth.v1alpha1.BlindedBeaconBlockDeneb blinded_block_deneb = 117; + + // Electra objects. + ethereum.eth.v1alpha1.BeaconBlockElectra block_electra = 118; + ethereum.eth.v1alpha1.BlindedBeaconBlockElectra blinded_block_electra = 119; + ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + aggregate_attestation_and_proof_electra = 120; + + // Fulu objects. + ethereum.eth.v1alpha1.BeaconBlockElectra block_fulu = 121; + ethereum.eth.v1alpha1.BlindedBeaconBlockFulu blinded_block_fulu = 122; + } + + reserved 4, 5; // Reserving old, deleted fields. + uint64 signing_slot = 6 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; } // SignResponse returned by a RemoteSigner gRPC service. message SignResponse { - enum Status { - UNKNOWN = 0; - SUCCEEDED = 1; - DENIED = 2; - FAILED = 3; - } - - // BLS12-381 signature for the data specified in the request. - bytes signature = 1; - - // Status of the signing response, standardized as an enum - // to ensure different remote signing servers follow the - // same conventions. - Status status = 2; + enum Status { + UNKNOWN = 0; + SUCCEEDED = 1; + DENIED = 2; + FAILED = 3; + } + + // BLS12-381 signature for the data specified in the request. + bytes signature = 1; + + // Status of the signing response, standardized as an enum + // to ensure different remote signing servers follow the + // same conventions. + Status status = 2; } // ProposerOptionPayload is a property of ProposerSettingsPayload @@ -98,11 +116,15 @@ message ProposerOptionPayload { // BuilderConfig is a property of ProposerOptionPayload message BuilderConfig { bool enabled = 1; - uint64 gas_limit = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/validator.Uint64"]; + uint64 gas_limit = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/validator.Uint64" + ]; repeated string relays = 3; } -// ProposerSettingsPayload is used to unmarshal files sent from the validator flag as well as safe to bolt db bucket +// ProposerSettingsPayload is used to unmarshal files sent from the validator +// flag as well as safe to bolt db bucket message ProposerSettingsPayload { map proposer_config = 1; ProposerOptionPayload default_config = 2; diff --git a/proto/prysm/v1alpha1/validator.pb.go b/proto/prysm/v1alpha1/validator.pb.go index 53416223b4fe..1a74d8911201 100755 --- a/proto/prysm/v1alpha1/validator.pb.go +++ b/proto/prysm/v1alpha1/validator.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/validator.proto package eth @@ -371,6 +371,7 @@ type StreamBlocksResponse struct { // *StreamBlocksResponse_CapellaBlock // *StreamBlocksResponse_DenebBlock // *StreamBlocksResponse_ElectraBlock + // *StreamBlocksResponse_FuluBlock Block isStreamBlocksResponse_Block `protobuf_oneof:"block"` } @@ -455,6 +456,13 @@ func (x *StreamBlocksResponse) GetElectraBlock() *SignedBeaconBlockElectra { return nil } +func (x *StreamBlocksResponse) GetFuluBlock() *SignedBeaconBlockFulu { + if x, ok := x.GetBlock().(*StreamBlocksResponse_FuluBlock); ok { + return x.FuluBlock + } + return nil +} + type isStreamBlocksResponse_Block interface { isStreamBlocksResponse_Block() } @@ -483,6 +491,10 @@ type StreamBlocksResponse_ElectraBlock struct { ElectraBlock *SignedBeaconBlockElectra `protobuf:"bytes,6,opt,name=electra_block,json=electraBlock,proto3,oneof"` } +type StreamBlocksResponse_FuluBlock struct { + FuluBlock *SignedBeaconBlockFulu `protobuf:"bytes,7,opt,name=fulu_block,json=fuluBlock,proto3,oneof"` +} + func (*StreamBlocksResponse_Phase0Block) isStreamBlocksResponse_Block() {} func (*StreamBlocksResponse_AltairBlock) isStreamBlocksResponse_Block() {} @@ -495,6 +507,8 @@ func (*StreamBlocksResponse_DenebBlock) isStreamBlocksResponse_Block() {} func (*StreamBlocksResponse_ElectraBlock) isStreamBlocksResponse_Block() {} +func (*StreamBlocksResponse_FuluBlock) isStreamBlocksResponse_Block() {} + type DomainRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3148,7 +3162,7 @@ var file_proto_prysm_v1alpha1_validator_proto_rawDesc = []byte{ 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x3a, 0x02, 0x18, - 0x01, 0x22, 0xa7, 0x04, 0x0a, 0x14, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, + 0x01, 0x22, 0xf6, 0x04, 0x0a, 0x14, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x30, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, @@ -3181,226 +3195,251 @@ var file_proto_prysm_v1alpha1_validator_proto_rawDesc = []byte{ 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x48, 0x00, - 0x52, 0x0c, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x02, - 0x18, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x85, 0x01, 0x0a, 0x0d, - 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5c, 0x0a, - 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, - 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, - 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x64, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x64, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x22, 0x3b, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x22, 0x47, 0x0a, 0x1a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, - 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x22, 0xcd, 0x02, 0x0a, 0x1b, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x08, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, - 0x1a, 0xd6, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, + 0x52, 0x0c, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x4d, + 0x0a, 0x0a, 0x66, 0x75, 0x6c, 0x75, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x75, 0x6c, 0x75, + 0x48, 0x00, 0x52, 0x09, 0x66, 0x75, 0x6c, 0x75, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x02, 0x18, + 0x01, 0x42, 0x07, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x85, 0x01, 0x0a, 0x0d, 0x44, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5c, 0x0a, 0x05, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, + 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, + 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, + 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, + 0x69, 0x6e, 0x22, 0x3b, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, + 0x47, 0x0a, 0x1a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, + 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x22, 0xcd, 0x02, 0x0a, 0x1b, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x91, 0x01, 0x0a, 0x12, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x65, - 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, - 0x17, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x4b, 0x0a, - 0x0e, 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, - 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, - 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x3e, 0x0a, 0x15, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, - 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x7f, 0x0a, 0x16, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x3f, 0x0a, 0x16, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, - 0x38, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0xc5, 0x03, 0x0a, - 0x17, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x65, 0x74, 0x68, 0x31, - 0x5f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x65, 0x74, 0x68, - 0x31, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x7b, 0x0a, 0x16, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x14, 0x64, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x6f, 0x74, - 0x12, 0x71, 0x0a, 0x10, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, - 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, - 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x0f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x70, - 0x6f, 0x63, 0x68, 0x12, 0x3f, 0x0a, 0x1c, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x71, 0x75, - 0x65, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, - 0x75, 0x65, 0x75, 0x65, 0x22, 0x65, 0x0a, 0x1e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, + 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x1a, + 0xd6, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x91, 0x01, 0x0a, 0x12, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x65, 0x6e, + 0x65, 0x73, 0x69, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0b, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x17, + 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, + 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x15, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x4b, 0x0a, 0x0e, + 0x53, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x73, 0x79, 0x6e, 0x63, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, + 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x67, 0x65, + 0x6e, 0x65, 0x73, 0x69, 0x73, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x3e, 0x0a, 0x15, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x09, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0x7f, 0x0a, 0x16, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, + 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x3f, 0x0a, 0x16, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, + 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x22, 0xc5, 0x03, 0x0a, 0x17, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, - 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x73, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x03, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x83, 0x02, 0x0a, 0x1f, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x4a, 0x0a, 0x08, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, - 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x98, 0x01, 0x0a, 0x0d, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x65, 0x74, 0x68, 0x31, 0x5f, + 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x65, 0x74, 0x68, 0x31, + 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x12, 0x7b, 0x0a, 0x16, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x5f, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, - 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x22, 0xd3, 0x07, 0x0a, - 0x0e, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x5c, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x5f, 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x75, 0x74, 0x79, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x56, 0x0a, - 0x11, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x64, 0x75, 0x74, 0x69, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x44, 0x75, 0x74, 0x79, 0x52, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x44, - 0x75, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x84, 0x06, 0x0a, 0x04, 0x44, 0x75, 0x74, 0x79, 0x12, 0x6d, - 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x78, 0x0a, - 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x14, 0x64, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x6c, 0x6f, 0x74, 0x12, + 0x71, 0x0a, 0x10, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, + 0x68, 0x52, 0x0f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x70, 0x6f, + 0x63, 0x68, 0x12, 0x3f, 0x0a, 0x1c, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x71, 0x75, 0x65, + 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, + 0x65, 0x75, 0x65, 0x22, 0x65, 0x0a, 0x1e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, + 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, + 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x03, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x83, 0x02, 0x0a, 0x1f, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, + 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, 0x0a, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x4a, 0x0a, 0x08, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x6a, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, - 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, - 0x6c, 0x6f, 0x74, 0x12, 0x6c, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, - 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, - 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, - 0x6f, 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x6f, 0x74, - 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x09, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, - 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, - 0x73, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x2c, - 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, - 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x41, 0x74, 0x53, 0x6c, 0x6f, 0x74, 0x4a, 0x04, 0x08, 0x01, - 0x10, 0x02, 0x22, 0xb0, 0x02, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, + 0x22, 0x98, 0x01, 0x0a, 0x0d, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x2b, - 0x0a, 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0c, 0x72, - 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x22, 0x0a, 0x08, 0x67, - 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, - 0x24, 0x0a, 0x0e, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6d, 0x65, 0x76, 0x5f, 0x62, 0x6f, 0x6f, 0x73, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x4d, 0x65, 0x76, - 0x42, 0x6f, 0x6f, 0x73, 0x74, 0x12, 0x4e, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, - 0x5f, 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x6f, 0x6f, 0x73, 0x74, 0x46, - 0x61, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x38, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x22, - 0x3a, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, 0x69, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x09, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, - 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x08, 0x65, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xed, 0x01, 0x0a, 0x16, - 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34, 0x38, 0x52, + 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x22, 0xd3, 0x07, 0x0a, 0x0e, + 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, + 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, + 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x75, 0x74, 0x79, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x11, + 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x64, 0x75, 0x74, 0x69, 0x65, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, + 0x75, 0x74, 0x79, 0x52, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x44, 0x75, + 0x74, 0x69, 0x65, 0x73, 0x1a, 0x84, 0x06, 0x0a, 0x04, 0x44, 0x75, 0x74, 0x79, 0x12, 0x6d, 0x0a, + 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, + 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x78, 0x0a, 0x0f, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x6a, 0x0a, 0x0d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, + 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, + 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, + 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x0c, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x53, 0x6c, + 0x6f, 0x74, 0x12, 0x6c, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x5f, 0x73, + 0x6c, 0x6f, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, + 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, + 0x74, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x53, 0x6c, 0x6f, 0x74, 0x73, + 0x12, 0x25, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x09, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x73, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x73, + 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x12, 0x2c, 0x0a, + 0x12, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x73, + 0x6c, 0x6f, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x74, 0x65, 0x65, 0x73, 0x41, 0x74, 0x53, 0x6c, 0x6f, 0x74, 0x4a, 0x04, 0x08, 0x01, 0x10, + 0x02, 0x22, 0xb0, 0x02, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x2b, 0x0a, + 0x0d, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x5f, 0x72, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0c, 0x72, 0x61, + 0x6e, 0x64, 0x61, 0x6f, 0x52, 0x65, 0x76, 0x65, 0x61, 0x6c, 0x12, 0x22, 0x0a, 0x08, 0x67, 0x72, + 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x18, 0x02, 0x33, 0x32, 0x52, 0x08, 0x67, 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x12, 0x24, + 0x0a, 0x0e, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6d, 0x65, 0x76, 0x5f, 0x62, 0x6f, 0x6f, 0x73, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x4d, 0x65, 0x76, 0x42, + 0x6f, 0x6f, 0x73, 0x74, 0x12, 0x4e, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x5f, + 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x42, 0x6f, 0x6f, 0x73, 0x74, 0x46, 0x61, + 0x63, 0x74, 0x6f, 0x72, 0x22, 0x38, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, + 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, 0x69, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x09, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, + 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, + 0x52, 0x08, 0x65, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xed, 0x01, 0x0a, 0x16, 0x41, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, + 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, + 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, + 0x12, 0x78, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x4c, 0x0a, 0x0e, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x15, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, + 0x02, 0x33, 0x32, 0x52, 0x13, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x44, 0x61, 0x74, 0x61, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xd0, 0x02, 0x0a, 0x19, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, @@ -3414,658 +3453,638 @@ var file_proto_prysm_v1alpha1_validator_proto_rawDesc = []byte{ 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x4c, 0x0a, 0x0e, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, - 0x15, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x74, - 0x61, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, - 0x18, 0x02, 0x33, 0x32, 0x52, 0x13, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xd0, 0x02, 0x0a, 0x19, 0x41, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, - 0x6f, 0x74, 0x12, 0x78, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, - 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, - 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, - 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2f, 0x0a, 0x0a, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, - 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2d, 0x0a, - 0x0e, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0d, 0x73, - 0x6c, 0x6f, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x81, 0x01, 0x0a, - 0x1a, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x13, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, - 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x11, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x22, 0x8f, 0x01, 0x0a, 0x21, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x13, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, - 0x11, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x22, 0x96, 0x01, 0x0a, 0x1c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x76, 0x0a, 0x1a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x67, + 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2f, 0x0a, 0x0a, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x0e, + 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x0d, 0x73, 0x6c, + 0x6f, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x1a, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x13, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, - 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x52, 0x17, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0xa4, 0x01, 0x0a, 0x23, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x7d, 0x0a, 0x1a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, - 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x17, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, - 0x6f, 0x66, 0x22, 0x5b, 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x15, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x13, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x6f, 0x6f, 0x74, 0x22, - 0x9a, 0x02, 0x0a, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, - 0x6e, 0x65, 0x74, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x05, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x05, 0x73, 0x6c, 0x6f, 0x74, - 0x73, 0x12, 0x74, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, - 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x65, 0x49, 0x64, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x08, 0x52, 0x0c, - 0x69, 0x73, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x9e, 0x05, 0x0a, - 0x09, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, - 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x16, 0x77, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x15, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x66, - 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6c, 0x61, 0x73, 0x68, - 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, - 0x64, 0x12, 0x88, 0x01, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, - 0x52, 0x1a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x69, 0x67, - 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x71, 0x0a, 0x10, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, - 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x0f, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, - 0x65, 0x0a, 0x0a, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x09, 0x65, 0x78, 0x69, - 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x75, 0x0a, 0x12, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x11, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, + 0x8f, 0x01, 0x0a, 0x21, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x13, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, + 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x11, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x22, 0x96, 0x01, 0x0a, 0x1c, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x76, 0x0a, 0x1a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x52, 0x17, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0xa4, 0x01, 0x0a, 0x23, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x7d, 0x0a, 0x1a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x17, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x22, 0x5b, 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x15, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x13, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x9a, + 0x02, 0x0a, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, + 0x65, 0x74, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x05, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x11, 0x77, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x8e, 0x05, - 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x19, 0x67, 0x6c, 0x6f, 0x62, - 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x42, 0x02, 0x18, 0x01, 0x52, - 0x17, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0b, 0x76, 0x6f, 0x74, 0x65, - 0x64, 0x5f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, - 0x01, 0x52, 0x0a, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x45, 0x74, 0x68, 0x65, 0x72, 0x12, 0x29, 0x0a, - 0x0e, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0d, 0x65, 0x6c, 0x69, 0x67, 0x69, - 0x62, 0x6c, 0x65, 0x45, 0x74, 0x68, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x47, - 0x77, 0x65, 0x69, 0x12, 0x3f, 0x0a, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x67, - 0x77, 0x65, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, - 0x47, 0x77, 0x65, 0x69, 0x12, 0x4c, 0x0a, 0x23, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x1f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, 0x77, - 0x65, 0x69, 0x12, 0x3b, 0x0a, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x67, 0x77, 0x65, 0x69, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, - 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x47, 0x77, 0x65, 0x69, 0x12, - 0x41, 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x77, 0x65, 0x69, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, - 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, 0x77, - 0x65, 0x69, 0x12, 0x4e, 0x0a, 0x24, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, 0x77, - 0x65, 0x69, 0x12, 0x4a, 0x0a, 0x22, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1e, - 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x65, 0x61, - 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, 0x77, 0x65, 0x69, 0x22, 0xad, - 0x03, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, - 0x65, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, - 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, - 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, - 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, - 0x70, 0x6f, 0x63, 0x68, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x66, - 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xce, - 0x02, 0x0a, 0x13, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, - 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, - 0x11, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x73, 0x1a, 0xca, 0x01, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, - 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, - 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x05, 0x73, 0x6c, 0x6f, 0x74, 0x73, + 0x12, 0x74, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x5f, 0x69, 0x64, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x74, 0x65, 0x65, 0x49, 0x64, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x08, 0x52, 0x0c, 0x69, + 0x73, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x9e, 0x05, 0x0a, 0x09, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, + 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, + 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x16, 0x77, 0x69, + 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x15, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x43, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x64, + 0x12, 0x88, 0x01, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x5f, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, - 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x22, - 0xe4, 0x01, 0x0a, 0x14, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x6f, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, - 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, - 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x64, - 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, 0x3d, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, - 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4f, 0x6e, 0x6c, - 0x79, 0x3a, 0x02, 0x18, 0x01, 0x22, 0x3e, 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, - 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4f, 0x6e, 0x6c, - 0x79, 0x3a, 0x02, 0x18, 0x01, 0x22, 0xca, 0x02, 0x0a, 0x1c, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, - 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x69, 0x0a, 0x0a, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, - 0x73, 0x1a, 0xbe, 0x01, 0x0a, 0x15, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x0d, 0x66, - 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, - 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x1a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x69, 0x67, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x71, 0x0a, 0x10, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, + 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, + 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x0f, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x65, + 0x0a, 0x0a, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, + 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x09, 0x65, 0x78, 0x69, 0x74, + 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x75, 0x0a, 0x12, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, - 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x22, 0x4e, 0x0a, 0x1b, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, - 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x22, 0x4b, 0x0a, 0x1c, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, - 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x22, - 0x91, 0x01, 0x0a, 0x1e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, - 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x4b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x88, 0x02, 0x0a, 0x26, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, - 0x0a, 0x04, 0x6d, 0x73, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, - 0x65, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x6d, 0x73, 0x67, 0x73, 0x12, - 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, - 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, + 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x11, 0x77, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x22, 0x8e, 0x05, 0x0a, + 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, + 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x19, 0x67, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x42, 0x02, 0x18, 0x01, 0x52, 0x17, + 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0b, 0x76, 0x6f, 0x74, 0x65, 0x64, + 0x5f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x0a, 0x76, 0x6f, 0x74, 0x65, 0x64, 0x45, 0x74, 0x68, 0x65, 0x72, 0x12, 0x29, 0x0a, 0x0e, + 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0d, 0x65, 0x6c, 0x69, 0x67, 0x69, 0x62, + 0x6c, 0x65, 0x45, 0x74, 0x68, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x67, 0x77, 0x65, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x47, 0x77, + 0x65, 0x69, 0x12, 0x3f, 0x0a, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x77, + 0x65, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, + 0x77, 0x65, 0x69, 0x12, 0x4c, 0x0a, 0x23, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x1f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, 0x77, 0x65, + 0x69, 0x12, 0x3b, 0x0a, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, + 0x70, 0x6f, 0x63, 0x68, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x47, 0x77, 0x65, 0x69, 0x12, 0x41, + 0x0a, 0x1d, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, + 0x70, 0x6f, 0x63, 0x68, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, 0x77, 0x65, + 0x69, 0x12, 0x4e, 0x0a, 0x24, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, 0x77, 0x65, + 0x69, 0x12, 0x4a, 0x0a, 0x22, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x5f, 0x67, 0x77, 0x65, 0x69, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1e, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x47, 0x77, 0x65, 0x69, 0x22, 0xad, 0x03, + 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x65, + 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, + 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, - 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x75, - 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, - 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, - 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, - 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x64, - 0x0a, 0x27, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, - 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, - 0x12, 0x12, 0x0a, 0x04, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x62, 0x69, 0x74, 0x73, 0x2a, 0x9a, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, - 0x44, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, - 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, - 0x56, 0x45, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x10, - 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, - 0x0a, 0x0a, 0x06, 0x45, 0x58, 0x49, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x49, - 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x41, 0x52, 0x54, - 0x49, 0x41, 0x4c, 0x4c, 0x59, 0x5f, 0x44, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x44, 0x10, - 0x08, 0x32, 0xf2, 0x28, 0x0a, 0x13, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x80, 0x01, 0x0a, 0x09, 0x47, 0x65, - 0x74, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x81, 0x01, 0x0a, - 0x0a, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x24, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, - 0x12, 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x12, 0x8e, 0x01, 0x0a, 0x11, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x29, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x88, 0x02, 0x01, 0x30, - 0x01, 0x12, 0xaf, 0x01, 0x0a, 0x11, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x65, 0x74, 0x68, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, + 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, 0x65, 0x70, + 0x6f, 0x63, 0x68, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x31, 0x0a, 0x14, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xce, 0x02, + 0x0a, 0x13, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x6a, 0x0a, 0x12, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, + 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x11, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x73, 0x1a, 0xca, 0x01, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, + 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x5c, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x46, 0x82, 0xb5, 0x18, 0x42, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, + 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x05, + 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x0b, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, + 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0xe4, + 0x01, 0x0a, 0x14, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, - 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x30, 0x01, 0x12, 0x94, 0x01, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x98, 0x01, 0x0a, 0x0f, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, - 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0xb2, 0x01, 0x0a, 0x17, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, - 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, - 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, - 0x72, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x0e, 0x47, - 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x23, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, - 0x69, 0x63, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x25, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x97, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x2e, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x6f, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, + 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, + 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x75, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, + 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, 0x3d, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, + 0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4f, 0x6e, 0x6c, 0x79, + 0x3a, 0x02, 0x18, 0x01, 0x22, 0x3e, 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x76, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4f, 0x6e, 0x6c, 0x79, + 0x3a, 0x02, 0x18, 0x01, 0x22, 0xca, 0x02, 0x0a, 0x1c, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, + 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x69, 0x0a, 0x0a, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, + 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, + 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x73, + 0x1a, 0xbe, 0x01, 0x0a, 0x15, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, + 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, + 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, + 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x22, 0x4e, 0x0a, 0x1b, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, + 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, 0x06, + 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x22, 0x4b, 0x0a, 0x1c, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, + 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x30, + 0x52, 0x0c, 0x66, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x22, 0x91, + 0x01, 0x0a, 0x1e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2f, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x9a, 0xb5, 0x18, + 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, + 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x88, 0x02, 0x0a, 0x26, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, + 0x04, 0x6d, 0x73, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x1a, 0x26, 0x2e, 0x65, + 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x6d, 0x73, 0x67, 0x73, 0x12, 0x59, + 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, + 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, + 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, + 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x75, 0x62, + 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x75, + 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, + 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, + 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x64, 0x0a, + 0x27, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, + 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x12, + 0x12, 0x0a, 0x04, 0x62, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, + 0x69, 0x74, 0x73, 0x2a, 0x9a, 0x01, 0x0a, 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, + 0x57, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x44, + 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, + 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, + 0x45, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x04, + 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x4c, 0x41, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0a, + 0x0a, 0x06, 0x45, 0x58, 0x49, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, + 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x50, 0x41, 0x52, 0x54, 0x49, + 0x41, 0x4c, 0x4c, 0x59, 0x5f, 0x44, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x45, 0x44, 0x10, 0x08, + 0x32, 0xf4, 0x28, 0x0a, 0x13, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x4e, 0x6f, 0x64, 0x65, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x80, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, + 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, + 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, 0x2a, 0x22, - 0x1d, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0xa0, - 0x01, 0x0a, 0x15, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, - 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x50, 0x72, - 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x3a, 0x01, 0x2a, - 0x22, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, - 0x65, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x72, 0x12, 0xbf, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, - 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x32, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, - 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x3a, 0x01, - 0x2a, 0x22, 0x30, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x66, 0x65, 0x65, 0x5f, 0x72, - 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x75, 0x62, 0x5f, - 0x6b, 0x65, 0x79, 0x12, 0x98, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x75, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x75, 0x74, 0x69, 0x65, 0x73, 0x12, 0x81, 0x01, 0x0a, 0x0a, + 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x24, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, - 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, - 0x61, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x8f, - 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, - 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, + 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, + 0x8e, 0x01, 0x0a, 0x11, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x29, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, + 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x88, 0x02, 0x01, 0x30, 0x01, + 0x12, 0xb2, 0x01, 0x0a, 0x11, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x3a, 0x01, 0x2a, 0x22, 0x23, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0xa5, 0x01, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x29, + 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x94, 0x01, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, + 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x98, 0x01, 0x0a, + 0x0f, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, + 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0xb2, 0x01, 0x0a, 0x17, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x65, 0x74, 0x68, + 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, + 0x0e, 0x47, 0x65, 0x74, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x23, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x69, 0x63, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, + 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x97, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, + 0x73, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x2f, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x1a, 0x26, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x3a, 0x01, 0x2a, 0x22, 0x2b, 0x2f, 0x65, 0x74, - 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xb2, 0x01, 0x0a, 0x1d, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x3a, 0x01, + 0x2a, 0x22, 0x1d, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x32, + 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x12, 0xa0, 0x01, 0x0a, 0x15, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, + 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x65, + 0x61, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, + 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x3a, + 0x01, 0x2a, 0x22, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x65, 0x70, + 0x61, 0x72, 0x65, 0x5f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x6f, + 0x73, 0x65, 0x72, 0x12, 0xbf, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x46, 0x65, 0x65, 0x52, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, + 0x32, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x65, 0x65, 0x52, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, + 0x3a, 0x01, 0x2a, 0x22, 0x30, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x66, 0x65, 0x65, + 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x75, + 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x12, 0x98, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, 0x68, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xc8, 0x01, - 0x0a, 0x24, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x45, - 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, + 0x61, 0x74, 0x61, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x8f, 0x01, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x25, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x3a, 0x01, 0x2a, 0x22, 0x23, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xbe, 0x01, 0x0a, 0x23, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0xa4, 0x01, 0x0a, 0x19, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, + 0x12, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x41, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x25, 0x2e, 0x65, 0x74, 0x68, + 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, 0x3a, 0x01, 0x2a, 0x22, 0x2b, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xb2, 0x01, 0x0a, 0x1d, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x30, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, + 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xc8, + 0x01, 0x0a, 0x24, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, + 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, + 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0xbe, 0x01, 0x0a, 0x23, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, + 0x66, 0x12, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, + 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, + 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xd4, 0x01, 0x0a, 0x2a, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, + 0x6f, 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, + 0x6d, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0xd4, 0x01, 0x0a, 0x2a, 0x53, 0x75, - 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x12, 0x3a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x2e, 0x3a, 0x01, 0x2a, 0x22, 0x29, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, - 0x12, 0x8e, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, 0x69, 0x74, - 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, - 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x1a, 0x2a, 0x2e, 0x65, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, + 0x61, 0x12, 0x8e, 0x01, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, 0x69, + 0x74, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x56, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x45, 0x78, 0x69, 0x74, 0x1a, 0x2a, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, 0x69, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x21, 0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x65, 0x78, + 0x69, 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x19, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, + 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28, 0x2f, 0x65, + 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x9a, 0x01, 0x0a, 0x11, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x45, 0x78, 0x69, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, - 0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x65, 0x78, 0x69, - 0x74, 0x12, 0xa1, 0x01, 0x0a, 0x19, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x12, - 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, + 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, + 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x67, 0x61, 0x6e, + 0x67, 0x65, 0x72, 0x12, 0x9f, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, + 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x2e, 0x65, 0x74, + 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x3a, 0x01, 0x2a, 0x22, 0x28, 0x2f, 0x65, 0x74, + 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x9a, 0x01, 0x0a, 0x11, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, - 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, - 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x44, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x47, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x6f, 0x70, 0x70, 0x65, 0x6c, 0x67, 0x61, 0x6e, 0x67, - 0x65, 0x72, 0x12, 0x9f, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x33, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, - 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, - 0x6f, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x31, 0x12, 0x2f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, - 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, - 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x89, 0x01, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, - 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0xb4, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x33, + 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x53, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, + 0x65, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0xc4, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, + 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01, 0x2a, 0x22, + 0x2e, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, + 0xaf, 0x01, 0x0a, 0x20, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, + 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, + 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, + 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, - 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, + 0x40, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x3a, 0x01, 0x2a, 0x22, 0x35, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0xb4, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62, 0x63, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x33, 0x2e, - 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x75, 0x62, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53, - 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, - 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x73, 0x75, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, - 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0xc4, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x53, - 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x30, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x3a, 0x01, 0x2a, 0x22, 0x2e, - 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0xaf, - 0x01, 0x0a, 0x20, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x12, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, - 0x64, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x40, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x3a, 0x01, 0x2a, 0x22, 0x35, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, - 0x12, 0x9e, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, 0x73, - 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, - 0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x12, - 0x2b, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x88, 0x02, 0x01, 0x30, - 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x73, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, - 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x9e, 0x01, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, - 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x31, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, - 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xae, 0x01, 0x0a, 0x17, 0x41, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, 0x62, 0x6e, - 0x65, 0x74, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, - 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, 0x62, 0x6e, - 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x3a, 0x01, 0x2a, 0x22, 0x39, 0x2f, 0x65, - 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x61, 0x73, 0x73, - 0x69, 0x67, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x6f, - 0x5f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0xec, 0x01, 0x0a, 0x1f, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x3d, 0x2e, 0x65, 0x74, + 0x74, 0x6f, 0x72, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x72, 0x6f, 0x6f, + 0x66, 0x12, 0x9e, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, + 0x73, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x6c, 0x6f, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, + 0x12, 0x2b, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, + 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x88, 0x02, 0x01, + 0x30, 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x12, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x73, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x72, 0x12, 0x2a, 0x2e, 0x65, 0x74, 0x68, 0x65, + 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x65, 0x74, 0x68, + 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x88, 0x02, 0x01, 0x30, 0x01, 0x12, 0x9e, 0x01, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, + 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x31, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, + 0x2a, 0x22, 0x24, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xae, 0x01, 0x0a, 0x17, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, 0x62, + 0x6e, 0x65, 0x74, 0x12, 0x35, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, + 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x54, 0x6f, 0x53, 0x75, 0x62, + 0x6e, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x3a, 0x01, 0x2a, 0x22, 0x39, 0x2f, + 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x61, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x74, + 0x6f, 0x5f, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x12, 0xec, 0x01, 0x0a, 0x1f, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x12, 0x3d, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, + 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x42, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, - 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, - 0x41, 0x6e, 0x64, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x69, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x44, 0x12, 0x42, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, - 0x6b, 0x73, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x69, - 0x67, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x42, 0x93, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, - 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, - 0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c, - 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x44, 0x12, 0x42, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x73, 0x2f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x73, + 0x69, 0x67, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x42, 0x93, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, + 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, + 0x65, 0x74, 0x68, 0xaa, 0x02, 0x0f, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, + 0x74, 0x68, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, + 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4140,22 +4159,23 @@ var file_proto_prysm_v1alpha1_validator_proto_goTypes = []interface{}{ (*SignedBeaconBlockCapella)(nil), // 54: ethereum.eth.v1alpha1.SignedBeaconBlockCapella (*SignedBeaconBlockDeneb)(nil), // 55: ethereum.eth.v1alpha1.SignedBeaconBlockDeneb (*SignedBeaconBlockElectra)(nil), // 56: ethereum.eth.v1alpha1.SignedBeaconBlockElectra - (*wrapperspb.UInt64Value)(nil), // 57: google.protobuf.UInt64Value - (*AggregateAttestationAndProof)(nil), // 58: ethereum.eth.v1alpha1.AggregateAttestationAndProof - (*AggregateAttestationAndProofElectra)(nil), // 59: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - (*SignedAggregateAttestationAndProof)(nil), // 60: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof - (*SignedAggregateAttestationAndProofElectra)(nil), // 61: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra - (*SyncCommitteeMessage)(nil), // 62: ethereum.eth.v1alpha1.SyncCommitteeMessage - (*emptypb.Empty)(nil), // 63: google.protobuf.Empty - (*GenericSignedBeaconBlock)(nil), // 64: ethereum.eth.v1alpha1.GenericSignedBeaconBlock - (*Attestation)(nil), // 65: ethereum.eth.v1alpha1.Attestation - (*AttestationElectra)(nil), // 66: ethereum.eth.v1alpha1.AttestationElectra - (*SignedVoluntaryExit)(nil), // 67: ethereum.eth.v1alpha1.SignedVoluntaryExit - (*SignedContributionAndProof)(nil), // 68: ethereum.eth.v1alpha1.SignedContributionAndProof - (*SignedValidatorRegistrationsV1)(nil), // 69: ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1 - (*GenericBeaconBlock)(nil), // 70: ethereum.eth.v1alpha1.GenericBeaconBlock - (*AttestationData)(nil), // 71: ethereum.eth.v1alpha1.AttestationData - (*SyncCommitteeContribution)(nil), // 72: ethereum.eth.v1alpha1.SyncCommitteeContribution + (*SignedBeaconBlockFulu)(nil), // 57: ethereum.eth.v1alpha1.SignedBeaconBlockFulu + (*wrapperspb.UInt64Value)(nil), // 58: google.protobuf.UInt64Value + (*AggregateAttestationAndProof)(nil), // 59: ethereum.eth.v1alpha1.AggregateAttestationAndProof + (*AggregateAttestationAndProofElectra)(nil), // 60: ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + (*SignedAggregateAttestationAndProof)(nil), // 61: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof + (*SignedAggregateAttestationAndProofElectra)(nil), // 62: ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra + (*SyncCommitteeMessage)(nil), // 63: ethereum.eth.v1alpha1.SyncCommitteeMessage + (*emptypb.Empty)(nil), // 64: google.protobuf.Empty + (*GenericSignedBeaconBlock)(nil), // 65: ethereum.eth.v1alpha1.GenericSignedBeaconBlock + (*Attestation)(nil), // 66: ethereum.eth.v1alpha1.Attestation + (*SingleAttestation)(nil), // 67: ethereum.eth.v1alpha1.SingleAttestation + (*SignedVoluntaryExit)(nil), // 68: ethereum.eth.v1alpha1.SignedVoluntaryExit + (*SignedContributionAndProof)(nil), // 69: ethereum.eth.v1alpha1.SignedContributionAndProof + (*SignedValidatorRegistrationsV1)(nil), // 70: ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1 + (*GenericBeaconBlock)(nil), // 71: ethereum.eth.v1alpha1.GenericBeaconBlock + (*AttestationData)(nil), // 72: ethereum.eth.v1alpha1.AttestationData + (*SyncCommitteeContribution)(nil), // 73: ethereum.eth.v1alpha1.SyncCommitteeContribution } var file_proto_prysm_v1alpha1_validator_proto_depIdxs = []int32{ 51, // 0: ethereum.eth.v1alpha1.StreamBlocksResponse.phase0_block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlock @@ -4164,91 +4184,92 @@ var file_proto_prysm_v1alpha1_validator_proto_depIdxs = []int32{ 54, // 3: ethereum.eth.v1alpha1.StreamBlocksResponse.capella_block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockCapella 55, // 4: ethereum.eth.v1alpha1.StreamBlocksResponse.deneb_block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockDeneb 56, // 5: ethereum.eth.v1alpha1.StreamBlocksResponse.electra_block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockElectra - 46, // 6: ethereum.eth.v1alpha1.ValidatorActivationResponse.statuses:type_name -> ethereum.eth.v1alpha1.ValidatorActivationResponse.Status - 0, // 7: ethereum.eth.v1alpha1.ValidatorStatusResponse.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatus - 16, // 8: ethereum.eth.v1alpha1.MultipleValidatorStatusResponse.statuses:type_name -> ethereum.eth.v1alpha1.ValidatorStatusResponse - 47, // 9: ethereum.eth.v1alpha1.DutiesResponse.current_epoch_duties:type_name -> ethereum.eth.v1alpha1.DutiesResponse.Duty - 47, // 10: ethereum.eth.v1alpha1.DutiesResponse.next_epoch_duties:type_name -> ethereum.eth.v1alpha1.DutiesResponse.Duty - 57, // 11: ethereum.eth.v1alpha1.BlockRequest.builder_boost_factor:type_name -> google.protobuf.UInt64Value - 58, // 12: ethereum.eth.v1alpha1.AggregateSelectionResponse.aggregate_and_proof:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof - 59, // 13: ethereum.eth.v1alpha1.AggregateSelectionElectraResponse.aggregate_and_proof:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra - 60, // 14: ethereum.eth.v1alpha1.SignedAggregateSubmitRequest.signed_aggregate_and_proof:type_name -> ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof - 61, // 15: ethereum.eth.v1alpha1.SignedAggregateSubmitElectraRequest.signed_aggregate_and_proof:type_name -> ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra - 0, // 16: ethereum.eth.v1alpha1.ValidatorInfo.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatus - 48, // 17: ethereum.eth.v1alpha1.DoppelGangerRequest.validator_requests:type_name -> ethereum.eth.v1alpha1.DoppelGangerRequest.ValidatorRequest - 49, // 18: ethereum.eth.v1alpha1.DoppelGangerResponse.responses:type_name -> ethereum.eth.v1alpha1.DoppelGangerResponse.ValidatorResponse - 50, // 19: ethereum.eth.v1alpha1.PrepareBeaconProposerRequest.recipients:type_name -> ethereum.eth.v1alpha1.PrepareBeaconProposerRequest.FeeRecipientContainer - 0, // 20: ethereum.eth.v1alpha1.AssignValidatorToSubnetRequest.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatus - 62, // 21: ethereum.eth.v1alpha1.AggregatedSigAndAggregationBitsRequest.msgs:type_name -> ethereum.eth.v1alpha1.SyncCommitteeMessage - 16, // 22: ethereum.eth.v1alpha1.ValidatorActivationResponse.Status.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatusResponse - 0, // 23: ethereum.eth.v1alpha1.DutiesResponse.Duty.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatus - 19, // 24: ethereum.eth.v1alpha1.BeaconNodeValidator.GetDuties:input_type -> ethereum.eth.v1alpha1.DutiesRequest - 7, // 25: ethereum.eth.v1alpha1.BeaconNodeValidator.DomainData:input_type -> ethereum.eth.v1alpha1.DomainRequest - 63, // 26: ethereum.eth.v1alpha1.BeaconNodeValidator.WaitForChainStart:input_type -> google.protobuf.Empty - 9, // 27: ethereum.eth.v1alpha1.BeaconNodeValidator.WaitForActivation:input_type -> ethereum.eth.v1alpha1.ValidatorActivationRequest - 13, // 28: ethereum.eth.v1alpha1.BeaconNodeValidator.ValidatorIndex:input_type -> ethereum.eth.v1alpha1.ValidatorIndexRequest - 15, // 29: ethereum.eth.v1alpha1.BeaconNodeValidator.ValidatorStatus:input_type -> ethereum.eth.v1alpha1.ValidatorStatusRequest - 17, // 30: ethereum.eth.v1alpha1.BeaconNodeValidator.MultipleValidatorStatus:input_type -> ethereum.eth.v1alpha1.MultipleValidatorStatusRequest - 21, // 31: ethereum.eth.v1alpha1.BeaconNodeValidator.GetBeaconBlock:input_type -> ethereum.eth.v1alpha1.BlockRequest - 64, // 32: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeBeaconBlock:input_type -> ethereum.eth.v1alpha1.GenericSignedBeaconBlock - 40, // 33: ethereum.eth.v1alpha1.BeaconNodeValidator.PrepareBeaconProposer:input_type -> ethereum.eth.v1alpha1.PrepareBeaconProposerRequest - 41, // 34: ethereum.eth.v1alpha1.BeaconNodeValidator.GetFeeRecipientByPubKey:input_type -> ethereum.eth.v1alpha1.FeeRecipientByPubKeyRequest - 24, // 35: ethereum.eth.v1alpha1.BeaconNodeValidator.GetAttestationData:input_type -> ethereum.eth.v1alpha1.AttestationDataRequest - 65, // 36: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestation:input_type -> ethereum.eth.v1alpha1.Attestation - 66, // 37: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestationElectra:input_type -> ethereum.eth.v1alpha1.AttestationElectra - 26, // 38: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProof:input_type -> ethereum.eth.v1alpha1.AggregateSelectionRequest - 26, // 39: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProofElectra:input_type -> ethereum.eth.v1alpha1.AggregateSelectionRequest - 29, // 40: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProof:input_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitRequest - 30, // 41: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProofElectra:input_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitElectraRequest - 67, // 42: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeExit:input_type -> ethereum.eth.v1alpha1.SignedVoluntaryExit - 32, // 43: ethereum.eth.v1alpha1.BeaconNodeValidator.SubscribeCommitteeSubnets:input_type -> ethereum.eth.v1alpha1.CommitteeSubnetsSubscribeRequest - 36, // 44: ethereum.eth.v1alpha1.BeaconNodeValidator.CheckDoppelGanger:input_type -> ethereum.eth.v1alpha1.DoppelGangerRequest - 63, // 45: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncMessageBlockRoot:input_type -> google.protobuf.Empty - 62, // 46: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSyncMessage:input_type -> ethereum.eth.v1alpha1.SyncCommitteeMessage - 2, // 47: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncSubcommitteeIndex:input_type -> ethereum.eth.v1alpha1.SyncSubcommitteeIndexRequest - 3, // 48: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncCommitteeContribution:input_type -> ethereum.eth.v1alpha1.SyncCommitteeContributionRequest - 68, // 49: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedContributionAndProof:input_type -> ethereum.eth.v1alpha1.SignedContributionAndProof - 38, // 50: ethereum.eth.v1alpha1.BeaconNodeValidator.StreamSlots:input_type -> ethereum.eth.v1alpha1.StreamSlotsRequest - 39, // 51: ethereum.eth.v1alpha1.BeaconNodeValidator.StreamBlocksAltair:input_type -> ethereum.eth.v1alpha1.StreamBlocksRequest - 69, // 52: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitValidatorRegistrations:input_type -> ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1 - 43, // 53: ethereum.eth.v1alpha1.BeaconNodeValidator.AssignValidatorToSubnet:input_type -> ethereum.eth.v1alpha1.AssignValidatorToSubnetRequest - 44, // 54: ethereum.eth.v1alpha1.BeaconNodeValidator.AggregatedSigAndAggregationBits:input_type -> ethereum.eth.v1alpha1.AggregatedSigAndAggregationBitsRequest - 20, // 55: ethereum.eth.v1alpha1.BeaconNodeValidator.GetDuties:output_type -> ethereum.eth.v1alpha1.DutiesResponse - 8, // 56: ethereum.eth.v1alpha1.BeaconNodeValidator.DomainData:output_type -> ethereum.eth.v1alpha1.DomainResponse - 11, // 57: ethereum.eth.v1alpha1.BeaconNodeValidator.WaitForChainStart:output_type -> ethereum.eth.v1alpha1.ChainStartResponse - 10, // 58: ethereum.eth.v1alpha1.BeaconNodeValidator.WaitForActivation:output_type -> ethereum.eth.v1alpha1.ValidatorActivationResponse - 14, // 59: ethereum.eth.v1alpha1.BeaconNodeValidator.ValidatorIndex:output_type -> ethereum.eth.v1alpha1.ValidatorIndexResponse - 16, // 60: ethereum.eth.v1alpha1.BeaconNodeValidator.ValidatorStatus:output_type -> ethereum.eth.v1alpha1.ValidatorStatusResponse - 18, // 61: ethereum.eth.v1alpha1.BeaconNodeValidator.MultipleValidatorStatus:output_type -> ethereum.eth.v1alpha1.MultipleValidatorStatusResponse - 70, // 62: ethereum.eth.v1alpha1.BeaconNodeValidator.GetBeaconBlock:output_type -> ethereum.eth.v1alpha1.GenericBeaconBlock - 22, // 63: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeBeaconBlock:output_type -> ethereum.eth.v1alpha1.ProposeResponse - 63, // 64: ethereum.eth.v1alpha1.BeaconNodeValidator.PrepareBeaconProposer:output_type -> google.protobuf.Empty - 42, // 65: ethereum.eth.v1alpha1.BeaconNodeValidator.GetFeeRecipientByPubKey:output_type -> ethereum.eth.v1alpha1.FeeRecipientByPubKeyResponse - 71, // 66: ethereum.eth.v1alpha1.BeaconNodeValidator.GetAttestationData:output_type -> ethereum.eth.v1alpha1.AttestationData - 25, // 67: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestation:output_type -> ethereum.eth.v1alpha1.AttestResponse - 25, // 68: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestationElectra:output_type -> ethereum.eth.v1alpha1.AttestResponse - 27, // 69: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProof:output_type -> ethereum.eth.v1alpha1.AggregateSelectionResponse - 28, // 70: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProofElectra:output_type -> ethereum.eth.v1alpha1.AggregateSelectionElectraResponse - 31, // 71: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProof:output_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitResponse - 31, // 72: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProofElectra:output_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitResponse - 23, // 73: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeExit:output_type -> ethereum.eth.v1alpha1.ProposeExitResponse - 63, // 74: ethereum.eth.v1alpha1.BeaconNodeValidator.SubscribeCommitteeSubnets:output_type -> google.protobuf.Empty - 37, // 75: ethereum.eth.v1alpha1.BeaconNodeValidator.CheckDoppelGanger:output_type -> ethereum.eth.v1alpha1.DoppelGangerResponse - 1, // 76: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncMessageBlockRoot:output_type -> ethereum.eth.v1alpha1.SyncMessageBlockRootResponse - 63, // 77: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSyncMessage:output_type -> google.protobuf.Empty - 4, // 78: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncSubcommitteeIndex:output_type -> ethereum.eth.v1alpha1.SyncSubcommitteeIndexResponse - 72, // 79: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncCommitteeContribution:output_type -> ethereum.eth.v1alpha1.SyncCommitteeContribution - 63, // 80: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedContributionAndProof:output_type -> google.protobuf.Empty - 5, // 81: ethereum.eth.v1alpha1.BeaconNodeValidator.StreamSlots:output_type -> ethereum.eth.v1alpha1.StreamSlotsResponse - 6, // 82: ethereum.eth.v1alpha1.BeaconNodeValidator.StreamBlocksAltair:output_type -> ethereum.eth.v1alpha1.StreamBlocksResponse - 63, // 83: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitValidatorRegistrations:output_type -> google.protobuf.Empty - 63, // 84: ethereum.eth.v1alpha1.BeaconNodeValidator.AssignValidatorToSubnet:output_type -> google.protobuf.Empty - 45, // 85: ethereum.eth.v1alpha1.BeaconNodeValidator.AggregatedSigAndAggregationBits:output_type -> ethereum.eth.v1alpha1.AggregatedSigAndAggregationBitsResponse - 55, // [55:86] is the sub-list for method output_type - 24, // [24:55] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name + 57, // 6: ethereum.eth.v1alpha1.StreamBlocksResponse.fulu_block:type_name -> ethereum.eth.v1alpha1.SignedBeaconBlockFulu + 46, // 7: ethereum.eth.v1alpha1.ValidatorActivationResponse.statuses:type_name -> ethereum.eth.v1alpha1.ValidatorActivationResponse.Status + 0, // 8: ethereum.eth.v1alpha1.ValidatorStatusResponse.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatus + 16, // 9: ethereum.eth.v1alpha1.MultipleValidatorStatusResponse.statuses:type_name -> ethereum.eth.v1alpha1.ValidatorStatusResponse + 47, // 10: ethereum.eth.v1alpha1.DutiesResponse.current_epoch_duties:type_name -> ethereum.eth.v1alpha1.DutiesResponse.Duty + 47, // 11: ethereum.eth.v1alpha1.DutiesResponse.next_epoch_duties:type_name -> ethereum.eth.v1alpha1.DutiesResponse.Duty + 58, // 12: ethereum.eth.v1alpha1.BlockRequest.builder_boost_factor:type_name -> google.protobuf.UInt64Value + 59, // 13: ethereum.eth.v1alpha1.AggregateSelectionResponse.aggregate_and_proof:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProof + 60, // 14: ethereum.eth.v1alpha1.AggregateSelectionElectraResponse.aggregate_and_proof:type_name -> ethereum.eth.v1alpha1.AggregateAttestationAndProofElectra + 61, // 15: ethereum.eth.v1alpha1.SignedAggregateSubmitRequest.signed_aggregate_and_proof:type_name -> ethereum.eth.v1alpha1.SignedAggregateAttestationAndProof + 62, // 16: ethereum.eth.v1alpha1.SignedAggregateSubmitElectraRequest.signed_aggregate_and_proof:type_name -> ethereum.eth.v1alpha1.SignedAggregateAttestationAndProofElectra + 0, // 17: ethereum.eth.v1alpha1.ValidatorInfo.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatus + 48, // 18: ethereum.eth.v1alpha1.DoppelGangerRequest.validator_requests:type_name -> ethereum.eth.v1alpha1.DoppelGangerRequest.ValidatorRequest + 49, // 19: ethereum.eth.v1alpha1.DoppelGangerResponse.responses:type_name -> ethereum.eth.v1alpha1.DoppelGangerResponse.ValidatorResponse + 50, // 20: ethereum.eth.v1alpha1.PrepareBeaconProposerRequest.recipients:type_name -> ethereum.eth.v1alpha1.PrepareBeaconProposerRequest.FeeRecipientContainer + 0, // 21: ethereum.eth.v1alpha1.AssignValidatorToSubnetRequest.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatus + 63, // 22: ethereum.eth.v1alpha1.AggregatedSigAndAggregationBitsRequest.msgs:type_name -> ethereum.eth.v1alpha1.SyncCommitteeMessage + 16, // 23: ethereum.eth.v1alpha1.ValidatorActivationResponse.Status.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatusResponse + 0, // 24: ethereum.eth.v1alpha1.DutiesResponse.Duty.status:type_name -> ethereum.eth.v1alpha1.ValidatorStatus + 19, // 25: ethereum.eth.v1alpha1.BeaconNodeValidator.GetDuties:input_type -> ethereum.eth.v1alpha1.DutiesRequest + 7, // 26: ethereum.eth.v1alpha1.BeaconNodeValidator.DomainData:input_type -> ethereum.eth.v1alpha1.DomainRequest + 64, // 27: ethereum.eth.v1alpha1.BeaconNodeValidator.WaitForChainStart:input_type -> google.protobuf.Empty + 9, // 28: ethereum.eth.v1alpha1.BeaconNodeValidator.WaitForActivation:input_type -> ethereum.eth.v1alpha1.ValidatorActivationRequest + 13, // 29: ethereum.eth.v1alpha1.BeaconNodeValidator.ValidatorIndex:input_type -> ethereum.eth.v1alpha1.ValidatorIndexRequest + 15, // 30: ethereum.eth.v1alpha1.BeaconNodeValidator.ValidatorStatus:input_type -> ethereum.eth.v1alpha1.ValidatorStatusRequest + 17, // 31: ethereum.eth.v1alpha1.BeaconNodeValidator.MultipleValidatorStatus:input_type -> ethereum.eth.v1alpha1.MultipleValidatorStatusRequest + 21, // 32: ethereum.eth.v1alpha1.BeaconNodeValidator.GetBeaconBlock:input_type -> ethereum.eth.v1alpha1.BlockRequest + 65, // 33: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeBeaconBlock:input_type -> ethereum.eth.v1alpha1.GenericSignedBeaconBlock + 40, // 34: ethereum.eth.v1alpha1.BeaconNodeValidator.PrepareBeaconProposer:input_type -> ethereum.eth.v1alpha1.PrepareBeaconProposerRequest + 41, // 35: ethereum.eth.v1alpha1.BeaconNodeValidator.GetFeeRecipientByPubKey:input_type -> ethereum.eth.v1alpha1.FeeRecipientByPubKeyRequest + 24, // 36: ethereum.eth.v1alpha1.BeaconNodeValidator.GetAttestationData:input_type -> ethereum.eth.v1alpha1.AttestationDataRequest + 66, // 37: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestation:input_type -> ethereum.eth.v1alpha1.Attestation + 67, // 38: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestationElectra:input_type -> ethereum.eth.v1alpha1.SingleAttestation + 26, // 39: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProof:input_type -> ethereum.eth.v1alpha1.AggregateSelectionRequest + 26, // 40: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProofElectra:input_type -> ethereum.eth.v1alpha1.AggregateSelectionRequest + 29, // 41: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProof:input_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitRequest + 30, // 42: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProofElectra:input_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitElectraRequest + 68, // 43: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeExit:input_type -> ethereum.eth.v1alpha1.SignedVoluntaryExit + 32, // 44: ethereum.eth.v1alpha1.BeaconNodeValidator.SubscribeCommitteeSubnets:input_type -> ethereum.eth.v1alpha1.CommitteeSubnetsSubscribeRequest + 36, // 45: ethereum.eth.v1alpha1.BeaconNodeValidator.CheckDoppelGanger:input_type -> ethereum.eth.v1alpha1.DoppelGangerRequest + 64, // 46: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncMessageBlockRoot:input_type -> google.protobuf.Empty + 63, // 47: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSyncMessage:input_type -> ethereum.eth.v1alpha1.SyncCommitteeMessage + 2, // 48: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncSubcommitteeIndex:input_type -> ethereum.eth.v1alpha1.SyncSubcommitteeIndexRequest + 3, // 49: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncCommitteeContribution:input_type -> ethereum.eth.v1alpha1.SyncCommitteeContributionRequest + 69, // 50: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedContributionAndProof:input_type -> ethereum.eth.v1alpha1.SignedContributionAndProof + 38, // 51: ethereum.eth.v1alpha1.BeaconNodeValidator.StreamSlots:input_type -> ethereum.eth.v1alpha1.StreamSlotsRequest + 39, // 52: ethereum.eth.v1alpha1.BeaconNodeValidator.StreamBlocksAltair:input_type -> ethereum.eth.v1alpha1.StreamBlocksRequest + 70, // 53: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitValidatorRegistrations:input_type -> ethereum.eth.v1alpha1.SignedValidatorRegistrationsV1 + 43, // 54: ethereum.eth.v1alpha1.BeaconNodeValidator.AssignValidatorToSubnet:input_type -> ethereum.eth.v1alpha1.AssignValidatorToSubnetRequest + 44, // 55: ethereum.eth.v1alpha1.BeaconNodeValidator.AggregatedSigAndAggregationBits:input_type -> ethereum.eth.v1alpha1.AggregatedSigAndAggregationBitsRequest + 20, // 56: ethereum.eth.v1alpha1.BeaconNodeValidator.GetDuties:output_type -> ethereum.eth.v1alpha1.DutiesResponse + 8, // 57: ethereum.eth.v1alpha1.BeaconNodeValidator.DomainData:output_type -> ethereum.eth.v1alpha1.DomainResponse + 11, // 58: ethereum.eth.v1alpha1.BeaconNodeValidator.WaitForChainStart:output_type -> ethereum.eth.v1alpha1.ChainStartResponse + 10, // 59: ethereum.eth.v1alpha1.BeaconNodeValidator.WaitForActivation:output_type -> ethereum.eth.v1alpha1.ValidatorActivationResponse + 14, // 60: ethereum.eth.v1alpha1.BeaconNodeValidator.ValidatorIndex:output_type -> ethereum.eth.v1alpha1.ValidatorIndexResponse + 16, // 61: ethereum.eth.v1alpha1.BeaconNodeValidator.ValidatorStatus:output_type -> ethereum.eth.v1alpha1.ValidatorStatusResponse + 18, // 62: ethereum.eth.v1alpha1.BeaconNodeValidator.MultipleValidatorStatus:output_type -> ethereum.eth.v1alpha1.MultipleValidatorStatusResponse + 71, // 63: ethereum.eth.v1alpha1.BeaconNodeValidator.GetBeaconBlock:output_type -> ethereum.eth.v1alpha1.GenericBeaconBlock + 22, // 64: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeBeaconBlock:output_type -> ethereum.eth.v1alpha1.ProposeResponse + 64, // 65: ethereum.eth.v1alpha1.BeaconNodeValidator.PrepareBeaconProposer:output_type -> google.protobuf.Empty + 42, // 66: ethereum.eth.v1alpha1.BeaconNodeValidator.GetFeeRecipientByPubKey:output_type -> ethereum.eth.v1alpha1.FeeRecipientByPubKeyResponse + 72, // 67: ethereum.eth.v1alpha1.BeaconNodeValidator.GetAttestationData:output_type -> ethereum.eth.v1alpha1.AttestationData + 25, // 68: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestation:output_type -> ethereum.eth.v1alpha1.AttestResponse + 25, // 69: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeAttestationElectra:output_type -> ethereum.eth.v1alpha1.AttestResponse + 27, // 70: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProof:output_type -> ethereum.eth.v1alpha1.AggregateSelectionResponse + 28, // 71: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitAggregateSelectionProofElectra:output_type -> ethereum.eth.v1alpha1.AggregateSelectionElectraResponse + 31, // 72: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProof:output_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitResponse + 31, // 73: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedAggregateSelectionProofElectra:output_type -> ethereum.eth.v1alpha1.SignedAggregateSubmitResponse + 23, // 74: ethereum.eth.v1alpha1.BeaconNodeValidator.ProposeExit:output_type -> ethereum.eth.v1alpha1.ProposeExitResponse + 64, // 75: ethereum.eth.v1alpha1.BeaconNodeValidator.SubscribeCommitteeSubnets:output_type -> google.protobuf.Empty + 37, // 76: ethereum.eth.v1alpha1.BeaconNodeValidator.CheckDoppelGanger:output_type -> ethereum.eth.v1alpha1.DoppelGangerResponse + 1, // 77: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncMessageBlockRoot:output_type -> ethereum.eth.v1alpha1.SyncMessageBlockRootResponse + 64, // 78: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSyncMessage:output_type -> google.protobuf.Empty + 4, // 79: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncSubcommitteeIndex:output_type -> ethereum.eth.v1alpha1.SyncSubcommitteeIndexResponse + 73, // 80: ethereum.eth.v1alpha1.BeaconNodeValidator.GetSyncCommitteeContribution:output_type -> ethereum.eth.v1alpha1.SyncCommitteeContribution + 64, // 81: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitSignedContributionAndProof:output_type -> google.protobuf.Empty + 5, // 82: ethereum.eth.v1alpha1.BeaconNodeValidator.StreamSlots:output_type -> ethereum.eth.v1alpha1.StreamSlotsResponse + 6, // 83: ethereum.eth.v1alpha1.BeaconNodeValidator.StreamBlocksAltair:output_type -> ethereum.eth.v1alpha1.StreamBlocksResponse + 64, // 84: ethereum.eth.v1alpha1.BeaconNodeValidator.SubmitValidatorRegistrations:output_type -> google.protobuf.Empty + 64, // 85: ethereum.eth.v1alpha1.BeaconNodeValidator.AssignValidatorToSubnet:output_type -> google.protobuf.Empty + 45, // 86: ethereum.eth.v1alpha1.BeaconNodeValidator.AggregatedSigAndAggregationBits:output_type -> ethereum.eth.v1alpha1.AggregatedSigAndAggregationBitsResponse + 56, // [56:87] is the sub-list for method output_type + 25, // [25:56] is the sub-list for method input_type + 25, // [25:25] is the sub-list for extension type_name + 25, // [25:25] is the sub-list for extension extendee + 0, // [0:25] is the sub-list for field type_name } func init() { file_proto_prysm_v1alpha1_validator_proto_init() } @@ -4868,6 +4889,7 @@ func file_proto_prysm_v1alpha1_validator_proto_init() { (*StreamBlocksResponse_CapellaBlock)(nil), (*StreamBlocksResponse_DenebBlock)(nil), (*StreamBlocksResponse_ElectraBlock)(nil), + (*StreamBlocksResponse_FuluBlock)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -4906,6 +4928,7 @@ type BeaconNodeValidatorClient interface { DomainData(ctx context.Context, in *DomainRequest, opts ...grpc.CallOption) (*DomainResponse, error) // Deprecated: Do not use. WaitForChainStart(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (BeaconNodeValidator_WaitForChainStartClient, error) + // Deprecated: Do not use. WaitForActivation(ctx context.Context, in *ValidatorActivationRequest, opts ...grpc.CallOption) (BeaconNodeValidator_WaitForActivationClient, error) ValidatorIndex(ctx context.Context, in *ValidatorIndexRequest, opts ...grpc.CallOption) (*ValidatorIndexResponse, error) ValidatorStatus(ctx context.Context, in *ValidatorStatusRequest, opts ...grpc.CallOption) (*ValidatorStatusResponse, error) @@ -4916,7 +4939,7 @@ type BeaconNodeValidatorClient interface { GetFeeRecipientByPubKey(ctx context.Context, in *FeeRecipientByPubKeyRequest, opts ...grpc.CallOption) (*FeeRecipientByPubKeyResponse, error) GetAttestationData(ctx context.Context, in *AttestationDataRequest, opts ...grpc.CallOption) (*AttestationData, error) ProposeAttestation(ctx context.Context, in *Attestation, opts ...grpc.CallOption) (*AttestResponse, error) - ProposeAttestationElectra(ctx context.Context, in *AttestationElectra, opts ...grpc.CallOption) (*AttestResponse, error) + ProposeAttestationElectra(ctx context.Context, in *SingleAttestation, opts ...grpc.CallOption) (*AttestResponse, error) SubmitAggregateSelectionProof(ctx context.Context, in *AggregateSelectionRequest, opts ...grpc.CallOption) (*AggregateSelectionResponse, error) SubmitAggregateSelectionProofElectra(ctx context.Context, in *AggregateSelectionRequest, opts ...grpc.CallOption) (*AggregateSelectionElectraResponse, error) SubmitSignedAggregateSelectionProof(ctx context.Context, in *SignedAggregateSubmitRequest, opts ...grpc.CallOption) (*SignedAggregateSubmitResponse, error) @@ -4997,6 +5020,7 @@ func (x *beaconNodeValidatorWaitForChainStartClient) Recv() (*ChainStartResponse return m, nil } +// Deprecated: Do not use. func (c *beaconNodeValidatorClient) WaitForActivation(ctx context.Context, in *ValidatorActivationRequest, opts ...grpc.CallOption) (BeaconNodeValidator_WaitForActivationClient, error) { stream, err := c.cc.NewStream(ctx, &_BeaconNodeValidator_serviceDesc.Streams[1], "/ethereum.eth.v1alpha1.BeaconNodeValidator/WaitForActivation", opts...) if err != nil { @@ -5110,7 +5134,7 @@ func (c *beaconNodeValidatorClient) ProposeAttestation(ctx context.Context, in * return out, nil } -func (c *beaconNodeValidatorClient) ProposeAttestationElectra(ctx context.Context, in *AttestationElectra, opts ...grpc.CallOption) (*AttestResponse, error) { +func (c *beaconNodeValidatorClient) ProposeAttestationElectra(ctx context.Context, in *SingleAttestation, opts ...grpc.CallOption) (*AttestResponse, error) { out := new(AttestResponse) err := c.cc.Invoke(ctx, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeAttestationElectra", in, out, opts...) if err != nil { @@ -5326,6 +5350,7 @@ type BeaconNodeValidatorServer interface { DomainData(context.Context, *DomainRequest) (*DomainResponse, error) // Deprecated: Do not use. WaitForChainStart(*emptypb.Empty, BeaconNodeValidator_WaitForChainStartServer) error + // Deprecated: Do not use. WaitForActivation(*ValidatorActivationRequest, BeaconNodeValidator_WaitForActivationServer) error ValidatorIndex(context.Context, *ValidatorIndexRequest) (*ValidatorIndexResponse, error) ValidatorStatus(context.Context, *ValidatorStatusRequest) (*ValidatorStatusResponse, error) @@ -5336,7 +5361,7 @@ type BeaconNodeValidatorServer interface { GetFeeRecipientByPubKey(context.Context, *FeeRecipientByPubKeyRequest) (*FeeRecipientByPubKeyResponse, error) GetAttestationData(context.Context, *AttestationDataRequest) (*AttestationData, error) ProposeAttestation(context.Context, *Attestation) (*AttestResponse, error) - ProposeAttestationElectra(context.Context, *AttestationElectra) (*AttestResponse, error) + ProposeAttestationElectra(context.Context, *SingleAttestation) (*AttestResponse, error) SubmitAggregateSelectionProof(context.Context, *AggregateSelectionRequest) (*AggregateSelectionResponse, error) SubmitAggregateSelectionProofElectra(context.Context, *AggregateSelectionRequest) (*AggregateSelectionElectraResponse, error) SubmitSignedAggregateSelectionProof(context.Context, *SignedAggregateSubmitRequest) (*SignedAggregateSubmitResponse, error) @@ -5401,7 +5426,7 @@ func (*UnimplementedBeaconNodeValidatorServer) GetAttestationData(context.Contex func (*UnimplementedBeaconNodeValidatorServer) ProposeAttestation(context.Context, *Attestation) (*AttestResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProposeAttestation not implemented") } -func (*UnimplementedBeaconNodeValidatorServer) ProposeAttestationElectra(context.Context, *AttestationElectra) (*AttestResponse, error) { +func (*UnimplementedBeaconNodeValidatorServer) ProposeAttestationElectra(context.Context, *SingleAttestation) (*AttestResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ProposeAttestationElectra not implemented") } func (*UnimplementedBeaconNodeValidatorServer) SubmitAggregateSelectionProof(context.Context, *AggregateSelectionRequest) (*AggregateSelectionResponse, error) { @@ -5701,7 +5726,7 @@ func _BeaconNodeValidator_ProposeAttestation_Handler(srv interface{}, ctx contex } func _BeaconNodeValidator_ProposeAttestationElectra_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AttestationElectra) + in := new(SingleAttestation) if err := dec(in); err != nil { return nil, err } @@ -5713,7 +5738,7 @@ func _BeaconNodeValidator_ProposeAttestationElectra_Handler(srv interface{}, ctx FullMethod: "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeAttestationElectra", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BeaconNodeValidatorServer).ProposeAttestationElectra(ctx, req.(*AttestationElectra)) + return srv.(BeaconNodeValidatorServer).ProposeAttestationElectra(ctx, req.(*SingleAttestation)) } return interceptor(ctx, in, info, handler) } diff --git a/proto/prysm/v1alpha1/validator.pb.gw.go b/proto/prysm/v1alpha1/validator.pb.gw.go deleted file mode 100755 index a045a335ef21..000000000000 --- a/proto/prysm/v1alpha1/validator.pb.gw.go +++ /dev/null @@ -1,2506 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: proto/prysm/v1alpha1/validator.proto - -/* -Package eth is a reverse proxy. - -It translates gRPC into RESTful JSON APIs. -*/ -package eth - -import ( - "context" - "io" - "net/http" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" - github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/emptypb" -) - -// Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = metadata.Join -var _ = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) -var _ = emptypb.Empty{} - -var ( - filter_BeaconNodeValidator_GetDuties_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_GetDuties_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DutiesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_GetDuties_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetDuties(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_GetDuties_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DutiesRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_GetDuties_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetDuties(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_DomainData_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_DomainData_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DomainRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_DomainData_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.DomainData(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_DomainData_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DomainRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_DomainData_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.DomainData(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_WaitForChainStart_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (BeaconNodeValidator_WaitForChainStartClient, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - stream, err := client.WaitForChainStart(ctx, &protoReq) - if err != nil { - return nil, metadata, err - } - header, err := stream.Header() - if err != nil { - return nil, metadata, err - } - metadata.HeaderMD = header - return stream, metadata, nil - -} - -var ( - filter_BeaconNodeValidator_WaitForActivation_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_WaitForActivation_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (BeaconNodeValidator_WaitForActivationClient, runtime.ServerMetadata, error) { - var protoReq ValidatorActivationRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_WaitForActivation_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - stream, err := client.WaitForActivation(ctx, &protoReq) - if err != nil { - return nil, metadata, err - } - header, err := stream.Header() - if err != nil { - return nil, metadata, err - } - metadata.HeaderMD = header - return stream, metadata, nil - -} - -var ( - filter_BeaconNodeValidator_ValidatorIndex_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_ValidatorIndex_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ValidatorIndexRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_ValidatorIndex_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ValidatorIndex(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_ValidatorIndex_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ValidatorIndexRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_ValidatorIndex_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ValidatorIndex(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_ValidatorStatus_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_ValidatorStatus_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ValidatorStatusRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_ValidatorStatus_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ValidatorStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_ValidatorStatus_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ValidatorStatusRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_ValidatorStatus_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ValidatorStatus(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_MultipleValidatorStatus_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_MultipleValidatorStatus_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq MultipleValidatorStatusRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_MultipleValidatorStatus_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.MultipleValidatorStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_MultipleValidatorStatus_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq MultipleValidatorStatusRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_MultipleValidatorStatus_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.MultipleValidatorStatus(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_GetBeaconBlock_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_GetBeaconBlock_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq BlockRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_GetBeaconBlock_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetBeaconBlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_GetBeaconBlock_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq BlockRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_GetBeaconBlock_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetBeaconBlock(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_ProposeBeaconBlock_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenericSignedBeaconBlock - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ProposeBeaconBlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_ProposeBeaconBlock_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GenericSignedBeaconBlock - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ProposeBeaconBlock(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_PrepareBeaconProposer_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq PrepareBeaconProposerRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.PrepareBeaconProposer(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_PrepareBeaconProposer_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq PrepareBeaconProposerRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.PrepareBeaconProposer(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_GetFeeRecipientByPubKey_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq FeeRecipientByPubKeyRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetFeeRecipientByPubKey(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_GetFeeRecipientByPubKey_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq FeeRecipientByPubKeyRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetFeeRecipientByPubKey(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_GetAttestationData_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_GetAttestationData_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttestationDataRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_GetAttestationData_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetAttestationData(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_GetAttestationData_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttestationDataRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_GetAttestationData_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetAttestationData(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_ProposeAttestation_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Attestation - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ProposeAttestation(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_ProposeAttestation_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq Attestation - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ProposeAttestation(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_ProposeAttestationElectra_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttestationElectra - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ProposeAttestationElectra(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_ProposeAttestationElectra_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AttestationElectra - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ProposeAttestationElectra(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_SubmitAggregateSelectionProof_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AggregateSelectionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitAggregateSelectionProof(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_SubmitAggregateSelectionProof_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AggregateSelectionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitAggregateSelectionProof(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AggregateSelectionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitAggregateSelectionProofElectra(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AggregateSelectionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitAggregateSelectionProofElectra(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedAggregateSubmitRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitSignedAggregateSelectionProof(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedAggregateSubmitRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitSignedAggregateSelectionProof(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedAggregateSubmitElectraRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitSignedAggregateSelectionProofElectra(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedAggregateSubmitElectraRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitSignedAggregateSelectionProofElectra(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_ProposeExit_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedVoluntaryExit - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.ProposeExit(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_ProposeExit_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedVoluntaryExit - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.ProposeExit(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_SubscribeCommitteeSubnets_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq CommitteeSubnetsSubscribeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubscribeCommitteeSubnets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_SubscribeCommitteeSubnets_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq CommitteeSubnetsSubscribeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubscribeCommitteeSubnets(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_CheckDoppelGanger_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_CheckDoppelGanger_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DoppelGangerRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_CheckDoppelGanger_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.CheckDoppelGanger(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_CheckDoppelGanger_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq DoppelGangerRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_CheckDoppelGanger_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.CheckDoppelGanger(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_GetSyncMessageBlockRoot_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := client.GetSyncMessageBlockRoot(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_GetSyncMessageBlockRoot_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty - var metadata runtime.ServerMetadata - - msg, err := server.GetSyncMessageBlockRoot(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_SubmitSyncMessage_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SyncCommitteeMessage - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitSyncMessage(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_SubmitSyncMessage_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SyncCommitteeMessage - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitSyncMessage(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_GetSyncSubcommitteeIndex_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_GetSyncSubcommitteeIndex_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SyncSubcommitteeIndexRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_GetSyncSubcommitteeIndex_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetSyncSubcommitteeIndex(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_GetSyncSubcommitteeIndex_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SyncSubcommitteeIndexRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_GetSyncSubcommitteeIndex_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetSyncSubcommitteeIndex(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_GetSyncCommitteeContribution_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SyncCommitteeContributionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetSyncCommitteeContribution(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_GetSyncCommitteeContribution_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SyncCommitteeContributionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetSyncCommitteeContribution(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_SubmitSignedContributionAndProof_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedContributionAndProof - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitSignedContributionAndProof(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_SubmitSignedContributionAndProof_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedContributionAndProof - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitSignedContributionAndProof(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_StreamSlots_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_StreamSlots_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (BeaconNodeValidator_StreamSlotsClient, runtime.ServerMetadata, error) { - var protoReq StreamSlotsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_StreamSlots_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - stream, err := client.StreamSlots(ctx, &protoReq) - if err != nil { - return nil, metadata, err - } - header, err := stream.Header() - if err != nil { - return nil, metadata, err - } - metadata.HeaderMD = header - return stream, metadata, nil - -} - -var ( - filter_BeaconNodeValidator_StreamBlocksAltair_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_StreamBlocksAltair_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (BeaconNodeValidator_StreamBlocksAltairClient, runtime.ServerMetadata, error) { - var protoReq StreamBlocksRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_StreamBlocksAltair_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - stream, err := client.StreamBlocksAltair(ctx, &protoReq) - if err != nil { - return nil, metadata, err - } - header, err := stream.Header() - if err != nil { - return nil, metadata, err - } - metadata.HeaderMD = header - return stream, metadata, nil - -} - -func request_BeaconNodeValidator_SubmitValidatorRegistrations_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedValidatorRegistrationsV1 - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SubmitValidatorRegistrations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_SubmitValidatorRegistrations_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SignedValidatorRegistrationsV1 - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SubmitValidatorRegistrations(ctx, &protoReq) - return msg, metadata, err - -} - -func request_BeaconNodeValidator_AssignValidatorToSubnet_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AssignValidatorToSubnetRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.AssignValidatorToSubnet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_AssignValidatorToSubnet_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AssignValidatorToSubnetRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.AssignValidatorToSubnet(ctx, &protoReq) - return msg, metadata, err - -} - -var ( - filter_BeaconNodeValidator_AggregatedSigAndAggregationBits_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_BeaconNodeValidator_AggregatedSigAndAggregationBits_0(ctx context.Context, marshaler runtime.Marshaler, client BeaconNodeValidatorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AggregatedSigAndAggregationBitsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_AggregatedSigAndAggregationBits_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.AggregatedSigAndAggregationBits(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_BeaconNodeValidator_AggregatedSigAndAggregationBits_0(ctx context.Context, marshaler runtime.Marshaler, server BeaconNodeValidatorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AggregatedSigAndAggregationBitsRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_BeaconNodeValidator_AggregatedSigAndAggregationBits_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.AggregatedSigAndAggregationBits(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterBeaconNodeValidatorHandlerServer registers the http handlers for service BeaconNodeValidator to "mux". -// UnaryRPC :call BeaconNodeValidatorServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterBeaconNodeValidatorHandlerFromEndpoint instead. -func RegisterBeaconNodeValidatorHandlerServer(ctx context.Context, mux *runtime.ServeMux, server BeaconNodeValidatorServer) error { - - mux.Handle("GET", pattern_BeaconNodeValidator_GetDuties_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetDuties") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_GetDuties_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetDuties_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_DomainData_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/DomainData") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_DomainData_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_DomainData_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_WaitForChainStart_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") - _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_WaitForActivation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") - _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_ValidatorIndex_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ValidatorIndex") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_ValidatorIndex_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ValidatorIndex_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_ValidatorStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ValidatorStatus") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_ValidatorStatus_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ValidatorStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_MultipleValidatorStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/MultipleValidatorStatus") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_MultipleValidatorStatus_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_MultipleValidatorStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_GetBeaconBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetBeaconBlock") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_GetBeaconBlock_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetBeaconBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_ProposeBeaconBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeBeaconBlock") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_ProposeBeaconBlock_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ProposeBeaconBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_PrepareBeaconProposer_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/PrepareBeaconProposer") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_PrepareBeaconProposer_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_PrepareBeaconProposer_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_GetFeeRecipientByPubKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetFeeRecipientByPubKey") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_GetFeeRecipientByPubKey_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetFeeRecipientByPubKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_GetAttestationData_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetAttestationData") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_GetAttestationData_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetAttestationData_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_ProposeAttestation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeAttestation") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_ProposeAttestation_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ProposeAttestation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_ProposeAttestationElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeAttestationElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_ProposeAttestationElectra_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ProposeAttestationElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitAggregateSelectionProof_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitAggregateSelectionProof") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_SubmitAggregateSelectionProof_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitAggregateSelectionProof_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitAggregateSelectionProofElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitSignedAggregateSelectionProof") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitSignedAggregateSelectionProofElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_ProposeExit_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeExit") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_ProposeExit_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ProposeExit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubscribeCommitteeSubnets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubscribeCommitteeSubnets") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_SubscribeCommitteeSubnets_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubscribeCommitteeSubnets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_CheckDoppelGanger_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/CheckDoppelGanger") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_CheckDoppelGanger_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_CheckDoppelGanger_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_GetSyncMessageBlockRoot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetSyncMessageBlockRoot") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_GetSyncMessageBlockRoot_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetSyncMessageBlockRoot_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitSyncMessage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitSyncMessage") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_SubmitSyncMessage_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitSyncMessage_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_GetSyncSubcommitteeIndex_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetSyncSubcommitteeIndex") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_GetSyncSubcommitteeIndex_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetSyncSubcommitteeIndex_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_GetSyncCommitteeContribution_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetSyncCommitteeContribution") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_GetSyncCommitteeContribution_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetSyncCommitteeContribution_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitSignedContributionAndProof_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitSignedContributionAndProof") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_SubmitSignedContributionAndProof_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitSignedContributionAndProof_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_StreamSlots_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") - _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_StreamBlocksAltair_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") - _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitValidatorRegistrations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitValidatorRegistrations") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_SubmitValidatorRegistrations_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitValidatorRegistrations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_AssignValidatorToSubnet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/AssignValidatorToSubnet") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_AssignValidatorToSubnet_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_AssignValidatorToSubnet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_AggregatedSigAndAggregationBits_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/AggregatedSigAndAggregationBits") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_BeaconNodeValidator_AggregatedSigAndAggregationBits_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_AggregatedSigAndAggregationBits_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -// RegisterBeaconNodeValidatorHandlerFromEndpoint is same as RegisterBeaconNodeValidatorHandler but -// automatically dials to "endpoint" and closes the connection when "ctx" gets done. -func RegisterBeaconNodeValidatorHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) - if err != nil { - return err - } - defer func() { - if err != nil { - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - return - } - go func() { - <-ctx.Done() - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - }() - }() - - return RegisterBeaconNodeValidatorHandler(ctx, mux, conn) -} - -// RegisterBeaconNodeValidatorHandler registers the http handlers for service BeaconNodeValidator to "mux". -// The handlers forward requests to the grpc endpoint over "conn". -func RegisterBeaconNodeValidatorHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { - return RegisterBeaconNodeValidatorHandlerClient(ctx, mux, NewBeaconNodeValidatorClient(conn)) -} - -// RegisterBeaconNodeValidatorHandlerClient registers the http handlers for service BeaconNodeValidator -// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "BeaconNodeValidatorClient". -// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "BeaconNodeValidatorClient" -// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "BeaconNodeValidatorClient" to call the correct interceptors. -func RegisterBeaconNodeValidatorHandlerClient(ctx context.Context, mux *runtime.ServeMux, client BeaconNodeValidatorClient) error { - - mux.Handle("GET", pattern_BeaconNodeValidator_GetDuties_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetDuties") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_GetDuties_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetDuties_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_DomainData_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/DomainData") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_DomainData_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_DomainData_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_WaitForChainStart_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/WaitForChainStart") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_WaitForChainStart_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_WaitForChainStart_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_WaitForActivation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/WaitForActivation") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_WaitForActivation_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_WaitForActivation_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_ValidatorIndex_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ValidatorIndex") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_ValidatorIndex_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ValidatorIndex_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_ValidatorStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ValidatorStatus") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_ValidatorStatus_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ValidatorStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_MultipleValidatorStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/MultipleValidatorStatus") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_MultipleValidatorStatus_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_MultipleValidatorStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_GetBeaconBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetBeaconBlock") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_GetBeaconBlock_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetBeaconBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_ProposeBeaconBlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeBeaconBlock") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_ProposeBeaconBlock_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ProposeBeaconBlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_PrepareBeaconProposer_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/PrepareBeaconProposer") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_PrepareBeaconProposer_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_PrepareBeaconProposer_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_GetFeeRecipientByPubKey_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetFeeRecipientByPubKey") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_GetFeeRecipientByPubKey_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetFeeRecipientByPubKey_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_GetAttestationData_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetAttestationData") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_GetAttestationData_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetAttestationData_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_ProposeAttestation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeAttestation") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_ProposeAttestation_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ProposeAttestation_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_ProposeAttestationElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeAttestationElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_ProposeAttestationElectra_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ProposeAttestationElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitAggregateSelectionProof_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitAggregateSelectionProof") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_SubmitAggregateSelectionProof_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitAggregateSelectionProof_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitAggregateSelectionProofElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitSignedAggregateSelectionProof") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitSignedAggregateSelectionProofElectra") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_ProposeExit_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/ProposeExit") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_ProposeExit_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_ProposeExit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubscribeCommitteeSubnets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubscribeCommitteeSubnets") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_SubscribeCommitteeSubnets_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubscribeCommitteeSubnets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_CheckDoppelGanger_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/CheckDoppelGanger") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_CheckDoppelGanger_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_CheckDoppelGanger_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_GetSyncMessageBlockRoot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetSyncMessageBlockRoot") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_GetSyncMessageBlockRoot_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetSyncMessageBlockRoot_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitSyncMessage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitSyncMessage") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_SubmitSyncMessage_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitSyncMessage_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_GetSyncSubcommitteeIndex_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetSyncSubcommitteeIndex") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_GetSyncSubcommitteeIndex_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetSyncSubcommitteeIndex_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_GetSyncCommitteeContribution_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/GetSyncCommitteeContribution") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_GetSyncCommitteeContribution_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_GetSyncCommitteeContribution_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitSignedContributionAndProof_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitSignedContributionAndProof") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_SubmitSignedContributionAndProof_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitSignedContributionAndProof_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_StreamSlots_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/StreamSlots") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_StreamSlots_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_StreamSlots_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_StreamBlocksAltair_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/StreamBlocksAltair") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_StreamBlocksAltair_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_StreamBlocksAltair_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_SubmitValidatorRegistrations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/SubmitValidatorRegistrations") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_SubmitValidatorRegistrations_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_SubmitValidatorRegistrations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_BeaconNodeValidator_AssignValidatorToSubnet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/AssignValidatorToSubnet") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_AssignValidatorToSubnet_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_AssignValidatorToSubnet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_BeaconNodeValidator_AggregatedSigAndAggregationBits_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/ethereum.eth.v1alpha1.BeaconNodeValidator/AggregatedSigAndAggregationBits") - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_BeaconNodeValidator_AggregatedSigAndAggregationBits_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_BeaconNodeValidator_AggregatedSigAndAggregationBits_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_BeaconNodeValidator_GetDuties_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "duties"}, "")) - - pattern_BeaconNodeValidator_DomainData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "domain"}, "")) - - pattern_BeaconNodeValidator_WaitForChainStart_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "validator", "chainstart", "stream"}, "")) - - pattern_BeaconNodeValidator_WaitForActivation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "validator", "activation", "stream"}, "")) - - pattern_BeaconNodeValidator_ValidatorIndex_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "index"}, "")) - - pattern_BeaconNodeValidator_ValidatorStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "status"}, "")) - - pattern_BeaconNodeValidator_MultipleValidatorStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "statuses"}, "")) - - pattern_BeaconNodeValidator_GetBeaconBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha2", "validator", "block"}, "")) - - pattern_BeaconNodeValidator_ProposeBeaconBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha2", "validator", "block"}, "")) - - pattern_BeaconNodeValidator_PrepareBeaconProposer_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "prepare_beacon_proposer"}, "")) - - pattern_BeaconNodeValidator_GetFeeRecipientByPubKey_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "fee_recipient_by_pub_key"}, "")) - - pattern_BeaconNodeValidator_GetAttestationData_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "attestation"}, "")) - - pattern_BeaconNodeValidator_ProposeAttestation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "attestation"}, "")) - - pattern_BeaconNodeValidator_ProposeAttestationElectra_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "attestation_electra"}, "")) - - pattern_BeaconNodeValidator_SubmitAggregateSelectionProof_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "aggregate"}, "")) - - pattern_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "aggregate_electra"}, "")) - - pattern_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "aggregate"}, "")) - - pattern_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "aggregate_electra"}, "")) - - pattern_BeaconNodeValidator_ProposeExit_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "exit"}, "")) - - pattern_BeaconNodeValidator_SubscribeCommitteeSubnets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "validator", "subnet", "subscribe"}, "")) - - pattern_BeaconNodeValidator_CheckDoppelGanger_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "doppelganger"}, "")) - - pattern_BeaconNodeValidator_GetSyncMessageBlockRoot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "sync_message_block_root"}, "")) - - pattern_BeaconNodeValidator_SubmitSyncMessage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "sync_message"}, "")) - - pattern_BeaconNodeValidator_GetSyncSubcommitteeIndex_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"eth", "v1alpha1", "sync_subcommittee_index"}, "")) - - pattern_BeaconNodeValidator_GetSyncCommitteeContribution_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "contribution_and_proof"}, "")) - - pattern_BeaconNodeValidator_SubmitSignedContributionAndProof_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "signed_contribution_and_proof"}, "")) - - pattern_BeaconNodeValidator_StreamSlots_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "validator", "blocks", "stream_slots"}, "")) - - pattern_BeaconNodeValidator_StreamBlocksAltair_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "validator", "blocks", "stream"}, "")) - - pattern_BeaconNodeValidator_SubmitValidatorRegistrations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"eth", "v1alpha1", "validator", "registration"}, "")) - - pattern_BeaconNodeValidator_AssignValidatorToSubnet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "validator", "blocks", "assign_validator_to_subnet"}, "")) - - pattern_BeaconNodeValidator_AggregatedSigAndAggregationBits_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"eth", "v1alpha1", "validator", "blocks", "aggregated_sig_and_aggregation_bits"}, "")) -) - -var ( - forward_BeaconNodeValidator_GetDuties_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_DomainData_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_WaitForChainStart_0 = runtime.ForwardResponseStream - - forward_BeaconNodeValidator_WaitForActivation_0 = runtime.ForwardResponseStream - - forward_BeaconNodeValidator_ValidatorIndex_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_ValidatorStatus_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_MultipleValidatorStatus_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_GetBeaconBlock_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_ProposeBeaconBlock_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_PrepareBeaconProposer_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_GetFeeRecipientByPubKey_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_GetAttestationData_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_ProposeAttestation_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_ProposeAttestationElectra_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_SubmitAggregateSelectionProof_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_SubmitAggregateSelectionProofElectra_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_SubmitSignedAggregateSelectionProof_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_SubmitSignedAggregateSelectionProofElectra_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_ProposeExit_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_SubscribeCommitteeSubnets_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_CheckDoppelGanger_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_GetSyncMessageBlockRoot_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_SubmitSyncMessage_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_GetSyncSubcommitteeIndex_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_GetSyncCommitteeContribution_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_SubmitSignedContributionAndProof_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_StreamSlots_0 = runtime.ForwardResponseStream - - forward_BeaconNodeValidator_StreamBlocksAltair_0 = runtime.ForwardResponseStream - - forward_BeaconNodeValidator_SubmitValidatorRegistrations_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_AssignValidatorToSubnet_0 = runtime.ForwardResponseMessage - - forward_BeaconNodeValidator_AggregatedSigAndAggregationBits_0 = runtime.ForwardResponseMessage -) diff --git a/proto/prysm/v1alpha1/validator.proto b/proto/prysm/v1alpha1/validator.proto index bd0e235e83e3..5c5bb045e718 100644 --- a/proto/prysm/v1alpha1/validator.proto +++ b/proto/prysm/v1alpha1/validator.proto @@ -37,803 +37,983 @@ option php_namespace = "Ethereum\\Eth\\v1alpha1"; // The beacon node validator API enables a validator to connect // and perform its obligations on the Ethereum Beacon Chain. service BeaconNodeValidator { - // Retrieves validator duties for the requested validators. - // - // The duties consist of: - // Proposer - the validator that creates a beacon chain block. - // Attester — a validator that is part of a committee that needs to sign off on a beacon chain - // block while simultaneously creating a cross link to a recent shard block on a particular shard chain. - // The server returns a list of duties which are the actions should be performed by validators for a given epoch. - // Validator duties should be polled every epoch, but due to chain reorg of >MIN_SEED_LOOKAHEAD could occur, - // the validator duties could chain. For complete safety, it is recommended to poll at every slot to ensure - // validator is fully aware of any sudden chain reorg. - rpc GetDuties(DutiesRequest) returns (DutiesResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/duties" - }; - } - - // DomainData fetches the current BLS signature domain version information from the - // running beacon node's state. This information is used when validators sign - // blocks and attestations appropriately based on their duty. - rpc DomainData(DomainRequest) returns (DomainResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/domain" - }; - } - - // WaitForChainStart queries the logs of the Validator Deposit Contract on the Ethereum - // proof-of-work chain to verify the beacon chain has started its runtime and - // validators are ready to begin their responsibilities. - // - // If the chain has not yet started, this endpoint starts a server-side stream which updates - // the client when the beacon chain is ready. - rpc WaitForChainStart(google.protobuf.Empty) returns (stream ChainStartResponse) { - option deprecated = true; - option (google.api.http) = { - get: "/eth/v1alpha1/validator/chainstart/stream" - }; - } - - // WaitForActivation checks if a validator public key exists in the active validator - // registry of the current beacon state. If the validator is NOT yet active, it starts a - // server-side stream which updates the client whenever the validator becomes active in - // the beacon node's state. - // - // The input to this endpoint is a list of validator public keys, and the corresponding - // stream will respond until at least a single corresponding validator to those - // keys is activated. - rpc WaitForActivation(ValidatorActivationRequest) returns (stream ValidatorActivationResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/activation/stream" - }; - } - - // ValidatorIndex retrieves a validator's index location in the beacon state's - // validator registry looking up whether the validator exists based on its - // public key. This method returns NOT_FOUND if no index is found for the public key - // specified in the request. - rpc ValidatorIndex(ValidatorIndexRequest) returns (ValidatorIndexResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/index" - }; - } - - // ValidatorStatus returns a validator's status based on the current epoch. - // The request can specify either a validator's public key or validator index. - // - // The status response can be one of the following: - // DEPOSITED - validator's deposit has been recognized by Ethereum 1, not yet recognized by Ethereum. - // PENDING - validator is in Ethereum's activation queue. - // ACTIVE - validator is active. - // EXITING - validator has initiated an an exit request, or has dropped below the ejection balance and is being kicked out. - // EXITED - validator is no longer validating. - // SLASHING - validator has been kicked out due to meeting a slashing condition. - // UNKNOWN_STATUS - validator does not have a known status in the network. - rpc ValidatorStatus(ValidatorStatusRequest) returns (ValidatorStatusResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/status" - }; - } - - // MultipleValidatorStatus returns a list of validator statuses on the current epoch. - // The request can specify a list of validator public keys. - // - // Returns a list of ValidatorStatusResponses. - rpc MultipleValidatorStatus(MultipleValidatorStatusRequest) returns (MultipleValidatorStatusResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/statuses" - }; - } - - // Retrieves the latest valid beacon block to be proposed on the beacon chain. - // - // The server returns a new beacon block, without proposer signature, that can be - // proposed on the beacon chain. The block should be filled with all the necessary - // data for proposer to sign. - rpc GetBeaconBlock(BlockRequest) returns (GenericBeaconBlock) { - option (google.api.http) = { - get: "/eth/v1alpha2/validator/block" - }; - } - - // Sends the newly signed beacon block to beacon node. - // - // The validator sends the newly signed beacon block to the beacon node so the beacon block can - // be included in the beacon chain. The beacon node is expected to validate and process the - // beacon block into its state. - rpc ProposeBeaconBlock(GenericSignedBeaconBlock) returns (ProposeResponse) { - option (google.api.http) = { - post: "/eth/v1alpha2/validator/block" - body: "*" - }; - } - - // PrepareBeaconProposer submits fee recipient information to be used when preparing block - // proposal execution payloads. - rpc PrepareBeaconProposer(PrepareBeaconProposerRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/prepare_beacon_proposer" - body: "*" - }; - } - - // GetFeeRecipientByPubKey returns a fee recipient from the beacon node's settings or db based on a given public key - rpc GetFeeRecipientByPubKey(FeeRecipientByPubKeyRequest) returns (FeeRecipientByPubKeyResponse){ - option (google.api.http) = { - post: "/eth/v1alpha1/validator/fee_recipient_by_pub_key" - body: "*" - }; - } - - // Retrieves the latest valid attestation data to be attested on the beacon chain. - // - // The server returns the latest valid data which represents the correct vote - // for the head of the beacon chain. - rpc GetAttestationData(AttestationDataRequest) returns (AttestationData) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/attestation" - }; - } - - // Sends the newly signed attestation to beacon node. - // - // The validator sends the newly signed attestation to the beacon node for the attestation to - // be included in the beacon chain. The beacon node is expected to validate and publish attestation on - // appropriate committee subnet. - rpc ProposeAttestation(Attestation) returns (AttestResponse) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/attestation" - body: "*" - }; - } - - // Sends the newly signed attestation to beacon node. - // - // The validator sends the newly signed attestation to the beacon node for the attestation to - // be included in the beacon chain. The beacon node is expected to validate and publish attestation on - // appropriate committee subnet. - rpc ProposeAttestationElectra(AttestationElectra) returns (AttestResponse) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/attestation_electra" - body: "*" - }; - } - - // Submit selection proof to the beacon node to aggregate all matching wire attestations with the same data root. - // the beacon node responses with an aggregate and proof object back to validator to sign over. - rpc SubmitAggregateSelectionProof(AggregateSelectionRequest) returns (AggregateSelectionResponse) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/aggregate" - body: "*" - }; - } - - // Submit selection proof to the beacon node to aggregate all matching wire attestations with the same data root. - // the beacon node responses with an aggregate and proof object back to validator to sign over. - rpc SubmitAggregateSelectionProofElectra(AggregateSelectionRequest) returns (AggregateSelectionElectraResponse) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/aggregate_electra" - body: "*" - }; - } - - // Submit a signed aggregate and proof object, the beacon node will broadcast the - // signed aggregated attestation and proof object. - rpc SubmitSignedAggregateSelectionProof(SignedAggregateSubmitRequest) returns (SignedAggregateSubmitResponse) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/aggregate" - body: "*" - }; - } - - // Submit a signed aggregate and proof object, the beacon node will broadcast the - // signed aggregated attestation and proof object. - rpc SubmitSignedAggregateSelectionProofElectra(SignedAggregateSubmitElectraRequest) returns (SignedAggregateSubmitResponse) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/aggregate_electra" - body: "*" - }; - } - - // Propose to leave the list of active validators. - // - // The beacon node is expected to validate the request and make it available for inclusion in - // the next proposed block. - rpc ProposeExit(SignedVoluntaryExit) returns (ProposeExitResponse) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/exit" - body: "*" - }; - } - - // Subscribe to particular committee ID subnets given validator's duty. - // - // The beacon node is expected to subscribe to the committee ID subnet given by the request. With this, - // beacon node serving attesters can find persistent peers on the subnet to publish attestation, - // and beacon node serving aggregator can join the subnet. - rpc SubscribeCommitteeSubnets(CommitteeSubnetsSubscribeRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/subnet/subscribe" - body: "*" - }; - } - - // Checks the beacon node if another instance of the provided validator keys have been - // attesting/proposing for you. - rpc CheckDoppelGanger(DoppelGangerRequest) returns (DoppelGangerResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/doppelganger" - }; - } - - // Retrieves a sync committee message block root to be signed over as part of sync committee duty. - rpc GetSyncMessageBlockRoot(google.protobuf.Empty) returns (SyncMessageBlockRootResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/sync_message_block_root" - }; - } - - // Submits a sync committee message to be broadcasted over network. This is part of sync committee duty. - rpc SubmitSyncMessage(SyncCommitteeMessage) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/sync_message" - body: "*" - }; - } - - // Retrieves the sync subcommittee index of a given validator. - // - // The server returns the sync subcommittee index given the validator public key, - // if the validator does not exist in the sync committee then an error would be returned. - // The subcommittee index is used for the aggregation of sync committee message. - rpc GetSyncSubcommitteeIndex(SyncSubcommitteeIndexRequest) returns (SyncSubcommitteeIndexResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/sync_subcommittee_index" - }; - } - - // Retrieve sync committee contribution to the beacon node to aggregate all matching sync committee messages with the same slot and root. - // the beacon node responses with a sync committee contribution object for the validator to sign over. - rpc GetSyncCommitteeContribution(SyncCommitteeContributionRequest) returns (SyncCommitteeContribution) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/contribution_and_proof" - body: "*" - }; - } - - // Submit a signed sync committee contribution and proof object, the beacon node will broadcast the - // signed contribution and proof object. - rpc SubmitSignedContributionAndProof(SignedContributionAndProof) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/signed_contribution_and_proof" - body: "*" - }; - } - - // Server-side stream of all slots of valid blocks as they are received by - // the beacon chain node. - // DEPRECATED: This endpoint is superseded by the /eth/v1/events Beacon API endpoint - rpc StreamSlots(StreamSlotsRequest) returns (stream StreamSlotsResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/blocks/stream_slots" - }; - option deprecated = true; - } - - // Server-side stream of all signed blocks as they are received by - // the beacon chain node. - // DEPRECATED: This endpoint is superseded by the /eth/v1/events Beacon API endpoint - rpc StreamBlocksAltair(StreamBlocksRequest) returns (stream StreamBlocksResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/blocks/stream" - }; - option deprecated = true; - } - - rpc SubmitValidatorRegistrations(SignedValidatorRegistrationsV1) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/registration" - body: "*" - }; - } - - rpc AssignValidatorToSubnet(AssignValidatorToSubnetRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/eth/v1alpha1/validator/blocks/assign_validator_to_subnet" - body: "*" - }; - } - - rpc AggregatedSigAndAggregationBits(AggregatedSigAndAggregationBitsRequest) returns (AggregatedSigAndAggregationBitsResponse) { - option (google.api.http) = { - get: "/eth/v1alpha1/validator/blocks/aggregated_sig_and_aggregation_bits" - }; - } + // Retrieves validator duties for the requested validators. + // + // The duties consist of: + // Proposer - the validator that creates a beacon chain block. + // Attester — a validator that is part of a committee that needs to sign off + // on a beacon chain + // block while simultaneously creating a cross link to a recent shard block + // on a particular shard chain. + // The server returns a list of duties which are the actions should be + // performed by validators for a given epoch. Validator duties should be + // polled every epoch, but due to chain reorg of >MIN_SEED_LOOKAHEAD could + // occur, the validator duties could chain. For complete safety, it is + // recommended to poll at every slot to ensure validator is fully aware of any + // sudden chain reorg. + rpc GetDuties(DutiesRequest) returns (DutiesResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/duties" + }; + } + + // DomainData fetches the current BLS signature domain version information + // from the running beacon node's state. This information is used when + // validators sign blocks and attestations appropriately based on their duty. + rpc DomainData(DomainRequest) returns (DomainResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/domain" + }; + } + + // WaitForChainStart queries the logs of the Validator Deposit Contract on the + // Ethereum proof-of-work chain to verify the beacon chain has started its + // runtime and validators are ready to begin their responsibilities. + // + // If the chain has not yet started, this endpoint starts a server-side stream + // which updates the client when the beacon chain is ready. + rpc WaitForChainStart(google.protobuf.Empty) + returns (stream ChainStartResponse) { + option deprecated = true; + option (google.api.http) = { + get : "/eth/v1alpha1/validator/chainstart/stream" + }; + } + + // WaitForActivation checks if a validator public key exists in the active + // validator registry of the current beacon state. If the validator is NOT yet + // active, it starts a server-side stream which updates the client whenever + // the validator becomes active in the beacon node's state. + // + // The input to this endpoint is a list of validator public keys, and the + // corresponding stream will respond until at least a single corresponding + // validator to those keys is activated. + rpc WaitForActivation(ValidatorActivationRequest) + returns (stream ValidatorActivationResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/activation/stream" + }; + option deprecated = true; + } + + // ValidatorIndex retrieves a validator's index location in the beacon state's + // validator registry looking up whether the validator exists based on its + // public key. This method returns NOT_FOUND if no index is found for the + // public key specified in the request. + rpc ValidatorIndex(ValidatorIndexRequest) returns (ValidatorIndexResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/index" + }; + } + + // ValidatorStatus returns a validator's status based on the current epoch. + // The request can specify either a validator's public key or validator index. + // + // The status response can be one of the following: + // DEPOSITED - validator's deposit has been recognized by Ethereum 1, not + //yet recognized by Ethereum. PENDING - validator is in Ethereum's activation + //queue. ACTIVE - validator is active. EXITING - validator has initiated an an + //exit request, or has dropped below the ejection balance and is being kicked + //out. EXITED - validator is no longer validating. SLASHING - validator has + //been kicked out due to meeting a slashing condition. UNKNOWN_STATUS - + //validator does not have a known status in the network. + rpc ValidatorStatus(ValidatorStatusRequest) + returns (ValidatorStatusResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/status" + }; + } + + // MultipleValidatorStatus returns a list of validator statuses on the current + // epoch. The request can specify a list of validator public keys. + // + // Returns a list of ValidatorStatusResponses. + rpc MultipleValidatorStatus(MultipleValidatorStatusRequest) + returns (MultipleValidatorStatusResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/statuses" + }; + } + + // Retrieves the latest valid beacon block to be proposed on the beacon chain. + // + // The server returns a new beacon block, without proposer signature, that can + // be proposed on the beacon chain. The block should be filled with all the + // necessary data for proposer to sign. + rpc GetBeaconBlock(BlockRequest) returns (GenericBeaconBlock) { + option (google.api.http) = { + get : "/eth/v1alpha2/validator/block" + }; + } + + // Sends the newly signed beacon block to beacon node. + // + // The validator sends the newly signed beacon block to the beacon node so the + // beacon block can be included in the beacon chain. The beacon node is + // expected to validate and process the beacon block into its state. + rpc ProposeBeaconBlock(GenericSignedBeaconBlock) returns (ProposeResponse) { + option (google.api.http) = { + post : "/eth/v1alpha2/validator/block" + body : "*" + }; + } + + // PrepareBeaconProposer submits fee recipient information to be used when + // preparing block proposal execution payloads. + rpc PrepareBeaconProposer(PrepareBeaconProposerRequest) + returns (google.protobuf.Empty) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/prepare_beacon_proposer" + body : "*" + }; + } + + // GetFeeRecipientByPubKey returns a fee recipient from the beacon node's + // settings or db based on a given public key + rpc GetFeeRecipientByPubKey(FeeRecipientByPubKeyRequest) + returns (FeeRecipientByPubKeyResponse) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/fee_recipient_by_pub_key" + body : "*" + }; + } + + // Retrieves the latest valid attestation data to be attested on the beacon + // chain. + // + // The server returns the latest valid data which represents the correct vote + // for the head of the beacon chain. + rpc GetAttestationData(AttestationDataRequest) returns (AttestationData) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/attestation" + }; + } + + // Sends the newly signed attestation to beacon node. + // + // The validator sends the newly signed attestation to the beacon node for the + // attestation to be included in the beacon chain. The beacon node is expected + // to validate and publish attestation on appropriate committee subnet. + rpc ProposeAttestation(Attestation) returns (AttestResponse) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/attestation" + body : "*" + }; + } + + // Sends the newly signed attestation to beacon node. + // + // The validator sends the newly signed attestation to the beacon node for the + // attestation to be included in the beacon chain. The beacon node is expected + // to validate and publish attestation on appropriate committee subnet. + rpc ProposeAttestationElectra(SingleAttestation) returns (AttestResponse) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/attestation_electra" + body : "*" + }; + } + + // Submit selection proof to the beacon node to aggregate all matching wire + // attestations with the same data root. the beacon node responses with an + // aggregate and proof object back to validator to sign over. + rpc SubmitAggregateSelectionProof(AggregateSelectionRequest) + returns (AggregateSelectionResponse) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/aggregate" + body : "*" + }; + } + + // Submit selection proof to the beacon node to aggregate all matching wire + // attestations with the same data root. the beacon node responses with an + // aggregate and proof object back to validator to sign over. + rpc SubmitAggregateSelectionProofElectra(AggregateSelectionRequest) + returns (AggregateSelectionElectraResponse) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/aggregate_electra" + body : "*" + }; + } + + // Submit a signed aggregate and proof object, the beacon node will broadcast + // the signed aggregated attestation and proof object. + rpc SubmitSignedAggregateSelectionProof(SignedAggregateSubmitRequest) + returns (SignedAggregateSubmitResponse) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/aggregate" + body : "*" + }; + } + + // Submit a signed aggregate and proof object, the beacon node will broadcast + // the signed aggregated attestation and proof object. + rpc SubmitSignedAggregateSelectionProofElectra( + SignedAggregateSubmitElectraRequest) + returns (SignedAggregateSubmitResponse) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/aggregate_electra" + body : "*" + }; + } + + // Propose to leave the list of active validators. + // + // The beacon node is expected to validate the request and make it available + // for inclusion in the next proposed block. + rpc ProposeExit(SignedVoluntaryExit) returns (ProposeExitResponse) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/exit" + body : "*" + }; + } + + // Subscribe to particular committee ID subnets given validator's duty. + // + // The beacon node is expected to subscribe to the committee ID subnet given + // by the request. With this, beacon node serving attesters can find + // persistent peers on the subnet to publish attestation, and beacon node + // serving aggregator can join the subnet. + rpc SubscribeCommitteeSubnets(CommitteeSubnetsSubscribeRequest) + returns (google.protobuf.Empty) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/subnet/subscribe" + body : "*" + }; + } + + // Checks the beacon node if another instance of the provided validator keys + // have been attesting/proposing for you. + rpc CheckDoppelGanger(DoppelGangerRequest) returns (DoppelGangerResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/doppelganger" + }; + } + + // Retrieves a sync committee message block root to be signed over as part of + // sync committee duty. + rpc GetSyncMessageBlockRoot(google.protobuf.Empty) + returns (SyncMessageBlockRootResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/sync_message_block_root" + }; + } + + // Submits a sync committee message to be broadcasted over network. This is + // part of sync committee duty. + rpc SubmitSyncMessage(SyncCommitteeMessage) returns (google.protobuf.Empty) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/sync_message" + body : "*" + }; + } + + // Retrieves the sync subcommittee index of a given validator. + // + // The server returns the sync subcommittee index given the validator public + // key, if the validator does not exist in the sync committee then an error + // would be returned. The subcommittee index is used for the aggregation of + // sync committee message. + rpc GetSyncSubcommitteeIndex(SyncSubcommitteeIndexRequest) + returns (SyncSubcommitteeIndexResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/sync_subcommittee_index" + }; + } + + // Retrieve sync committee contribution to the beacon node to aggregate all + // matching sync committee messages with the same slot and root. the beacon + // node responses with a sync committee contribution object for the validator + // to sign over. + rpc GetSyncCommitteeContribution(SyncCommitteeContributionRequest) + returns (SyncCommitteeContribution) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/contribution_and_proof" + body : "*" + }; + } + + // Submit a signed sync committee contribution and proof object, the beacon + // node will broadcast the signed contribution and proof object. + rpc SubmitSignedContributionAndProof(SignedContributionAndProof) + returns (google.protobuf.Empty) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/signed_contribution_and_proof" + body : "*" + }; + } + + // Server-side stream of all slots of valid blocks as they are received by + // the beacon chain node. + // DEPRECATED: This endpoint is superseded by the /eth/v1/events Beacon API + // endpoint + rpc StreamSlots(StreamSlotsRequest) returns (stream StreamSlotsResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/blocks/stream_slots" + }; + option deprecated = true; + } + + // Server-side stream of all signed blocks as they are received by + // the beacon chain node. + // DEPRECATED: This endpoint is superseded by the /eth/v1/events Beacon API + // endpoint + rpc StreamBlocksAltair(StreamBlocksRequest) + returns (stream StreamBlocksResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/blocks/stream" + }; + option deprecated = true; + } + + rpc SubmitValidatorRegistrations(SignedValidatorRegistrationsV1) + returns (google.protobuf.Empty) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/registration" + body : "*" + }; + } + + rpc AssignValidatorToSubnet(AssignValidatorToSubnetRequest) + returns (google.protobuf.Empty) { + option (google.api.http) = { + post : "/eth/v1alpha1/validator/blocks/assign_validator_to_subnet" + body : "*" + }; + } + + rpc AggregatedSigAndAggregationBits(AggregatedSigAndAggregationBitsRequest) + returns (AggregatedSigAndAggregationBitsResponse) { + option (google.api.http) = { + get : "/eth/v1alpha1/validator/blocks/aggregated_sig_and_aggregation_bits" + }; + } } // SyncMessageBlockRootResponse for beacon chain validator to retrieve and -// to sign over the block root as part of sync committee duty to facilitate light client. +// to sign over the block root as part of sync committee duty to facilitate +// light client. message SyncMessageBlockRootResponse { - // The block root of the head block. - bytes root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + // The block root of the head block. + bytes root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; } -// SyncSubcommitteeIndexRequest requests sync subcommittee index given the validator public key. +// SyncSubcommitteeIndexRequest requests sync subcommittee index given the +// validator public key. message SyncSubcommitteeIndexRequest { - // The validator's public key. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48"]; - // The slot of validator's assignment. - uint64 slot = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // The validator's public key. + bytes public_key = 1 [ (ethereum.eth.ext.ssz_size) = "48" ]; + // The slot of validator's assignment. + uint64 slot = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; } message SyncCommitteeContributionRequest { - // Slot for which the aggregation request applies. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - // 48 byte public key of the validator. - bytes public_key = 2 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; - // Subnet ID of where this contribution and proof should be broadcast to. - uint64 subnet_id = 3; -} - -// SyncSubcommitteeIndexResponse responds index of the sync subcommittee of a given validator. + // Slot for which the aggregation request applies. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + // 48 byte public key of the validator. + bytes public_key = 2 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; + // Subnet ID of where this contribution and proof should be broadcast to. + uint64 subnet_id = 3; +} + +// SyncSubcommitteeIndexResponse responds index of the sync subcommittee of a +// given validator. message SyncSubcommitteeIndexResponse { - // The subcommittee index itself. - // If the total validator count is not sufficient, there could be more than one index. - repeated uint64 indices = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; + // The subcommittee index itself. + // If the total validator count is not sufficient, there could be more than + // one index. + repeated uint64 indices = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.CommitteeIndex" ]; } -// DEPRECATED: This endpoint StreamSlots is superseded by the /eth/v1/events Beacon API endpoint +// DEPRECATED: This endpoint StreamSlots is superseded by the /eth/v1/events +// Beacon API endpoint message StreamSlotsResponse { - option deprecated = true; - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + option deprecated = true; + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; } -// DEPRECATED: This endpoint StreamBlocks is superseded by the /eth/v1/events Beacon API endpoint +// DEPRECATED: This endpoint StreamBlocks is superseded by the /eth/v1/events +// Beacon API endpoint message StreamBlocksResponse { - option deprecated = true; - oneof block { - // Representing a phase 0 block. - SignedBeaconBlock phase0_block = 1 ; + option deprecated = true; + oneof block { + // Representing a phase 0 block. + SignedBeaconBlock phase0_block = 1; + + // Representing an altair block. + SignedBeaconBlockAltair altair_block = 2; - // Representing an altair block. - SignedBeaconBlockAltair altair_block = 2; + // Representing a bellatrix block. + SignedBeaconBlockBellatrix bellatrix_block = 3; - // Representing a bellatrix block. - SignedBeaconBlockBellatrix bellatrix_block = 3; + // Representing a capella block. + SignedBeaconBlockCapella capella_block = 4; - // Representing a capella block. - SignedBeaconBlockCapella capella_block = 4; + // Representing a deneb block. + SignedBeaconBlockDeneb deneb_block = 5; - // Representing a deneb block. - SignedBeaconBlockDeneb deneb_block = 5; + // Representing an electra block. + SignedBeaconBlockElectra electra_block = 6; - // Representing a electra block. - SignedBeaconBlockElectra electra_block = 6; - } + // Representing a fulu block. + SignedBeaconBlockFulu fulu_block = 7; + } } message DomainRequest { - // The epoch for which the domain is being requested. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // The epoch for which the domain is being requested. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; - // The bytes domain specified by the validator. - bytes domain = 2; + // The bytes domain specified by the validator. + bytes domain = 2; } message DomainResponse { - // The signature domain is a byte array used by validators when - // signing data related to block proposals and attestations. - bytes signature_domain = 1; + // The signature domain is a byte array used by validators when + // signing data related to block proposals and attestations. + bytes signature_domain = 1; } message ValidatorActivationRequest { - // A list of 48 byte validator public keys. - repeated bytes public_keys = 1 [(ethereum.eth.ext.ssz_size) = "?,48"]; + // A list of 48 byte validator public keys. + repeated bytes public_keys = 1 [ (ethereum.eth.ext.ssz_size) = "?,48" ]; } message ValidatorActivationResponse { - message Status { - // A 48 byte validator public key. - bytes public_key = 1; + message Status { + // A 48 byte validator public key. + bytes public_key = 1; - // A wrapper representing a validator's status object. - ValidatorStatusResponse status = 2; + // A wrapper representing a validator's status object. + ValidatorStatusResponse status = 2; - // The validators index in the beacon state. - uint64 index = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - } - // A list of validator statuses mapped 1-to-1 with the public keys - // in the request. - repeated Status statuses = 1; + // The validators index in the beacon state. + uint64 index = 3 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + } + // A list of validator statuses mapped 1-to-1 with the public keys + // in the request. + repeated Status statuses = 1; } message ChainStartResponse { - // A boolean specifying whether or not the chain has started. - bool started = 1; + // A boolean specifying whether or not the chain has started. + bool started = 1; - // The genesis time of the beacon chain. - uint64 genesis_time = 2; + // The genesis time of the beacon chain. + uint64 genesis_time = 2; - // 32 byte hash tree root of the genesis validator set. - bytes genesis_validators_root = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // 32 byte hash tree root of the genesis validator set. + bytes genesis_validators_root = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message SyncedResponse { - // A boolean specifying whether or not the beacon node is synced and ready for the validator. - bool synced = 1; + // A boolean specifying whether or not the beacon node is synced and ready for + // the validator. + bool synced = 1; - // The genesis time of the beacon chain. - uint64 genesis_time = 2; + // The genesis time of the beacon chain. + uint64 genesis_time = 2; } message ValidatorIndexRequest { - // A 48 byte validator public key. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48"]; + // A 48 byte validator public key. + bytes public_key = 1 [ (ethereum.eth.ext.ssz_size) = "48" ]; } message ValidatorIndexResponse { - // The validator's index in the beacon chain state's validator registry. - uint64 index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // The validator's index in the beacon chain state's validator registry. + uint64 index = 1 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } message ValidatorStatusRequest { - // A 48 byte validator public key. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48"]; + // A 48 byte validator public key. + bytes public_key = 1 [ (ethereum.eth.ext.ssz_size) = "48" ]; } enum ValidatorStatus { - UNKNOWN_STATUS = 0; - DEPOSITED = 1; - PENDING = 2; - ACTIVE = 3; - EXITING = 4; - SLASHING = 5; - EXITED = 6; - INVALID = 7; - PARTIALLY_DEPOSITED = 8; + UNKNOWN_STATUS = 0; + DEPOSITED = 1; + PENDING = 2; + ACTIVE = 3; + EXITING = 4; + SLASHING = 5; + EXITED = 6; + INVALID = 7; + PARTIALLY_DEPOSITED = 8; } message ValidatorStatusResponse { - // The corresponding validator status. - ValidatorStatus status = 1; + // The corresponding validator status. + ValidatorStatus status = 1; - // The block number of the Ethereum proof-of-work chain - // where the deposit for the validator was included. - uint64 eth1_deposit_block_number = 2; + // The block number of the Ethereum proof-of-work chain + // where the deposit for the validator was included. + uint64 eth1_deposit_block_number = 2; - // The slot in the beacon chain in which the validator's - // deposit was included in a block. - uint64 deposit_inclusion_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // The slot in the beacon chain in which the validator's + // deposit was included in a block. + uint64 deposit_inclusion_slot = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // The epoch in the beacon chain in which the validator - // is determined as active. - uint64 activation_epoch = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // The epoch in the beacon chain in which the validator + // is determined as active. + uint64 activation_epoch = 4 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; - // The position in the activation queue of pending validators. - uint64 position_in_activation_queue = 5; + // The position in the activation queue of pending validators. + uint64 position_in_activation_queue = 5; } message MultipleValidatorStatusRequest { - // A list of 48 byte validator public keys. - repeated bytes public_keys = 1 [(ethereum.eth.ext.ssz_size) = "?,48"]; - // A list of validator indices. - repeated int64 indices = 2; + // A list of 48 byte validator public keys. + repeated bytes public_keys = 1 [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + // A list of validator indices. + repeated int64 indices = 2; } message MultipleValidatorStatusResponse { - // A list of 48 byte validator public keys. - repeated bytes public_keys = 1 [(ethereum.eth.ext.ssz_size) = "?,48"]; - // A list of ValidatorStatusResponses mapped 1-to-1 with the public keys. - repeated ValidatorStatusResponse statuses = 2; - // A list of validator indices. - repeated uint64 indices = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // A list of 48 byte validator public keys. + repeated bytes public_keys = 1 [ (ethereum.eth.ext.ssz_size) = "?,48" ]; + // A list of ValidatorStatusResponses mapped 1-to-1 with the public keys. + repeated ValidatorStatusResponse statuses = 2; + // A list of validator indices. + repeated uint64 indices = 3 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; } message DutiesRequest { - // Epoch at which validators should perform their duties. - uint64 epoch = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // Epoch at which validators should perform their duties. + uint64 epoch = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; - // Array of byte encoded BLS public keys. - repeated bytes public_keys = 2 [(ethereum.eth.ext.ssz_size) = "?,48"]; + // Array of byte encoded BLS public keys. + repeated bytes public_keys = 2 [ (ethereum.eth.ext.ssz_size) = "?,48" ]; } message DutiesResponse { - reserved 1; // Deprecated fields + reserved 1; // Deprecated fields - repeated Duty current_epoch_duties = 2; + repeated Duty current_epoch_duties = 2; - repeated Duty next_epoch_duties = 3; + repeated Duty next_epoch_duties = 3; - message Duty { - // The committee a validator is assigned to. - repeated uint64 committee = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + message Duty { + // The committee a validator is assigned to. + repeated uint64 committee = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; - // The index into the committee where the validator belongs in. - uint64 committee_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; + // The index into the committee where the validator belongs in. + uint64 committee_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.CommitteeIndex" ]; - // Slot at which a validator must attest. - uint64 attester_slot = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Slot at which a validator must attest. + uint64 attester_slot = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Slots at which a validator must propose a beacon chain block. - repeated uint64 proposer_slots = 4 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Slots at which a validator must propose a beacon chain block. + repeated uint64 proposer_slots = 4 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // 48 byte BLS public key for the validator who's assigned to perform a duty. - bytes public_key = 5 [(ethereum.eth.ext.ssz_size) = "48"]; + // 48 byte BLS public key for the validator who's assigned to perform a + // duty. + bytes public_key = 5 [ (ethereum.eth.ext.ssz_size) = "48" ]; - // The current status of the validator assigned to perform the duty. - ValidatorStatus status = 6; + // The current status of the validator assigned to perform the duty. + ValidatorStatus status = 6; - // The index of the validator in the beacon state. - uint64 validator_index = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; + // The index of the validator in the beacon state. + uint64 validator_index = 7 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; - // Whether the validator belongs in the sync committee and has to perform sync committee duty. - bool is_sync_committee = 8; + // Whether the validator belongs in the sync committee and has to perform + // sync committee duty. + bool is_sync_committee = 8; - // The number of committees in the duty's slot. - uint64 committees_at_slot = 9; - } + // The number of committees in the duty's slot. + uint64 committees_at_slot = 9; + } } message BlockRequest { - // Slot for which the block should be proposed. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Slot for which the block should be proposed. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Validator's 32 byte randao reveal secret of the current epoch. - bytes randao_reveal = 2 [(ethereum.eth.ext.ssz_size) = "48"]; + // Validator's 32 byte randao reveal secret of the current epoch. + bytes randao_reveal = 2 [ (ethereum.eth.ext.ssz_size) = "48" ]; - // Validator's 32 byte graffiti message for the new block. - bytes graffiti = 3 [(ethereum.eth.ext.ssz_size) = "32"]; + // Validator's 32 byte graffiti message for the new block. + bytes graffiti = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; - // Signal server to skip outsourcing block request from mev-boost/relayer so that returned block will always be a local block. - bool skip_mev_boost = 4; + // Signal server to skip outsourcing block request from mev-boost/relayer so + // that returned block will always be a local block. + bool skip_mev_boost = 4; - // Percentage multiplier to apply to the builder's payload value when choosing between a builder payload header and payload from the paired execution node - google.protobuf.UInt64Value builder_boost_factor = 5; + // Percentage multiplier to apply to the builder's payload value when choosing + // between a builder payload header and payload from the paired execution node + google.protobuf.UInt64Value builder_boost_factor = 5; } message ProposeResponse { - // The block root of the successfully proposed beacon block. - bytes block_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + // The block root of the successfully proposed beacon block. + bytes block_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message ProposeExitResponse { - // The root of the successfully proposed voluntary exit. - bytes exit_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + // The root of the successfully proposed voluntary exit. + bytes exit_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message AttestationDataRequest { - // Slot for which the attestation should be created. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; + // Slot for which the attestation should be created. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; - // Committee index the attestation should be created for. - uint64 committee_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; + // Committee index the attestation should be created for. + uint64 committee_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.CommitteeIndex" ]; } message AttestResponse { - // The root of the attestation data successfully submitted to the beacon node. - bytes attestation_data_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + // The root of the attestation data successfully submitted to the beacon node. + bytes attestation_data_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message AggregateSelectionRequest { - // Slot for which the aggregation request applies. - uint64 slot = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - // Committee index of the validator at the given slot. - uint64 committee_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; - // 48 byte public key of the validator. - bytes public_key = 3 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; - // 96 byte signature of the validator on the slot. This is used as proof that the validator is - // an aggregator for the given slot. - bytes slot_signature = 4 [(ethereum.eth.ext.ssz_size) = "96"]; + // Slot for which the aggregation request applies. + uint64 slot = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + // Committee index of the validator at the given slot. + uint64 committee_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.CommitteeIndex" ]; + // 48 byte public key of the validator. + bytes public_key = 3 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; + // 96 byte signature of the validator on the slot. This is used as proof that + // the validator is an aggregator for the given slot. + bytes slot_signature = 4 [ (ethereum.eth.ext.ssz_size) = "96" ]; } message AggregateSelectionResponse { - // The aggregate and proof message without the signature. - AggregateAttestationAndProof aggregate_and_proof = 1; + // The aggregate and proof message without the signature. + AggregateAttestationAndProof aggregate_and_proof = 1; } message AggregateSelectionElectraResponse { - // The aggregate and proof message without the signature. - AggregateAttestationAndProofElectra aggregate_and_proof = 1; + // The aggregate and proof message without the signature. + AggregateAttestationAndProofElectra aggregate_and_proof = 1; } message SignedAggregateSubmitRequest { - // The signed aggregate and proof message with the signature. - SignedAggregateAttestationAndProof signed_aggregate_and_proof = 1; + // The signed aggregate and proof message with the signature. + SignedAggregateAttestationAndProof signed_aggregate_and_proof = 1; } message SignedAggregateSubmitElectraRequest { - // The signed aggregate and proof message with the signature. - SignedAggregateAttestationAndProofElectra signed_aggregate_and_proof = 1; + // The signed aggregate and proof message with the signature. + SignedAggregateAttestationAndProofElectra signed_aggregate_and_proof = 1; } message SignedAggregateSubmitResponse { - // The 32 byte hash tree root of the aggregated attestation data. - bytes attestation_data_root = 1 [(ethereum.eth.ext.ssz_size) = "32"]; + // The 32 byte hash tree root of the aggregated attestation data. + bytes attestation_data_root = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message CommitteeSubnetsSubscribeRequest { - // A list of intended slots to subscribe. - repeated uint64 slots = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - // A list of intended committee ids to subscribe. It is mapped 1-to-1 with the slots - repeated uint64 committee_ids = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.CommitteeIndex"]; - // Whether to subscribe as an aggregator or by default attester. - // It is mapped 1-to-1 with the slots and committee ids. - // Subscribe as an aggregator means to join the subnet. - // Subscribe as an attester means finding persistent peers on the subnet to be able to publish attestations. - repeated bool is_aggregator = 3; + // A list of intended slots to subscribe. + repeated uint64 slots = 1 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + // A list of intended committee ids to subscribe. It is mapped 1-to-1 with the + // slots + repeated uint64 committee_ids = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.CommitteeIndex" ]; + // Whether to subscribe as an aggregator or by default attester. + // It is mapped 1-to-1 with the slots and committee ids. + // Subscribe as an aggregator means to join the subnet. + // Subscribe as an attester means finding persistent peers on the subnet to be + // able to publish attestations. + repeated bool is_aggregator = 3; } // An Ethereum validator. message Validator { - // 48 byte BLS public key used for the validator's activities. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; - - // 32 byte hash of the withdrawal destination public key. - bytes withdrawal_credentials = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - - // The validators current effective balance in gwei. - uint64 effective_balance = 3; - - // Whether or not the validator has been slashed. - bool slashed = 4; - - // Epoch when the validator became eligible for activation. This field may - // be zero if the validator was present in the Ethereum proof of stake genesis. This - // field is FAR_FUTURE_EPOCH if the validator has not been activated. - uint64 activation_eligibility_epoch = 5 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Epoch when the validator was activated. This field may be zero if the - // validator was present in the Ethereum proof of stake genesis. This field is - // FAR_FUTURE_EPOCH if the validator has not been activated. - uint64 activation_epoch = 6 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Epoch when the validator was exited. This field is FAR_FUTURE_EPOCH if - // the validator has not exited. - // FAR_FUTURE_EPOCH is a constant defined by the official Ethereum Beacon Chain specification: - // https://github.com/ethereum/consensus-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#constants - uint64 exit_epoch = 7 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // Epoch when the validator is eligible to withdraw their funds. This field - // is FAR_FUTURE_EPOCH if the validator has not exited. - // FAR_FUTURE_EPOCH is a constant defined by the official Ethereum Beacon Chain specification: - // https://github.com/ethereum/consensus-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#constants - uint64 withdrawable_epoch = 8 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; + // 48 byte BLS public key used for the validator's activities. + bytes public_key = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; + + // 32 byte hash of the withdrawal destination public key. + bytes withdrawal_credentials = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + + // The validators current effective balance in gwei. + uint64 effective_balance = 3; + + // Whether or not the validator has been slashed. + bool slashed = 4; + + // Epoch when the validator became eligible for activation. This field may + // be zero if the validator was present in the Ethereum proof of stake + // genesis. This field is FAR_FUTURE_EPOCH if the validator has not been + // activated. + uint64 activation_eligibility_epoch = 5 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Epoch when the validator was activated. This field may be zero if the + // validator was present in the Ethereum proof of stake genesis. This field is + // FAR_FUTURE_EPOCH if the validator has not been activated. + uint64 activation_epoch = 6 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Epoch when the validator was exited. This field is FAR_FUTURE_EPOCH if + // the validator has not exited. + // FAR_FUTURE_EPOCH is a constant defined by the official Ethereum Beacon + // Chain specification: + // https://github.com/ethereum/consensus-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#constants + uint64 exit_epoch = 7 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // Epoch when the validator is eligible to withdraw their funds. This field + // is FAR_FUTURE_EPOCH if the validator has not exited. + // FAR_FUTURE_EPOCH is a constant defined by the official Ethereum Beacon + // Chain specification: + // https://github.com/ethereum/consensus-specs/blob/v0.9.2/specs/core/0_beacon-chain.md#constants + uint64 withdrawable_epoch = 8 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; } // ValidatorParticipation stores participation metrics during a given epoch. message ValidatorParticipation { - // Percentage of validator participation in the given epoch. This field - // contains a value between 0 and 1. - float global_participation_rate = 1 [deprecated = true]; - // The total amount of ether, in gwei, that has been used in voting. - uint64 voted_ether = 2 [deprecated = true]; - // The total amount of ether, in gwei, that is eligible for voting. - uint64 eligible_ether = 3 [deprecated = true]; - // Total staked gwei that was active (i.e. eligible to vote) during the current epoch. - uint64 current_epoch_active_gwei = 4; - // Total staked gwei that had attestations included in a block during the current epoch, - // attestations by the same validator do not increase this figure. - uint64 current_epoch_attesting_gwei = 5; - // Total staked gwei that attested to the majority-elected Casper FFG target epoch during the current epoch. - uint64 current_epoch_target_attesting_gwei = 6; - // Same as current_epoch_active_gwei but for previous epoch. - uint64 previous_epoch_active_gwei = 7; - // Same as current_epoch_attesting_gwei but for previous epoch. - uint64 previous_epoch_attesting_gwei = 8; - // Same as current_epoch_target_attesting_gwei but for previous epoch. - uint64 previous_epoch_target_attesting_gwei = 9; - // Total staked gwei that attested to a head beacon block that is in the canonical chain. - uint64 previous_epoch_head_attesting_gwei = 10; -} - -// ValidatorInfo gives information about the state of a validator at a certain epoch. + // Percentage of validator participation in the given epoch. This field + // contains a value between 0 and 1. + float global_participation_rate = 1 [ deprecated = true ]; + // The total amount of ether, in gwei, that has been used in voting. + uint64 voted_ether = 2 [ deprecated = true ]; + // The total amount of ether, in gwei, that is eligible for voting. + uint64 eligible_ether = 3 [ deprecated = true ]; + // Total staked gwei that was active (i.e. eligible to vote) during the + // current epoch. + uint64 current_epoch_active_gwei = 4; + // Total staked gwei that had attestations included in a block during the + // current epoch, attestations by the same validator do not increase this + // figure. + uint64 current_epoch_attesting_gwei = 5; + // Total staked gwei that attested to the majority-elected Casper FFG target + // epoch during the current epoch. + uint64 current_epoch_target_attesting_gwei = 6; + // Same as current_epoch_active_gwei but for previous epoch. + uint64 previous_epoch_active_gwei = 7; + // Same as current_epoch_attesting_gwei but for previous epoch. + uint64 previous_epoch_attesting_gwei = 8; + // Same as current_epoch_target_attesting_gwei but for previous epoch. + uint64 previous_epoch_target_attesting_gwei = 9; + // Total staked gwei that attested to a head beacon block that is in the + // canonical chain. + uint64 previous_epoch_head_attesting_gwei = 10; +} + +// ValidatorInfo gives information about the state of a validator at a certain +// epoch. message ValidatorInfo { - // The validator's 48 byte BLS public key. - bytes public_key = 1; - - // The validator's index in the beacon state. - uint64 index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // The epoch for which the information pertains. - uint64 epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - - // The validator's current status. - ValidatorStatus status = 4; - - // The unix timestamp when the validator enters the next state. - // This could be in the past. Some values depend on chain operation and so will vary from epoch to epoch. - // Specific times for each state are as follows: - // - state == DEPOSITED: time at which Ethereum 1 deposit will be stored on-chain by Ethereum (variable, can be 0). - // - state == PENDING: time at which validator will be activated (variable). - // - state == ACTIVE: no value (next transition depends on user and network actions). - // - state == EXITING: time at which validator will exit. - // - state == SLASHING: time at which validator will exit. - // - state == EXITED: time at which validator funds will be withdrawable. - uint64 transition_timestamp = 5; - - // The validator's current balance in GWei. - uint64 balance = 6; - - // The validator's current effective balance in GWei. - // Only valid for states ACTIVE, EXITING, SLASHING. - uint64 effective_balance = 7; -} - -// DoppelGangerRequest represents the request sent by the validator in order to determine -// if there is any duplicate instance of it running in the network. + // The validator's 48 byte BLS public key. + bytes public_key = 1; + + // The validator's index in the beacon state. + uint64 index = 2 [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // The epoch for which the information pertains. + uint64 epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + + // The validator's current status. + ValidatorStatus status = 4; + + // The unix timestamp when the validator enters the next state. + // This could be in the past. Some values depend on chain operation and so + // will vary from epoch to epoch. Specific times for each state are as + // follows: + // - state == DEPOSITED: time at which Ethereum 1 deposit will be stored + // on-chain by Ethereum (variable, can be 0). + // - state == PENDING: time at which validator will be activated (variable). + // - state == ACTIVE: no value (next transition depends on user and network + // actions). + // - state == EXITING: time at which validator will exit. + // - state == SLASHING: time at which validator will exit. + // - state == EXITED: time at which validator funds will be withdrawable. + uint64 transition_timestamp = 5; + + // The validator's current balance in GWei. + uint64 balance = 6; + + // The validator's current effective balance in GWei. + // Only valid for states ACTIVE, EXITING, SLASHING. + uint64 effective_balance = 7; +} + +// DoppelGangerRequest represents the request sent by the validator in order to +// determine if there is any duplicate instance of it running in the network. message DoppelGangerRequest { - repeated ValidatorRequest validator_requests = 1; + repeated ValidatorRequest validator_requests = 1; - // ValidatorRequest data type which represents a request for each validator. - message ValidatorRequest { - // The validator's 48 byte BLS public key. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; - // The validator's last recorded epoch to attest. - uint64 epoch = 3 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch"]; - // The validator's last recorded signed root. - bytes signed_root = 2 [(ethereum.eth.ext.ssz_size) = "32"]; - } + // ValidatorRequest data type which represents a request for each validator. + message ValidatorRequest { + // The validator's 48 byte BLS public key. + bytes public_key = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; + // The validator's last recorded epoch to attest. + uint64 epoch = 3 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Epoch" + ]; + // The validator's last recorded signed root. + bytes signed_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; + } } // DoppelGangerResponse is the response payload sent by the beacon node // after it has checked for all duplicate keys in the network. message DoppelGangerResponse { - message ValidatorResponse { - // The validator's 48 byte BLS public key. - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; - // Whether a duplicate of the validator exists. - bool duplicate_exists = 2; - } - repeated ValidatorResponse responses = 1; -} - -// Request to only return slots with blocks that where verified by the beacon node. -// DEPRECATED: This endpoint StreamSlots is superseded by the /eth/v1/events Beacon API endpoint. + message ValidatorResponse { + // The validator's 48 byte BLS public key. + bytes public_key = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; + // Whether a duplicate of the validator exists. + bool duplicate_exists = 2; + } + repeated ValidatorResponse responses = 1; +} + +// Request to only return slots with blocks that where verified by the beacon +// node. DEPRECATED: This endpoint StreamSlots is superseded by the +// /eth/v1/events Beacon API endpoint. message StreamSlotsRequest { - option deprecated = true; - bool verified_only = 1; + option deprecated = true; + bool verified_only = 1; } // Request to only return blocks that is verified by the beacon node. -// DEPRECATED: This endpoint StreamBlocks is superseded by the /eth/v1/events Beacon API endpoint +// DEPRECATED: This endpoint StreamBlocks is superseded by the /eth/v1/events +// Beacon API endpoint message StreamBlocksRequest { - option deprecated = true; - bool verified_only = 1; + option deprecated = true; + bool verified_only = 1; } message PrepareBeaconProposerRequest { - message FeeRecipientContainer { - // The address of the fee recipient. - bytes fee_recipient = 1 [(ethereum.eth.ext.ssz_size) = "20"]; + message FeeRecipientContainer { + // The address of the fee recipient. + bytes fee_recipient = 1 [ (ethereum.eth.ext.ssz_size) = "20" ]; - // The proposer validator index. - uint64 validator_index = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - } - repeated FeeRecipientContainer recipients = 1; + // The proposer validator index. + uint64 validator_index = 2 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + } + repeated FeeRecipientContainer recipients = 1; } message FeeRecipientByPubKeyRequest { - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; + bytes public_key = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; } message FeeRecipientByPubKeyResponse { - bytes fee_recipient = 1 [(ethereum.eth.ext.ssz_size) = "20"]; + bytes fee_recipient = 1 [ (ethereum.eth.ext.ssz_size) = "20" ]; } message AssignValidatorToSubnetRequest { - bytes public_key = 1 [(ethereum.eth.ext.ssz_size) = "48", (ethereum.eth.ext.spec_name) = "pubkey"]; - ValidatorStatus status = 2; + bytes public_key = 1 [ + (ethereum.eth.ext.ssz_size) = "48", + (ethereum.eth.ext.spec_name) = "pubkey" + ]; + ValidatorStatus status = 2; } message AggregatedSigAndAggregationBitsRequest { - repeated SyncCommitteeMessage msgs = 1; - uint64 slot = 2 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"]; - uint64 subnet_id = 3; - bytes block_root = 4 [(ethereum.eth.ext.ssz_size) = "32"]; + repeated SyncCommitteeMessage msgs = 1; + uint64 slot = 2 [ + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot" + ]; + uint64 subnet_id = 3; + bytes block_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; } message AggregatedSigAndAggregationBitsResponse { - bytes aggregated_sig = 1; - bytes bits = 2; + bytes aggregated_sig = 1; + bytes bits = 2; } diff --git a/proto/prysm/v1alpha1/withdrawals.pb.go b/proto/prysm/v1alpha1/withdrawals.pb.go index 9a63cea1dfa4..3e9171a06a68 100755 --- a/proto/prysm/v1alpha1/withdrawals.pb.go +++ b/proto/prysm/v1alpha1/withdrawals.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/prysm/v1alpha1/withdrawals.proto package eth @@ -23,18 +23,17 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -type BLSToExecutionChange struct { +type SignedBLSToExecutionChange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ValidatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` - FromBlsPubkey []byte `protobuf:"bytes,2,opt,name=from_bls_pubkey,json=fromBlsPubkey,proto3" json:"from_bls_pubkey,omitempty" ssz-size:"48"` - ToExecutionAddress []byte `protobuf:"bytes,3,opt,name=to_execution_address,json=toExecutionAddress,proto3" json:"to_execution_address,omitempty" ssz-size:"20"` + Message *BLSToExecutionChange `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` } -func (x *BLSToExecutionChange) Reset() { - *x = BLSToExecutionChange{} +func (x *SignedBLSToExecutionChange) Reset() { + *x = SignedBLSToExecutionChange{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_withdrawals_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -42,13 +41,13 @@ func (x *BLSToExecutionChange) Reset() { } } -func (x *BLSToExecutionChange) String() string { +func (x *SignedBLSToExecutionChange) String() string { return protoimpl.X.MessageStringOf(x) } -func (*BLSToExecutionChange) ProtoMessage() {} +func (*SignedBLSToExecutionChange) ProtoMessage() {} -func (x *BLSToExecutionChange) ProtoReflect() protoreflect.Message { +func (x *SignedBLSToExecutionChange) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_withdrawals_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -60,43 +59,37 @@ func (x *BLSToExecutionChange) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use BLSToExecutionChange.ProtoReflect.Descriptor instead. -func (*BLSToExecutionChange) Descriptor() ([]byte, []int) { +// Deprecated: Use SignedBLSToExecutionChange.ProtoReflect.Descriptor instead. +func (*SignedBLSToExecutionChange) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_withdrawals_proto_rawDescGZIP(), []int{0} } -func (x *BLSToExecutionChange) GetValidatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { - if x != nil { - return x.ValidatorIndex - } - return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) -} - -func (x *BLSToExecutionChange) GetFromBlsPubkey() []byte { +func (x *SignedBLSToExecutionChange) GetMessage() *BLSToExecutionChange { if x != nil { - return x.FromBlsPubkey + return x.Message } return nil } -func (x *BLSToExecutionChange) GetToExecutionAddress() []byte { +func (x *SignedBLSToExecutionChange) GetSignature() []byte { if x != nil { - return x.ToExecutionAddress + return x.Signature } return nil } -type SignedBLSToExecutionChange struct { +type BLSToExecutionChange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Message *BLSToExecutionChange `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"` + ValidatorIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,1,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"` + FromBlsPubkey []byte `protobuf:"bytes,2,opt,name=from_bls_pubkey,json=fromBlsPubkey,proto3" json:"from_bls_pubkey,omitempty" ssz-size:"48"` + ToExecutionAddress []byte `protobuf:"bytes,3,opt,name=to_execution_address,json=toExecutionAddress,proto3" json:"to_execution_address,omitempty" ssz-size:"20"` } -func (x *SignedBLSToExecutionChange) Reset() { - *x = SignedBLSToExecutionChange{} +func (x *BLSToExecutionChange) Reset() { + *x = BLSToExecutionChange{} if protoimpl.UnsafeEnabled { mi := &file_proto_prysm_v1alpha1_withdrawals_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -104,13 +97,13 @@ func (x *SignedBLSToExecutionChange) Reset() { } } -func (x *SignedBLSToExecutionChange) String() string { +func (x *BLSToExecutionChange) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SignedBLSToExecutionChange) ProtoMessage() {} +func (*BLSToExecutionChange) ProtoMessage() {} -func (x *SignedBLSToExecutionChange) ProtoReflect() protoreflect.Message { +func (x *BLSToExecutionChange) ProtoReflect() protoreflect.Message { mi := &file_proto_prysm_v1alpha1_withdrawals_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -122,21 +115,28 @@ func (x *SignedBLSToExecutionChange) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SignedBLSToExecutionChange.ProtoReflect.Descriptor instead. -func (*SignedBLSToExecutionChange) Descriptor() ([]byte, []int) { +// Deprecated: Use BLSToExecutionChange.ProtoReflect.Descriptor instead. +func (*BLSToExecutionChange) Descriptor() ([]byte, []int) { return file_proto_prysm_v1alpha1_withdrawals_proto_rawDescGZIP(), []int{1} } -func (x *SignedBLSToExecutionChange) GetMessage() *BLSToExecutionChange { +func (x *BLSToExecutionChange) GetValidatorIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex { if x != nil { - return x.Message + return x.ValidatorIndex + } + return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0) +} + +func (x *BLSToExecutionChange) GetFromBlsPubkey() []byte { + if x != nil { + return x.FromBlsPubkey } return nil } -func (x *SignedBLSToExecutionChange) GetSignature() []byte { +func (x *BLSToExecutionChange) GetToExecutionAddress() []byte { if x != nil { - return x.Signature + return x.ToExecutionAddress } return nil } @@ -149,32 +149,32 @@ var file_proto_prysm_v1alpha1_withdrawals_proto_rawDesc = []byte{ 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfa, 0x01, 0x0a, - 0x14, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, - 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, - 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, - 0x0e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, - 0x2e, 0x0a, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x62, 0x6c, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, - 0x52, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x42, 0x6c, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, - 0x38, 0x0a, 0x14, 0x74, 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, - 0xb5, 0x18, 0x02, 0x32, 0x30, 0x52, 0x12, 0x74, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x1a, 0x53, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x89, 0x01, 0x0a, + 0x1a, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, + 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x4c, 0x53, 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xfa, 0x01, 0x0a, 0x14, 0x42, 0x4c, 0x53, + 0x54, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x12, 0x78, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, + 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, + 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0e, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2e, 0x0a, 0x0f, 0x66, + 0x72, 0x6f, 0x6d, 0x5f, 0x62, 0x6c, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x34, 0x38, 0x52, 0x0d, 0x66, 0x72, + 0x6f, 0x6d, 0x42, 0x6c, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x14, 0x74, + 0x6f, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, + 0x30, 0x52, 0x12, 0x74, 0x6f, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x9b, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, @@ -201,11 +201,11 @@ func file_proto_prysm_v1alpha1_withdrawals_proto_rawDescGZIP() []byte { var file_proto_prysm_v1alpha1_withdrawals_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_proto_prysm_v1alpha1_withdrawals_proto_goTypes = []interface{}{ - (*BLSToExecutionChange)(nil), // 0: ethereum.eth.v1alpha1.BLSToExecutionChange - (*SignedBLSToExecutionChange)(nil), // 1: ethereum.eth.v1alpha1.SignedBLSToExecutionChange + (*SignedBLSToExecutionChange)(nil), // 0: ethereum.eth.v1alpha1.SignedBLSToExecutionChange + (*BLSToExecutionChange)(nil), // 1: ethereum.eth.v1alpha1.BLSToExecutionChange } var file_proto_prysm_v1alpha1_withdrawals_proto_depIdxs = []int32{ - 0, // 0: ethereum.eth.v1alpha1.SignedBLSToExecutionChange.message:type_name -> ethereum.eth.v1alpha1.BLSToExecutionChange + 1, // 0: ethereum.eth.v1alpha1.SignedBLSToExecutionChange.message:type_name -> ethereum.eth.v1alpha1.BLSToExecutionChange 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name @@ -220,7 +220,7 @@ func file_proto_prysm_v1alpha1_withdrawals_proto_init() { } if !protoimpl.UnsafeEnabled { file_proto_prysm_v1alpha1_withdrawals_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BLSToExecutionChange); i { + switch v := v.(*SignedBLSToExecutionChange); i { case 0: return &v.state case 1: @@ -232,7 +232,7 @@ func file_proto_prysm_v1alpha1_withdrawals_proto_init() { } } file_proto_prysm_v1alpha1_withdrawals_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SignedBLSToExecutionChange); i { + switch v := v.(*BLSToExecutionChange); i { case 0: return &v.state case 1: diff --git a/proto/prysm/v1alpha1/withdrawals.pb.gw.go b/proto/prysm/v1alpha1/withdrawals.pb.gw.go deleted file mode 100755 index cdd03643f0c7..000000000000 --- a/proto/prysm/v1alpha1/withdrawals.pb.gw.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package ignore diff --git a/proto/prysm/v1alpha1/withdrawals.proto b/proto/prysm/v1alpha1/withdrawals.proto index 517f6f050acd..5cc96e71bf13 100644 --- a/proto/prysm/v1alpha1/withdrawals.proto +++ b/proto/prysm/v1alpha1/withdrawals.proto @@ -24,25 +24,26 @@ option java_outer_classname = "WithdrawalsProto"; option java_package = "org.ethereum.eth.v1alpha1"; option php_namespace = "Ethereum\\Eth\\v1alpha1"; -// The message requesting a BLS to execution withdrawal credentials change -message BLSToExecutionChange { - // The validator index requesting the change - uint64 validator_index = 1 [(ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"]; - - // The public key of the BLS address requesting the change - bytes from_bls_pubkey = 2 [(ethereum.eth.ext.ssz_size) = "48"]; - - // The new execution address to be the withdrawal credentials - bytes to_execution_address = 3 [(ethereum.eth.ext.ssz_size) = "20"]; -} - // The signed version of a BLSToExecutionChange message SignedBLSToExecutionChange { - // The BLSToExecutionChange message itself - BLSToExecutionChange message = 1; + // The BLSToExecutionChange message itself + BLSToExecutionChange message = 1; - // The 96 byte BLS signature from the withdrawal address requesting the change - bytes signature = 2 [(ethereum.eth.ext.ssz_size) = "96"]; + // The 96 byte BLS signature from the withdrawal address requesting the change + bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; } - +// The message requesting a BLS to execution withdrawal credentials change +message BLSToExecutionChange { + // The validator index requesting the change + uint64 validator_index = 1 + [ (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/prysm/v5/consensus-types/" + "primitives.ValidatorIndex" ]; + + // The public key of the BLS address requesting the change + bytes from_bls_pubkey = 2 [ (ethereum.eth.ext.ssz_size) = "48" ]; + + // The new execution address to be the withdrawal credentials + bytes to_execution_address = 3 [ (ethereum.eth.ext.ssz_size) = "20" ]; +} diff --git a/proto/ssz_proto_library.bzl b/proto/ssz_proto_library.bzl index 982be54cc022..868c727a3fa1 100644 --- a/proto/ssz_proto_library.bzl +++ b/proto/ssz_proto_library.bzl @@ -26,16 +26,21 @@ mainnet = { "max_blobs_per_block.size": "6", "max_blob_commitments.size": "4096", "kzg_commitment_inclusion_proof_depth.size": "17", - "max_withdrawal_requests_per_payload.size":"16", + "max_withdrawal_requests_per_payload.size": "16", "max_deposit_requests_per_payload.size": "8192", "max_attesting_indices.size": "131072", "max_committees_per_slot.size": "64", "committee_bits.size": "8", "committee_bits.type": "github.com/prysmaticlabs/go-bitfield.Bitvector64", - "pending_balance_deposits_limit": "134217728", + "pending_deposits_limit": "134217728", "pending_partial_withdrawals_limit": "134217728", "pending_consolidations_limit": "262144", - "max_consolidation_requests_per_payload.size": "1", + "max_consolidation_requests_per_payload.size": "2", + "field_elements_per_cell.size": "64", + "field_elements_per_ext_blob.size": "8192", + "bytes_per_cell.size": "2048", # FIELD_ELEMENTS_PER_CELL * BYTES_PER_FIELD_ELEMENT + "cells_per_blob.size": "128", + "kzg_commitments_inclusion_proof_depth.size": "4", } minimal = { @@ -56,18 +61,23 @@ minimal = { "logs_bloom.size": "256", "extra_data.size": "32", "max_blobs_per_block.size": "6", - "max_blob_commitments.size": "16", - "kzg_commitment_inclusion_proof_depth.size": "9", - "max_withdrawal_requests_per_payload.size":"2", + "max_blob_commitments.size": "32", + "kzg_commitment_inclusion_proof_depth.size": "10", + "max_withdrawal_requests_per_payload.size": "2", "max_deposit_requests_per_payload.size": "4", "max_attesting_indices.size": "8192", "max_committees_per_slot.size": "4", "committee_bits.size": "1", "committee_bits.type": "github.com/prysmaticlabs/go-bitfield.Bitvector4", - "pending_balance_deposits_limit": "134217728", + "pending_deposits_limit": "134217728", "pending_partial_withdrawals_limit": "64", "pending_consolidations_limit": "64", - "max_consolidation_requests_per_payload.size": "1", + "max_consolidation_requests_per_payload.size": "2", + "field_elements_per_cell.size": "64", + "field_elements_per_ext_blob.size": "8192", + "bytes_per_cell.size": "2048", # FIELD_ELEMENTS_PER_CELL * BYTES_PER_FIELD_ELEMENT + "cells_per_blob.size": "128", + "kzg_commitments_inclusion_proof_depth.size": "4", } ###### Rules definitions ####### diff --git a/proto/testing/test.pb.go b/proto/testing/test.pb.go index 6d3e0aa6a9c7..b5891dc142d4 100755 --- a/proto/testing/test.pb.go +++ b/proto/testing/test.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.25.1 +// protoc-gen-go v1.33.0 +// protoc v3.21.7 // source: proto/testing/test.proto package testing diff --git a/proto/testing/test.proto b/proto/testing/test.proto index b5ea00d01968..6f65823f76fe 100644 --- a/proto/testing/test.proto +++ b/proto/testing/test.proto @@ -12,7 +12,7 @@ extend google.protobuf.FieldOptions { message TestMessage { string foo = 1; - string bar = 2 [(ssz_size) = "32", (spec_name) = "foo"]; + string bar = 2 [ (ssz_size) = "32", (spec_name) = "foo" ]; } message TestNestedMessage { @@ -46,9 +46,7 @@ message Person { } // Our address book file is just one of these. -message AddressBook { - repeated Person people = 1; -} +message AddressBook { repeated Person people = 1; } message TestSimpleMessage { bytes foo = 1; diff --git a/runtime/debug/BUILD.bazel b/runtime/debug/BUILD.bazel index db34de5e7ed2..bd3d7bdcedc6 100644 --- a/runtime/debug/BUILD.bazel +++ b/runtime/debug/BUILD.bazel @@ -18,7 +18,6 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/runtime/debug", visibility = ["//visibility:public"], deps = [ - "@com_github_fjl_memsize//memsizeui:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", diff --git a/runtime/debug/debug.go b/runtime/debug/debug.go index ab79ec4bece8..45c6994c5e02 100644 --- a/runtime/debug/debug.go +++ b/runtime/debug/debug.go @@ -37,7 +37,6 @@ import ( "sync" "time" - "github.com/fjl/memsize/memsizeui" log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" ) @@ -45,8 +44,6 @@ import ( // Handler is the global debugging handler. var Handler = new(HandlerT) -// Memsize is the memsizeui Handler(?). -var Memsize memsizeui.Handler var ( // PProfFlag to enable pprof HTTP server. PProfFlag = &cli.BoolFlag{ @@ -351,7 +348,6 @@ func Setup(ctx *cli.Context) error { } func startPProf(address string) { - http.Handle("/memsize/", http.StripPrefix("/memsize", &Memsize)) log.WithField("addr", fmt.Sprintf("http://%s/debug/pprof", address)).Info("Starting pprof server") go func() { srv := &http.Server{ diff --git a/runtime/interop/BUILD.bazel b/runtime/interop/BUILD.bazel index e82eda2dd5ea..50cffc8cc2e0 100644 --- a/runtime/interop/BUILD.bazel +++ b/runtime/interop/BUILD.bazel @@ -24,7 +24,6 @@ go_library( "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", - "//consensus-types/interfaces:go_default_library", "//container/trie:go_default_library", "//crypto/bls:go_default_library", "//crypto/hash:go_default_library", @@ -49,6 +48,7 @@ go_test( "generate_genesis_state_bellatrix_test.go", "generate_genesis_state_test.go", "generate_keys_test.go", + "premine-state_test.go", ], data = [ "keygen_test_vector.yaml", @@ -61,9 +61,12 @@ go_test( "//container/trie:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", + "//time:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", + "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_go_yaml_yaml//:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", ], diff --git a/runtime/interop/genesis.go b/runtime/interop/genesis.go index df2dc0ad5a33..61c2531fd4ad 100644 --- a/runtime/interop/genesis.go +++ b/runtime/interop/genesis.go @@ -1,13 +1,13 @@ package interop import ( - "fmt" "math" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" clparams "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/time/slots" @@ -126,57 +126,64 @@ func GethPragueTime(genesisTime uint64, cfg *clparams.BeaconChainConfig) *uint64 // like in an e2e test. The parameters are minimal but the full value is returned unmarshaled so that it can be // customized as desired. func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) *core.Genesis { - ttd, ok := big.NewInt(0).SetString(clparams.BeaconConfig().TerminalTotalDifficulty, 10) - if !ok { - panic(fmt.Sprintf("unable to parse TerminalTotalDifficulty as an integer = %s", clparams.BeaconConfig().TerminalTotalDifficulty)) - } - shanghaiTime := GethShanghaiTime(genesisTime, cfg) + if cfg.CapellaForkEpoch == 0 { + shanghaiTime = &genesisTime + } cancunTime := GethCancunTime(genesisTime, cfg) + if cfg.DenebForkEpoch == 0 { + cancunTime = &genesisTime + } pragueTime := GethPragueTime(genesisTime, cfg) + if cfg.ElectraForkEpoch == 0 { + pragueTime = &genesisTime + } cc := ¶ms.ChainConfig{ - ChainID: big.NewInt(defaultTestChainId), - HomesteadBlock: bigz, - DAOForkBlock: bigz, - EIP150Block: bigz, - EIP155Block: bigz, - EIP158Block: bigz, - ByzantiumBlock: bigz, - ConstantinopleBlock: bigz, - PetersburgBlock: bigz, - IstanbulBlock: bigz, - MuirGlacierBlock: bigz, - BerlinBlock: bigz, - LondonBlock: bigz, - ArrowGlacierBlock: bigz, - GrayGlacierBlock: bigz, - MergeNetsplitBlock: bigz, - TerminalTotalDifficulty: ttd, - TerminalTotalDifficultyPassed: false, - Clique: ¶ms.CliqueConfig{ - Period: cfg.SecondsPerETH1Block, - Epoch: 20000, + ChainID: big.NewInt(defaultTestChainId), + HomesteadBlock: bigz, + DAOForkBlock: bigz, + EIP150Block: bigz, + EIP155Block: bigz, + EIP158Block: bigz, + ByzantiumBlock: bigz, + ConstantinopleBlock: bigz, + PetersburgBlock: bigz, + IstanbulBlock: bigz, + MuirGlacierBlock: bigz, + BerlinBlock: bigz, + LondonBlock: bigz, + ArrowGlacierBlock: bigz, + GrayGlacierBlock: bigz, + MergeNetsplitBlock: bigz, + TerminalTotalDifficulty: bigz, + ShanghaiTime: shanghaiTime, + CancunTime: cancunTime, + PragueTime: pragueTime, + DepositContractAddress: common.HexToAddress(cfg.DepositContractAddress), + BlobScheduleConfig: ¶ms.BlobScheduleConfig{ + Cancun: ¶ms.BlobConfig{ + Target: 3, + Max: 6, + UpdateFraction: 3338477, + }, + Prague: ¶ms.BlobConfig{ + Target: 6, + Max: 9, + UpdateFraction: 5007716, + }, }, - ShanghaiTime: shanghaiTime, - CancunTime: cancunTime, - PragueTime: pragueTime, } da := defaultDepositContractAllocation(cfg.DepositContractAddress) ma := minerAllocation() - extra, err := hexutil.Decode(DefaultCliqueSigner) - if err != nil { - panic(fmt.Sprintf("unable to decode DefaultCliqueSigner, with error %v", err.Error())) - } return &core.Genesis{ Config: cc, Nonce: 0, // overridden for authorized signer votes in clique, so we should leave it empty? Timestamp: genesisTime, - ExtraData: extra, - GasLimit: math.MaxUint64 >> 1, // shift 1 back from the max, just in case + GasLimit: cfg.DefaultBuilderGasLimit, Difficulty: common.HexToHash(defaultDifficulty).Big(), Mixhash: common.HexToHash(defaultMixhash), Coinbase: common.HexToAddress(defaultCoinbase), - Alloc: core.GenesisAlloc{ + Alloc: types.GenesisAlloc{ da.Address: da.Account, ma.Address: ma.Account, }, @@ -186,13 +193,13 @@ func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) *co type depositAllocation struct { Address common.Address - Account core.GenesisAccount + Account types.Account } func minerAllocation() depositAllocation { return depositAllocation{ Address: common.HexToAddress(defaultMinerAddress), - Account: core.GenesisAccount{ + Account: types.Account{ Balance: minerBalance, }, } @@ -209,7 +216,7 @@ func defaultDepositContractAllocation(contractAddress string) depositAllocation } return depositAllocation{ Address: common.HexToAddress(contractAddress), - Account: core.GenesisAccount{ + Account: types.Account{ Code: codeBytes, Storage: s, Balance: bigz, diff --git a/runtime/interop/premine-state.go b/runtime/interop/premine-state.go index 235f8a1968e3..58802b4966c6 100644 --- a/runtime/interop/premine-state.go +++ b/runtime/interop/premine-state.go @@ -13,7 +13,6 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/container/trie" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" @@ -66,7 +65,7 @@ func NewPreminedGenesis(ctx context.Context, t, nvals, pCreds uint64, version in func (s *PremineGenesisConfig) prepare(ctx context.Context) (state.BeaconState, error) { switch s.Version { - case version.Phase0, version.Altair, version.Bellatrix, version.Capella, version.Deneb, version.Electra: + case version.Phase0, version.Altair, version.Bellatrix, version.Capella, version.Deneb, version.Electra, version.Fulu: default: return nil, errors.Wrapf(errUnsupportedVersion, "version=%s", version.String(s.Version)) } @@ -155,6 +154,16 @@ func (s *PremineGenesisConfig) empty() (state.BeaconState, error) { if err != nil { return nil, err } + case version.Electra: + e, err = state_native.InitializeFromProtoElectra(ðpb.BeaconStateElectra{}) + if err != nil { + return nil, err + } + case version.Fulu: + e, err = state_native.InitializeFromProtoFulu(ðpb.BeaconStateElectra{}) + if err != nil { + return nil, err + } default: return nil, errUnsupportedVersion } @@ -336,6 +345,10 @@ func (s *PremineGenesisConfig) setFork(g state.BeaconState) error { pv, cv = params.BeaconConfig().BellatrixForkVersion, params.BeaconConfig().CapellaForkVersion case version.Deneb: pv, cv = params.BeaconConfig().CapellaForkVersion, params.BeaconConfig().DenebForkVersion + case version.Electra: + pv, cv = params.BeaconConfig().DenebForkVersion, params.BeaconConfig().ElectraForkVersion + case version.Fulu: + pv, cv = params.BeaconConfig().ElectraForkVersion, params.BeaconConfig().FuluForkVersion default: return errUnsupportedVersion } @@ -524,6 +537,72 @@ func (s *PremineGenesisConfig) setLatestBlockHeader(g state.BeaconState) error { BlsToExecutionChanges: make([]*ethpb.SignedBLSToExecutionChange, 0), BlobKzgCommitments: make([][]byte, 0), } + case version.Electra: + body = ðpb.BeaconBlockBodyElectra{ + RandaoReveal: make([]byte, 96), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, 32), + BlockHash: make([]byte, 32), + }, + Graffiti: make([]byte, 32), + SyncAggregate: ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + Transactions: make([][]byte, 0), + Withdrawals: make([]*enginev1.Withdrawal, 0), + }, + BlsToExecutionChanges: make([]*ethpb.SignedBLSToExecutionChange, 0), + BlobKzgCommitments: make([][]byte, 0), + ExecutionRequests: &enginev1.ExecutionRequests{ + Deposits: make([]*enginev1.DepositRequest, 0), + Withdrawals: make([]*enginev1.WithdrawalRequest, 0), + Consolidations: make([]*enginev1.ConsolidationRequest, 0), + }, + } + case version.Fulu: + body = ðpb.BeaconBlockBodyElectra{ + RandaoReveal: make([]byte, 96), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, 32), + BlockHash: make([]byte, 32), + }, + Graffiti: make([]byte, 32), + SyncAggregate: ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + Transactions: make([][]byte, 0), + Withdrawals: make([]*enginev1.Withdrawal, 0), + }, + BlsToExecutionChanges: make([]*ethpb.SignedBLSToExecutionChange, 0), + BlobKzgCommitments: make([][]byte, 0), + ExecutionRequests: &enginev1.ExecutionRequests{ + Deposits: make([]*enginev1.DepositRequest, 0), + Withdrawals: make([]*enginev1.WithdrawalRequest, 0), + Consolidations: make([]*enginev1.ConsolidationRequest, 0), + }, + } default: return errUnsupportedVersion } @@ -541,16 +620,14 @@ func (s *PremineGenesisConfig) setLatestBlockHeader(g state.BeaconState) error { } func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error { - if s.Version < version.Bellatrix { - return nil - } - gb := s.GB + extraData := gb.Extra() + if len(extraData) > 32 { + extraData = extraData[:32] + } - var ed interfaces.ExecutionData - switch s.Version { - case version.Bellatrix: - payload := &enginev1.ExecutionPayload{ + if s.Version >= version.Deneb { + payload := &enginev1.ExecutionPayloadDeneb{ ParentHash: gb.ParentHash().Bytes(), FeeRecipient: gb.Coinbase().Bytes(), StateRoot: gb.Root().Bytes(), @@ -561,24 +638,34 @@ func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error { GasLimit: gb.GasLimit(), GasUsed: gb.GasUsed(), Timestamp: gb.Time(), - ExtraData: gb.Extra()[:32], + ExtraData: extraData, BaseFeePerGas: bytesutil.PadTo(bytesutil.ReverseByteOrder(gb.BaseFee().Bytes()), fieldparams.RootLength), BlockHash: gb.Hash().Bytes(), Transactions: make([][]byte, 0), + Withdrawals: make([]*enginev1.Withdrawal, 0), + ExcessBlobGas: unwrapUint64Ptr(gb.ExcessBlobGas()), + BlobGasUsed: unwrapUint64Ptr(gb.BlobGasUsed()), } - wep, err := blocks.WrappedExecutionPayload(payload) + + wep, err := blocks.WrappedExecutionPayloadDeneb(payload) if err != nil { return err } - eph, err := blocks.PayloadToHeader(wep) + + eph, err := blocks.PayloadToHeaderDeneb(wep) if err != nil { return err } - ed, err = blocks.WrappedExecutionPayloadHeader(eph) + + ed, err := blocks.WrappedExecutionPayloadHeaderDeneb(eph) if err != nil { return err } - case version.Capella: + + return g.SetLatestExecutionPayloadHeader(ed) + } + + if s.Version >= version.Capella { payload := &enginev1.ExecutionPayloadCapella{ ParentHash: gb.ParentHash().Bytes(), FeeRecipient: gb.Coinbase().Bytes(), @@ -590,26 +677,32 @@ func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error { GasLimit: gb.GasLimit(), GasUsed: gb.GasUsed(), Timestamp: gb.Time(), - ExtraData: gb.Extra()[:32], + ExtraData: extraData, BaseFeePerGas: bytesutil.PadTo(bytesutil.ReverseByteOrder(gb.BaseFee().Bytes()), fieldparams.RootLength), BlockHash: gb.Hash().Bytes(), Transactions: make([][]byte, 0), Withdrawals: make([]*enginev1.Withdrawal, 0), } + wep, err := blocks.WrappedExecutionPayloadCapella(payload) if err != nil { return err } + eph, err := blocks.PayloadToHeaderCapella(wep) if err != nil { return err } - ed, err = blocks.WrappedExecutionPayloadHeaderCapella(eph) + ed, err := blocks.WrappedExecutionPayloadHeaderCapella(eph) if err != nil { return err } - case version.Deneb: - payload := &enginev1.ExecutionPayloadDeneb{ + + return g.SetLatestExecutionPayloadHeader(ed) + } + + if s.Version >= version.Bellatrix { + payload := &enginev1.ExecutionPayload{ ParentHash: gb.ParentHash().Bytes(), FeeRecipient: gb.Coinbase().Bytes(), StateRoot: gb.Root().Bytes(), @@ -620,30 +713,42 @@ func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error { GasLimit: gb.GasLimit(), GasUsed: gb.GasUsed(), Timestamp: gb.Time(), - ExtraData: gb.Extra()[:32], + ExtraData: extraData, BaseFeePerGas: bytesutil.PadTo(bytesutil.ReverseByteOrder(gb.BaseFee().Bytes()), fieldparams.RootLength), BlockHash: gb.Hash().Bytes(), Transactions: make([][]byte, 0), - Withdrawals: make([]*enginev1.Withdrawal, 0), - ExcessBlobGas: *gb.ExcessBlobGas(), - BlobGasUsed: *gb.BlobGasUsed(), } - wep, err := blocks.WrappedExecutionPayloadDeneb(payload) + + wep, err := blocks.WrappedExecutionPayload(payload) if err != nil { return err } - eph, err := blocks.PayloadToHeaderDeneb(wep) + + eph, err := blocks.PayloadToHeader(wep) if err != nil { return err } - ed, err = blocks.WrappedExecutionPayloadHeaderDeneb(eph) + + ed, err := blocks.WrappedExecutionPayloadHeader(eph) if err != nil { return err } - default: - return errUnsupportedVersion + + return g.SetLatestExecutionPayloadHeader(ed) + } + + if s.Version >= version.Phase0 { + return nil + } + + return errUnsupportedVersion +} + +func unwrapUint64Ptr(u *uint64) uint64 { + if u == nil { + return 0 } - return g.SetLatestExecutionPayloadHeader(ed) + return *u } func nZeroRoots(n uint64) [][]byte { diff --git a/runtime/interop/premine-state_test.go b/runtime/interop/premine-state_test.go new file mode 100644 index 000000000000..a296a1c196ae --- /dev/null +++ b/runtime/interop/premine-state_test.go @@ -0,0 +1,26 @@ +package interop + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/time" +) + +func TestPremineGenesis_Electra(t *testing.T) { + one := uint64(1) + + genesis := types.NewBlockWithHeader(&types.Header{ + Time: uint64(time.Now().Unix()), + Extra: make([]byte, 32), + BaseFee: big.NewInt(1), + ExcessBlobGas: &one, + BlobGasUsed: &one, + }) + _, err := NewPreminedGenesis(context.Background(), genesis.Time(), 10, 10, version.Electra, genesis) + require.NoError(t, err) +} diff --git a/runtime/logging/logrus-prefixed-formatter/BUILD.bazel b/runtime/logging/logrus-prefixed-formatter/BUILD.bazel index edd538441cb9..0056c5db1a76 100644 --- a/runtime/logging/logrus-prefixed-formatter/BUILD.bazel +++ b/runtime/logging/logrus-prefixed-formatter/BUILD.bazel @@ -14,15 +14,10 @@ go_library( go_test( name = "go_default_test", - srcs = [ - "formatter_test.go", - "logrus_prefixed_formatter_suite_test.go", - ], + srcs = ["formatter_test.go"], deps = [ ":go_default_library", "//testing/require:go_default_library", - "@com_github_onsi_ginkgo//:go_default_library", - "@com_github_onsi_gomega//:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", ], diff --git a/runtime/logging/logrus-prefixed-formatter/formatter_test.go b/runtime/logging/logrus-prefixed-formatter/formatter_test.go index 615ff5c6a5f9..dd3693bf9175 100644 --- a/runtime/logging/logrus-prefixed-formatter/formatter_test.go +++ b/runtime/logging/logrus-prefixed-formatter/formatter_test.go @@ -5,55 +5,76 @@ import ( "regexp" "testing" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" "github.com/pkg/errors" prefixed "github.com/prysmaticlabs/prysm/v5/runtime/logging/logrus-prefixed-formatter" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/sirupsen/logrus" ) -var _ = Describe("Formatter", func() { - var formatter *prefixed.TextFormatter - var log *logrus.Logger - var output *LogOutput +type LogOutput struct { + buffer string +} - BeforeEach(func() { - output = new(LogOutput) - formatter = new(prefixed.TextFormatter) - log = logrus.New() - log.Out = output - log.Formatter = formatter - log.Level = logrus.DebugLevel - }) +func (o *LogOutput) Write(p []byte) (int, error) { + o.buffer += string(p) + return len(p), nil +} - Describe("logfmt output", func() { - It("should output simple message", func() { - formatter.DisableTimestamp = true - log.Debug("test") - Ω(output.GetValue()).Should(Equal("level=debug msg=test\n")) - }) +func (o *LogOutput) GetValue() string { + return o.buffer +} - It("should output message with additional field", func() { - formatter.DisableTimestamp = true - log.WithFields(logrus.Fields{"animal": "walrus"}).Debug("test") - Ω(output.GetValue()).Should(Equal("level=debug msg=test animal=walrus\n")) - }) - }) +func TestFormatter_logfmt_output(t *testing.T) { + tests := []struct { + name string + callback func(l *logrus.Logger) + expected string + }{ + { + name: "should output simple message", + callback: func(l *logrus.Logger) { + l.Debug("test") + }, + expected: "level=debug msg=test\n", + }, + { + name: "should output message with additional field", + callback: func(l *logrus.Logger) { + l.WithFields(logrus.Fields{"animal": "walrus"}).Debug("test") + }, + expected: "level=debug msg=test animal=walrus\n", + }, + } - Describe("Formatted output", func() { - It("should output formatted message", func() { + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + output := new(LogOutput) + formatter := new(prefixed.TextFormatter) formatter.DisableTimestamp = true - formatter.ForceFormatting = true - log.Debug("test") - Ω(output.GetValue()).Should(Equal("DEBUG test\n")) + log := logrus.New() + log.Out = output + log.Formatter = formatter + log.Level = logrus.DebugLevel + + tt.callback(log) + require.Equal(t, output.GetValue(), tt.expected) }) - }) + } +} - Describe("Theming support", func() { +func TestFormatter_formatted_output(t *testing.T) { + output := new(LogOutput) + formatter := new(prefixed.TextFormatter) + formatter.DisableTimestamp = true + formatter.ForceFormatting = true + log := logrus.New() + log.Out = output + log.Formatter = formatter + log.Level = logrus.DebugLevel - }) -}) + log.Debug("test") + require.Equal(t, output.GetValue(), "DEBUG test\n") +} func TestFormatter_SuppressErrorStackTraces(t *testing.T) { formatter := new(prefixed.TextFormatter) diff --git a/runtime/logging/logrus-prefixed-formatter/logrus_prefixed_formatter_suite_test.go b/runtime/logging/logrus-prefixed-formatter/logrus_prefixed_formatter_suite_test.go deleted file mode 100644 index 78e9b2fbf756..000000000000 --- a/runtime/logging/logrus-prefixed-formatter/logrus_prefixed_formatter_suite_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package prefixed_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -type LogOutput struct { - buffer string -} - -func (o *LogOutput) Write(p []byte) (int, error) { - o.buffer += string(p) - return len(p), nil -} - -func (o *LogOutput) GetValue() string { - return o.buffer -} - -func TestLogrusPrefixedFormatter(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "LogrusPrefixedFormatter Suite") -} diff --git a/runtime/messagehandler/BUILD.bazel b/runtime/messagehandler/BUILD.bazel index d8edca3c50e7..1c5cbf4c227b 100644 --- a/runtime/messagehandler/BUILD.bazel +++ b/runtime/messagehandler/BUILD.bazel @@ -6,9 +6,10 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/runtime/messagehandler", visibility = ["//visibility:public"], deps = [ + "//monitoring/tracing/trace:go_default_library", "@com_github_libp2p_go_libp2p_pubsub//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@io_opentelemetry_go_otel//codes:go_default_library", ], ) diff --git a/runtime/messagehandler/messagehandler.go b/runtime/messagehandler/messagehandler.go index 6355bbe6106c..26d860c11cf5 100644 --- a/runtime/messagehandler/messagehandler.go +++ b/runtime/messagehandler/messagehandler.go @@ -8,8 +8,9 @@ import ( "runtime/debug" pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" + "go.opentelemetry.io/otel/codes" ) const noMsgData = "message contains no data" @@ -25,10 +26,7 @@ func SafelyHandleMessage(ctx context.Context, fn func(ctx context.Context, messa if err := fn(ctx, msg); err != nil { // Report any error on the span, if one exists. if span := trace.FromContext(ctx); span != nil { - span.SetStatus(trace.Status{ - Code: trace.StatusCodeInternal, - Message: err.Error(), - }) + span.SetStatus(codes.Error, err.Error()) } } } @@ -52,10 +50,7 @@ func HandlePanic(ctx context.Context, msg *pubsub.Message) { return } if span := trace.FromContext(ctx); span != nil { - span.SetStatus(trace.Status{ - Code: trace.StatusCodeInternal, - Message: fmt.Sprintf("Panic: %v", r), - }) + span.SetStatus(codes.Error, fmt.Sprintf("Panic: %v", r)) } } } diff --git a/runtime/service_registry.go b/runtime/service_registry.go index d5bbab034ff3..84fcba0a045f 100644 --- a/runtime/service_registry.go +++ b/runtime/service_registry.go @@ -40,7 +40,6 @@ func NewServiceRegistry() *ServiceRegistry { // StartAll initialized each service in order of registration. func (s *ServiceRegistry) StartAll() { - log.Debugf("Starting %d services: %v", len(s.serviceTypes), s.serviceTypes) for _, kind := range s.serviceTypes { log.Debugf("Starting service type %v", kind) go s.services[kind].Start() diff --git a/runtime/version/fork.go b/runtime/version/fork.go index 902393c8bc80..6f9cffe8faba 100644 --- a/runtime/version/fork.go +++ b/runtime/version/fork.go @@ -1,6 +1,8 @@ package version -import "github.com/pkg/errors" +import ( + "github.com/pkg/errors" +) const ( Phase0 = iota @@ -9,6 +11,7 @@ const ( Capella Deneb Electra + Fulu ) var versionToString = map[int]string{ @@ -18,6 +21,7 @@ var versionToString = map[int]string{ Capella: "capella", Deneb: "deneb", Electra: "electra", + Fulu: "fulu", } // stringToVersion and allVersions are populated in init() diff --git a/testing/assertions/BUILD.bazel b/testing/assertions/BUILD.bazel index ae67367cf254..c80dbfe51ba1 100644 --- a/testing/assertions/BUILD.bazel +++ b/testing/assertions/BUILD.bazel @@ -8,8 +8,10 @@ go_library( deps = [ "//encoding/ssz/equality:go_default_library", "@com_github_d4l3k_messagediff//:go_default_library", + "@com_github_google_go_cmp//cmp:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", + "@org_golang_google_protobuf//testing/protocmp:go_default_library", ], ) diff --git a/testing/assertions/assertions.go b/testing/assertions/assertions.go index 5bf5303967df..0b566880f4bb 100644 --- a/testing/assertions/assertions.go +++ b/testing/assertions/assertions.go @@ -10,9 +10,11 @@ import ( "strings" "github.com/d4l3k/messagediff" + "github.com/google/go-cmp/cmp" "github.com/prysmaticlabs/prysm/v5/encoding/ssz/equality" "github.com/sirupsen/logrus/hooks/test" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" ) // AssertionTestingTB exposes enough testing.TB methods for assertions. @@ -52,13 +54,12 @@ func DeepEqual(loggerFn assertionLoggerFn, expected, actual interface{}, msg ... if !isDeepEqual(expected, actual) { errMsg := parseMsg("Values are not equal", msg...) _, file, line, _ := runtime.Caller(2) - var diff string + opts := cmp.Options{cmp.AllowUnexported(expected), cmp.AllowUnexported(actual)} if _, isProto := expected.(proto.Message); isProto { - diff = ProtobufPrettyDiff(expected, actual) - } else { - diff, _ = messagediff.PrettyDiff(expected, actual) + opts = append(opts, protocmp.Transform()) } - loggerFn("%s:%d %s, want: %#v, got: %#v, diff: %s", filepath.Base(file), line, errMsg, expected, actual, diff) + diff := cmp.Diff(expected, actual, opts...) + loggerFn("%s:%d %s, expected != actual, diff: %s", filepath.Base(file), line, errMsg, diff) } } diff --git a/testing/assertions/assertions_test.go b/testing/assertions/assertions_test.go index 118c06642a39..0550e2456937 100644 --- a/testing/assertions/assertions_test.go +++ b/testing/assertions/assertions_test.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" "testing" + "unicode" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" testpb "github.com/prysmaticlabs/prysm/v5/proto/testing" @@ -188,7 +189,7 @@ func TestAssert_DeepEqual(t *testing.T) { expected: struct{ i int }{42}, actual: struct{ i int }{41}, }, - expectedErr: "Values are not equal, want: struct { i int }{i:42}, got: struct { i int }{i:41}", + expectedErr: "Values are not equal, expected != actual, diff: struct{ i int }{\n- \ti: 42,\n+ \ti: 41,\n }\n", }, { name: "custom error message", @@ -198,7 +199,7 @@ func TestAssert_DeepEqual(t *testing.T) { actual: struct{ i int }{41}, msgs: []interface{}{"Custom values are not equal"}, }, - expectedErr: "Custom values are not equal, want: struct { i int }{i:42}, got: struct { i int }{i:41}", + expectedErr: "Custom values are not equal, expected != actual, diff: struct{ i int }{\n- \ti: 42,\n+ \ti: 41,\n }", }, { name: "custom error message with params", @@ -208,24 +209,39 @@ func TestAssert_DeepEqual(t *testing.T) { actual: struct{ i int }{41}, msgs: []interface{}{"Custom values are not equal (for slot %d)", 12}, }, - expectedErr: "Custom values are not equal (for slot 12), want: struct { i int }{i:42}, got: struct { i int }{i:41}", + expectedErr: "Custom values are not equal (for slot 12), expected != actual, diff: struct{ i int }{\n- \ti: 42,\n+ \ti: 41,\n }\n", }, } for _, tt := range tests { - verify := func() { - if tt.expectedErr == "" && tt.args.tb.ErrorfMsg != "" { - t.Errorf("Unexpected error: %v", tt.args.tb.ErrorfMsg) - } else if !strings.Contains(tt.args.tb.ErrorfMsg, tt.expectedErr) { + verify := func(t testing.TB) { + // Trim unicode space characters for an easier comparison. + got := strings.Map(func(r rune) rune { + if unicode.IsSpace(r) { + return -1 + } + return r + }, tt.args.tb.ErrorfMsg) + want := strings.Map(func(r rune) rune { + if unicode.IsSpace(r) { + return -1 + } + return r + }, tt.expectedErr) + if want == "" && got != "" { + t.Errorf("Unexpected error: %v", got) + } else if !strings.Contains(got, want) { + t.Logf("got=%q", got) + t.Logf("want=%q", want) t.Errorf("got: %q, want: %q", tt.args.tb.ErrorfMsg, tt.expectedErr) } } t.Run(fmt.Sprintf("Assert/%s", tt.name), func(t *testing.T) { assert.DeepEqual(tt.args.tb, tt.args.expected, tt.args.actual, tt.args.msgs...) - verify() + verify(t) }) t.Run(fmt.Sprintf("Require/%s", tt.name), func(t *testing.T) { require.DeepEqual(tt.args.tb, tt.args.expected, tt.args.actual, tt.args.msgs...) - verify() + verify(t) }) } } diff --git a/testing/bls/hash_to_G2_test.go b/testing/bls/hash_to_G2_test.go index 48db52b6b6f1..ff3c4c8c1689 100644 --- a/testing/bls/hash_to_G2_test.go +++ b/testing/bls/hash_to_G2_test.go @@ -17,7 +17,7 @@ func TestHashToG2(t *testing.T) { } func testHashToG2(t *testing.T) { - t.Skip("Hash To G2 needs co-ordinates exposed") + t.Skip("Hash To G2 needs coordinates exposed") fNames, fContent := utils.RetrieveFiles("hash_to_G2", t) for i, file := range fNames { diff --git a/testing/endtoend/component_handler_test.go b/testing/endtoend/component_handler_test.go index 11a1ece74424..88e1ff430b7c 100644 --- a/testing/endtoend/component_handler_test.go +++ b/testing/endtoend/component_handler_test.go @@ -28,6 +28,7 @@ type componentHandler struct { web3Signer e2etypes.ComponentRunner bootnode e2etypes.ComponentRunner eth1Miner e2etypes.ComponentRunner + txGen e2etypes.ComponentRunner builders e2etypes.MultipleComponentRunners eth1Proxy e2etypes.MultipleComponentRunners eth1Nodes e2etypes.MultipleComponentRunners diff --git a/testing/endtoend/components/beacon_node.go b/testing/endtoend/components/beacon_node.go index a42da708bf35..d47036dfe052 100644 --- a/testing/endtoend/components/beacon_node.go +++ b/testing/endtoend/components/beacon_node.go @@ -261,7 +261,7 @@ func (node *BeaconNode) Start(ctx context.Context) error { fmt.Sprintf("--%s=%d", cmdshared.P2PTCPPort.Name, e2e.TestParams.Ports.PrysmBeaconNodeTCPPort+index), fmt.Sprintf("--%s=%d", cmdshared.P2PMaxPeers.Name, expectedNumOfPeers), fmt.Sprintf("--%s=%d", flags.MonitoringPortFlag.Name, e2e.TestParams.Ports.PrysmBeaconNodeMetricsPort+index), - fmt.Sprintf("--%s=%d", flags.GRPCGatewayPort.Name, e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort+index), + fmt.Sprintf("--%s=%d", flags.HTTPServerPort.Name, e2e.TestParams.Ports.PrysmBeaconNodeHTTPPort+index), fmt.Sprintf("--%s=%d", flags.ContractDeploymentBlock.Name, 0), fmt.Sprintf("--%s=%d", flags.MinPeersPerSubnet.Name, 0), fmt.Sprintf("--%s=%d", cmdshared.RPCMaxPageSizeFlag.Name, params.BeaconConfig().MinGenesisActiveValidatorCount), @@ -275,7 +275,6 @@ func (node *BeaconNode) Start(ctx context.Context) error { "--" + cmdshared.ValidatorMonitorIndicesFlag.Name + "=2", "--" + cmdshared.ForceClearDB.Name, "--" + cmdshared.AcceptTosFlag.Name, - "--" + features.EnableQUIC.Name, } if config.UsePprof { args = append(args, "--pprof", fmt.Sprintf("--pprofport=%d", e2e.TestParams.Ports.PrysmBeaconNodePprofPort+index)) diff --git a/testing/endtoend/components/eth1/BUILD.bazel b/testing/endtoend/components/eth1/BUILD.bazel index 46bc9c0a7c92..93facd8b3be1 100644 --- a/testing/endtoend/components/eth1/BUILD.bazel +++ b/testing/endtoend/components/eth1/BUILD.bazel @@ -28,12 +28,14 @@ go_library( "//testing/endtoend/types:go_default_library", "//testing/middleware/engine-api-proxy:go_default_library", "//testing/util:go_default_library", + "@com_github_ethereum_go_ethereum//:go_default_library", "@com_github_ethereum_go_ethereum//accounts/abi/bind:go_default_library", "@com_github_ethereum_go_ethereum//accounts/keystore:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_ethereum_go_ethereum//crypto/kzg4844:go_default_library", "@com_github_ethereum_go_ethereum//ethclient:go_default_library", + "@com_github_ethereum_go_ethereum//ethclient/gethclient:go_default_library", "@com_github_ethereum_go_ethereum//rpc:go_default_library", "@com_github_holiman_uint256//:go_default_library", "@com_github_mariusvanderwijden_fuzzyvm//filler:go_default_library", diff --git a/testing/endtoend/components/eth1/depositor.go b/testing/endtoend/components/eth1/depositor.go index dc03e3c82356..329bccade1ee 100644 --- a/testing/endtoend/components/eth1/depositor.go +++ b/testing/endtoend/components/eth1/depositor.go @@ -176,6 +176,62 @@ func (d *Depositor) SendAndMine(ctx context.Context, offset, nvals int, batch ty return nil } +// SendAndMineByBatch uses the deterministic validator generator to generate deposits for `nvals` (number of validators). +// To control which validators should receive deposits, so that we can generate deposits at different stages of e2e, +// the `offset` parameter skips the first N validators in the deterministic list. +// In order to test the requirement that our deposit follower is able to handle multiple partial deposits, +// the `partial` flag specifies that half of the deposits should be broken up into 2 transactions. +// Once the set of deposits has been generated, it submits a transaction for each deposit +// (using 2 transactions for partial deposits) and then uses WaitForBlocks to send these transactions by one batch per block. +// The batch size is determined by the provided batch size provided as an argument. +func (d *Depositor) SendAndMineByBatch(ctx context.Context, offset, nvals, batchSize int, batch types.DepositBatch, partial bool) error { + balance, err := d.Client.BalanceAt(ctx, d.Key.Address, nil) + if err != nil { + return err + } + // This is the "Send" part of the function. Compute deposits for `nvals` validators, + // with half of those deposits being split over 2 transactions if the `partial` flag is true, + // and throwing away any validators before `offset`. + deposits, err := computeDeposits(offset, nvals, partial) + if err != nil { + return err + } + numBatch := len(deposits) / batchSize + log.WithField("numDeposits", len(deposits)).WithField("batchSize", batchSize).WithField("numBatches", numBatch).WithField("balance", balance.String()).WithField("account", d.Key.Address.Hex()).Info("SendAndMineByBatch check") + for i := 0; i < numBatch; i++ { + txo, err := d.txops(ctx) + if err != nil { + return err + } + for _, dd := range deposits[i*batchSize : (i+1)*batchSize] { + if err := d.SendDeposit(dd, txo, batch); err != nil { + return err + } + } + // This is the "AndMine" part of the function. WaitForBlocks will spam transactions to/from the given key + // to advance the EL chain and until the chain has advanced the requested amount. + if err = WaitForBlocks(d.Client, d.Key, 1); err != nil { + return fmt.Errorf("failed to mine blocks %w", err) + } + } + txo, err := d.txops(ctx) + if err != nil { + return err + } + // Send out the last partial batch + for _, dd := range deposits[numBatch*batchSize:] { + if err := d.SendDeposit(dd, txo, batch); err != nil { + return err + } + } + // This is the "AndMine" part of the function. WaitForBlocks will spam transactions to/from the given key + // to advance the EL chain and until the chain has advanced the requested amount. + if err = WaitForBlocks(d.Client, d.Key, 1); err != nil { + return fmt.Errorf("failed to mine blocks %w", err) + } + return nil +} + // SendDeposit sends a single deposit. A record of this deposit will be tracked for the life of the Depositor, // allowing evaluators to use the deposit history to make assertions about those deposits. func (d *Depositor) SendDeposit(dep *eth.Deposit, txo *bind.TransactOpts, batch types.DepositBatch) error { diff --git a/testing/endtoend/components/eth1/miner.go b/testing/endtoend/components/eth1/miner.go index 9d7998ea6ac0..461c293993c3 100644 --- a/testing/endtoend/components/eth1/miner.go +++ b/testing/endtoend/components/eth1/miner.go @@ -143,11 +143,9 @@ func (m *Miner) initAttempt(ctx context.Context, attempt int) (*os.File, error) "--ws.origins=\"*\"", "--ipcdisable", "--verbosity=4", - "--mine", fmt.Sprintf("--unlock=%s", EthAddress), "--allow-insecure-unlock", "--syncmode=full", - fmt.Sprintf("--miner.etherbase=%s", EthAddress), fmt.Sprintf("--txpool.locals=%s", EthAddress), fmt.Sprintf("--password=%s", pwFile), } diff --git a/testing/endtoend/components/eth1/node.go b/testing/endtoend/components/eth1/node.go index e0cef7d32838..e3296dcc80da 100644 --- a/testing/endtoend/components/eth1/node.go +++ b/testing/endtoend/components/eth1/node.go @@ -127,12 +127,16 @@ func (node *Node) Start(ctx context.Context) error { if err = runCmd.Start(); err != nil { return fmt.Errorf("failed to start eth1 chain: %w", err) } - if err = helpers.WaitForTextInFile(errLog, "Started P2P networking"); err != nil { + // TODO: the log is not very descriptive but it's always the first log where the chain has + // - a peer + // - http server started + // - genesis synced + if err = helpers.WaitForTextInFile(errLog, "Node revalidated"); err != nil { kerr := runCmd.Process.Kill() if kerr != nil { log.WithError(kerr).Error("error sending kill to failed node command process") } - retryErr = fmt.Errorf("P2P log not found, this means the eth1 chain had issues starting: %w", err) + retryErr = fmt.Errorf("the first node revalidated log not found, this means the eth1 chain had issues starting: %w", err) continue } node.cmd = runCmd diff --git a/testing/endtoend/components/eth1/transactions.go b/testing/endtoend/components/eth1/transactions.go index 5426adae257d..18963147ccc5 100644 --- a/testing/endtoend/components/eth1/transactions.go +++ b/testing/endtoend/components/eth1/transactions.go @@ -12,11 +12,13 @@ import ( "github.com/MariusVanDerWijden/FuzzyVM/filler" txfuzz "github.com/MariusVanDerWijden/tx-fuzz" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/ethclient/gethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/holiman/uint256" "github.com/pkg/errors" @@ -37,6 +39,13 @@ type TransactionGenerator struct { seed int64 started chan struct{} cancel context.CancelFunc + paused bool +} + +func (t *TransactionGenerator) UnderlyingProcess() *os.Process { + // Transaction Generator runs under the same underlying process so + // we return an empty process object. + return &os.Process{} } func NewTransactionGenerator(keystore string, seed int64) *TransactionGenerator { @@ -92,6 +101,9 @@ func (t *TransactionGenerator) Start(ctx context.Context) error { case <-ctx.Done(): return nil case <-ticker.C: + if t.paused { + continue + } backend := ethclient.NewClient(client) err = SendTransaction(client, mineKey.PrivateKey, f, gasPrice, mineKey.Address.String(), txCount, backend, false) if err != nil { @@ -209,11 +221,13 @@ func SendTransaction(client *rpc.Client, key *ecdsa.PrivateKey, f *filler.Filler // Pause pauses the component and its underlying process. func (t *TransactionGenerator) Pause() error { + t.paused = true return nil } // Resume resumes the component and its underlying process. func (t *TransactionGenerator) Resume() error { + t.paused = false return nil } @@ -257,27 +271,47 @@ func RandomBlobTx(rpc *rpc.Client, f *filler.Filler, sender common.Address, nonc // 4844 transaction without AL tip, feecap, err := getCaps(rpc, gasPrice) if err != nil { - return nil, err + return nil, errors.Wrap(err, "getCaps") } data, err := randomBlobData() if err != nil { - return nil, err + return nil, errors.Wrap(err, "randomBlobData") } return New4844Tx(nonce, &to, gas, chainID, tip, feecap, value, code, big.NewInt(1000000), data, make(types.AccessList, 0)), nil case 1: - // 4844 transaction with AL - tx := types.NewTransaction(nonce, to, value, gas, gasPrice, code) - al, err := txfuzz.CreateAccessList(rpc, tx, sender) + // 4844 transaction with AL nonce, to, value, gas, gasPrice, code + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + To: &to, + Value: value, + Gas: gas, + GasPrice: gasPrice, + Data: code, + }) + + // TODO: replace call with al, err := txfuzz.CreateAccessList(rpc, tx, sender) when txfuzz is fixed in new release + // an error occurs mentioning error="CreateAccessList: both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified" + msg := ethereum.CallMsg{ + From: sender, + To: tx.To(), + Gas: tx.Gas(), + GasPrice: tx.GasPrice(), + Value: tx.Value(), + Data: tx.Data(), + AccessList: nil, + } + geth := gethclient.New(rpc) + al, _, _, err := geth.CreateAccessList(context.Background(), msg) if err != nil { - return nil, err + return nil, errors.Wrap(err, "CreateAccessList") } tip, feecap, err := getCaps(rpc, gasPrice) if err != nil { - return nil, err + return nil, errors.Wrap(err, "getCaps") } data, err := randomBlobData() if err != nil { - return nil, err + return nil, errors.Wrap(err, "randomBlobData") } return New4844Tx(nonce, &to, gas, chainID, tip, feecap, value, code, big.NewInt(1000000), data, *al), nil } @@ -342,17 +376,18 @@ func EncodeBlobs(data []byte) ([]kzg4844.Blob, []kzg4844.Commitment, []kzg4844.P versionedHashes []common.Hash ) for _, blob := range blobs { - commit, err := kzg4844.BlobToCommitment(blob) + b := blob + commit, err := kzg4844.BlobToCommitment(&b) if err != nil { return nil, nil, nil, nil, err } commits = append(commits, commit) - proof, err := kzg4844.ComputeBlobProof(blob, commit) + proof, err := kzg4844.ComputeBlobProof(&b, commit) if err != nil { return nil, nil, nil, nil, err } - if err := kzg4844.VerifyBlobProof(blob, commit, proof); err != nil { + if err := kzg4844.VerifyBlobProof(&b, commit, proof); err != nil { return nil, nil, nil, nil, err } proofs = append(proofs, proof) diff --git a/testing/endtoend/components/lighthouse_beacon.go b/testing/endtoend/components/lighthouse_beacon.go index 105565af62db..0d370623757a 100644 --- a/testing/endtoend/components/lighthouse_beacon.go +++ b/testing/endtoend/components/lighthouse_beacon.go @@ -189,7 +189,6 @@ func (node *LighthouseBeaconNode) Start(ctx context.Context) error { fmt.Sprintf("--metrics-port=%d", e2e.TestParams.Ports.LighthouseBeaconNodeMetricsPort+index), "--metrics", "--http", - "--http-allow-sync-stalled", "--enable-private-discovery", "--debug-level=debug", "--suggested-fee-recipient=0x878705ba3f8bc32fcf7f4caa1a35e72af65cf766", @@ -266,7 +265,7 @@ func (node *LighthouseBeaconNode) createTestnetDir(ctx context.Context, index in if err := file.WriteFile(bootPath, enrYaml); err != nil { return "", err } - deployPath := filepath.Join(testNetDir, "deploy_block.txt") + deployPath := filepath.Join(testNetDir, "deposit_contract_block.txt") deployYaml := []byte("0") if err := file.WriteFile(deployPath, deployYaml); err != nil { return "", err diff --git a/testing/endtoend/components/lighthouse_validator.go b/testing/endtoend/components/lighthouse_validator.go index a412480aa154..fde4a0f26e7d 100644 --- a/testing/endtoend/components/lighthouse_validator.go +++ b/testing/endtoend/components/lighthouse_validator.go @@ -20,26 +20,25 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v5/testing/endtoend/params" "github.com/prysmaticlabs/prysm/v5/testing/endtoend/types" - e2etypes "github.com/prysmaticlabs/prysm/v5/testing/endtoend/types" "github.com/prysmaticlabs/prysm/v5/validator/keymanager" keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4" "golang.org/x/sync/errgroup" ) -var _ e2etypes.ComponentRunner = (*LighthouseValidatorNode)(nil) -var _ e2etypes.ComponentRunner = (*LighthouseValidatorNodeSet)(nil) -var _ e2etypes.MultipleComponentRunners = (*LighthouseValidatorNodeSet)(nil) +var _ types.ComponentRunner = (*LighthouseValidatorNode)(nil) +var _ types.ComponentRunner = (*LighthouseValidatorNodeSet)(nil) +var _ types.MultipleComponentRunners = (*LighthouseValidatorNodeSet)(nil) // LighthouseValidatorNodeSet represents set of lighthouse validator nodes. type LighthouseValidatorNodeSet struct { - e2etypes.ComponentRunner - config *e2etypes.E2EConfig + types.ComponentRunner + config *types.E2EConfig started chan struct{} - nodes []e2etypes.ComponentRunner + nodes []types.ComponentRunner } // NewLighthouseValidatorNodeSet creates and returns a set of lighthouse validator nodes. -func NewLighthouseValidatorNodeSet(config *e2etypes.E2EConfig) *LighthouseValidatorNodeSet { +func NewLighthouseValidatorNodeSet(config *types.E2EConfig) *LighthouseValidatorNodeSet { return &LighthouseValidatorNodeSet{ config: config, started: make(chan struct{}, 1), @@ -59,7 +58,7 @@ func (s *LighthouseValidatorNodeSet) Start(ctx context.Context) error { validatorsPerNode := validatorNum / beaconNodeNum // Create validator nodes. - nodes := make([]e2etypes.ComponentRunner, lighthouseBeaconNum) + nodes := make([]types.ComponentRunner, lighthouseBeaconNum) for i := 0; i < lighthouseBeaconNum; i++ { offsetIdx := i + prysmBeaconNum nodes[i] = NewLighthouseValidatorNode(s.config, validatorsPerNode, i, validatorsPerNode*offsetIdx) @@ -134,7 +133,7 @@ func (s *LighthouseValidatorNodeSet) StopAtIndex(i int) error { } // ComponentAtIndex returns the component at the provided index. -func (s *LighthouseValidatorNodeSet) ComponentAtIndex(i int) (e2etypes.ComponentRunner, error) { +func (s *LighthouseValidatorNodeSet) ComponentAtIndex(i int) (types.ComponentRunner, error) { if i >= len(s.nodes) { return nil, errors.Errorf("provided index exceeds slice size: %d >= %d", i, len(s.nodes)) } @@ -143,8 +142,8 @@ func (s *LighthouseValidatorNodeSet) ComponentAtIndex(i int) (e2etypes.Component // LighthouseValidatorNode represents a lighthouse validator node. type LighthouseValidatorNode struct { - e2etypes.ComponentRunner - config *e2etypes.E2EConfig + types.ComponentRunner + config *types.E2EConfig started chan struct{} validatorNum int index int @@ -153,7 +152,7 @@ type LighthouseValidatorNode struct { } // NewLighthouseValidatorNode creates and returns a lighthouse validator node. -func NewLighthouseValidatorNode(config *e2etypes.E2EConfig, validatorNum, index, offset int) *LighthouseValidatorNode { +func NewLighthouseValidatorNode(config *types.E2EConfig, validatorNum, index, offset int) *LighthouseValidatorNode { return &LighthouseValidatorNode{ config: config, validatorNum: validatorNum, @@ -179,7 +178,7 @@ func (v *LighthouseValidatorNode) Start(ctx context.Context) error { // beacon node, we split half the validators to run with // lighthouse and the other half with prysm. if v.config.UseValidatorCrossClient && index%2 == 0 { - httpPort = e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort + httpPort = e2e.TestParams.Ports.PrysmBeaconNodeHTTPPort } args := []string{ "validator_client", diff --git a/testing/endtoend/components/validator.go b/testing/endtoend/components/validator.go index 117c2ec3cb7f..4135c99539c0 100644 --- a/testing/endtoend/components/validator.go +++ b/testing/endtoend/components/validator.go @@ -221,12 +221,13 @@ func (v *ValidatorNode) Start(ctx context.Context) error { if err != nil { return err } + portFlagName := "grpc-gateway-port" // TODO: replace port flag name with flags.HTTPServerPort.Name in a future release args := []string{ fmt.Sprintf("--%s=%s/eth2-val-%d", cmdshared.DataDirFlag.Name, e2e.TestParams.TestPath, index), fmt.Sprintf("--%s=%s", cmdshared.LogFileName.Name, logFile.Name()), fmt.Sprintf("--%s=%s", flags.GraffitiFileFlag.Name, gFile), fmt.Sprintf("--%s=%d", flags.MonitoringPortFlag.Name, e2e.TestParams.Ports.ValidatorMetricsPort+index), - fmt.Sprintf("--%s=%d", flags.GRPCGatewayPort.Name, e2e.TestParams.Ports.ValidatorGatewayPort+index), + fmt.Sprintf("--%s=%d", portFlagName, e2e.TestParams.Ports.ValidatorHTTPPort+index), fmt.Sprintf("--%s=localhost:%d", flags.BeaconRPCProviderFlag.Name, beaconRPCPort), fmt.Sprintf("--%s=%s", flags.GRPCHeadersFlag.Name, "dummy=value,foo=bar"), // Sending random headers shouldn't break anything. @@ -238,10 +239,10 @@ func (v *ValidatorNode) Start(ctx context.Context) error { } if v.config.UseBeaconRestApi { - beaconRestApiPort := e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort + index - if beaconRestApiPort >= e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort+e2e.TestParams.BeaconNodeCount { + beaconRestApiPort := e2e.TestParams.Ports.PrysmBeaconNodeHTTPPort + index + if beaconRestApiPort >= e2e.TestParams.Ports.PrysmBeaconNodeHTTPPort+e2e.TestParams.BeaconNodeCount { // Point any extra validator clients to a node we know is running. - beaconRestApiPort = e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort + beaconRestApiPort = e2e.TestParams.Ports.PrysmBeaconNodeHTTPPort } args = append(args, diff --git a/testing/endtoend/components/web3remotesigner.go b/testing/endtoend/components/web3remotesigner.go index 83aa0781901c..6484ec6c20e4 100644 --- a/testing/endtoend/components/web3remotesigner.go +++ b/testing/endtoend/components/web3remotesigner.go @@ -148,7 +148,7 @@ func (w *Web3RemoteSigner) monitorStart() { } res, err := client.Do(req) _ = err - if res != nil && res.StatusCode == 200 { + if res != nil && res.StatusCode == http.StatusOK { close(w.started) return } diff --git a/testing/endtoend/deps.bzl b/testing/endtoend/deps.bzl index 5a25c8223fb2..313c7f5e7f74 100644 --- a/testing/endtoend/deps.bzl +++ b/testing/endtoend/deps.bzl @@ -1,20 +1,20 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # gazelle:keep -lighthouse_version = "v4.6.0-rc.0" -lighthouse_archive_name = "lighthouse-%s-x86_64-unknown-linux-gnu-portable.tar.gz" % lighthouse_version +lighthouse_version = "v7.0.0-beta.0" +lighthouse_archive_name = "lighthouse-%s-x86_64-unknown-linux-gnu.tar.gz" % lighthouse_version def e2e_deps(): http_archive( name = "web3signer", - urls = ["https://artifacts.consensys.net/public/web3signer/raw/names/web3signer.tar.gz/versions/23.11.0/web3signer-23.11.0.tar.gz"], - sha256 = "e7643a6aa32efd859e96a82cb3ea03a294fd92c22fffeab987e5ec97500867a8", + urls = ["https://artifacts.consensys.net/public/web3signer/raw/names/web3signer.tar.gz/versions/25.2.0/web3signer-25.2.0.tar.gz"], + sha256 = "2445eaea11755621626a92d18f12c62676eb9f12ee8c8259b222d87d27505578", build_file = "@prysm//testing/endtoend:web3signer.BUILD", - strip_prefix = "web3signer-23.11.0", + strip_prefix = "web3signer-25.2.0", ) http_archive( name = "lighthouse", - integrity = "sha256-9jmQN1AJUyogscUYibFchZMUXH0ZRKofW4oPhAFVRAE=", + integrity = "sha256-qMPifuh7u0epItu8DzZ8YdZ2fVZNW7WKnbmmAgjh/us=", build_file = "@prysm//testing/endtoend:lighthouse.BUILD", url = ("https://github.com/sigp/lighthouse/releases/download/%s/" + lighthouse_archive_name) % lighthouse_version, ) diff --git a/testing/endtoend/endtoend_setup_test.go b/testing/endtoend/endtoend_setup_test.go index b4518853e1a7..c54d6fb6dd2a 100644 --- a/testing/endtoend/endtoend_setup_test.go +++ b/testing/endtoend/endtoend_setup_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/prysmaticlabs/prysm/v5/config/params" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ev "github.com/prysmaticlabs/prysm/v5/testing/endtoend/evaluators" "github.com/prysmaticlabs/prysm/v5/testing/endtoend/evaluators/beaconapi" e2eParams "github.com/prysmaticlabs/prysm/v5/testing/endtoend/params" @@ -21,7 +22,7 @@ func e2eMinimal(t *testing.T, cfg *params.BeaconChainConfig, cfgo ...types.E2ECo // Run for 12 epochs if not in long-running to confirm long-running has no issues. var err error - epochsToRun := 14 + epochsToRun := 16 epochStr, longRunning := os.LookupEnv("E2E_EPOCHS") if longRunning { epochsToRun, err = strconv.Atoi(epochStr) @@ -53,17 +54,18 @@ func e2eMinimal(t *testing.T, cfg *params.BeaconChainConfig, cfgo ...types.E2ECo ev.DepositedValidatorsAreActive, ev.ValidatorsVoteWithTheMajority, ev.ColdStateCheckpoint, - ev.AltairForkTransition, - ev.BellatrixForkTransition, - ev.CapellaForkTransition, - ev.DenebForkTransition, - ev.APIGatewayV1Alpha1VerifyIntegrity, ev.FinishedSyncing, ev.AllNodesHaveSameHead, ev.ValidatorSyncParticipation, ev.FeeRecipientIsPresent, //ev.TransactionsPresent, TODO: Re-enable Transaction evaluator once it tx pool issues are fixed. } + evals = addIfForkSet(evals, cfg.AltairForkEpoch, ev.AltairForkTransition) + evals = addIfForkSet(evals, cfg.BellatrixForkEpoch, ev.BellatrixForkTransition) + evals = addIfForkSet(evals, cfg.CapellaForkEpoch, ev.CapellaForkTransition) + evals = addIfForkSet(evals, cfg.DenebForkEpoch, ev.DenebForkTransition) + evals = addIfForkSet(evals, cfg.ElectraForkEpoch, ev.ElectraForkTransition) + testConfig := &types.E2EConfig{ BeaconFlags: []string{ fmt.Sprintf("--slots-per-archive-point=%d", params.BeaconConfig().SlotsPerEpoch*16), @@ -103,7 +105,7 @@ func e2eMainnet(t *testing.T, usePrysmSh, useMultiClient bool, cfg *params.Beaco } // Run for 10 epochs if not in long-running to confirm long-running has no issues. var err error - epochsToRun := 14 + epochsToRun := 16 epochStr, longRunning := os.LookupEnv("E2E_EPOCHS") if longRunning { epochsToRun, err = strconv.Atoi(epochStr) @@ -129,16 +131,17 @@ func e2eMainnet(t *testing.T, usePrysmSh, useMultiClient bool, cfg *params.Beaco ev.ValidatorsHaveWithdrawn, ev.DepositedValidatorsAreActive, ev.ColdStateCheckpoint, - ev.AltairForkTransition, - ev.BellatrixForkTransition, - ev.CapellaForkTransition, - ev.DenebForkTransition, - ev.APIGatewayV1Alpha1VerifyIntegrity, ev.FinishedSyncing, ev.AllNodesHaveSameHead, ev.FeeRecipientIsPresent, //ev.TransactionsPresent, TODO: Re-enable Transaction evaluator once it tx pool issues are fixed. } + evals = addIfForkSet(evals, cfg.AltairForkEpoch, ev.AltairForkTransition) + evals = addIfForkSet(evals, cfg.BellatrixForkEpoch, ev.BellatrixForkTransition) + evals = addIfForkSet(evals, cfg.CapellaForkEpoch, ev.CapellaForkTransition) + evals = addIfForkSet(evals, cfg.DenebForkEpoch, ev.DenebForkTransition) + evals = addIfForkSet(evals, cfg.ElectraForkEpoch, ev.ElectraForkTransition) + testConfig := &types.E2EConfig{ BeaconFlags: []string{ fmt.Sprintf("--slots-per-archive-point=%d", params.BeaconConfig().SlotsPerEpoch*16), @@ -174,8 +177,20 @@ func e2eMainnet(t *testing.T, usePrysmSh, useMultiClient bool, cfg *params.Beaco return newTestRunner(t, testConfig) } -func scenarioEvals() []types.Evaluator { - return []types.Evaluator{ +// addIfForkSet appends the specified transition if epoch is valid. +func addIfForkSet( + evals []types.Evaluator, + fork primitives.Epoch, + transition types.Evaluator, +) []types.Evaluator { + if fork != 0 && fork != params.BeaconConfig().FarFutureEpoch { + evals = append(evals, transition) + } + return evals +} + +func scenarioEvals(cfg *params.BeaconChainConfig) []types.Evaluator { + evals := []types.Evaluator{ ev.PeersConnect, ev.HealthzCheck, ev.MetricsCheck, @@ -185,19 +200,20 @@ func scenarioEvals() []types.Evaluator { ev.ProposeVoluntaryExit, ev.ValidatorsHaveExited, ev.ColdStateCheckpoint, - ev.AltairForkTransition, - ev.BellatrixForkTransition, - ev.CapellaForkTransition, - ev.DenebForkTransition, - ev.APIGatewayV1Alpha1VerifyIntegrity, ev.FinishedSyncing, ev.AllNodesHaveSameHead, ev.ValidatorSyncParticipation, } + evals = addIfForkSet(evals, cfg.AltairForkEpoch, ev.AltairForkTransition) + evals = addIfForkSet(evals, cfg.BellatrixForkEpoch, ev.BellatrixForkTransition) + evals = addIfForkSet(evals, cfg.CapellaForkEpoch, ev.CapellaForkTransition) + evals = addIfForkSet(evals, cfg.DenebForkEpoch, ev.DenebForkTransition) + evals = addIfForkSet(evals, cfg.ElectraForkEpoch, ev.ElectraForkTransition) + return evals } -func scenarioEvalsMulti() []types.Evaluator { - return []types.Evaluator{ +func scenarioEvalsMulti(cfg *params.BeaconChainConfig) []types.Evaluator { + evals := []types.Evaluator{ ev.PeersConnect, ev.HealthzCheck, ev.MetricsCheck, @@ -206,12 +222,13 @@ func scenarioEvalsMulti() []types.Evaluator { ev.ProposeVoluntaryExit, ev.ValidatorsHaveExited, ev.ColdStateCheckpoint, - ev.AltairForkTransition, - ev.BellatrixForkTransition, - ev.CapellaForkTransition, - ev.DenebForkTransition, - ev.APIGatewayV1Alpha1VerifyIntegrity, ev.FinishedSyncing, ev.AllNodesHaveSameHead, } + evals = addIfForkSet(evals, cfg.AltairForkEpoch, ev.AltairForkTransition) + evals = addIfForkSet(evals, cfg.BellatrixForkEpoch, ev.BellatrixForkTransition) + evals = addIfForkSet(evals, cfg.CapellaForkEpoch, ev.CapellaForkTransition) + evals = addIfForkSet(evals, cfg.DenebForkEpoch, ev.DenebForkTransition) + evals = addIfForkSet(evals, cfg.ElectraForkEpoch, ev.ElectraForkTransition) + return evals } diff --git a/testing/endtoend/endtoend_test.go b/testing/endtoend/endtoend_test.go index 8e8f3d51e4f8..2529ef13534e 100644 --- a/testing/endtoend/endtoend_test.go +++ b/testing/endtoend/endtoend_test.go @@ -225,6 +225,7 @@ func (r *testRunner) testDepositsAndTx(ctx context.Context, g *errgroup.Group, func (r *testRunner) testTxGeneration(ctx context.Context, g *errgroup.Group, keystorePath string, requiredNodes []e2etypes.ComponentRunner) { txGenerator := eth1.NewTransactionGenerator(keystorePath, r.config.Seed) + r.comHandler.txGen = txGenerator g.Go(func() error { if err := helpers.ComponentsStarted(ctx, requiredNodes); err != nil { return fmt.Errorf("transaction generator requires eth1 nodes to be run: %w", err) @@ -501,6 +502,19 @@ func (r *testRunner) defaultEndToEndRun() error { if err := r.runEvaluators(ec, conns, tickingStartTime); err != nil { return errors.Wrap(err, "one or more evaluators failed") } + // Test execution request processing in electra. + if r.config.TestDeposits && params.ElectraEnabled() { + if err := r.comHandler.txGen.Pause(); err != nil { + r.t.Error(err) + } + err = r.depositor.SendAndMineByBatch(ctx, int(params.BeaconConfig().MinGenesisActiveValidatorCount)+int(e2e.DepositCount), int(e2e.PostElectraDepositCount), int(params.BeaconConfig().MaxDepositRequestsPerPayload), e2etypes.PostElectraDepositBatch, false) + if err != nil { + r.t.Error(err) + } + if err := r.comHandler.txGen.Resume(); err != nil { + r.t.Error(err) + } + } index := e2e.TestParams.BeaconNodeCount + e2e.TestParams.LighthouseBeaconNodeCount if config.TestSync { @@ -633,12 +647,12 @@ func (r *testRunner) multiScenarioMulticlient(ec *e2etypes.EvaluationContext, ep recoveryEpochStart, recoveryEpochEnd := lastForkEpoch+3, lastForkEpoch+4 secondRecoveryEpochStart, secondRecoveryEpochEnd := lastForkEpoch+8, lastForkEpoch+9 - newPayloadMethod := "engine_newPayloadV3" + newPayloadMethod := "engine_newPayloadV4" forkChoiceUpdatedMethod := "engine_forkchoiceUpdatedV3" - // Fallback if deneb is not set. - if params.BeaconConfig().DenebForkEpoch == math.MaxUint64 { - newPayloadMethod = "engine_newPayloadV2" - forkChoiceUpdatedMethod = "engine_forkchoiceUpdatedV2" + // Fallback if Electra is not set. + if params.BeaconConfig().ElectraForkEpoch == math.MaxUint64 { + newPayloadMethod = "engine_newPayloadV3" + forkChoiceUpdatedMethod = "engine_forkchoiceUpdatedV3" } switch primitives.Epoch(epoch) { @@ -754,10 +768,10 @@ func (r *testRunner) multiScenario(ec *e2etypes.EvaluationContext, epoch uint64, secondRecoveryEpochStart, secondRecoveryEpochEnd := lastForkEpoch+8, lastForkEpoch+9 thirdRecoveryEpochStart, thirdRecoveryEpochEnd := lastForkEpoch+13, lastForkEpoch+14 - newPayloadMethod := "engine_newPayloadV3" - // Fallback if deneb is not set. - if params.BeaconConfig().DenebForkEpoch == math.MaxUint64 { - newPayloadMethod = "engine_newPayloadV2" + newPayloadMethod := "engine_newPayloadV4" + // Fallback if Electra is not set. + if params.BeaconConfig().ElectraForkEpoch == math.MaxUint64 { + newPayloadMethod = "engine_newPayloadV3" } switch primitives.Epoch(epoch) { case freezeStartEpoch: diff --git a/testing/endtoend/evaluators/BUILD.bazel b/testing/endtoend/evaluators/BUILD.bazel index 8a4da9abd7fe..3b59c0095cf6 100644 --- a/testing/endtoend/evaluators/BUILD.bazel +++ b/testing/endtoend/evaluators/BUILD.bazel @@ -4,7 +4,6 @@ go_library( name = "go_default_library", testonly = True, srcs = [ - "api_gateway_v1alpha1.go", "builder.go", "data.go", "execution_engine.go", @@ -55,7 +54,6 @@ go_library( "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_ethereum_go_ethereum//ethclient:go_default_library", "@com_github_ethereum_go_ethereum//rpc:go_default_library", - "@com_github_golang_protobuf//ptypes/empty", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", diff --git a/testing/endtoend/evaluators/api_gateway_v1alpha1.go b/testing/endtoend/evaluators/api_gateway_v1alpha1.go deleted file mode 100644 index 3b1ed1f893a6..000000000000 --- a/testing/endtoend/evaluators/api_gateway_v1alpha1.go +++ /dev/null @@ -1,501 +0,0 @@ -package evaluators - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "net/http" - - "github.com/golang/protobuf/ptypes/empty" - "github.com/pkg/errors" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - e2e "github.com/prysmaticlabs/prysm/v5/testing/endtoend/params" - "github.com/prysmaticlabs/prysm/v5/testing/endtoend/policies" - e2etypes "github.com/prysmaticlabs/prysm/v5/testing/endtoend/types" - "google.golang.org/grpc" -) - -// APIGatewayV1Alpha1VerifyIntegrity of our API gateway for the Prysm v1alpha1 API. -// This ensures our gRPC HTTP gateway returns and processes the same data _for the same endpoints_ -// as using a gRPC connection to interact with the API. Running this in end-to-end tests helps us -// ensure parity between our HTTP gateway for our API and gRPC never breaks. -// This evaluator checks a few request/response trips for both GET and POST requests. -var APIGatewayV1Alpha1VerifyIntegrity = e2etypes.Evaluator{ - Name: "api_gateway_v1alpha1_verify_integrity_epoch_%d", - Policy: policies.OnEpoch(2), - Evaluation: apiGatewayV1Alpha1Verify, -} - -const ( - v1Alpha1GatewayPathTemplate = "http://localhost:%d/eth/v1alpha1" -) - -type apiComparisonFunc func(beaconNodeIdx int, conn *grpc.ClientConn) error - -func apiGatewayV1Alpha1Verify(_ *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) error { - for beaconNodeIdx, conn := range conns { - if err := runAPIComparisonFunctions( - beaconNodeIdx, - conn, - withComparePeers, - withCompareListAttestations, - withCompareValidators, - withCompareChainHead, - ); err != nil { - return err - } - } - return nil -} - -func withComparePeers(beaconNodeIdx int, conn *grpc.ClientConn) error { - type peerJSON struct { - Address string `json:"address"` - Direction string `json:"direction"` - ConnectionState string `json:"connectionState"` - PeerId string `json:"peerId"` - Enr string `json:"enr"` - } - type peersResponseJSON struct { - Peers []*peerJSON `json:"peers"` - } - ctx := context.Background() - nodeClient := ethpb.NewNodeClient(conn) - resp, err := nodeClient.ListPeers(ctx, &empty.Empty{}) - if err != nil { - return err - } - respJSON := &peersResponseJSON{} - if err := doGatewayJSONRequest( - "/node/peers", - beaconNodeIdx, - respJSON, - ); err != nil { - return err - } - - if len(respJSON.Peers) != len(resp.Peers) { - return fmt.Errorf( - "HTTP gateway number of peers %d does not match gRPC %d", - len(respJSON.Peers), - len(resp.Peers), - ) - } - grpcPeerMap := make(map[string]*ethpb.Peer) - jsonPeerMap := make(map[string]*peerJSON) - for i := 0; i < len(respJSON.Peers); i++ { - grpcPeerMap[resp.Peers[i].PeerId] = resp.Peers[i] - jsonPeerMap[respJSON.Peers[i].PeerId] = respJSON.Peers[i] - } - - for id, peer := range jsonPeerMap { - grpcPeer, ok := grpcPeerMap[id] - if !ok { - return errors.Errorf("grpc peer %s doesn't exist", id) - } - if peer.Address != grpcPeer.Address { - return fmt.Errorf( - "HTTP gateway peer %s with address %s does not match gRPC %s", - id, - peer.Address, - grpcPeer.Address, - ) - } - if peer.Direction != grpcPeer.Direction.String() { - return fmt.Errorf( - "HTTP gateway peer %s with direction %s does not match gRPC %s", - id, - peer.Direction, - grpcPeer.Direction, - ) - } - if peer.ConnectionState != grpcPeer.ConnectionState.String() { - return fmt.Errorf( - "HTTP gateway peer %s with connection state %s does not match gRPC %s", - id, - peer.ConnectionState, - grpcPeer.ConnectionState, - ) - } - if peer.PeerId != grpcPeer.PeerId { - return fmt.Errorf( - "HTTP gateway peer %s with peer id %s does not match gRPC %s", - id, - peer.PeerId, - grpcPeer.PeerId, - ) - } - if peer.Enr != grpcPeer.Enr { - return fmt.Errorf( - "HTTP gateway peer %s with enr %s does not match gRPC %s", - id, - peer.Enr, - grpcPeer.Enr, - ) - } - } - return nil -} - -func withCompareListAttestations(beaconNodeIdx int, conn *grpc.ClientConn) error { - type checkpointJSON struct { - Epoch string `json:"epoch"` - Root string `json:"root"` - } - type attestationDataJSON struct { - Slot string `json:"slot"` - CommitteeIndex string `json:"committeeIndex"` - BeaconBlockRoot string `json:"beaconBlockRoot"` - Source *checkpointJSON `json:"source"` - Target *checkpointJSON `json:"target"` - } - type attestationJSON struct { - AggregationBits string `json:"aggregationBits"` - Data *attestationDataJSON `json:"data"` - Signature string `json:"signature"` - } - type attestationsResponseJSON struct { - Attestations []*attestationJSON `json:"attestations"` - NextPageToken string `json:"nextPageToken"` - TotalSize int32 `json:"totalSize"` - } - ctx := context.Background() - beaconClient := ethpb.NewBeaconChainClient(conn) - resp, err := beaconClient.ListAttestations(ctx, ðpb.ListAttestationsRequest{ - QueryFilter: ðpb.ListAttestationsRequest_GenesisEpoch{GenesisEpoch: true}, - }) - if err != nil { - return err - } - respJSON := &attestationsResponseJSON{} - if err := doGatewayJSONRequest( - "/beacon/attestations?genesis_epoch=true", - beaconNodeIdx, - respJSON, - ); err != nil { - return err - } - - // Begin comparisons. - if respJSON.NextPageToken != resp.NextPageToken { - return fmt.Errorf( - "HTTP gateway next page token %s does not match gRPC %s", - respJSON.NextPageToken, - resp.NextPageToken, - ) - } - if respJSON.TotalSize != resp.TotalSize { - return fmt.Errorf( - "HTTP gateway total size %d does not match gRPC %d", - respJSON.TotalSize, - resp.TotalSize, - ) - } - for i, att := range respJSON.Attestations { - grpcAtt := resp.Attestations[i] - if att.AggregationBits != base64.StdEncoding.EncodeToString(grpcAtt.AggregationBits) { - return fmt.Errorf( - "HTTP gateway attestation %d aggregation bits %s does not match gRPC %d", - i, - att.AggregationBits, - grpcAtt.AggregationBits, - ) - } - data := att.Data - grpcData := grpcAtt.Data - if data.Slot != fmt.Sprintf("%d", grpcData.Slot) { - return fmt.Errorf( - "HTTP gateway attestation %d slot %s does not match gRPC %d", - i, - data.Slot, - grpcData.Slot, - ) - } - if data.CommitteeIndex != fmt.Sprintf("%d", grpcData.CommitteeIndex) { - return fmt.Errorf( - "HTTP gateway attestation %d committee index %s does not match gRPC %d", - i, - data.CommitteeIndex, - grpcData.CommitteeIndex, - ) - } - if data.BeaconBlockRoot != base64.StdEncoding.EncodeToString(grpcData.BeaconBlockRoot) { - return fmt.Errorf( - "HTTP gateway attestation %d beacon block root %s does not match gRPC %d", - i, - data.BeaconBlockRoot, - grpcData.BeaconBlockRoot, - ) - } - if data.Source.Epoch != fmt.Sprintf("%d", grpcData.Source.Epoch) { - return fmt.Errorf( - "HTTP gateway attestation %d source epoch %s does not match gRPC %d", - i, - data.Source.Epoch, - grpcData.Source.Epoch, - ) - } - if data.Source.Root != base64.StdEncoding.EncodeToString(grpcData.Source.Root) { - return fmt.Errorf( - "HTTP gateway attestation %d source root %s does not match gRPC %d", - i, - data.Source.Root, - grpcData.Source.Root, - ) - } - if data.Target.Epoch != fmt.Sprintf("%d", grpcData.Target.Epoch) { - return fmt.Errorf( - "HTTP gateway attestation %d target epoch %s does not match gRPC %d", - i, - data.Target.Epoch, - grpcData.Target.Epoch, - ) - } - if data.Target.Root != base64.StdEncoding.EncodeToString(grpcData.Target.Root) { - return fmt.Errorf( - "HTTP gateway attestation %d target root %s does not match gRPC %d", - i, - data.Target.Root, - grpcData.Target.Root, - ) - } - if att.Signature != base64.StdEncoding.EncodeToString(grpcAtt.Signature) { - return fmt.Errorf( - "HTTP gateway attestation %d signature %s does not match gRPC %d", - i, - att.Signature, - grpcAtt.Signature, - ) - } - } - return nil -} - -func withCompareValidators(beaconNodeIdx int, conn *grpc.ClientConn) error { - type validatorJSON struct { - PublicKey string `json:"publicKey"` - WithdrawalCredentials string `json:"withdrawalCredentials"` - EffectiveBalance string `json:"effectiveBalance"` - Slashed bool `json:"slashed"` - ActivationEligibilityEpoch string `json:"activationEligibilityEpoch"` - ActivationEpoch string `json:"activationEpoch"` - ExitEpoch string `json:"exitEpoch"` - WithdrawableEpoch string `json:"withdrawableEpoch"` - } - type validatorContainerJSON struct { - Index string `json:"index"` - Validator *validatorJSON `json:"validator"` - } - type validatorsResponseJSON struct { - Epoch string `json:"epoch"` - ValidatorList []*validatorContainerJSON `json:"validatorList"` - NextPageToken string `json:"nextPageToken"` - TotalSize int32 `json:"totalSize"` - } - ctx := context.Background() - beaconClient := ethpb.NewBeaconChainClient(conn) - resp, err := beaconClient.ListValidators(ctx, ðpb.ListValidatorsRequest{ - QueryFilter: ðpb.ListValidatorsRequest_Genesis{ - Genesis: true, - }, - PageSize: 4, - }) - if err != nil { - return err - } - respJSON := &validatorsResponseJSON{} - if err := doGatewayJSONRequest( - "/validators?genesis=true&page_size=4", - beaconNodeIdx, - respJSON, - ); err != nil { - return err - } - - // Begin comparisons. - if respJSON.Epoch != fmt.Sprintf("%d", resp.Epoch) { - return fmt.Errorf( - "HTTP gateway epoch %s does not match gRPC %d", - respJSON.Epoch, - resp.Epoch, - ) - } - if respJSON.NextPageToken != resp.NextPageToken { - return fmt.Errorf( - "HTTP gateway next page token %s does not match gRPC %s", - respJSON.NextPageToken, - resp.NextPageToken, - ) - } - if respJSON.TotalSize != resp.TotalSize { - return fmt.Errorf( - "HTTP gateway total size %d does not match gRPC %d", - respJSON.TotalSize, - resp.TotalSize, - ) - } - - // Compare validators. - for i, val := range respJSON.ValidatorList { - if val.Index != fmt.Sprintf("%d", resp.ValidatorList[i].Index) { - return fmt.Errorf( - "HTTP gateway validator %d index %s does not match gRPC %d", - i, - val.Index, - resp.ValidatorList[i].Index, - ) - } - httpVal := val.Validator - grpcVal := resp.ValidatorList[i].Validator - if httpVal.PublicKey != base64.StdEncoding.EncodeToString(grpcVal.PublicKey) { - return fmt.Errorf( - "HTTP gateway validator %d public key %s does not match gRPC %d", - i, - httpVal.PublicKey, - grpcVal.PublicKey, - ) - } - continue - } - return nil -} - -// Compares a regular beacon chain head GET request with no arguments gRPC and gRPC gateway. -func withCompareChainHead(beaconNodeIdx int, conn *grpc.ClientConn) error { - // used for gateway, if using pure HTTP use shared.ChainHead - type chainHeadResponseJSON struct { - HeadSlot string `json:"headSlot"` - HeadEpoch string `json:"headEpoch"` - HeadBlockRoot string `json:"headBlockRoot"` - FinalizedSlot string `json:"finalizedSlot"` - FinalizedEpoch string `json:"finalizedEpoch"` - FinalizedBlockRoot string `json:"finalizedBlockRoot"` - JustifiedSlot string `json:"justifiedSlot"` - JustifiedEpoch string `json:"justifiedEpoch"` - JustifiedBlockRoot string `json:"justifiedBlockRoot"` - PreviousJustifiedSlot string `json:"previousJustifiedSlot"` - PreviousJustifiedEpoch string `json:"previousJustifiedEpoch"` - PreviousJustifiedBlockRoot string `json:"previousJustifiedBlockRoot"` - } - beaconClient := ethpb.NewBeaconChainClient(conn) - ctx := context.Background() - resp, err := beaconClient.GetChainHead(ctx, &empty.Empty{}) - if err != nil { - return err - } - respJSON := &chainHeadResponseJSON{} - if err := doGatewayJSONRequest( - "/beacon/chainhead", - beaconNodeIdx, - respJSON, - ); err != nil { - return err - } - - if respJSON.HeadSlot != fmt.Sprintf("%d", resp.HeadSlot) { - return fmt.Errorf( - "HTTP gateway head slot %s does not match gRPC %d", - respJSON.HeadSlot, - resp.HeadSlot, - ) - } - if respJSON.HeadEpoch != fmt.Sprintf("%d", resp.HeadEpoch) { - return fmt.Errorf( - "HTTP gateway head epoch %s does not match gRPC %d", - respJSON.HeadEpoch, - resp.HeadEpoch, - ) - } - if respJSON.HeadBlockRoot != base64.StdEncoding.EncodeToString(resp.HeadBlockRoot) { - return fmt.Errorf( - "HTTP gateway head block root %s does not match gRPC %s", - respJSON.HeadBlockRoot, - resp.HeadBlockRoot, - ) - } - if respJSON.FinalizedSlot != fmt.Sprintf("%d", resp.FinalizedSlot) { - return fmt.Errorf( - "HTTP gateway finalized slot %s does not match gRPC %d", - respJSON.FinalizedSlot, - resp.FinalizedSlot, - ) - } - if respJSON.FinalizedEpoch != fmt.Sprintf("%d", resp.FinalizedEpoch) { - return fmt.Errorf( - "HTTP gateway finalized epoch %s does not match gRPC %d", - respJSON.FinalizedEpoch, - resp.FinalizedEpoch, - ) - } - if respJSON.FinalizedBlockRoot != base64.StdEncoding.EncodeToString(resp.FinalizedBlockRoot) { - return fmt.Errorf( - "HTTP gateway finalized block root %s does not match gRPC %s", - respJSON.FinalizedBlockRoot, - resp.FinalizedBlockRoot, - ) - } - if respJSON.JustifiedSlot != fmt.Sprintf("%d", resp.JustifiedSlot) { - return fmt.Errorf( - "HTTP gateway justified slot %s does not match gRPC %d", - respJSON.JustifiedSlot, - resp.JustifiedSlot, - ) - } - if respJSON.JustifiedEpoch != fmt.Sprintf("%d", resp.JustifiedEpoch) { - return fmt.Errorf( - "HTTP gateway justified epoch %s does not match gRPC %d", - respJSON.JustifiedEpoch, - resp.JustifiedEpoch, - ) - } - if respJSON.JustifiedBlockRoot != base64.StdEncoding.EncodeToString(resp.JustifiedBlockRoot) { - return fmt.Errorf( - "HTTP gateway justified block root %s does not match gRPC %s", - respJSON.JustifiedBlockRoot, - resp.JustifiedBlockRoot, - ) - } - if respJSON.PreviousJustifiedSlot != fmt.Sprintf("%d", resp.PreviousJustifiedSlot) { - return fmt.Errorf( - "HTTP gateway justified slot %s does not match gRPC %d", - respJSON.FinalizedSlot, - resp.FinalizedSlot, - ) - } - if respJSON.PreviousJustifiedEpoch != fmt.Sprintf("%d", resp.PreviousJustifiedEpoch) { - return fmt.Errorf( - "HTTP gateway justified epoch %s does not match gRPC %d", - respJSON.FinalizedEpoch, - resp.FinalizedEpoch, - ) - } - if respJSON.PreviousJustifiedBlockRoot != base64.StdEncoding.EncodeToString(resp.PreviousJustifiedBlockRoot) { - return fmt.Errorf( - "HTTP gateway justified block root %s does not match gRPC %s", - respJSON.JustifiedBlockRoot, - resp.JustifiedBlockRoot, - ) - } - return nil -} - -func doGatewayJSONRequest(requestPath string, beaconNodeIdx int, dst interface{}) error { - basePath := fmt.Sprintf(v1Alpha1GatewayPathTemplate, e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort+beaconNodeIdx) - httpResp, err := http.Get( - basePath + requestPath, - ) - if err != nil { - return err - } - return json.NewDecoder(httpResp.Body).Decode(&dst) -} - -func runAPIComparisonFunctions(beaconNodeIdx int, conn *grpc.ClientConn, fs ...apiComparisonFunc) error { - for _, f := range fs { - if err := f(beaconNodeIdx, conn); err != nil { - return err - } - } - return nil -} diff --git a/testing/endtoend/evaluators/beaconapi/requests.go b/testing/endtoend/evaluators/beaconapi/requests.go index 291b70741f5c..fa4ada71ee07 100644 --- a/testing/endtoend/evaluators/beaconapi/requests.go +++ b/testing/endtoend/evaluators/beaconapi/requests.go @@ -80,8 +80,8 @@ var getRequests = map[string]endpoint{ withParams(func(_ primitives.Epoch) []string { return []string{"head"} })), - "/beacon/blocks/{param1}/attestations": newMetadata[structs.GetBlockAttestationsResponse]( - v1PathTemplate, + "/beacon/blocks/{param1}/attestations": newMetadata[structs.GetBlockAttestationsV2Response]( + v2PathTemplate, withParams(func(_ primitives.Epoch) []string { return []string{"head"} })), @@ -99,7 +99,7 @@ var getRequests = map[string]endpoint{ return []string{"head"} })), "/beacon/pool/attestations": newMetadata[structs.ListAttestationsResponse]( - v1PathTemplate, + v2PathTemplate, withSanityCheckOnly()), "/beacon/pool/attester_slashings": newMetadata[structs.GetAttesterSlashingsResponse]( v1PathTemplate, diff --git a/testing/endtoend/evaluators/beaconapi/util.go b/testing/endtoend/evaluators/beaconapi/util.go index 5c8aa1d70fb5..3d0f7914f9ca 100644 --- a/testing/endtoend/evaluators/beaconapi/util.go +++ b/testing/endtoend/evaluators/beaconapi/util.go @@ -33,7 +33,7 @@ func doJSONGetRequest(template, requestPath string, beaconNodeIdx int, resp inte var port int switch bnType[0] { case "Prysm": - port = params.TestParams.Ports.PrysmBeaconNodeGatewayPort + port = params.TestParams.Ports.PrysmBeaconNodeHTTPPort case "Lighthouse": port = params.TestParams.Ports.LighthouseBeaconNodeHTTPPort default: @@ -74,7 +74,7 @@ func doSSZGetRequest(template, requestPath string, beaconNodeIdx int, bnType ... var port int switch bnType[0] { case "Prysm": - port = params.TestParams.Ports.PrysmBeaconNodeGatewayPort + port = params.TestParams.Ports.PrysmBeaconNodeHTTPPort case "Lighthouse": port = params.TestParams.Ports.LighthouseBeaconNodeHTTPPort default: @@ -116,7 +116,7 @@ func doJSONPostRequest(template, requestPath string, beaconNodeIdx int, postObj, var port int switch bnType[0] { case "Prysm": - port = params.TestParams.Ports.PrysmBeaconNodeGatewayPort + port = params.TestParams.Ports.PrysmBeaconNodeHTTPPort case "Lighthouse": port = params.TestParams.Ports.LighthouseBeaconNodeHTTPPort default: diff --git a/testing/endtoend/evaluators/beaconapi/verify.go b/testing/endtoend/evaluators/beaconapi/verify.go index baa9a12d2068..f4daa391a732 100644 --- a/testing/endtoend/evaluators/beaconapi/verify.go +++ b/testing/endtoend/evaluators/beaconapi/verify.go @@ -154,7 +154,7 @@ func postEvaluation(nodeIdx int, requests map[string]endpoint, epoch primitives. if err := bb.UnmarshalSSZ(blindedBlockData.getSszResp()); err != nil { return errors.Wrap(err, msgSSZUnmarshalFailed) } - } else { + } else if epoch < params.BeaconConfig().ElectraForkEpoch { b := ðpb.SignedBeaconBlockDeneb{} if err := b.UnmarshalSSZ(blockData.getSszResp()); err != nil { return errors.Wrap(err, msgSSZUnmarshalFailed) @@ -163,6 +163,15 @@ func postEvaluation(nodeIdx int, requests map[string]endpoint, epoch primitives. if err := bb.UnmarshalSSZ(blindedBlockData.getSszResp()); err != nil { return errors.Wrap(err, msgSSZUnmarshalFailed) } + } else { + b := ðpb.SignedBeaconBlockElectra{} + if err := b.UnmarshalSSZ(blockData.getSszResp()); err != nil { + return errors.Wrap(err, msgSSZUnmarshalFailed) + } + bb := ðpb.SignedBlindedBeaconBlockElectra{} + if err := bb.UnmarshalSSZ(blindedBlockData.getSszResp()); err != nil { + return errors.Wrap(err, msgSSZUnmarshalFailed) + } } // verify that dependent root of proposer duties matches block header @@ -181,7 +190,7 @@ func postEvaluation(nodeIdx int, requests map[string]endpoint, epoch primitives. } // perform a health check - basePath := fmt.Sprintf(v1PathTemplate, params2.TestParams.Ports.PrysmBeaconNodeGatewayPort+nodeIdx) + basePath := fmt.Sprintf(v1PathTemplate, params2.TestParams.Ports.PrysmBeaconNodeHTTPPort+nodeIdx) resp, err := http.Get(basePath + "/node/health") if err != nil { return errors.Wrap(err, "could not perform a health check") diff --git a/testing/endtoend/evaluators/builder.go b/testing/endtoend/evaluators/builder.go index e9a7f8ebc21b..c696e8982da9 100644 --- a/testing/endtoend/evaluators/builder.go +++ b/testing/endtoend/evaluators/builder.go @@ -3,11 +3,13 @@ package evaluators import ( "context" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/ssz" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/endtoend/policies" e2etypes "github.com/prysmaticlabs/prysm/v5/testing/endtoend/types" "github.com/prysmaticlabs/prysm/v5/time/slots" @@ -64,7 +66,7 @@ func builderActive(_ *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) err if err != nil { return err } - if forkStartSlot == b.Block().Slot() || forkStartSlot+1 == b.Block().Slot() { + if forkStartSlot == b.Block().Slot() || forkStartSlot+1 == b.Block().Slot() || lowestBound <= 1 { // Skip fork slot and the next one, as we don't send FCUs yet. continue } @@ -82,10 +84,10 @@ func builderActive(_ *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) err continue } if string(execPayload.ExtraData()) != "prysm-builder" { - return errors.Errorf("block with slot %d was not built by the builder. It has an extra data of %s", b.Block().Slot(), string(execPayload.ExtraData())) + return errors.Errorf("%s block with slot %d was not built by the builder. It has an extra data of %s and txRoot of %s", version.String(b.Version()), b.Block().Slot(), string(execPayload.ExtraData()), hexutil.Encode(txRoot)) } if execPayload.GasLimit() == 0 { - return errors.Errorf("block with slot %d has a gas limit of 0, when it should be in the 30M range", b.Block().Slot()) + return errors.Errorf("%s block with slot %d has a gas limit of 0, when it should be in the 30M range", version.String(b.Version()), b.Block().Slot()) } } if lowestBound == currEpoch { @@ -107,7 +109,7 @@ func builderActive(_ *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) err if err != nil { return err } - if forkStartSlot == b.Block().Slot() || forkStartSlot+1 == b.Block().Slot() { + if forkStartSlot == b.Block().Slot() || forkStartSlot+1 == b.Block().Slot() || lowestBound <= 1 { // Skip fork slot and the next one, as we don't send FCUs yet. continue } @@ -125,10 +127,10 @@ func builderActive(_ *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) err continue } if string(execPayload.ExtraData()) != "prysm-builder" { - return errors.Errorf("block with slot %d was not built by the builder. It has an extra data of %s", b.Block().Slot(), string(execPayload.ExtraData())) + return errors.Errorf("%s block with slot %d was not built by the builder. It has an extra data of %s and txRoot of %s", version.String(b.Version()), b.Block().Slot(), string(execPayload.ExtraData()), hexutil.Encode(txRoot)) } if execPayload.GasLimit() == 0 { - return errors.Errorf("block with slot %d has a gas limit of 0, when it should be in the 30M range", b.Block().Slot()) + return errors.Errorf("%s block with slot %d has a gas limit of 0, when it should be in the 30M range", version.String(b.Version()), b.Block().Slot()) } } return nil diff --git a/testing/endtoend/evaluators/execution_engine.go b/testing/endtoend/evaluators/execution_engine.go index f02dae04c4fd..98f0a59e57c0 100644 --- a/testing/endtoend/evaluators/execution_engine.go +++ b/testing/endtoend/evaluators/execution_engine.go @@ -27,7 +27,7 @@ var OptimisticSyncEnabled = types.Evaluator{ func optimisticSyncEnabled(_ *types.EvaluationContext, conns ...*grpc.ClientConn) error { for nodeIndex := range conns { - path := fmt.Sprintf("http://localhost:%d/eth/v1/beacon/blinded_blocks/head", params.TestParams.Ports.PrysmBeaconNodeGatewayPort+nodeIndex) + path := fmt.Sprintf("http://localhost:%d/eth/v1/beacon/blinded_blocks/head", params.TestParams.Ports.PrysmBeaconNodeHTTPPort+nodeIndex) resp := structs.GetBlockV2Response{} httpResp, err := http.Get(path) // #nosec G107 -- path can't be constant because it depends on port param and node index if err != nil { @@ -53,7 +53,7 @@ func optimisticSyncEnabled(_ *types.EvaluationContext, conns ...*grpc.ClientConn return err } for i := startSlot; i <= primitives.Slot(headSlot); i++ { - path = fmt.Sprintf("http://localhost:%d/eth/v1/beacon/blinded_blocks/%d", params.TestParams.Ports.PrysmBeaconNodeGatewayPort+nodeIndex, i) + path = fmt.Sprintf("http://localhost:%d/eth/v1/beacon/blinded_blocks/%d", params.TestParams.Ports.PrysmBeaconNodeHTTPPort+nodeIndex, i) resp = structs.GetBlockV2Response{} httpResp, err = http.Get(path) // #nosec G107 -- path can't be constant because it depends on port param and node index if err != nil { @@ -130,6 +130,15 @@ func retrieveHeadSlot(resp *structs.GetBlockV2Response) (uint64, error) { if err != nil { return 0, err } + case version.String(version.Electra): + b := &structs.BeaconBlockElectra{} + if err := json.Unmarshal(resp.Data.Message, b); err != nil { + return 0, err + } + headSlot, err = strconv.ParseUint(b.Slot, 10, 64) + if err != nil { + return 0, err + } default: return 0, errors.New("no valid block type retrieved") } diff --git a/testing/endtoend/evaluators/fork.go b/testing/endtoend/evaluators/fork.go index 54463043585a..1bf061ed6c58 100644 --- a/testing/endtoend/evaluators/fork.go +++ b/testing/endtoend/evaluators/fork.go @@ -53,6 +53,7 @@ var CapellaForkTransition = types.Evaluator{ Evaluation: capellaForkOccurs, } +// DenebForkTransition ensures that the Deneb hard fork has occurred successfully var DenebForkTransition = types.Evaluator{ Name: "deneb_fork_transition_%d", Policy: func(e primitives.Epoch) bool { @@ -62,6 +63,16 @@ var DenebForkTransition = types.Evaluator{ Evaluation: denebForkOccurs, } +// ElectraForkTransition ensures that the electra hard fork has occurred successfully +var ElectraForkTransition = types.Evaluator{ + Name: "electra_fork_transition_%d", + Policy: func(e primitives.Epoch) bool { + fEpoch := params.BeaconConfig().ElectraForkEpoch + return policies.OnEpoch(fEpoch)(e) + }, + Evaluation: electraForkOccurs, +} + func altairForkOccurs(_ *types.EvaluationContext, conns ...*grpc.ClientConn) error { conn := conns[0] client := ethpb.NewBeaconNodeValidatorClient(conn) @@ -234,3 +245,46 @@ func denebForkOccurs(_ *types.EvaluationContext, conns ...*grpc.ClientConn) erro } return nil } + +func electraForkOccurs(_ *types.EvaluationContext, conns ...*grpc.ClientConn) error { + conn := conns[0] + client := ethpb.NewBeaconNodeValidatorClient(conn) + ctx, cancel := context.WithTimeout(context.Background(), streamDeadline) + defer cancel() + stream, err := client.StreamBlocksAltair(ctx, ðpb.StreamBlocksRequest{VerifiedOnly: true}) + if err != nil { + return errors.Wrap(err, "failed to get stream") + } + fSlot, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch) + if err != nil { + return err + } + if errors.Is(ctx.Err(), context.Canceled) { + return errors.New("context canceled prematurely") + } + res, err := stream.Recv() + if err != nil { + return err + } + if res == nil || res.Block == nil { + return errors.New("nil block returned by beacon node") + } + + if res.GetBlock() == nil { + return errors.New("nil block returned by beacon node") + } + if res.GetElectraBlock() == nil { + return errors.Errorf("non-electra block returned after the fork with type %T", res.Block) + } + blk, err := blocks.NewSignedBeaconBlock(res.GetElectraBlock()) + if err != nil { + return err + } + if err := blocks.BeaconBlockIsNil(blk); err != nil { + return err + } + if blk.Block().Slot() < fSlot { + return errors.Errorf("wanted a block at slot >= %d but received %d", fSlot, blk.Block().Slot()) + } + return nil +} diff --git a/testing/endtoend/evaluators/metrics.go b/testing/endtoend/evaluators/metrics.go index ea100eb41dcb..bf76b767f909 100644 --- a/testing/endtoend/evaluators/metrics.go +++ b/testing/endtoend/evaluators/metrics.go @@ -207,7 +207,7 @@ func valueOfTopic(pageContent, topic string) (int, error) { } var result float64 for i, stringIndex := range indexesFound { - // Only performing every third result found since theres 2 comments above every metric. + // Only performing every third result found since there are 2 comments above every metric. if i == 0 || i%2 != 0 { continue } diff --git a/testing/endtoend/evaluators/operations.go b/testing/endtoend/evaluators/operations.go index b683f8c863b3..ec19c89adc3f 100644 --- a/testing/endtoend/evaluators/operations.go +++ b/testing/endtoend/evaluators/operations.go @@ -230,10 +230,16 @@ func activatesDepositedValidators(ec *e2etypes.EvaluationContext, conns ...*grpc continue } delete(expected, key) - if v.ActivationEpoch != epoch { + // Validator can't be activated yet . + if v.ActivationEligibilityEpoch > chainHead.FinalizedEpoch { continue } - deposits++ + if v.ActivationEpoch < epoch { + continue + } + if v.ActivationEpoch == epoch { + deposits++ + } if v.EffectiveBalance < params.BeaconConfig().MaxEffectiveBalance { lowBalance++ } @@ -250,7 +256,7 @@ func activatesDepositedValidators(ec *e2etypes.EvaluationContext, conns ...*grpc return fmt.Errorf("missing %d validators for post-genesis deposits", len(expected)) } - if uint64(deposits) != params.BeaconConfig().MinPerEpochChurnLimit { + if deposits > 0 && uint64(deposits) != params.BeaconConfig().MinPerEpochChurnLimit { return fmt.Errorf("expected %d deposits to be processed in epoch %d, received %d", params.BeaconConfig().MinPerEpochChurnLimit, epoch, deposits) } @@ -318,6 +324,15 @@ func depositedValidatorsAreActive(ec *e2etypes.EvaluationContext, conns ...*grpc delete(expected, key) continue } + // This is to handle the changed validator activation procedure post-electra. + if v.ActivationEligibilityEpoch != math.MaxUint64 && v.ActivationEligibilityEpoch > chainHead.FinalizedEpoch { + delete(expected, key) + continue + } + if v.ActivationEpoch != math.MaxUint64 && v.ActivationEpoch > chainHead.HeadEpoch { + delete(expected, key) + continue + } if !corehelpers.IsActiveValidator(v, chainHead.HeadEpoch) { inactive++ } @@ -511,8 +526,16 @@ func validatorsVoteWithTheMajority(ec *e2etypes.EvaluationContext, conns ...*grp b := blk.GetBlindedDenebBlock().Message slot = b.Slot vote = b.Body.Eth1Data.BlockHash + case *ethpb.BeaconBlockContainer_ElectraBlock: + b := blk.GetElectraBlock().Block + slot = b.Slot + vote = b.Body.Eth1Data.BlockHash + case *ethpb.BeaconBlockContainer_BlindedElectraBlock: + b := blk.GetBlindedElectraBlock().Message + slot = b.Slot + vote = b.Body.Eth1Data.BlockHash default: - return errors.New("block neither phase0,altair or bellatrix") + return fmt.Errorf("block of type %T is unknown", blk.Block) } ec.SeenVotes[slot] = vote @@ -626,7 +649,7 @@ func submitWithdrawal(ec *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) }) } - beaconAPIClient, err := beacon.NewClient(fmt.Sprintf("http://localhost:%d/eth/v1", e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort)) // only uses the first node so no updates to port + beaconAPIClient, err := beacon.NewClient(fmt.Sprintf("http://localhost:%d/eth/v1", e2e.TestParams.Ports.PrysmBeaconNodeHTTPPort)) // only uses the first node so no updates to port if err != nil { return err } diff --git a/testing/endtoend/evaluators/validator.go b/testing/endtoend/evaluators/validator.go index e8d9b4e2a403..07720bbc6113 100644 --- a/testing/endtoend/evaluators/validator.go +++ b/testing/endtoend/evaluators/validator.go @@ -126,6 +126,12 @@ func validatorsParticipating(_ *types.EvaluationContext, conns ...*grpc.ClientCo if e2eparams.TestParams.LighthouseBeaconNodeCount != 0 { expected = float32(expectedMulticlientParticipation) } + if participation.Epoch == params.BeaconConfig().ElectraForkEpoch { + // The first slot of Electra will be missed due to the switching of attestation types + // 5/6 slots =~0.83 + // validator REST always is slightly reduced at ~0.82 + expected = 0.82 + } if participation.Epoch > 0 && participation.Epoch.Sub(1) == params.BeaconConfig().BellatrixForkEpoch { // Reduce Participation requirement to 95% to account for longer EE calls for // the merge block. Target and head will likely be missed for a few validators at @@ -133,7 +139,7 @@ func validatorsParticipating(_ *types.EvaluationContext, conns ...*grpc.ClientCo expected = 0.95 } if partRate < expected { - path := fmt.Sprintf("http://localhost:%d/eth/v2/debug/beacon/states/head", e2eparams.TestParams.Ports.PrysmBeaconNodeGatewayPort) + path := fmt.Sprintf("http://localhost:%d/eth/v2/debug/beacon/states/head", e2eparams.TestParams.Ports.PrysmBeaconNodeHTTPPort) resp := structs.GetBeaconStateV2Response{} httpResp, err := http.Get(path) // #nosec G107 -- path can't be constant because it depends on port param if err != nil { @@ -172,6 +178,18 @@ func validatorsParticipating(_ *types.EvaluationContext, conns ...*grpc.ClientCo return err } respPrevEpochParticipation = st.PreviousEpochParticipation + case version.String(version.Deneb): + st := &structs.BeaconStateDeneb{} + if err = json.Unmarshal(resp.Data, st); err != nil { + return err + } + respPrevEpochParticipation = st.PreviousEpochParticipation + case version.String(version.Electra): + st := &structs.BeaconStateElectra{} + if err = json.Unmarshal(resp.Data, st); err != nil { + return err + } + respPrevEpochParticipation = st.PreviousEpochParticipation default: return fmt.Errorf("unrecognized version %s", resp.Version) } @@ -233,7 +251,7 @@ func validatorsSyncParticipation(_ *types.EvaluationContext, conns ...*grpc.Clie return errors.Wrapf(err, "block type doesn't exist for block at epoch %d", lowestBound) } - if b.IsNil() { + if b == nil || b.IsNil() { return errors.New("nil block provided") } forkStartSlot, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch) @@ -274,7 +292,7 @@ func validatorsSyncParticipation(_ *types.EvaluationContext, conns ...*grpc.Clie return errors.Wrapf(err, "block type doesn't exist for block at epoch %d", lowestBound) } - if b.IsNil() { + if b == nil || b.IsNil() { return errors.New("nil block provided") } forkSlot, err := slots.EpochStart(params.BeaconConfig().AltairForkEpoch) @@ -329,6 +347,12 @@ func syncCompatibleBlockFromCtr(container *ethpb.BeaconBlockContainer) (interfac if container.GetBlindedDenebBlock() != nil { return blocks.NewSignedBeaconBlock(container.GetBlindedDenebBlock()) } + if container.GetElectraBlock() != nil { + return blocks.NewSignedBeaconBlock(container.GetElectraBlock()) + } + if container.GetBlindedElectraBlock() != nil { + return blocks.NewSignedBeaconBlock(container.GetBlindedElectraBlock()) + } return nil, errors.New("no supported block type in container") } diff --git a/testing/endtoend/geth_deps.go b/testing/endtoend/geth_deps.go index b021138818c7..d06d54c1bc50 100644 --- a/testing/endtoend/geth_deps.go +++ b/testing/endtoend/geth_deps.go @@ -12,7 +12,6 @@ import ( _ "github.com/ethereum/go-ethereum/eth" // Required for go-ethereum e2e. _ "github.com/ethereum/go-ethereum/eth/downloader" // Required for go-ethereum e2e. _ "github.com/ethereum/go-ethereum/ethclient" // Required for go-ethereum e2e. - _ "github.com/ethereum/go-ethereum/les" // Required for go-ethereum e2e. _ "github.com/ethereum/go-ethereum/log" // Required for go-ethereum e2e. _ "github.com/ethereum/go-ethereum/metrics" // Required for go-ethereum e2e. _ "github.com/ethereum/go-ethereum/node" // Required for go-ethereum e2e. diff --git a/testing/endtoend/helpers/helpers.go b/testing/endtoend/helpers/helpers.go index d9dbd29adfbc..ed982b6ed4c5 100644 --- a/testing/endtoend/helpers/helpers.go +++ b/testing/endtoend/helpers/helpers.go @@ -132,7 +132,7 @@ func WaitForTextInFile(src *os.File, match string) error { select { case <-ctx.Done(): - return fmt.Errorf("could not find requested text \"%s\" in %s before deadline:\n", match, f.Name()) + return fmt.Errorf("could not find requested text \"%s\" in %s before deadline", match, f.Name()) case <-foundChan: return nil case err = <-errChan: @@ -323,7 +323,7 @@ func NewLocalConnections(ctx context.Context, numConns int) ([]*grpc.ClientConn, func BeaconAPIHostnames(numConns int) []string { hostnames := make([]string, 0) for i := 0; i < numConns; i++ { - port := e2e.TestParams.Ports.PrysmBeaconNodeGatewayPort + i + port := e2e.TestParams.Ports.PrysmBeaconNodeHTTPPort + i hostnames = append(hostnames, net.JoinHostPort("127.0.0.1", strconv.Itoa(port))) } return hostnames @@ -358,7 +358,6 @@ func WaitOnNodes(ctx context.Context, nodes []e2etypes.ComponentRunner, nodesSta // Start nodes. g, ctx := errgroup.WithContext(ctx) for _, node := range nodes { - node := node g.Go(func() error { return node.Start(ctx) }) diff --git a/testing/endtoend/mainnet_e2e_test.go b/testing/endtoend/mainnet_e2e_test.go index 409b6bf8d6ee..dfdaf28dc489 100644 --- a/testing/endtoend/mainnet_e2e_test.go +++ b/testing/endtoend/mainnet_e2e_test.go @@ -10,10 +10,10 @@ import ( // Run mainnet e2e config with the current release validator against latest beacon node. func TestEndToEnd_MainnetConfig_ValidatorAtCurrentRelease(t *testing.T) { - r := e2eMainnet(t, true, false, types.InitForkCfg(version.Phase0, version.Deneb, params.E2EMainnetTestConfig())) + r := e2eMainnet(t, true, false, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2EMainnetTestConfig())) r.run() } func TestEndToEnd_MainnetConfig_MultiClient(t *testing.T) { - e2eMainnet(t, false, true, types.InitForkCfg(version.Phase0, version.Deneb, params.E2EMainnetTestConfig()), types.WithValidatorCrossClient()).run() + e2eMainnet(t, false, true, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2EMainnetTestConfig()), types.WithValidatorCrossClient()).run() } diff --git a/testing/endtoend/mainnet_scenario_e2e_test.go b/testing/endtoend/mainnet_scenario_e2e_test.go index 956dc9991278..1b9364083ab8 100644 --- a/testing/endtoend/mainnet_scenario_e2e_test.go +++ b/testing/endtoend/mainnet_scenario_e2e_test.go @@ -9,8 +9,10 @@ import ( ) func TestEndToEnd_MultiScenarioRun_Multiclient(t *testing.T) { - runner := e2eMainnet(t, false, true, types.InitForkCfg(version.Phase0, version.Deneb, params.E2EMainnetTestConfig()), types.WithEpochs(24)) - runner.config.Evaluators = scenarioEvalsMulti() + cfg := types.InitForkCfg(version.Bellatrix, version.Electra, params.E2EMainnetTestConfig()) + runner := e2eMainnet(t, false, true, cfg, types.WithEpochs(26)) + // override for scenario tests + runner.config.Evaluators = scenarioEvalsMulti(cfg) runner.config.EvalInterceptor = runner.multiScenarioMulticlient runner.scenarioRunner() } diff --git a/testing/endtoend/minimal_builder_e2e_test.go b/testing/endtoend/minimal_builder_e2e_test.go index 600adbcbd8f7..086467c1864c 100644 --- a/testing/endtoend/minimal_builder_e2e_test.go +++ b/testing/endtoend/minimal_builder_e2e_test.go @@ -9,11 +9,11 @@ import ( ) func TestEndToEnd_MinimalConfig_WithBuilder(t *testing.T) { - r := e2eMinimal(t, types.InitForkCfg(version.Phase0, version.Deneb, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithBuilder()) + r := e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithBuilder()) r.run() } func TestEndToEnd_MinimalConfig_WithBuilder_ValidatorRESTApi(t *testing.T) { - r := e2eMinimal(t, types.InitForkCfg(version.Phase0, version.Deneb, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithBuilder(), types.WithValidatorRESTApi()) + r := e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithBuilder(), types.WithValidatorRESTApi()) r.run() } diff --git a/testing/endtoend/minimal_e2e_test.go b/testing/endtoend/minimal_e2e_test.go index 0fedd8680c8c..c24de5b014ad 100644 --- a/testing/endtoend/minimal_e2e_test.go +++ b/testing/endtoend/minimal_e2e_test.go @@ -9,6 +9,6 @@ import ( ) func TestEndToEnd_MinimalConfig(t *testing.T) { - r := e2eMinimal(t, types.InitForkCfg(version.Phase0, version.Deneb, params.E2ETestConfig()), types.WithCheckpointSync()) + r := e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithCheckpointSync()) r.run() } diff --git a/testing/endtoend/minimal_scenario_e2e_test.go b/testing/endtoend/minimal_scenario_e2e_test.go index 33628927a709..ca6cd61e069e 100644 --- a/testing/endtoend/minimal_scenario_e2e_test.go +++ b/testing/endtoend/minimal_scenario_e2e_test.go @@ -9,30 +9,32 @@ import ( ) func TestEndToEnd_MultiScenarioRun(t *testing.T) { - runner := e2eMinimal(t, types.InitForkCfg(version.Phase0, version.Deneb, params.E2ETestConfig()), types.WithEpochs(26)) - - runner.config.Evaluators = scenarioEvals() + cfg := types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()) + runner := e2eMinimal(t, cfg, types.WithEpochs(28)) + // override for scenario tests + runner.config.Evaluators = scenarioEvals(cfg) runner.config.EvalInterceptor = runner.multiScenario runner.scenarioRunner() } func TestEndToEnd_MinimalConfig_Web3Signer(t *testing.T) { - e2eMinimal(t, types.InitForkCfg(version.Phase0, version.Deneb, params.E2ETestConfig()), types.WithRemoteSigner()).run() + e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithRemoteSigner()).run() } func TestEndToEnd_MinimalConfig_Web3Signer_PersistentKeys(t *testing.T) { - e2eMinimal(t, types.InitForkCfg(version.Phase0, version.Deneb, params.E2ETestConfig()), types.WithRemoteSignerAndPersistentKeysFile()).run() + e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithRemoteSignerAndPersistentKeysFile()).run() } func TestEndToEnd_MinimalConfig_ValidatorRESTApi(t *testing.T) { - e2eMinimal(t, types.InitForkCfg(version.Phase0, version.Deneb, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithValidatorRESTApi()).run() + e2eMinimal(t, types.InitForkCfg(version.Bellatrix, version.Electra, params.E2ETestConfig()), types.WithCheckpointSync(), types.WithValidatorRESTApi()).run() } func TestEndToEnd_ScenarioRun_EEOffline(t *testing.T) { t.Skip("TODO(#10242) Prysm is current unable to handle an offline e2e") - runner := e2eMinimal(t, types.InitForkCfg(version.Phase0, version.Deneb, params.E2ETestConfig())) - - runner.config.Evaluators = scenarioEvals() + cfg := types.InitForkCfg(version.Bellatrix, version.Deneb, params.E2ETestConfig()) + runner := e2eMinimal(t, cfg) + // override for scenario tests + runner.config.Evaluators = scenarioEvals(cfg) runner.config.EvalInterceptor = runner.eeOffline runner.scenarioRunner() } diff --git a/testing/endtoend/params/params.go b/testing/endtoend/params/params.go index dd71b9c53cdd..e15c3f09bc0f 100644 --- a/testing/endtoend/params/params.go +++ b/testing/endtoend/params/params.go @@ -47,14 +47,14 @@ type ports struct { PrysmBeaconNodeUDPPort int PrysmBeaconNodeQUICPort int PrysmBeaconNodeTCPPort int - PrysmBeaconNodeGatewayPort int + PrysmBeaconNodeHTTPPort int PrysmBeaconNodeMetricsPort int PrysmBeaconNodePprofPort int LighthouseBeaconNodeP2PPort int LighthouseBeaconNodeHTTPPort int LighthouseBeaconNodeMetricsPort int ValidatorMetricsPort int - ValidatorGatewayPort int + ValidatorHTTPPort int JaegerTracingPort int } @@ -120,6 +120,9 @@ var StandardLighthouseNodeCount = 2 // DepositCount is the number of deposits the E2E runner should make to evaluate post-genesis deposit processing. var DepositCount = uint64(64) +// PostElectraDepositCount is the number of deposits the E2E runner should make to evaluate post-electra deposit processing. +var PostElectraDepositCount = uint64(32) + // PregenesisExecCreds is the number of withdrawal credentials of genesis validators which use an execution address. var PregenesisExecCreds = uint64(8) @@ -146,7 +149,7 @@ const ( prysmBeaconNodeUDPPort = prysmBeaconNodeRPCPort + portSpan prysmBeaconNodeQUICPort = prysmBeaconNodeRPCPort + 2*portSpan prysmBeaconNodeTCPPort = prysmBeaconNodeRPCPort + 3*portSpan - prysmBeaconNodeGatewayPort = prysmBeaconNodeRPCPort + 4*portSpan + prysmBeaconNodeHTTPPort = prysmBeaconNodeRPCPort + 4*portSpan prysmBeaconNodeMetricsPort = prysmBeaconNodeRPCPort + 5*portSpan prysmBeaconNodePprofPort = prysmBeaconNodeRPCPort + 6*portSpan @@ -154,8 +157,8 @@ const ( lighthouseBeaconNodeHTTPPort = lighthouseBeaconNodeP2PPort + portSpan lighthouseBeaconNodeMetricsPort = lighthouseBeaconNodeP2PPort + 2*portSpan - validatorGatewayPort = 6150 - validatorMetricsPort = validatorGatewayPort + portSpan + validatorHTTPPort = 6150 + validatorMetricsPort = validatorHTTPPort + portSpan jaegerTracingPort = 9150 @@ -339,7 +342,7 @@ func initializeStandardPorts(shardCount, shardIndex int, ports *ports, existingR if err != nil { return err } - beaconNodeGatewayPort, err := port(prysmBeaconNodeGatewayPort, shardCount, shardIndex, existingRegistrations) + beaconNodeHTTPPort, err := port(prysmBeaconNodeHTTPPort, shardCount, shardIndex, existingRegistrations) if err != nil { return err } @@ -351,7 +354,7 @@ func initializeStandardPorts(shardCount, shardIndex int, ports *ports, existingR if err != nil { return err } - validatorGatewayPort, err := port(validatorGatewayPort, shardCount, shardIndex, existingRegistrations) + validatorHTTPPort, err := port(validatorHTTPPort, shardCount, shardIndex, existingRegistrations) if err != nil { return err } @@ -374,11 +377,11 @@ func initializeStandardPorts(shardCount, shardIndex int, ports *ports, existingR ports.PrysmBeaconNodeUDPPort = beaconNodeUDPPort ports.PrysmBeaconNodeQUICPort = beaconNodeQUICPort ports.PrysmBeaconNodeTCPPort = beaconNodeTCPPort - ports.PrysmBeaconNodeGatewayPort = beaconNodeGatewayPort + ports.PrysmBeaconNodeHTTPPort = beaconNodeHTTPPort ports.PrysmBeaconNodeMetricsPort = beaconNodeMetricsPort ports.PrysmBeaconNodePprofPort = beaconNodePprofPort ports.ValidatorMetricsPort = validatorMetricsPort - ports.ValidatorGatewayPort = validatorGatewayPort + ports.ValidatorHTTPPort = validatorHTTPPort ports.JaegerTracingPort = jaegerTracingPort return nil } diff --git a/testing/endtoend/params/params_test.go b/testing/endtoend/params/params_test.go index e0f795984b37..cc7fbfea5ff1 100644 --- a/testing/endtoend/params/params_test.go +++ b/testing/endtoend/params/params_test.go @@ -31,7 +31,7 @@ func TestStandardPorts(t *testing.T) { testPorts := &ports{} assert.NoError(t, initializeStandardPorts(2, 0, testPorts, &existingRegistrations)) assert.Equal(t, 17, len(existingRegistrations)) - assert.NotEqual(t, 0, testPorts.PrysmBeaconNodeGatewayPort) + assert.NotEqual(t, 0, testPorts.PrysmBeaconNodeHTTPPort) assert.NotEqual(t, 0, testPorts.PrysmBeaconNodeTCPPort) assert.NotEqual(t, 0, testPorts.JaegerTracingPort) } diff --git a/testing/endtoend/types/fork.go b/testing/endtoend/types/fork.go index 8e4a6cad92e7..775194f8e1ba 100644 --- a/testing/endtoend/types/fork.go +++ b/testing/endtoend/types/fork.go @@ -25,6 +25,12 @@ func InitForkCfg(start, end int, c *params.BeaconChainConfig) *params.BeaconChai if start >= version.Deneb { c.DenebForkEpoch = 0 } + if start >= version.Electra { + c.ElectraForkEpoch = 0 + } + if end < version.Electra { + c.ElectraForkEpoch = math.MaxUint64 + } if end < version.Deneb { c.DenebForkEpoch = math.MaxUint64 } diff --git a/testing/endtoend/types/types.go b/testing/endtoend/types/types.go index d5257a76f43f..62fdff879e23 100644 --- a/testing/endtoend/types/types.go +++ b/testing/endtoend/types/types.go @@ -116,6 +116,9 @@ const ( // PostGenesisDepositBatch deposits are sent to test that deposits appear in blocks as expected // and validators become active. PostGenesisDepositBatch + // PostElectraDepositBatch deposits are sent to test that deposits sent after electra has been transitioned + // work as expected. + PostElectraDepositBatch ) // DepositBalancer represents a type that can sum, by validator, all deposits made in E2E prior to the function call. diff --git a/testing/middleware/builder/BUILD.bazel b/testing/middleware/builder/BUILD.bazel index 349fd15d4fd8..97dcca3adcad 100644 --- a/testing/middleware/builder/BUILD.bazel +++ b/testing/middleware/builder/BUILD.bazel @@ -12,6 +12,7 @@ go_library( "//api/client/builder:go_default_library", "//api/server/structs:go_default_library", "//beacon-chain/core/signing:go_default_library", + "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", @@ -22,13 +23,13 @@ go_library( "//network/authorization:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "@com_github_ethereum_go_ethereum//beacon/engine:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_ethereum_go_ethereum//rpc:go_default_library", "@com_github_ethereum_go_ethereum//trie:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", ], diff --git a/testing/middleware/builder/builder.go b/testing/middleware/builder/builder.go index a0ed717c0fd3..cff17b467b1d 100644 --- a/testing/middleware/builder/builder.go +++ b/testing/middleware/builder/builder.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/json" - "errors" "fmt" "io" "math/big" @@ -21,10 +20,11 @@ import ( gethTypes "github.com/ethereum/go-ethereum/core/types" gethRPC "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" - gMux "github.com/gorilla/mux" + "github.com/pkg/errors" builderAPI "github.com/prysmaticlabs/prysm/v5/api/client/builder" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" @@ -35,14 +35,15 @@ import ( "github.com/prysmaticlabs/prysm/v5/network/authorization" v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/sirupsen/logrus" ) const ( - statusPath = "/eth/v1/builder/status" - registerPath = "/eth/v1/builder/validators" - headerPath = "/eth/v1/builder/header/{slot:[0-9]+}/{parent_hash:0x[a-fA-F0-9]+}/{pubkey:0x[a-fA-F0-9]+}" - blindedPath = "/eth/v1/builder/blinded_blocks" + statusPath = "GET /eth/v1/builder/status" + registerPath = "POST /eth/v1/builder/validators" + headerPath = "GET /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}" + blindedPath = "POST /eth/v1/builder/blinded_blocks" // ForkchoiceUpdatedMethod v1 request string for JSON-RPC. ForkchoiceUpdatedMethod = "engine_forkchoiceUpdatedV1" @@ -56,6 +57,8 @@ const ( GetPayloadMethodV2 = "engine_getPayloadV2" // GetPayloadMethodV3 v3 request string for JSON-RPC. GetPayloadMethodV3 = "engine_getPayloadV3" + // GetPayloadMethodV4 v4 request string for JSON-RPC. + GetPayloadMethodV4 = "engine_getPayloadV4" ) var ( @@ -86,32 +89,16 @@ type ExecPayloadResponse struct { Version string `json:"version"` Data *v1.ExecutionPayload `json:"data"` } - -type ExecHeaderResponseCapella struct { - Version string `json:"version"` - Data struct { - Signature hexutil.Bytes `json:"signature"` - Message *builderAPI.BuilderBidCapella `json:"message"` - } `json:"data"` -} - -type ExecHeaderResponseDeneb struct { - Version string `json:"version"` - Data struct { - Signature hexutil.Bytes `json:"signature"` - Message *builderAPI.BuilderBidDeneb `json:"message"` - } `json:"data"` -} - type Builder struct { cfg *config address string execClient *gethRPC.Client currId *v1.PayloadIDBytes prevBeaconRoot []byte + currVersion int currPayload interfaces.ExecutionData blobBundle *v1.BlobsBundle - mux *gMux.Router + mux *http.ServeMux validatorMap map[string]*eth.ValidatorRegistrationV1 valLock sync.RWMutex srv *http.Server @@ -141,9 +128,8 @@ func New(opts ...Option) (*Builder, error) { if err != nil { return nil, err } - mux := http.NewServeMux() - mux.Handle("/", p) - router := gMux.NewRouter() + router := http.NewServeMux() + router.Handle("/", p) router.HandleFunc(statusPath, func(writer http.ResponseWriter, request *http.Request) { writer.WriteHeader(http.StatusOK) }) @@ -152,7 +138,7 @@ func New(opts ...Option) (*Builder, error) { router.HandleFunc(blindedPath, p.handleBlindedBlock) addr := net.JoinHostPort(p.cfg.builderHost, strconv.Itoa(p.cfg.builderPort)) srv := &http.Server{ - Handler: mux, + Handler: router, Addr: addr, ReadHeaderTimeout: time.Second, } @@ -303,13 +289,17 @@ func (p *Builder) registerValidators(w http.ResponseWriter, req *http.Request) { } func (p *Builder) handleHeaderRequest(w http.ResponseWriter, req *http.Request) { - urlParams := gMux.Vars(req) - pHash := urlParams["parent_hash"] + pHash := req.PathValue("parent_hash") if pHash == "" { http.Error(w, "no valid parent hash", http.StatusBadRequest) return } - reqSlot := urlParams["slot"] + _, err := bytesutil.DecodeHexWithLength(pHash, common.HashLength) + if err != nil { + http.Error(w, "invalid parent hash", http.StatusBadRequest) + return + } + reqSlot := req.PathValue("slot") if reqSlot == "" { http.Error(w, "no valid slot provided", http.StatusBadRequest) return @@ -319,8 +309,23 @@ func (p *Builder) handleHeaderRequest(w http.ResponseWriter, req *http.Request) http.Error(w, "invalid slot provided", http.StatusBadRequest) return } + reqPubkey := req.PathValue("pubkey") + if reqPubkey == "" { + http.Error(w, "no valid pubkey provided", http.StatusBadRequest) + return + } + _, err = bytesutil.DecodeHexWithLength(reqPubkey, fieldparams.BLSPubkeyLength) + if err != nil { + http.Error(w, "invalid pubkey", http.StatusBadRequest) + return + } ax := types.Slot(slot) currEpoch := types.Epoch(ax / params.BeaconConfig().SlotsPerEpoch) + if currEpoch >= params.BeaconConfig().ElectraForkEpoch { + p.handleHeaderRequestElectra(w) + return + } + if currEpoch >= params.BeaconConfig().DenebForkEpoch { p.handleHeaderRequestDeneb(w) return @@ -401,6 +406,7 @@ func (p *Builder) handleHeaderRequest(w http.ResponseWriter, req *http.Request) http.Error(w, err.Error(), http.StatusInternalServerError) return } + p.currVersion = version.Bellatrix p.currPayload = wObj w.WriteHeader(http.StatusOK) } @@ -461,7 +467,7 @@ func (p *Builder) handleHeaderRequestCapella(w http.ResponseWriter) { return } sig := secKey.Sign(rt[:]) - hdrResp := &ExecHeaderResponseCapella{ + hdrResp := &builderAPI.ExecHeaderResponseCapella{ Version: "capella", Data: struct { Signature hexutil.Bytes `json:"signature"` @@ -478,6 +484,7 @@ func (p *Builder) handleHeaderRequestCapella(w http.ResponseWriter) { http.Error(w, err.Error(), http.StatusInternalServerError) return } + p.currVersion = version.Capella p.currPayload = wObj w.WriteHeader(http.StatusOK) } @@ -546,7 +553,7 @@ func (p *Builder) handleHeaderRequestDeneb(w http.ResponseWriter) { return } sig := secKey.Sign(rt[:]) - hdrResp := &ExecHeaderResponseDeneb{ + hdrResp := &builderAPI.ExecHeaderResponseDeneb{ Version: "deneb", Data: struct { Signature hexutil.Bytes `json:"signature"` @@ -563,12 +570,148 @@ func (p *Builder) handleHeaderRequestDeneb(w http.ResponseWriter) { http.Error(w, err.Error(), http.StatusInternalServerError) return } + p.currVersion = version.Deneb + p.currPayload = wObj + p.blobBundle = b.BlobsBundle + w.WriteHeader(http.StatusOK) +} + +func (p *Builder) handleHeaderRequestElectra(w http.ResponseWriter) { + b, err := p.retrievePendingBlockElectra() + if err != nil { + p.cfg.logger.WithError(err).Error("Could not retrieve pending block") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + secKey, err := bls.RandKey() + if err != nil { + p.cfg.logger.WithError(err).Error("Could not retrieve secret key") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + v := big.NewInt(0).SetBytes(bytesutil.ReverseByteOrder(b.Value)) + // we set the payload value as twice its actual one so that it always chooses builder payloads vs local payloads + v = v.Mul(v, big.NewInt(2)) + wObj, err := blocks.WrappedExecutionPayloadDeneb(b.Payload) + if err != nil { + p.cfg.logger.WithError(err).Error("Could not wrap execution payload") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + hdr, err := blocks.PayloadToHeaderElectra(wObj) + if err != nil { + p.cfg.logger.WithError(err).Error("Could not make payload into header") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + val := builderAPI.Uint256{Int: v} + var commitments []hexutil.Bytes + for _, c := range b.BlobsBundle.KzgCommitments { + copiedC := c + commitments = append(commitments, copiedC) + } + wrappedHdr := &builderAPI.ExecutionPayloadHeaderDeneb{ExecutionPayloadHeaderDeneb: hdr} + requests, err := b.GetDecodedExecutionRequests() + if err != nil { + p.cfg.logger.WithError(err).Error("Could not get decoded execution requests") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + rv1 := &builderAPI.ExecutionRequestsV1{ + Deposits: make([]*builderAPI.DepositRequestV1, len(requests.Deposits)), + Withdrawals: make([]*builderAPI.WithdrawalRequestV1, len(requests.Withdrawals)), + Consolidations: make([]*builderAPI.ConsolidationRequestV1, len(requests.Consolidations)), + } + + for i, d := range requests.Deposits { + amount := new(big.Int).SetUint64(d.Amount) + index := new(big.Int).SetUint64(d.Index) + dr := &builderAPI.DepositRequestV1{ + PubKey: d.Pubkey, + WithdrawalCredentials: d.WithdrawalCredentials, + Amount: builderAPI.Uint256{Int: amount}, + Signature: d.Signature, + Index: builderAPI.Uint256{Int: index}, + } + rv1.Deposits[i] = dr + } + + for i, w := range requests.Withdrawals { + bi := new(big.Int).SetUint64(w.Amount) + wr := &builderAPI.WithdrawalRequestV1{ + SourceAddress: w.SourceAddress, + ValidatorPubkey: w.ValidatorPubkey, + Amount: builderAPI.Uint256{Int: bi}, + } + rv1.Withdrawals[i] = wr + } + + for i, c := range requests.Consolidations { + cr := &builderAPI.ConsolidationRequestV1{ + SourceAddress: c.SourceAddress, + SourcePubkey: c.SourcePubkey, + TargetPubkey: c.TargetPubkey, + } + rv1.Consolidations[i] = cr + } + + bid := &builderAPI.BuilderBidElectra{ + Header: wrappedHdr, + BlobKzgCommitments: commitments, + Value: val, + Pubkey: secKey.PublicKey().Marshal(), + ExecutionRequests: rv1, + } + + sszBid := ð.BuilderBidElectra{ + Header: hdr, + BlobKzgCommitments: b.BlobsBundle.KzgCommitments, + Value: val.SSZBytes(), + Pubkey: secKey.PublicKey().Marshal(), + ExecutionRequests: requests, + } + d, err := signing.ComputeDomain(params.BeaconConfig().DomainApplicationBuilder, + nil, /* fork version */ + nil /* genesis val root */) + if err != nil { + p.cfg.logger.WithError(err).Error("Could not compute the domain") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + rt, err := signing.ComputeSigningRoot(sszBid, d) + if err != nil { + p.cfg.logger.WithError(err).Error("Could not compute the signing root") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + sig := secKey.Sign(rt[:]) + hdrResp := &builderAPI.ExecHeaderResponseElectra{ + Version: "electra", + Data: struct { + Signature hexutil.Bytes `json:"signature"` + Message *builderAPI.BuilderBidElectra `json:"message"` + }{ + Signature: sig.Marshal(), + Message: bid, + }, + } + + err = json.NewEncoder(w).Encode(hdrResp) + if err != nil { + p.cfg.logger.WithError(err).Error("Could not encode response") + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + p.currVersion = version.Electra p.currPayload = wObj p.blobBundle = b.BlobsBundle w.WriteHeader(http.StatusOK) } func (p *Builder) handleBlindedBlock(w http.ResponseWriter, req *http.Request) { + // TODO update for fork specific sb := &builderAPI.SignedBlindedBeaconBlockBellatrix{ SignedBlindedBeaconBlockBellatrix: ð.SignedBlindedBeaconBlockBellatrix{}, } @@ -583,7 +726,7 @@ func (p *Builder) handleBlindedBlock(w http.ResponseWriter, req *http.Request) { return } - resp, err := builderAPI.ExecutionPayloadResponseFromData(p.currPayload, p.blobBundle) + resp, err := ExecutionPayloadResponseFromData(p.currVersion, p.currPayload, p.blobBundle) if err != nil { p.cfg.logger.WithError(err).Error("Could not convert the payload") http.Error(w, err.Error(), http.StatusInternalServerError) @@ -598,6 +741,48 @@ func (p *Builder) handleBlindedBlock(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) } +var errInvalidTypeConversion = errors.New("unable to translate between api and foreign type") + +// ExecutionPayloadResponseFromData converts an ExecutionData interface value to a payload response. +// This involves serializing the execution payload value so that the abstract payload envelope can be used. +func ExecutionPayloadResponseFromData(v int, ed interfaces.ExecutionData, bundle *v1.BlobsBundle) (*builderAPI.ExecutionPayloadResponse, error) { + pb := ed.Proto() + var data interface{} + var err error + ver := version.String(v) + switch pbStruct := pb.(type) { + case *v1.ExecutionPayloadDeneb: + payloadStruct, err := builderAPI.FromProtoDeneb(pbStruct) + if err != nil { + return nil, errors.Wrap(err, "failed to convert a Deneb ExecutionPayload to an API response") + } + data = &builderAPI.ExecutionPayloadDenebAndBlobsBundle{ + ExecutionPayload: &payloadStruct, + BlobsBundle: builderAPI.FromBundleProto(bundle), + } + case *v1.ExecutionPayloadCapella: + data, err = builderAPI.FromProtoCapella(pbStruct) + if err != nil { + return nil, errors.Wrap(err, "failed to convert a Capella ExecutionPayload to an API response") + } + case *v1.ExecutionPayload: + data, err = builderAPI.FromProto(pbStruct) + if err != nil { + return nil, errors.Wrap(err, "failed to convert a Bellatrix ExecutionPayload to an API response") + } + default: + return nil, errInvalidTypeConversion + } + encoded, err := json.Marshal(data) + if err != nil { + return nil, errors.Wrapf(err, "failed to marshal execution payload version=%s", ver) + } + return &builderAPI.ExecutionPayloadResponse{ + Version: ver, + Data: encoded, + }, nil +} + func (p *Builder) retrievePendingBlock() (*v1.ExecutionPayload, error) { result := &engine.ExecutableData{} if p.currId == nil { @@ -607,7 +792,7 @@ func (p *Builder) retrievePendingBlock() (*v1.ExecutionPayload, error) { if err != nil { return nil, err } - payloadEnv, err := modifyExecutionPayload(*result, big.NewInt(0), nil) + payloadEnv, err := modifyExecutionPayload(*result, big.NewInt(0), nil, nil) if err != nil { return nil, err } @@ -632,7 +817,7 @@ func (p *Builder) retrievePendingBlockCapella() (*v1.ExecutionPayloadCapellaWith if err != nil { return nil, err } - payloadEnv, err := modifyExecutionPayload(*result.ExecutionPayload, result.BlockValue, nil) + payloadEnv, err := modifyExecutionPayload(*result.ExecutionPayload, result.BlockValue, nil, nil) if err != nil { return nil, err } @@ -660,7 +845,7 @@ func (p *Builder) retrievePendingBlockDeneb() (*v1.ExecutionPayloadDenebWithValu if p.prevBeaconRoot == nil { p.cfg.logger.Errorf("previous root is nil") } - payloadEnv, err := modifyExecutionPayload(*result.ExecutionPayload, result.BlockValue, p.prevBeaconRoot) + payloadEnv, err := modifyExecutionPayload(*result.ExecutionPayload, result.BlockValue, p.prevBeaconRoot, nil) if err != nil { return nil, err } @@ -677,6 +862,36 @@ func (p *Builder) retrievePendingBlockDeneb() (*v1.ExecutionPayloadDenebWithValu return denebPayload, nil } +func (p *Builder) retrievePendingBlockElectra() (*v1.ExecutionBundleElectra, error) { + result := &engine.ExecutionPayloadEnvelope{} + if p.currId == nil { + return nil, errors.New("no payload id is cached") + } + err := p.execClient.CallContext(context.Background(), result, GetPayloadMethodV4, *p.currId) + if err != nil { + return nil, err + } + if p.prevBeaconRoot == nil { + p.cfg.logger.Errorf("previous root is nil") + } + + payloadEnv, err := modifyExecutionPayload(*result.ExecutionPayload, result.BlockValue, p.prevBeaconRoot, result.Requests) + if err != nil { + return nil, err + } + payloadEnv.BlobsBundle = result.BlobsBundle + marshalledOutput, err := payloadEnv.MarshalJSON() + if err != nil { + return nil, err + } + electraPayload := &v1.ExecutionBundleElectra{} + if err = json.Unmarshal(marshalledOutput, electraPayload); err != nil { + return nil, err + } + p.currId = nil + return electraPayload, nil +} + func (p *Builder) sendHttpRequest(req *http.Request, requestBytes []byte) (*http.Response, error) { proxyReq, err := http.NewRequest(req.Method, p.cfg.destinationUrl.String(), req.Body) if err != nil { @@ -739,16 +954,16 @@ func unmarshalRPCObject(b []byte) (*jsonRPCObject, error) { return r, nil } -func modifyExecutionPayload(execPayload engine.ExecutableData, fees *big.Int, prevBeaconRoot []byte) (*engine.ExecutionPayloadEnvelope, error) { - modifiedBlock, err := executableDataToBlock(execPayload, prevBeaconRoot) +func modifyExecutionPayload(execPayload engine.ExecutableData, fees *big.Int, prevBeaconRoot []byte, requests [][]byte) (*engine.ExecutionPayloadEnvelope, error) { + modifiedBlock, err := executableDataToBlock(execPayload, prevBeaconRoot, requests) if err != nil { return &engine.ExecutionPayloadEnvelope{}, err } - return engine.BlockToExecutableData(modifiedBlock, fees, nil /*blobs*/), nil + return engine.BlockToExecutableData(modifiedBlock, fees, nil /*blobs*/, requests /*requests*/), nil } // This modifies the provided payload to imprint the builder's extra data -func executableDataToBlock(params engine.ExecutableData, prevBeaconRoot []byte) (*gethTypes.Block, error) { +func executableDataToBlock(params engine.ExecutableData, prevBeaconRoot []byte, requests [][]byte) (*gethTypes.Block, error) { txs, err := decodeTransactions(params.Transactions) if err != nil { return nil, err @@ -761,6 +976,13 @@ func executableDataToBlock(params engine.ExecutableData, prevBeaconRoot []byte) h := gethTypes.DeriveSha(gethTypes.Withdrawals(params.Withdrawals), trie.NewStackTrie(nil)) withdrawalsRoot = &h } + + var requestsHash *common.Hash + if requests != nil { + h := gethTypes.CalcRequestsHash(requests) + requestsHash = &h + } + header := &gethTypes.Header{ ParentHash: params.ParentHash, UncleHash: gethTypes.EmptyUncleHash, @@ -780,12 +1002,20 @@ func executableDataToBlock(params engine.ExecutableData, prevBeaconRoot []byte) WithdrawalsHash: withdrawalsRoot, BlobGasUsed: params.BlobGasUsed, ExcessBlobGas: params.ExcessBlobGas, + RequestsHash: requestsHash, } + if prevBeaconRoot != nil { pRoot := common.Hash(prevBeaconRoot) header.ParentBeaconRoot = &pRoot } - block := gethTypes.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals) + + body := gethTypes.Body{ + Transactions: txs, + Uncles: nil, + Withdrawals: params.Withdrawals, + } + block := gethTypes.NewBlockWithHeader(header).WithBody(body) return block, nil } diff --git a/testing/middleware/engine-api-proxy/proxy.go b/testing/middleware/engine-api-proxy/proxy.go index 24c0576a06a7..f29602a3bdf1 100644 --- a/testing/middleware/engine-api-proxy/proxy.go +++ b/testing/middleware/engine-api-proxy/proxy.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net" "net/http" "strings" @@ -240,7 +239,7 @@ func (p *Proxy) sendHttpRequest(req *http.Request, requestBytes []byte) (*http.R } // Set the modified request as the proxy request body. - proxyReq.Body = ioutil.NopCloser(bytes.NewBuffer(requestBytes)) + proxyReq.Body = io.NopCloser(bytes.NewBuffer(requestBytes)) // Required proxy headers for forwarding JSON-RPC requests to the execution client. proxyReq.Header.Set("Host", req.Host) @@ -261,14 +260,14 @@ func (p *Proxy) sendHttpRequest(req *http.Request, requestBytes []byte) (*http.R // Peek into the bytes of an HTTP request's body. func parseRequestBytes(req *http.Request) ([]byte, error) { - requestBytes, err := ioutil.ReadAll(req.Body) + requestBytes, err := io.ReadAll(req.Body) if err != nil { return nil, err } if err = req.Body.Close(); err != nil { return nil, err } - req.Body = ioutil.NopCloser(bytes.NewBuffer(requestBytes)) + req.Body = io.NopCloser(bytes.NewBuffer(requestBytes)) return requestBytes, nil } diff --git a/testing/mock/beacon_validator_client_mock.go b/testing/mock/beacon_validator_client_mock.go index 24c55182c7f6..d104bb76439b 100644 --- a/testing/mock/beacon_validator_client_mock.go +++ b/testing/mock/beacon_validator_client_mock.go @@ -324,7 +324,7 @@ func (mr *MockBeaconNodeValidatorClientMockRecorder) ProposeAttestation(arg0, ar } // ProposeAttestationElectra mocks base method. -func (m *MockBeaconNodeValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.AttestationElectra, arg2 ...grpc.CallOption) (*eth.AttestResponse, error) { +func (m *MockBeaconNodeValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.SingleAttestation, arg2 ...grpc.CallOption) (*eth.AttestResponse, error) { m.ctrl.T.Helper() varargs := []any{arg0, arg1} for _, a := range arg2 { diff --git a/testing/mock/beacon_validator_server_mock.go b/testing/mock/beacon_validator_server_mock.go index 9643784dfc27..d610f37b9c00 100644 --- a/testing/mock/beacon_validator_server_mock.go +++ b/testing/mock/beacon_validator_server_mock.go @@ -253,7 +253,7 @@ func (mr *MockBeaconNodeValidatorServerMockRecorder) ProposeAttestation(arg0, ar } // ProposeAttestationElectra mocks base method. -func (m *MockBeaconNodeValidatorServer) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.AttestationElectra) (*eth.AttestResponse, error) { +func (m *MockBeaconNodeValidatorServer) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.SingleAttestation) (*eth.AttestResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ProposeAttestationElectra", arg0, arg1) ret0, _ := ret[0].(*eth.AttestResponse) diff --git a/testing/slasher/simulator/BUILD.bazel b/testing/slasher/simulator/BUILD.bazel index 679ded283765..4639acfe5b7b 100644 --- a/testing/slasher/simulator/BUILD.bazel +++ b/testing/slasher/simulator/BUILD.bazel @@ -32,6 +32,7 @@ go_library( "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", @@ -55,6 +56,7 @@ go_test( "//crypto/bls:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/slashings:go_default_library", + "//runtime/version:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", ], diff --git a/testing/slasher/simulator/attestation_generator.go b/testing/slasher/simulator/attestation_generator.go index be06c930958e..6c83845ec6f7 100644 --- a/testing/slasher/simulator/attestation_generator.go +++ b/testing/slasher/simulator/attestation_generator.go @@ -15,15 +15,14 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/rand" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" ) -func (s *Simulator) generateAttestationsForSlot( - ctx context.Context, slot primitives.Slot, -) ([]*ethpb.IndexedAttestation, []*ethpb.AttesterSlashing, error) { - attestations := make([]*ethpb.IndexedAttestation, 0) - slashings := make([]*ethpb.AttesterSlashing, 0) +func (s *Simulator) generateAttestationsForSlot(ctx context.Context, ver int, slot primitives.Slot) ([]ethpb.IndexedAtt, []ethpb.AttSlashing, error) { + attestations := make([]ethpb.IndexedAtt, 0) + slashings := make([]ethpb.AttSlashing, 0) currentEpoch := slots.ToEpoch(slot) committeesPerSlot := helpers.SlotCommitteeCount(s.srvConfig.Params.NumValidators) @@ -64,12 +63,23 @@ func (s *Simulator) generateAttestationsForSlot( for idx := i; idx < attEndIdx; idx++ { indices = append(indices, idx) } - att := ðpb.IndexedAttestation{ - AttestingIndices: indices, - Data: attData, - Signature: params.BeaconConfig().EmptySignature[:], + + var att ethpb.IndexedAtt + if ver >= version.Electra { + att = ðpb.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: attData, + Signature: params.BeaconConfig().EmptySignature[:], + } + } else { + att = ðpb.IndexedAttestation{ + AttestingIndices: indices, + Data: attData, + Signature: params.BeaconConfig().EmptySignature[:], + } } - beaconState, err := s.srvConfig.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target) + + beaconState, err := s.srvConfig.AttestationStateFetcher.AttestationTargetState(ctx, att.GetData().Target) if err != nil { return nil, nil, err } @@ -79,7 +89,12 @@ func (s *Simulator) generateAttestationsForSlot( if err != nil { return nil, nil, err } - att.Signature = aggSig.Marshal() + + if ver >= version.Electra { + att.(*ethpb.IndexedAttestationElectra).Signature = aggSig.Marshal() + } else { + att.(*ethpb.IndexedAttestation).Signature = aggSig.Marshal() + } attestations = append(attestations, att) if rand.NewGenerator().Float64() < s.srvConfig.Params.AttesterSlashingProbab { @@ -88,29 +103,50 @@ func (s *Simulator) generateAttestationsForSlot( if err != nil { return nil, nil, err } - slashableAtt.Signature = aggSig.Marshal() - slashedIndices = append(slashedIndices, slashableAtt.AttestingIndices...) - attDataRoot, err := att.Data.HashTreeRoot() + if ver >= version.Electra { + slashableAtt.(*ethpb.IndexedAttestationElectra).Signature = aggSig.Marshal() + } else { + slashableAtt.(*ethpb.IndexedAttestation).Signature = aggSig.Marshal() + } + + slashedIndices = append(slashedIndices, slashableAtt.GetAttestingIndices()...) + + attDataRoot, err := att.GetData().HashTreeRoot() if err != nil { return nil, nil, errors.Wrap(err, "cannot compte `att` hash tree root") } - slashableAttDataRoot, err := slashableAtt.Data.HashTreeRoot() + slashableAttDataRoot, err := slashableAtt.GetData().HashTreeRoot() if err != nil { return nil, nil, errors.Wrap(err, "cannot compte `slashableAtt` hash tree root") } - slashing := ðpb.AttesterSlashing{ - Attestation_1: att, - Attestation_2: slashableAtt, + var slashing ethpb.AttSlashing + if ver >= version.Electra { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: att.(*ethpb.IndexedAttestationElectra), + Attestation_2: slashableAtt.(*ethpb.IndexedAttestationElectra), + } + } else { + slashing = ðpb.AttesterSlashing{ + Attestation_1: att.(*ethpb.IndexedAttestation), + Attestation_2: slashableAtt.(*ethpb.IndexedAttestation), + } } // Ensure the attestation with the lower data root is the first attestation. if bytes.Compare(attDataRoot[:], slashableAttDataRoot[:]) > 0 { - slashing = ðpb.AttesterSlashing{ - Attestation_1: slashableAtt, - Attestation_2: att, + if ver >= version.Electra { + slashing = ðpb.AttesterSlashingElectra{ + Attestation_1: slashableAtt.(*ethpb.IndexedAttestationElectra), + Attestation_2: att.(*ethpb.IndexedAttestationElectra), + } + } else { + slashing = ðpb.AttesterSlashing{ + Attestation_1: slashableAtt.(*ethpb.IndexedAttestation), + Attestation_2: att.(*ethpb.IndexedAttestation), + } } } @@ -131,46 +167,55 @@ func (s *Simulator) generateAttestationsForSlot( } func (s *Simulator) aggregateSigForAttestation( - beaconState state.ReadOnlyBeaconState, att *ethpb.IndexedAttestation, + beaconState state.ReadOnlyBeaconState, att ethpb.IndexedAtt, ) (bls.Signature, error) { domain, err := signing.Domain( beaconState.Fork(), - att.Data.Target.Epoch, + att.GetData().Target.Epoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorsRoot(), ) if err != nil { return nil, err } - signingRoot, err := signing.ComputeSigningRoot(att.Data, domain) + signingRoot, err := signing.ComputeSigningRoot(att.GetData(), domain) if err != nil { return nil, err } - sigs := make([]bls.Signature, len(att.AttestingIndices)) - for i, validatorIndex := range att.AttestingIndices { + sigs := make([]bls.Signature, len(att.GetAttestingIndices())) + for i, validatorIndex := range att.GetAttestingIndices() { privKey := s.srvConfig.PrivateKeysByValidatorIndex[primitives.ValidatorIndex(validatorIndex)] sigs[i] = privKey.Sign(signingRoot[:]) } return bls.AggregateSignatures(sigs), nil } -func makeSlashableFromAtt(att *ethpb.IndexedAttestation, indices []uint64) *ethpb.IndexedAttestation { - if att.Data.Source.Epoch <= 2 { +func makeSlashableFromAtt(att ethpb.IndexedAtt, indices []uint64) ethpb.IndexedAtt { + if att.GetData().Source.Epoch <= 2 { return makeDoubleVoteFromAtt(att, indices) } attData := ðpb.AttestationData{ - Slot: att.Data.Slot, - CommitteeIndex: att.Data.CommitteeIndex, - BeaconBlockRoot: att.Data.BeaconBlockRoot, + Slot: att.GetData().Slot, + CommitteeIndex: att.GetData().CommitteeIndex, + BeaconBlockRoot: att.GetData().BeaconBlockRoot, Source: ðpb.Checkpoint{ - Epoch: att.Data.Source.Epoch - 3, - Root: att.Data.Source.Root, + Epoch: att.GetData().Source.Epoch - 3, + Root: att.GetData().Source.Root, }, Target: ðpb.Checkpoint{ - Epoch: att.Data.Target.Epoch, - Root: att.Data.Target.Root, + Epoch: att.GetData().Target.Epoch, + Root: att.GetData().Target.Root, }, } + + if att.Version() >= version.Electra { + return ðpb.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: attData, + Signature: params.BeaconConfig().EmptySignature[:], + } + } + return ðpb.IndexedAttestation{ AttestingIndices: indices, Data: attData, @@ -178,20 +223,29 @@ func makeSlashableFromAtt(att *ethpb.IndexedAttestation, indices []uint64) *ethp } } -func makeDoubleVoteFromAtt(att *ethpb.IndexedAttestation, indices []uint64) *ethpb.IndexedAttestation { +func makeDoubleVoteFromAtt(att ethpb.IndexedAtt, indices []uint64) ethpb.IndexedAtt { attData := ðpb.AttestationData{ - Slot: att.Data.Slot, - CommitteeIndex: att.Data.CommitteeIndex, + Slot: att.GetData().Slot, + CommitteeIndex: att.GetData().CommitteeIndex, BeaconBlockRoot: bytesutil.PadTo([]byte("slash me"), 32), Source: ðpb.Checkpoint{ - Epoch: att.Data.Source.Epoch, - Root: att.Data.Source.Root, + Epoch: att.GetData().Source.Epoch, + Root: att.GetData().Source.Root, }, Target: ðpb.Checkpoint{ - Epoch: att.Data.Target.Epoch, - Root: att.Data.Target.Root, + Epoch: att.GetData().Target.Epoch, + Root: att.GetData().Target.Root, }, } + + if att.Version() >= version.Electra { + return ðpb.IndexedAttestationElectra{ + AttestingIndices: indices, + Data: attData, + Signature: params.BeaconConfig().EmptySignature[:], + } + } + return ðpb.IndexedAttestation{ AttestingIndices: indices, Data: attData, diff --git a/testing/slasher/simulator/attestation_generator_test.go b/testing/slasher/simulator/attestation_generator_test.go index d42b4b3a5f4d..210771394921 100644 --- a/testing/slasher/simulator/attestation_generator_test.go +++ b/testing/slasher/simulator/attestation_generator_test.go @@ -6,6 +6,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/slashings" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -20,14 +21,18 @@ func TestGenerateAttestationsForSlot_Slashing(t *testing.T) { } srv := setupService(t, simParams) - epoch3Atts, _, err := srv.generateAttestationsForSlot(ctx, params.BeaconConfig().SlotsPerEpoch*3) - require.NoError(t, err) - epoch4Atts, _, err := srv.generateAttestationsForSlot(ctx, params.BeaconConfig().SlotsPerEpoch*4) - require.NoError(t, err) - for i := 0; i < len(epoch3Atts); i += 2 { - goodAtt := epoch3Atts[i] - surroundAtt := epoch4Atts[i+1] - require.Equal(t, true, slashings.IsSurround(surroundAtt, goodAtt)) + for _, v := range []int{version.Phase0, version.Electra} { + t.Run(version.String(v), func(t *testing.T) { + epoch3Atts, _, err := srv.generateAttestationsForSlot(ctx, v, params.BeaconConfig().SlotsPerEpoch*3) + require.NoError(t, err) + epoch4Atts, _, err := srv.generateAttestationsForSlot(ctx, v, params.BeaconConfig().SlotsPerEpoch*4) + require.NoError(t, err) + for i := 0; i < len(epoch3Atts); i += 2 { + goodAtt := epoch3Atts[i] + surroundAtt := epoch4Atts[i+1] + require.Equal(t, true, slashings.IsSurround(surroundAtt, goodAtt)) + } + }) } } @@ -41,24 +46,29 @@ func TestGenerateAttestationsForSlot_CorrectIndices(t *testing.T) { AttesterSlashingProbab: 0, } srv := setupService(t, simParams) - slot0Atts, _, err := srv.generateAttestationsForSlot(ctx, 0) - require.NoError(t, err) - slot1Atts, _, err := srv.generateAttestationsForSlot(ctx, 1) - require.NoError(t, err) - slot2Atts, _, err := srv.generateAttestationsForSlot(ctx, 2) - require.NoError(t, err) - var validatorIndices []uint64 - for _, att := range append(slot0Atts, slot1Atts...) { - validatorIndices = append(validatorIndices, att.AttestingIndices...) - } - for _, att := range slot2Atts { - validatorIndices = append(validatorIndices, att.AttestingIndices...) - } - // Making sure indices are one after the other for attestations. - var validatorIndex uint64 - for _, ii := range validatorIndices { - require.Equal(t, validatorIndex, ii) - validatorIndex++ + for _, v := range []int{version.Phase0, version.Electra} { + t.Run(version.String(v), func(t *testing.T) { + slot0Atts, _, err := srv.generateAttestationsForSlot(ctx, v, 0) + require.NoError(t, err) + slot1Atts, _, err := srv.generateAttestationsForSlot(ctx, v, 1) + require.NoError(t, err) + slot2Atts, _, err := srv.generateAttestationsForSlot(ctx, v, 2) + require.NoError(t, err) + var validatorIndices []uint64 + for _, att := range append(slot0Atts, slot1Atts...) { + validatorIndices = append(validatorIndices, att.GetAttestingIndices()...) + } + for _, att := range slot2Atts { + validatorIndices = append(validatorIndices, att.GetAttestingIndices()...) + } + + // Making sure indices are one after the other for attestations. + var validatorIndex uint64 + for _, ii := range validatorIndices { + require.Equal(t, validatorIndex, ii) + validatorIndex++ + } + }) } } diff --git a/testing/slasher/simulator/simulator.go b/testing/slasher/simulator/simulator.go index e09f13d95bc0..f53b039567c9 100644 --- a/testing/slasher/simulator/simulator.go +++ b/testing/slasher/simulator/simulator.go @@ -19,6 +19,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/sirupsen/logrus" ) @@ -62,7 +63,7 @@ type Simulator struct { sentAttSlashingFeed *event.Feed sentBlockSlashingFeed *event.Feed sentProposerSlashings map[[32]byte]*ethpb.ProposerSlashing - sentAttesterSlashings map[[32]byte]*ethpb.AttesterSlashing + sentAttesterSlashings map[[32]byte]ethpb.AttSlashing genesisTime time.Time } @@ -111,7 +112,7 @@ func New(ctx context.Context, srvConfig *ServiceConfig) (*Simulator, error) { sentAttSlashingFeed: sentAttSlashingFeed, sentBlockSlashingFeed: sentBlockSlashingFeed, sentProposerSlashings: make(map[[32]byte]*ethpb.ProposerSlashing), - sentAttesterSlashings: make(map[[32]byte]*ethpb.AttesterSlashing), + sentAttesterSlashings: make(map[[32]byte]ethpb.AttSlashing), }, nil } @@ -206,7 +207,7 @@ func (s *Simulator) simulateBlocksAndAttestations(ctx context.Context) { s.beaconBlocksFeed.Send(bb) } - atts, attSlashings, err := s.generateAttestationsForSlot(ctx, slot) + atts, attSlashings, err := s.generateAttestationsForSlot(ctx, version.Phase0, slot) if err != nil { log.WithError(err).Fatal("Could not generate attestations for slot") } @@ -271,20 +272,20 @@ func (s *Simulator) verifySlashingsWereDetected(ctx context.Context) { for slashingRoot, slashing := range s.sentAttesterSlashings { if _, ok := detectedAttesterSlashings[slashingRoot]; !ok { log.WithFields(logrus.Fields{ - "targetEpoch": slashing.Attestation_1.Data.Target.Epoch, - "prevTargetEpoch": slashing.Attestation_2.Data.Target.Epoch, - "sourceEpoch": slashing.Attestation_1.Data.Source.Epoch, - "prevSourceEpoch": slashing.Attestation_2.Data.Source.Epoch, - "prevBeaconBlockRoot": fmt.Sprintf("%#x", slashing.Attestation_1.Data.BeaconBlockRoot), - "newBeaconBlockRoot": fmt.Sprintf("%#x", slashing.Attestation_2.Data.BeaconBlockRoot), + "targetEpoch": slashing.FirstAttestation().GetData().Target.Epoch, + "prevTargetEpoch": slashing.SecondAttestation().GetData().Target.Epoch, + "sourceEpoch": slashing.FirstAttestation().GetData().Source.Epoch, + "prevSourceEpoch": slashing.SecondAttestation().GetData().Source.Epoch, + "prevBeaconBlockRoot": fmt.Sprintf("%#x", slashing.FirstAttestation().GetData().BeaconBlockRoot), + "newBeaconBlockRoot": fmt.Sprintf("%#x", slashing.SecondAttestation().GetData().BeaconBlockRoot), }).Errorf("Did not detect simulated attester slashing") continue } log.WithFields(logrus.Fields{ - "targetEpoch": slashing.Attestation_1.Data.Target.Epoch, - "prevTargetEpoch": slashing.Attestation_2.Data.Target.Epoch, - "sourceEpoch": slashing.Attestation_1.Data.Source.Epoch, - "prevSourceEpoch": slashing.Attestation_2.Data.Source.Epoch, + "targetEpoch": slashing.FirstAttestation().GetData().Target.Epoch, + "prevTargetEpoch": slashing.SecondAttestation().GetData().Target.Epoch, + "sourceEpoch": slashing.FirstAttestation().GetData().Source.Epoch, + "prevSourceEpoch": slashing.SecondAttestation().GetData().Source.Epoch, }).Info("Correctly detected simulated attester slashing") } } diff --git a/testing/spectest/exclusions.txt b/testing/spectest/exclusions.txt index 6da3a2125169..433f144ff38a 100644 --- a/testing/spectest/exclusions.txt +++ b/testing/spectest/exclusions.txt @@ -24,179 +24,6 @@ tests/general/phase0/ssz_generic/boolean tests/general/phase0/ssz_generic/containers tests/general/phase0/ssz_generic/uints -# EIP6110 -tests/mainnet/eip6110/epoch_processing/effective_balance_updates -tests/mainnet/eip6110/epoch_processing/eth1_data_reset -tests/mainnet/eip6110/epoch_processing/historical_summaries_update -tests/mainnet/eip6110/epoch_processing/inactivity_updates -tests/mainnet/eip6110/epoch_processing/justification_and_finalization -tests/mainnet/eip6110/epoch_processing/participation_flag_updates -tests/mainnet/eip6110/epoch_processing/randao_mixes_reset -tests/mainnet/eip6110/epoch_processing/registry_updates -tests/mainnet/eip6110/epoch_processing/rewards_and_penalties -tests/mainnet/eip6110/epoch_processing/slashings -tests/mainnet/eip6110/epoch_processing/slashings_reset -tests/mainnet/eip6110/finality/finality -tests/mainnet/eip6110/fork_choice/ex_ante -tests/mainnet/eip6110/fork_choice/get_head -tests/mainnet/eip6110/fork_choice/get_proposer_head -tests/mainnet/eip6110/fork_choice/on_block -tests/mainnet/eip6110/fork_choice/should_override_forkchoice_update -tests/mainnet/eip6110/operations/attestation -tests/mainnet/eip6110/operations/attester_slashing -tests/mainnet/eip6110/operations/block_header -tests/mainnet/eip6110/operations/bls_to_execution_change -tests/mainnet/eip6110/operations/deposit -tests/mainnet/eip6110/operations/execution_payload -tests/mainnet/eip6110/operations/proposer_slashing -tests/mainnet/eip6110/operations/sync_aggregate -tests/mainnet/eip6110/operations/voluntary_exit -tests/mainnet/eip6110/operations/withdrawals -tests/mainnet/eip6110/rewards/basic -tests/mainnet/eip6110/rewards/leak -tests/mainnet/eip6110/rewards/random -tests/mainnet/eip6110/sanity/blocks -tests/mainnet/eip6110/sanity/slots -tests/mainnet/eip6110/ssz_static/AggregateAndProof -tests/mainnet/eip6110/ssz_static/Attestation -tests/mainnet/eip6110/ssz_static/AttestationData -tests/mainnet/eip6110/ssz_static/AttesterSlashing -tests/mainnet/eip6110/ssz_static/BLSToExecutionChange -tests/mainnet/eip6110/ssz_static/BeaconBlock -tests/mainnet/eip6110/ssz_static/BeaconBlockBody -tests/mainnet/eip6110/ssz_static/BeaconBlockHeader -tests/mainnet/eip6110/ssz_static/BeaconState -tests/mainnet/eip6110/ssz_static/BlobIdentifier -tests/mainnet/eip6110/ssz_static/BlobSidecar -tests/mainnet/eip6110/ssz_static/Checkpoint -tests/mainnet/eip6110/ssz_static/ContributionAndProof -tests/mainnet/eip6110/ssz_static/Deposit -tests/mainnet/eip6110/ssz_static/DepositData -tests/mainnet/eip6110/ssz_static/DepositMessage -tests/mainnet/eip6110/ssz_static/DepositReceipt -tests/mainnet/eip6110/ssz_static/Eth1Block -tests/mainnet/eip6110/ssz_static/Eth1Data -tests/mainnet/eip6110/ssz_static/ExecutionPayload -tests/mainnet/eip6110/ssz_static/ExecutionPayloadHeader -tests/mainnet/eip6110/ssz_static/Fork -tests/mainnet/eip6110/ssz_static/ForkData -tests/mainnet/eip6110/ssz_static/HistoricalBatch -tests/mainnet/eip6110/ssz_static/HistoricalSummary -tests/mainnet/eip6110/ssz_static/IndexedAttestation -tests/mainnet/eip6110/ssz_static/LightClientBootstrap -tests/mainnet/eip6110/ssz_static/LightClientFinalityUpdate -tests/mainnet/eip6110/ssz_static/LightClientHeader -tests/mainnet/eip6110/ssz_static/LightClientOptimisticUpdate -tests/mainnet/eip6110/ssz_static/LightClientUpdate -tests/mainnet/eip6110/ssz_static/PendingAttestation -tests/mainnet/eip6110/ssz_static/PowBlock -tests/mainnet/eip6110/ssz_static/ProposerSlashing -tests/mainnet/eip6110/ssz_static/SignedAggregateAndProof -tests/mainnet/eip6110/ssz_static/SignedBLSToExecutionChange -tests/mainnet/eip6110/ssz_static/SignedBeaconBlock -tests/mainnet/eip6110/ssz_static/SignedBeaconBlockHeader -tests/mainnet/eip6110/ssz_static/SignedContributionAndProof -tests/mainnet/eip6110/ssz_static/SignedVoluntaryExit -tests/mainnet/eip6110/ssz_static/SigningData -tests/mainnet/eip6110/ssz_static/SyncAggregate -tests/mainnet/eip6110/ssz_static/SyncAggregatorSelectionData -tests/mainnet/eip6110/ssz_static/SyncCommittee -tests/mainnet/eip6110/ssz_static/SyncCommitteeContribution -tests/mainnet/eip6110/ssz_static/SyncCommitteeMessage -tests/mainnet/eip6110/ssz_static/Validator -tests/mainnet/eip6110/ssz_static/VoluntaryExit -tests/mainnet/eip6110/ssz_static/Withdrawal -tests/mainnet/eip6110/sync/optimistic -tests/mainnet/eip6110/transition/core -tests/minimal/eip6110/epoch_processing/effective_balance_updates -tests/minimal/eip6110/epoch_processing/eth1_data_reset -tests/minimal/eip6110/epoch_processing/historical_summaries_update -tests/minimal/eip6110/epoch_processing/inactivity_updates -tests/minimal/eip6110/epoch_processing/justification_and_finalization -tests/minimal/eip6110/epoch_processing/participation_flag_updates -tests/minimal/eip6110/epoch_processing/randao_mixes_reset -tests/minimal/eip6110/epoch_processing/registry_updates -tests/minimal/eip6110/epoch_processing/rewards_and_penalties -tests/minimal/eip6110/epoch_processing/slashings -tests/minimal/eip6110/epoch_processing/slashings_reset -tests/minimal/eip6110/epoch_processing/sync_committee_updates -tests/minimal/eip6110/finality/finality -tests/minimal/eip6110/fork_choice/ex_ante -tests/minimal/eip6110/fork_choice/get_head -tests/minimal/eip6110/fork_choice/get_proposer_head -tests/minimal/eip6110/fork_choice/on_block -tests/minimal/eip6110/fork_choice/reorg -tests/minimal/eip6110/fork_choice/should_override_forkchoice_update -tests/minimal/eip6110/fork_choice/withholding -tests/minimal/eip6110/genesis/initialization -tests/minimal/eip6110/genesis/validity -tests/minimal/eip6110/operations/attestation -tests/minimal/eip6110/operations/attester_slashing -tests/minimal/eip6110/operations/block_header -tests/minimal/eip6110/operations/bls_to_execution_change -tests/minimal/eip6110/operations/deposit -tests/minimal/eip6110/operations/execution_payload -tests/minimal/eip6110/operations/proposer_slashing -tests/minimal/eip6110/operations/sync_aggregate -tests/minimal/eip6110/operations/voluntary_exit -tests/minimal/eip6110/operations/withdrawals -tests/minimal/eip6110/rewards/basic -tests/minimal/eip6110/rewards/leak -tests/minimal/eip6110/rewards/random -tests/minimal/eip6110/sanity/blocks -tests/minimal/eip6110/sanity/slots -tests/minimal/eip6110/ssz_static/AggregateAndProof -tests/minimal/eip6110/ssz_static/Attestation -tests/minimal/eip6110/ssz_static/AttestationData -tests/minimal/eip6110/ssz_static/AttesterSlashing -tests/minimal/eip6110/ssz_static/BLSToExecutionChange -tests/minimal/eip6110/ssz_static/BeaconBlock -tests/minimal/eip6110/ssz_static/BeaconBlockBody -tests/minimal/eip6110/ssz_static/BeaconBlockHeader -tests/minimal/eip6110/ssz_static/BeaconState -tests/minimal/eip6110/ssz_static/BlobIdentifier -tests/minimal/eip6110/ssz_static/BlobSidecar -tests/minimal/eip6110/ssz_static/Checkpoint -tests/minimal/eip6110/ssz_static/ContributionAndProof -tests/minimal/eip6110/ssz_static/Deposit -tests/minimal/eip6110/ssz_static/DepositData -tests/minimal/eip6110/ssz_static/DepositMessage -tests/minimal/eip6110/ssz_static/DepositReceipt -tests/minimal/eip6110/ssz_static/Eth1Block -tests/minimal/eip6110/ssz_static/Eth1Data -tests/minimal/eip6110/ssz_static/ExecutionPayload -tests/minimal/eip6110/ssz_static/ExecutionPayloadHeader -tests/minimal/eip6110/ssz_static/Fork -tests/minimal/eip6110/ssz_static/ForkData -tests/minimal/eip6110/ssz_static/HistoricalBatch -tests/minimal/eip6110/ssz_static/HistoricalSummary -tests/minimal/eip6110/ssz_static/IndexedAttestation -tests/minimal/eip6110/ssz_static/LightClientBootstrap -tests/minimal/eip6110/ssz_static/LightClientFinalityUpdate -tests/minimal/eip6110/ssz_static/LightClientHeader -tests/minimal/eip6110/ssz_static/LightClientOptimisticUpdate -tests/minimal/eip6110/ssz_static/LightClientUpdate -tests/minimal/eip6110/ssz_static/PendingAttestation -tests/minimal/eip6110/ssz_static/PowBlock -tests/minimal/eip6110/ssz_static/ProposerSlashing -tests/minimal/eip6110/ssz_static/SignedAggregateAndProof -tests/minimal/eip6110/ssz_static/SignedBLSToExecutionChange -tests/minimal/eip6110/ssz_static/SignedBeaconBlock -tests/minimal/eip6110/ssz_static/SignedBeaconBlockHeader -tests/minimal/eip6110/ssz_static/SignedContributionAndProof -tests/minimal/eip6110/ssz_static/SignedVoluntaryExit -tests/minimal/eip6110/ssz_static/SigningData -tests/minimal/eip6110/ssz_static/SyncAggregate -tests/minimal/eip6110/ssz_static/SyncAggregatorSelectionData -tests/minimal/eip6110/ssz_static/SyncCommittee -tests/minimal/eip6110/ssz_static/SyncCommitteeContribution -tests/minimal/eip6110/ssz_static/SyncCommitteeMessage -tests/minimal/eip6110/ssz_static/Validator -tests/minimal/eip6110/ssz_static/VoluntaryExit -tests/minimal/eip6110/ssz_static/Withdrawal -tests/minimal/eip6110/sync/optimistic -tests/minimal/eip6110/transition/core - # Whisk tests/mainnet/whisk/ssz_static/AggregateAndProof tests/mainnet/whisk/ssz_static/Attestation diff --git a/testing/spectest/mainnet/electra/epoch_processing/BUILD.bazel b/testing/spectest/mainnet/electra/epoch_processing/BUILD.bazel index 9315ef295420..0c7f666d06ab 100644 --- a/testing/spectest/mainnet/electra/epoch_processing/BUILD.bazel +++ b/testing/spectest/mainnet/electra/epoch_processing/BUILD.bazel @@ -9,8 +9,8 @@ go_test( "inactivity_updates_test.go", "justification_and_finalization_test.go", "participation_flag_updates_test.go", - "pending_balance_updates_test.go", "pending_consolidations_test.go", + "pending_deposits_updates_test.go", "randao_mixes_reset_test.go", "registry_updates_test.go", "rewards_and_penalties_test.go", diff --git a/testing/spectest/mainnet/electra/epoch_processing/pending_balance_updates_test.go b/testing/spectest/mainnet/electra/epoch_processing/pending_balance_updates_test.go deleted file mode 100644 index 7c47df8e8282..000000000000 --- a/testing/spectest/mainnet/electra/epoch_processing/pending_balance_updates_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package epoch_processing - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/electra/epoch_processing" -) - -func TestMainnet_Electra_EpochProcessing_PendingBalanceDeposits(t *testing.T) { - epoch_processing.RunPendingBalanceDepositsTests(t, "mainnet") -} diff --git a/testing/spectest/mainnet/electra/epoch_processing/pending_deposits_updates_test.go b/testing/spectest/mainnet/electra/epoch_processing/pending_deposits_updates_test.go new file mode 100644 index 000000000000..374a8a175230 --- /dev/null +++ b/testing/spectest/mainnet/electra/epoch_processing/pending_deposits_updates_test.go @@ -0,0 +1,11 @@ +package epoch_processing + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/electra/epoch_processing" +) + +func TestMainnet_Electra_EpochProcessing_PendingDeposits(t *testing.T) { + epoch_processing.RunPendingDepositsTests(t, "mainnet") +} diff --git a/testing/spectest/mainnet/electra/merkle_proof/merkle_proof_test.go b/testing/spectest/mainnet/electra/merkle_proof/merkle_proof_test.go index 63e54f24a20c..b894261f1ff9 100644 --- a/testing/spectest/mainnet/electra/merkle_proof/merkle_proof_test.go +++ b/testing/spectest/mainnet/electra/merkle_proof/merkle_proof_test.go @@ -7,6 +7,5 @@ import ( ) func TestMainnet_Electra_MerkleProof(t *testing.T) { - t.Skip("TODO: Electra") // These spectests are missing? merkle_proof.RunMerkleProofTests(t, "mainnet") } diff --git a/testing/spectest/mainnet/phase0/epoch_processing/epoch_processing_test.go b/testing/spectest/mainnet/phase0/epoch_processing/epoch_processing_test.go index 71a0bd8c540c..cde9270e3f8f 100644 --- a/testing/spectest/mainnet/phase0/epoch_processing/epoch_processing_test.go +++ b/testing/spectest/mainnet/phase0/epoch_processing/epoch_processing_test.go @@ -1,6 +1,7 @@ package epoch_processing import ( + "os" "testing" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -13,5 +14,5 @@ func TestMain(m *testing.M) { c.MinGenesisActiveValidatorCount = 16384 params.OverrideBeaconConfig(c) - m.Run() + os.Exit(m.Run()) } diff --git a/testing/spectest/minimal/electra/epoch_processing/BUILD.bazel b/testing/spectest/minimal/electra/epoch_processing/BUILD.bazel index 2e85ef9c939c..3415b173c1b7 100644 --- a/testing/spectest/minimal/electra/epoch_processing/BUILD.bazel +++ b/testing/spectest/minimal/electra/epoch_processing/BUILD.bazel @@ -9,8 +9,8 @@ go_test( "inactivity_updates_test.go", "justification_and_finalization_test.go", "participation_flag_updates_test.go", - "pending_balance_updates_test.go", "pending_consolidations_test.go", + "pending_deposits_updates_test.go", "randao_mixes_reset_test.go", "registry_updates_test.go", "rewards_and_penalties_test.go", diff --git a/testing/spectest/minimal/electra/epoch_processing/pending_balance_updates_test.go b/testing/spectest/minimal/electra/epoch_processing/pending_balance_updates_test.go deleted file mode 100644 index a2cc73b1a3ca..000000000000 --- a/testing/spectest/minimal/electra/epoch_processing/pending_balance_updates_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package epoch_processing - -import ( - "testing" - - "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/electra/epoch_processing" -) - -func TestMinimal_Electra_EpochProcessing_PendingBalanceDeposits(t *testing.T) { - epoch_processing.RunPendingBalanceDepositsTests(t, "minimal") -} diff --git a/testing/spectest/minimal/electra/epoch_processing/pending_deposits_updates_test.go b/testing/spectest/minimal/electra/epoch_processing/pending_deposits_updates_test.go new file mode 100644 index 000000000000..960ffbf8536e --- /dev/null +++ b/testing/spectest/minimal/electra/epoch_processing/pending_deposits_updates_test.go @@ -0,0 +1,11 @@ +package epoch_processing + +import ( + "testing" + + "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/electra/epoch_processing" +) + +func TestMinimal_Electra_EpochProcessing_PendingDeposits(t *testing.T) { + epoch_processing.RunPendingDepositsTests(t, "minimal") +} diff --git a/testing/spectest/minimal/electra/merkle_proof/merkle_proof_test.go b/testing/spectest/minimal/electra/merkle_proof/merkle_proof_test.go index 9d494ff90881..b2b7a8271326 100644 --- a/testing/spectest/minimal/electra/merkle_proof/merkle_proof_test.go +++ b/testing/spectest/minimal/electra/merkle_proof/merkle_proof_test.go @@ -7,6 +7,5 @@ import ( ) func TestMinimal_Electra_MerkleProof(t *testing.T) { - t.Skip("TODO: Electra") // These spectests are missing? merkle_proof.RunMerkleProofTests(t, "minimal") } diff --git a/testing/spectest/minimal/phase0/epoch_processing/epoch_processing_test.go b/testing/spectest/minimal/phase0/epoch_processing/epoch_processing_test.go index 71a0bd8c540c..cde9270e3f8f 100644 --- a/testing/spectest/minimal/phase0/epoch_processing/epoch_processing_test.go +++ b/testing/spectest/minimal/phase0/epoch_processing/epoch_processing_test.go @@ -1,6 +1,7 @@ package epoch_processing import ( + "os" "testing" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -13,5 +14,5 @@ func TestMain(m *testing.M) { c.MinGenesisActiveValidatorCount = 16384 params.OverrideBeaconConfig(c) - m.Run() + os.Exit(m.Run()) } diff --git a/testing/spectest/shared/altair/epoch_processing/BUILD.bazel b/testing/spectest/shared/altair/epoch_processing/BUILD.bazel index d566fdbd43af..0ac32be75d29 100644 --- a/testing/spectest/shared/altair/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/altair/epoch_processing/BUILD.bazel @@ -26,7 +26,6 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", - "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/altair/epoch_processing/slashings.go b/testing/spectest/shared/altair/epoch_processing/slashings.go index c06b7bc172c8..8c712e1e9335 100644 --- a/testing/spectest/shared/altair/epoch_processing/slashings.go +++ b/testing/spectest/shared/altair/epoch_processing/slashings.go @@ -7,7 +7,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" ) @@ -30,7 +29,6 @@ func RunSlashingsTests(t *testing.T, config string) { } func processSlashingsWrapper(t *testing.T, st state.BeaconState) (state.BeaconState, error) { - st, err := epoch.ProcessSlashings(st, params.BeaconConfig().ProportionalSlashingMultiplierAltair) - require.NoError(t, err, "Could not process slashings") + require.NoError(t, epoch.ProcessSlashings(st), "Could not process slashings") return st, nil } diff --git a/testing/spectest/shared/altair/operations/BUILD.bazel b/testing/spectest/shared/altair/operations/BUILD.bazel index a668f22b8e56..05aeecc89e81 100644 --- a/testing/spectest/shared/altair/operations/BUILD.bazel +++ b/testing/spectest/shared/altair/operations/BUILD.bazel @@ -17,21 +17,13 @@ go_library( visibility = ["//testing/spectest:__subpackages__"], deps = [ "//beacon-chain/core/altair:go_default_library", - "//beacon-chain/core/blocks:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/validators:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//testing/require:go_default_library", - "//testing/spectest/utils:go_default_library", + "//runtime/version:go_default_library", + "//testing/spectest/shared/common/operations:go_default_library", "//testing/util:go_default_library", - "@com_github_golang_snappy//:go_default_library", - "@com_github_google_go_cmp//cmp:go_default_library", - "@io_bazel_rules_go//go/tools/bazel:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", - "@org_golang_google_protobuf//testing/protocmp:go_default_library", ], ) diff --git a/testing/spectest/shared/altair/operations/attestation.go b/testing/spectest/shared/altair/operations/attestation.go index 2de911878881..efba6a2fdd67 100644 --- a/testing/spectest/shared/altair/operations/attestation.go +++ b/testing/spectest/shared/altair/operations/attestation.go @@ -1,59 +1,27 @@ package operations import ( - "context" - "errors" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - b "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttestationTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "altair", "operations/attestation/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "altair", "operations/attestation/pyspec_tests") +func blockWithAttestation(attestationSSZ []byte) (interfaces.SignedBeaconBlock, error) { + att := ðpb.Attestation{} + if err := att.UnmarshalSSZ(attestationSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attestationFile, err := util.BazelFileBytes(folderPath, "attestation.ssz_snappy") - require.NoError(t, err) - attestationSSZ, err := snappy.Decode(nil /* dst */, attestationFile) - require.NoError(t, err, "Failed to decompress") - att := ðpb.Attestation{} - require.NoError(t, att.UnmarshalSSZ(attestationSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyAltair{Attestations: []*ethpb.Attestation{att}} - processAtt := func(ctx context.Context, st state.BeaconState, blk interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, err = altair.ProcessAttestationsNoVerifySignature(ctx, st, blk.Block()) - if err != nil { - return nil, err - } - aSet, err := b.AttestationSignatureBatch(ctx, st, blk.Block().Body().Attestations()) - if err != nil { - return nil, err - } - verified, err := aSet.Verify() - if err != nil { - return nil, err - } - if !verified { - return nil, errors.New("could not batch verify attestation signature") - } - return st, nil - } + b := util.NewBeaconBlockAltair() + b.Block.Body = ðpb.BeaconBlockBodyAltair{Attestations: []*ethpb.Attestation{att}} + return blocks.NewSignedBeaconBlock(b) +} - RunBlockOperationTest(t, folderPath, body, processAtt) - }) - } +func RunAttestationTest(t *testing.T, config string) { + common.RunAttestationTest(t, config, version.String(version.Altair), blockWithAttestation, altair.ProcessAttestationsNoVerifySignature, sszToState) } diff --git a/testing/spectest/shared/altair/operations/attester_slashing.go b/testing/spectest/shared/altair/operations/attester_slashing.go index 93c9e2c5537f..f80832a7a104 100644 --- a/testing/spectest/shared/altair/operations/attester_slashing.go +++ b/testing/spectest/shared/altair/operations/attester_slashing.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttesterSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "altair", "operations/attester_slashing/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "altair", "operations/attester_slashing/pyspec_tests") +func blockWithAttesterSlashing(asSSZ []byte) (interfaces.SignedBeaconBlock, error) { + as := ðpb.AttesterSlashing{} + if err := as.UnmarshalSSZ(asSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attSlashingFile, err := util.BazelFileBytes(folderPath, "attester_slashing.ssz_snappy") - require.NoError(t, err) - attSlashingSSZ, err := snappy.Decode(nil /* dst */, attSlashingFile) - require.NoError(t, err, "Failed to decompress") - attSlashing := ðpb.AttesterSlashing{} - require.NoError(t, attSlashing.UnmarshalSSZ(attSlashingSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockAltair() + b.Block.Body = ðpb.BeaconBlockBodyAltair{AttesterSlashings: []*ethpb.AttesterSlashing{as}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyAltair{AttesterSlashings: []*ethpb.AttesterSlashing{attSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessAttesterSlashings(ctx, s, b.Block().Body().AttesterSlashings(), validators.SlashValidator) - }) - }) - } +func RunAttesterSlashingTest(t *testing.T, config string) { + common.RunAttesterSlashingTest(t, config, version.String(version.Altair), blockWithAttesterSlashing, sszToState) } diff --git a/testing/spectest/shared/altair/operations/block_header.go b/testing/spectest/shared/altair/operations/block_header.go index 103b6e33d3aa..f43176b9d0e6 100644 --- a/testing/spectest/shared/altair/operations/block_header.go +++ b/testing/spectest/shared/altair/operations/block_header.go @@ -1,90 +1,12 @@ package operations import ( - "context" - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunBlockHeaderTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "altair", "operations/block_header/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "altair", "operations/block_header/pyspec_tests") - } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - - blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "block.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockFile) - require.NoError(t, err, "Failed to decompress") - block := ðpb.BeaconBlockAltair{} - require.NoError(t, block.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateAltair{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoAltair(preBeaconStateBase) - require.NoError(t, err) - - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - // Spectest blocks are not signed, so we'll call NoVerify to skip sig verification. - bodyRoot, err := block.Body.HashTreeRoot() - require.NoError(t, err) - beaconState, err := blocks.ProcessBlockHeaderNoVerify(context.Background(), preBeaconState, block.Slot, block.ProposerIndex, block.ParentRoot, bodyRoot[:]) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateAltair{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateAltair(beaconState.ToProto()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } + common.RunBlockHeaderTest(t, config, version.String(version.Altair), sszToBlock, sszToState) } diff --git a/testing/spectest/shared/altair/operations/deposit.go b/testing/spectest/shared/altair/operations/deposit.go index 7b18ef1ae3e1..fa9e101291d9 100644 --- a/testing/spectest/shared/altair/operations/deposit.go +++ b/testing/spectest/shared/altair/operations/deposit.go @@ -1,41 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunDepositTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "altair", "operations/deposit/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "altair", "operations/deposit/pyspec_tests") +func blockWithDeposit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + d := ðpb.Deposit{} + if err := d.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - depositFile, err := util.BazelFileBytes(folderPath, "deposit.ssz_snappy") - require.NoError(t, err) - depositSSZ, err := snappy.Decode(nil /* dst */, depositFile) - require.NoError(t, err, "Failed to decompress") - deposit := ðpb.Deposit{} - require.NoError(t, deposit.UnmarshalSSZ(depositSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockAltair() + b.Block.Body = ðpb.BeaconBlockBodyAltair{Deposits: []*ethpb.Deposit{d}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyAltair{Deposits: []*ethpb.Deposit{deposit}} - processDepositsFunc := func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return altair.ProcessDeposits(ctx, s, b.Block().Body().Deposits()) - } - RunBlockOperationTest(t, folderPath, body, processDepositsFunc) - }) - } +func RunDepositTest(t *testing.T, config string) { + common.RunDepositTest(t, config, version.String(version.Altair), blockWithDeposit, altair.ProcessDeposits, sszToState) } diff --git a/testing/spectest/shared/altair/operations/helpers.go b/testing/spectest/shared/altair/operations/helpers.go index 188eb237e3b8..4312d2a366d6 100644 --- a/testing/spectest/shared/altair/operations/helpers.go +++ b/testing/spectest/shared/altair/operations/helpers.go @@ -1,88 +1,25 @@ package operations import ( - "context" - "os" - "path" - "strings" - "testing" - - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" ) -type blockOperation func(context.Context, state.BeaconState, interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) - -// RunBlockOperationTest takes in the prestate and the beacon block body, processes it through the -// passed in block operation function and checks the post state with the expected post state. -func RunBlockOperationTest( - t *testing.T, - folderPath string, - body *ethpb.BeaconBlockBodyAltair, - operationFn blockOperation, -) { - preBeaconStateFile, err := util.BazelFileBytes(path.Join(folderPath, "pre.ssz_snappy")) - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preStateBase := ðpb.BeaconStateAltair{} - if err := preStateBase.UnmarshalSSZ(preBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) - } - preState, err := state_native.InitializeFromProtoAltair(preStateBase) - require.NoError(t, err) - - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(folderPath, "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else if err != nil { - t.Fatal(err) +func sszToState(b []byte) (state.BeaconState, error) { + base := ðpb.BeaconStateAltair{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return state_native.InitializeFromProtoAltair(base) +} - helpers.ClearCache() - b := util.NewBeaconBlockAltair() - b.Block.Body = body - wsb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - beaconState, err := operationFn(context.Background(), preState, wsb) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateAltair{} - if err := postBeaconState.UnmarshalSSZ(postBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) - } - pbState, err := state_native.ProtobufBeaconStateAltair(beaconState.ToProtoUnsafe()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return +func sszToBlock(b []byte) (interfaces.SignedBeaconBlock, error) { + base := ðpb.BeaconBlockAltair{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockAltair{Block: base}) } diff --git a/testing/spectest/shared/altair/operations/proposer_slashing.go b/testing/spectest/shared/altair/operations/proposer_slashing.go index 29af6d0a0d77..99b9be588aa9 100644 --- a/testing/spectest/shared/altair/operations/proposer_slashing.go +++ b/testing/spectest/shared/altair/operations/proposer_slashing.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunProposerSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "altair", "operations/proposer_slashing/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "altair", "operations/proposer_slashing/pyspec_tests") +func blockWithProposerSlashing(ssz []byte) (interfaces.SignedBeaconBlock, error) { + ps := ðpb.ProposerSlashing{} + if err := ps.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - proposerSlashingFile, err := util.BazelFileBytes(folderPath, "proposer_slashing.ssz_snappy") - require.NoError(t, err) - proposerSlashingSSZ, err := snappy.Decode(nil /* dst */, proposerSlashingFile) - require.NoError(t, err, "Failed to decompress") - proposerSlashing := ðpb.ProposerSlashing{} - require.NoError(t, proposerSlashing.UnmarshalSSZ(proposerSlashingSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockAltair() + b.Block.Body = ðpb.BeaconBlockBodyAltair{ProposerSlashings: []*ethpb.ProposerSlashing{ps}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyAltair{ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessProposerSlashings(ctx, s, b.Block().Body().ProposerSlashings(), validators.SlashValidator) - }) - }) - } +func RunProposerSlashingTest(t *testing.T, config string) { + common.RunProposerSlashingTest(t, config, version.String(version.Altair), blockWithProposerSlashing, sszToState) } diff --git a/testing/spectest/shared/altair/operations/sync_committee.go b/testing/spectest/shared/altair/operations/sync_committee.go index 173a8aea7665..2ef08cecb12b 100644 --- a/testing/spectest/shared/altair/operations/sync_committee.go +++ b/testing/spectest/shared/altair/operations/sync_committee.go @@ -1,44 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunSyncCommitteeTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "altair", "operations/sync_aggregate/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "altair", "operations/sync_aggregate/pyspec_tests") +func blockWithSyncAggregate(ssz []byte) (interfaces.SignedBeaconBlock, error) { + sa := ðpb.SyncAggregate{} + if err := sa.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - syncCommitteeFile, err := util.BazelFileBytes(folderPath, "sync_aggregate.ssz_snappy") - require.NoError(t, err) - syncCommitteeSSZ, err := snappy.Decode(nil /* dst */, syncCommitteeFile) - require.NoError(t, err, "Failed to decompress") - sc := ðpb.SyncAggregate{} - require.NoError(t, sc.UnmarshalSSZ(syncCommitteeSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockAltair() + b.Block.Body = ðpb.BeaconBlockBodyAltair{SyncAggregate: sa} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyAltair{SyncAggregate: sc} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, _, err := altair.ProcessSyncAggregate(context.Background(), s, body.SyncAggregate) - if err != nil { - return nil, err - } - return st, nil - }) - }) - } +func RunSyncCommitteeTest(t *testing.T, config string) { + common.RunSyncCommitteeTest(t, config, version.String(version.Altair), blockWithSyncAggregate, sszToState) } diff --git a/testing/spectest/shared/altair/operations/voluntary_exit.go b/testing/spectest/shared/altair/operations/voluntary_exit.go index 5e1bbf919d8a..f602930683b6 100644 --- a/testing/spectest/shared/altair/operations/voluntary_exit.go +++ b/testing/spectest/shared/altair/operations/voluntary_exit.go @@ -1,40 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunVoluntaryExitTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "altair", "operations/voluntary_exit/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "altair", "operations/voluntary_exit/pyspec_tests") +func blockWithVoluntaryExit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := ðpb.SignedVoluntaryExit{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - exitFile, err := util.BazelFileBytes(folderPath, "voluntary_exit.ssz_snappy") - require.NoError(t, err) - exitSSZ, err := snappy.Decode(nil /* dst */, exitFile) - require.NoError(t, err, "Failed to decompress") - voluntaryExit := ðpb.SignedVoluntaryExit{} - require.NoError(t, voluntaryExit.UnmarshalSSZ(exitSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockAltair() + b.Block.Body = ðpb.BeaconBlockBodyAltair{VoluntaryExits: []*ethpb.SignedVoluntaryExit{e}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyAltair{VoluntaryExits: []*ethpb.SignedVoluntaryExit{voluntaryExit}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessVoluntaryExits(ctx, s, b.Block().Body().VoluntaryExits()) - }) - }) - } +func RunVoluntaryExitTest(t *testing.T, config string) { + common.RunVoluntaryExitTest(t, config, version.String(version.Altair), blockWithVoluntaryExit, sszToState) } diff --git a/testing/spectest/shared/bellatrix/epoch_processing/BUILD.bazel b/testing/spectest/shared/bellatrix/epoch_processing/BUILD.bazel index 03ac47eaec86..569637985d43 100644 --- a/testing/spectest/shared/bellatrix/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/bellatrix/epoch_processing/BUILD.bazel @@ -26,7 +26,6 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", - "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/bellatrix/epoch_processing/slashings.go b/testing/spectest/shared/bellatrix/epoch_processing/slashings.go index 09ea116074f4..a75490f5b966 100644 --- a/testing/spectest/shared/bellatrix/epoch_processing/slashings.go +++ b/testing/spectest/shared/bellatrix/epoch_processing/slashings.go @@ -7,7 +7,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" ) @@ -30,7 +29,6 @@ func RunSlashingsTests(t *testing.T, config string) { } func processSlashingsWrapper(t *testing.T, st state.BeaconState) (state.BeaconState, error) { - st, err := epoch.ProcessSlashings(st, params.BeaconConfig().ProportionalSlashingMultiplierBellatrix) - require.NoError(t, err, "Could not process slashings") + require.NoError(t, epoch.ProcessSlashings(st), "Could not process slashings") return st, nil } diff --git a/testing/spectest/shared/bellatrix/operations/BUILD.bazel b/testing/spectest/shared/bellatrix/operations/BUILD.bazel index 3e5b2027dc0c..8ab888a3ddd3 100644 --- a/testing/spectest/shared/bellatrix/operations/BUILD.bazel +++ b/testing/spectest/shared/bellatrix/operations/BUILD.bazel @@ -18,21 +18,13 @@ go_library( visibility = ["//testing/spectest:__subpackages__"], deps = [ "//beacon-chain/core/altair:go_default_library", - "//beacon-chain/core/blocks:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/validators:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//testing/require:go_default_library", - "//testing/spectest/utils:go_default_library", + "//runtime/version:go_default_library", + "//testing/spectest/shared/common/operations:go_default_library", "//testing/util:go_default_library", - "@com_github_golang_snappy//:go_default_library", - "@com_github_google_go_cmp//cmp:go_default_library", - "@io_bazel_rules_go//go/tools/bazel:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", - "@org_golang_google_protobuf//testing/protocmp:go_default_library", ], ) diff --git a/testing/spectest/shared/bellatrix/operations/attestation.go b/testing/spectest/shared/bellatrix/operations/attestation.go index 2839bf38b7f9..0a2f88093e70 100644 --- a/testing/spectest/shared/bellatrix/operations/attestation.go +++ b/testing/spectest/shared/bellatrix/operations/attestation.go @@ -1,59 +1,27 @@ package operations import ( - "context" - "errors" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - b "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttestationTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "bellatrix", "operations/attestation/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "bellatrix", "operations/attestation/pyspec_tests") +func blockWithAttestation(attestationSSZ []byte) (interfaces.SignedBeaconBlock, error) { + att := ðpb.Attestation{} + if err := att.UnmarshalSSZ(attestationSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attestationFile, err := util.BazelFileBytes(folderPath, "attestation.ssz_snappy") - require.NoError(t, err) - attestationSSZ, err := snappy.Decode(nil /* dst */, attestationFile) - require.NoError(t, err, "Failed to decompress") - att := ðpb.Attestation{} - require.NoError(t, att.UnmarshalSSZ(attestationSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyBellatrix{Attestations: []*ethpb.Attestation{att}} - processAtt := func(ctx context.Context, st state.BeaconState, blk interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, err = altair.ProcessAttestationsNoVerifySignature(ctx, st, blk.Block()) - if err != nil { - return nil, err - } - aSet, err := b.AttestationSignatureBatch(ctx, st, blk.Block().Body().Attestations()) - if err != nil { - return nil, err - } - verified, err := aSet.Verify() - if err != nil { - return nil, err - } - if !verified { - return nil, errors.New("could not batch verify attestation signature") - } - return st, nil - } + b := util.NewBeaconBlockBellatrix() + b.Block.Body = ðpb.BeaconBlockBodyBellatrix{Attestations: []*ethpb.Attestation{att}} + return blocks.NewSignedBeaconBlock(b) +} - RunBlockOperationTest(t, folderPath, body, processAtt) - }) - } +func RunAttestationTest(t *testing.T, config string) { + common.RunAttestationTest(t, config, version.String(version.Bellatrix), blockWithAttestation, altair.ProcessAttestationsNoVerifySignature, sszToState) } diff --git a/testing/spectest/shared/bellatrix/operations/attester_slashing.go b/testing/spectest/shared/bellatrix/operations/attester_slashing.go index 76d61b0021e5..ef6c7e81017a 100644 --- a/testing/spectest/shared/bellatrix/operations/attester_slashing.go +++ b/testing/spectest/shared/bellatrix/operations/attester_slashing.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttesterSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "bellatrix", "operations/attester_slashing/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "bellatrix", "operations/attester_slashing/pyspec_tests") +func blockWithAttesterSlashing(asSSZ []byte) (interfaces.SignedBeaconBlock, error) { + as := ðpb.AttesterSlashing{} + if err := as.UnmarshalSSZ(asSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attSlashingFile, err := util.BazelFileBytes(folderPath, "attester_slashing.ssz_snappy") - require.NoError(t, err) - attSlashingSSZ, err := snappy.Decode(nil /* dst */, attSlashingFile) - require.NoError(t, err, "Failed to decompress") - attSlashing := ðpb.AttesterSlashing{} - require.NoError(t, attSlashing.UnmarshalSSZ(attSlashingSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockBellatrix() + b.Block.Body = ðpb.BeaconBlockBodyBellatrix{AttesterSlashings: []*ethpb.AttesterSlashing{as}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyBellatrix{AttesterSlashings: []*ethpb.AttesterSlashing{attSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessAttesterSlashings(ctx, s, b.Block().Body().AttesterSlashings(), validators.SlashValidator) - }) - }) - } +func RunAttesterSlashingTest(t *testing.T, config string) { + common.RunAttesterSlashingTest(t, config, version.String(version.Bellatrix), blockWithAttesterSlashing, sszToState) } diff --git a/testing/spectest/shared/bellatrix/operations/block_header.go b/testing/spectest/shared/bellatrix/operations/block_header.go index 51d911bedabb..ae06b1f4e51b 100644 --- a/testing/spectest/shared/bellatrix/operations/block_header.go +++ b/testing/spectest/shared/bellatrix/operations/block_header.go @@ -1,90 +1,12 @@ package operations import ( - "context" - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunBlockHeaderTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "bellatrix", "operations/block_header/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "bellatrix", "operations/block_header/pyspec_tests") - } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - - blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "block.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockFile) - require.NoError(t, err, "Failed to decompress") - block := ðpb.BeaconBlockBellatrix{} - require.NoError(t, block.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateBellatrix{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoBellatrix(preBeaconStateBase) - require.NoError(t, err) - - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - // Spectest blocks are not signed, so we'll call NoVerify to skip sig verification. - bodyRoot, err := block.Body.HashTreeRoot() - require.NoError(t, err) - beaconState, err := blocks.ProcessBlockHeaderNoVerify(context.Background(), preBeaconState, block.Slot, block.ProposerIndex, block.ParentRoot, bodyRoot[:]) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateBellatrix{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateBellatrix(beaconState.ToProto()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } + common.RunBlockHeaderTest(t, config, version.String(version.Bellatrix), sszToBlock, sszToState) } diff --git a/testing/spectest/shared/bellatrix/operations/deposit.go b/testing/spectest/shared/bellatrix/operations/deposit.go index ac1b807cc28b..55ef0c904918 100644 --- a/testing/spectest/shared/bellatrix/operations/deposit.go +++ b/testing/spectest/shared/bellatrix/operations/deposit.go @@ -1,41 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunDepositTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "bellatrix", "operations/deposit/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "bellatrix", "operations/deposit/pyspec_tests") +func blockWithDeposit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + d := ðpb.Deposit{} + if err := d.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - depositFile, err := util.BazelFileBytes(folderPath, "deposit.ssz_snappy") - require.NoError(t, err) - depositSSZ, err := snappy.Decode(nil /* dst */, depositFile) - require.NoError(t, err, "Failed to decompress") - deposit := ðpb.Deposit{} - require.NoError(t, deposit.UnmarshalSSZ(depositSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockBellatrix() + b.Block.Body = ðpb.BeaconBlockBodyBellatrix{Deposits: []*ethpb.Deposit{d}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyBellatrix{Deposits: []*ethpb.Deposit{deposit}} - processDepositsFunc := func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return altair.ProcessDeposits(ctx, s, b.Block().Body().Deposits()) - } - RunBlockOperationTest(t, folderPath, body, processDepositsFunc) - }) - } +func RunDepositTest(t *testing.T, config string) { + common.RunDepositTest(t, config, version.String(version.Bellatrix), blockWithDeposit, altair.ProcessDeposits, sszToState) } diff --git a/testing/spectest/shared/bellatrix/operations/execution_payload.go b/testing/spectest/shared/bellatrix/operations/execution_payload.go index 233e57175752..4283f9d256e0 100644 --- a/testing/spectest/shared/bellatrix/operations/execution_payload.go +++ b/testing/spectest/shared/bellatrix/operations/execution_payload.go @@ -1,98 +1,12 @@ package operations import ( - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - blocks2 "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunExecutionPayloadTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "bellatrix", "operations/execution_payload/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "bellatrix", "operations/execution_payload/pyspec_tests") - } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - - blockBodyFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "body.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockBodyFile) - require.NoError(t, err, "Failed to decompress") - block := ðpb.BeaconBlockBodyBellatrix{} - require.NoError(t, block.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateBellatrix{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoBellatrix(preBeaconStateBase) - require.NoError(t, err) - - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - payload, err := blocks2.WrappedExecutionPayload(block.ExecutionPayload) - require.NoError(t, err) - - file, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "execution.yaml") - require.NoError(t, err) - config := &ExecutionConfig{} - require.NoError(t, utils.UnmarshalYaml(file, config), "Failed to Unmarshal") - - gotState, err := blocks.ProcessPayload(preBeaconState, payload) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateBellatrix{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateBellatrix(gotState.ToProto()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else if config.Valid { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } -} - -type ExecutionConfig struct { - Valid bool `json:"execution_valid"` + common.RunExecutionPayloadTest(t, config, version.String(version.Bellatrix), sszToBlockBody, sszToState) } diff --git a/testing/spectest/shared/bellatrix/operations/helpers.go b/testing/spectest/shared/bellatrix/operations/helpers.go index c234c6d0f7e9..b1b4d3cb3f93 100644 --- a/testing/spectest/shared/bellatrix/operations/helpers.go +++ b/testing/spectest/shared/bellatrix/operations/helpers.go @@ -1,88 +1,33 @@ package operations import ( - "context" - "os" - "path" - "strings" - "testing" - - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" ) -type blockOperation func(context.Context, state.BeaconState, interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) - -// RunBlockOperationTest takes in the prestate and the beacon block body, processes it through the -// passed in block operation function and checks the post state with the expected post state. -func RunBlockOperationTest( - t *testing.T, - folderPath string, - body *ethpb.BeaconBlockBodyBellatrix, - operationFn blockOperation, -) { - preBeaconStateFile, err := util.BazelFileBytes(path.Join(folderPath, "pre.ssz_snappy")) - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preStateBase := ðpb.BeaconStateBellatrix{} - if err := preStateBase.UnmarshalSSZ(preBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) +func sszToState(b []byte) (state.BeaconState, error) { + base := ðpb.BeaconStateBellatrix{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } - preState, err := state_native.InitializeFromProtoBellatrix(preStateBase) - require.NoError(t, err) + return state_native.InitializeFromProtoBellatrix(base) +} - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(folderPath, "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else if err != nil { - t.Fatal(err) +func sszToBlock(b []byte) (interfaces.SignedBeaconBlock, error) { + base := ðpb.BeaconBlockBellatrix{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{Block: base}) +} - helpers.ClearCache() - b := util.NewBeaconBlockBellatrix() - b.Block.Body = body - wsb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - beaconState, err := operationFn(context.Background(), preState, wsb) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateBellatrix{} - if err := postBeaconState.UnmarshalSSZ(postBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) - } - pbState, err := state_native.ProtobufBeaconStateBellatrix(beaconState.ToProtoUnsafe()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return +func sszToBlockBody(b []byte) (interfaces.ReadOnlyBeaconBlockBody, error) { + base := ðpb.BeaconBlockBodyBellatrix{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewBeaconBlockBody(base) } diff --git a/testing/spectest/shared/bellatrix/operations/proposer_slashing.go b/testing/spectest/shared/bellatrix/operations/proposer_slashing.go index 39631c054273..3f0bfa2d75b3 100644 --- a/testing/spectest/shared/bellatrix/operations/proposer_slashing.go +++ b/testing/spectest/shared/bellatrix/operations/proposer_slashing.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunProposerSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "bellatrix", "operations/proposer_slashing/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "bellatrix", "operations/proposer_slashing/pyspec_tests") +func blockWithProposerSlashing(ssz []byte) (interfaces.SignedBeaconBlock, error) { + ps := ðpb.ProposerSlashing{} + if err := ps.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - proposerSlashingFile, err := util.BazelFileBytes(folderPath, "proposer_slashing.ssz_snappy") - require.NoError(t, err) - proposerSlashingSSZ, err := snappy.Decode(nil /* dst */, proposerSlashingFile) - require.NoError(t, err, "Failed to decompress") - proposerSlashing := ðpb.ProposerSlashing{} - require.NoError(t, proposerSlashing.UnmarshalSSZ(proposerSlashingSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockBellatrix() + b.Block.Body = ðpb.BeaconBlockBodyBellatrix{ProposerSlashings: []*ethpb.ProposerSlashing{ps}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyBellatrix{ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessProposerSlashings(ctx, s, b.Block().Body().ProposerSlashings(), validators.SlashValidator) - }) - }) - } +func RunProposerSlashingTest(t *testing.T, config string) { + common.RunProposerSlashingTest(t, config, version.String(version.Bellatrix), blockWithProposerSlashing, sszToState) } diff --git a/testing/spectest/shared/bellatrix/operations/sync_committee.go b/testing/spectest/shared/bellatrix/operations/sync_committee.go index 431e0bd98731..f74db78539a7 100644 --- a/testing/spectest/shared/bellatrix/operations/sync_committee.go +++ b/testing/spectest/shared/bellatrix/operations/sync_committee.go @@ -1,44 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunSyncCommitteeTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "bellatrix", "operations/sync_aggregate/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "bellatrix", "operations/sync_aggregate/pyspec_tests") +func blockWithSyncAggregate(ssz []byte) (interfaces.SignedBeaconBlock, error) { + sa := ðpb.SyncAggregate{} + if err := sa.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - syncCommitteeFile, err := util.BazelFileBytes(folderPath, "sync_aggregate.ssz_snappy") - require.NoError(t, err) - syncCommitteeSSZ, err := snappy.Decode(nil /* dst */, syncCommitteeFile) - require.NoError(t, err, "Failed to decompress") - sc := ðpb.SyncAggregate{} - require.NoError(t, sc.UnmarshalSSZ(syncCommitteeSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockBellatrix() + b.Block.Body = ðpb.BeaconBlockBodyBellatrix{SyncAggregate: sa} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyBellatrix{SyncAggregate: sc} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, _, err := altair.ProcessSyncAggregate(context.Background(), s, body.SyncAggregate) - if err != nil { - return nil, err - } - return st, nil - }) - }) - } +func RunSyncCommitteeTest(t *testing.T, config string) { + common.RunSyncCommitteeTest(t, config, version.String(version.Bellatrix), blockWithSyncAggregate, sszToState) } diff --git a/testing/spectest/shared/bellatrix/operations/voluntary_exit.go b/testing/spectest/shared/bellatrix/operations/voluntary_exit.go index 6c07aa7e725d..330a4fb05217 100644 --- a/testing/spectest/shared/bellatrix/operations/voluntary_exit.go +++ b/testing/spectest/shared/bellatrix/operations/voluntary_exit.go @@ -1,40 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunVoluntaryExitTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "bellatrix", "operations/voluntary_exit/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "bellatrix", "operations/voluntary_exit/pyspec_tests") +func blockWithVoluntaryExit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := ðpb.SignedVoluntaryExit{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - exitFile, err := util.BazelFileBytes(folderPath, "voluntary_exit.ssz_snappy") - require.NoError(t, err) - exitSSZ, err := snappy.Decode(nil /* dst */, exitFile) - require.NoError(t, err, "Failed to decompress") - voluntaryExit := ðpb.SignedVoluntaryExit{} - require.NoError(t, voluntaryExit.UnmarshalSSZ(exitSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockBellatrix() + b.Block.Body = ðpb.BeaconBlockBodyBellatrix{VoluntaryExits: []*ethpb.SignedVoluntaryExit{e}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyBellatrix{VoluntaryExits: []*ethpb.SignedVoluntaryExit{voluntaryExit}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessVoluntaryExits(ctx, s, b.Block().Body().VoluntaryExits()) - }) - }) - } +func RunVoluntaryExitTest(t *testing.T, config string) { + common.RunVoluntaryExitTest(t, config, version.String(version.Bellatrix), blockWithVoluntaryExit, sszToState) } diff --git a/testing/spectest/shared/capella/epoch_processing/BUILD.bazel b/testing/spectest/shared/capella/epoch_processing/BUILD.bazel index 9fd12223eb3e..02aca35745dd 100644 --- a/testing/spectest/shared/capella/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/capella/epoch_processing/BUILD.bazel @@ -26,7 +26,6 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", - "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/capella/epoch_processing/slashings.go b/testing/spectest/shared/capella/epoch_processing/slashings.go index ca837abc6144..8495508d4176 100644 --- a/testing/spectest/shared/capella/epoch_processing/slashings.go +++ b/testing/spectest/shared/capella/epoch_processing/slashings.go @@ -7,7 +7,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" ) @@ -30,7 +29,6 @@ func RunSlashingsTests(t *testing.T, config string) { } func processSlashingsWrapper(t *testing.T, st state.BeaconState) (state.BeaconState, error) { - st, err := epoch.ProcessSlashings(st, params.BeaconConfig().ProportionalSlashingMultiplierBellatrix) - require.NoError(t, err, "Could not process slashings") + require.NoError(t, epoch.ProcessSlashings(st), "Could not process slashings") return st, nil } diff --git a/testing/spectest/shared/capella/operations/BUILD.bazel b/testing/spectest/shared/capella/operations/BUILD.bazel index f3c6b5fbe260..95c7369130f0 100644 --- a/testing/spectest/shared/capella/operations/BUILD.bazel +++ b/testing/spectest/shared/capella/operations/BUILD.bazel @@ -20,23 +20,14 @@ go_library( visibility = ["//testing/spectest:__subpackages__"], deps = [ "//beacon-chain/core/altair:go_default_library", - "//beacon-chain/core/blocks:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/validators:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//testing/require:go_default_library", - "//testing/spectest/utils:go_default_library", + "//runtime/version:go_default_library", + "//testing/spectest/shared/common/operations:go_default_library", "//testing/util:go_default_library", - "@com_github_golang_snappy//:go_default_library", - "@com_github_google_go_cmp//cmp:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@io_bazel_rules_go//go/tools/bazel:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", - "@org_golang_google_protobuf//testing/protocmp:go_default_library", ], ) diff --git a/testing/spectest/shared/capella/operations/attestation.go b/testing/spectest/shared/capella/operations/attestation.go index c23cda82aa39..d649070a8290 100644 --- a/testing/spectest/shared/capella/operations/attestation.go +++ b/testing/spectest/shared/capella/operations/attestation.go @@ -1,59 +1,27 @@ package operations import ( - "context" - "errors" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - b "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttestationTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/attestation/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/attestation/pyspec_tests") +func blockWithAttestation(attestationSSZ []byte) (interfaces.SignedBeaconBlock, error) { + att := ðpb.Attestation{} + if err := att.UnmarshalSSZ(attestationSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attestationFile, err := util.BazelFileBytes(folderPath, "attestation.ssz_snappy") - require.NoError(t, err) - attestationSSZ, err := snappy.Decode(nil /* dst */, attestationFile) - require.NoError(t, err, "Failed to decompress") - att := ðpb.Attestation{} - require.NoError(t, att.UnmarshalSSZ(attestationSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyCapella{Attestations: []*ethpb.Attestation{att}} - processAtt := func(ctx context.Context, st state.BeaconState, blk interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, err = altair.ProcessAttestationsNoVerifySignature(ctx, st, blk.Block()) - if err != nil { - return nil, err - } - aSet, err := b.AttestationSignatureBatch(ctx, st, blk.Block().Body().Attestations()) - if err != nil { - return nil, err - } - verified, err := aSet.Verify() - if err != nil { - return nil, err - } - if !verified { - return nil, errors.New("could not batch verify attestation signature") - } - return st, nil - } + b := util.NewBeaconBlockCapella() + b.Block.Body = ðpb.BeaconBlockBodyCapella{Attestations: []*ethpb.Attestation{att}} + return blocks.NewSignedBeaconBlock(b) +} - RunBlockOperationTest(t, folderPath, body, processAtt) - }) - } +func RunAttestationTest(t *testing.T, config string) { + common.RunAttestationTest(t, config, version.String(version.Capella), blockWithAttestation, altair.ProcessAttestationsNoVerifySignature, sszToState) } diff --git a/testing/spectest/shared/capella/operations/attester_slashing.go b/testing/spectest/shared/capella/operations/attester_slashing.go index 47909240dd7e..c7b035e07144 100644 --- a/testing/spectest/shared/capella/operations/attester_slashing.go +++ b/testing/spectest/shared/capella/operations/attester_slashing.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttesterSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/attester_slashing/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/attester_slashing/pyspec_tests") +func blockWithAttesterSlashing(asSSZ []byte) (interfaces.SignedBeaconBlock, error) { + as := ðpb.AttesterSlashing{} + if err := as.UnmarshalSSZ(asSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attSlashingFile, err := util.BazelFileBytes(folderPath, "attester_slashing.ssz_snappy") - require.NoError(t, err) - attSlashingSSZ, err := snappy.Decode(nil /* dst */, attSlashingFile) - require.NoError(t, err, "Failed to decompress") - attSlashing := ðpb.AttesterSlashing{} - require.NoError(t, attSlashing.UnmarshalSSZ(attSlashingSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockCapella() + b.Block.Body = ðpb.BeaconBlockBodyCapella{AttesterSlashings: []*ethpb.AttesterSlashing{as}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyCapella{AttesterSlashings: []*ethpb.AttesterSlashing{attSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessAttesterSlashings(ctx, s, b.Block().Body().AttesterSlashings(), validators.SlashValidator) - }) - }) - } +func RunAttesterSlashingTest(t *testing.T, config string) { + common.RunAttesterSlashingTest(t, config, version.String(version.Capella), blockWithAttesterSlashing, sszToState) } diff --git a/testing/spectest/shared/capella/operations/block_header.go b/testing/spectest/shared/capella/operations/block_header.go index 1ca2ff80d6da..328ae6526589 100644 --- a/testing/spectest/shared/capella/operations/block_header.go +++ b/testing/spectest/shared/capella/operations/block_header.go @@ -1,90 +1,12 @@ package operations import ( - "context" - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunBlockHeaderTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/block_header/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/block_header/pyspec_tests") - } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - - blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "block.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockFile) - require.NoError(t, err, "Failed to decompress") - block := ðpb.BeaconBlockCapella{} - require.NoError(t, block.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateCapella{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoCapella(preBeaconStateBase) - require.NoError(t, err) - - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - // Spectest blocks are not signed, so we'll call NoVerify to skip sig verification. - bodyRoot, err := block.Body.HashTreeRoot() - require.NoError(t, err) - beaconState, err := blocks.ProcessBlockHeaderNoVerify(context.Background(), preBeaconState, block.Slot, block.ProposerIndex, block.ParentRoot, bodyRoot[:]) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateCapella{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateCapella(beaconState.ToProto()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } + common.RunBlockHeaderTest(t, config, version.String(version.Capella), sszToBlock, sszToState) } diff --git a/testing/spectest/shared/capella/operations/bls_to_execution_changes.go b/testing/spectest/shared/capella/operations/bls_to_execution_changes.go index 1a41a6ca7d77..6fa289bfc98a 100644 --- a/testing/spectest/shared/capella/operations/bls_to_execution_changes.go +++ b/testing/spectest/shared/capella/operations/bls_to_execution_changes.go @@ -1,62 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunBLSToExecutionChangeTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/bls_to_execution_change/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/bls_to_execution_change/pyspec_tests") +func blockWithBlsChange(ssz []byte) (interfaces.SignedBeaconBlock, error) { + c := ðpb.SignedBLSToExecutionChange{} + if err := c.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - changeFile, err := util.BazelFileBytes(folderPath, "address_change.ssz_snappy") - require.NoError(t, err) - changeSSZ, err := snappy.Decode(nil /* dst */, changeFile) - require.NoError(t, err, "Failed to decompress") - change := ðpb.SignedBLSToExecutionChange{} - require.NoError(t, change.UnmarshalSSZ(changeSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockCapella() + b.Block.Body = ðpb.BeaconBlockBodyCapella{BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{c}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyCapella{ - BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{change}, - } - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, err := blocks.ProcessBLSToExecutionChanges(s, b.Block()) - if err != nil { - return nil, err - } - changes, err := b.Block().Body().BLSToExecutionChanges() - if err != nil { - return nil, err - } - cSet, err := blocks.BLSChangesSignatureBatch(st, changes) - if err != nil { - return nil, err - } - ok, err := cSet.Verify() - if err != nil { - return nil, err - } - if !ok { - return nil, errors.New("signature did not verify") - } - return st, nil - }) - }) - } +func RunBLSToExecutionChangeTest(t *testing.T, config string) { + common.RunBLSToExecutionChangeTest(t, config, version.String(version.Capella), blockWithBlsChange, sszToState) } diff --git a/testing/spectest/shared/capella/operations/deposit.go b/testing/spectest/shared/capella/operations/deposit.go index 59c384bd4762..09320013b58e 100644 --- a/testing/spectest/shared/capella/operations/deposit.go +++ b/testing/spectest/shared/capella/operations/deposit.go @@ -1,41 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunDepositTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/deposit/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/deposit/pyspec_tests") +func blockWithDeposit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + d := ðpb.Deposit{} + if err := d.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - depositFile, err := util.BazelFileBytes(folderPath, "deposit.ssz_snappy") - require.NoError(t, err) - depositSSZ, err := snappy.Decode(nil /* dst */, depositFile) - require.NoError(t, err, "Failed to decompress") - deposit := ðpb.Deposit{} - require.NoError(t, deposit.UnmarshalSSZ(depositSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockCapella() + b.Block.Body = ðpb.BeaconBlockBodyCapella{Deposits: []*ethpb.Deposit{d}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyCapella{Deposits: []*ethpb.Deposit{deposit}} - processDepositsFunc := func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return altair.ProcessDeposits(ctx, s, b.Block().Body().Deposits()) - } - RunBlockOperationTest(t, folderPath, body, processDepositsFunc) - }) - } +func RunDepositTest(t *testing.T, config string) { + common.RunDepositTest(t, config, version.String(version.Capella), blockWithDeposit, altair.ProcessDeposits, sszToState) } diff --git a/testing/spectest/shared/capella/operations/execution_payload.go b/testing/spectest/shared/capella/operations/execution_payload.go index 453c265110fc..470e70531bc3 100644 --- a/testing/spectest/shared/capella/operations/execution_payload.go +++ b/testing/spectest/shared/capella/operations/execution_payload.go @@ -1,99 +1,12 @@ package operations import ( - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - blocks2 "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunExecutionPayloadTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/execution_payload/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/execution_payload/pyspec_tests") - } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - - blockBodyFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "body.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockBodyFile) - require.NoError(t, err, "Failed to decompress") - block := ðpb.BeaconBlockBodyCapella{} - require.NoError(t, block.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateCapella{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoCapella(preBeaconStateBase) - require.NoError(t, err) - - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - payload, err := blocks2.WrappedExecutionPayloadCapella(block.ExecutionPayload) - require.NoError(t, err) - - file, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "execution.yaml") - require.NoError(t, err) - config := &ExecutionConfig{} - require.NoError(t, utils.UnmarshalYaml(file, config), "Failed to Unmarshal") - - if postSSZExists { - require.NoError(t, blocks.ValidatePayloadWhenMergeCompletes(preBeaconState, payload)) - require.NoError(t, blocks.ValidatePayload(preBeaconState, payload)) - require.NoError(t, preBeaconState.SetLatestExecutionPayloadHeader(payload)) - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateCapella{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateCapella(preBeaconState.ToProto()) - require.NoError(t, err) - t.Log(pbState) - t.Log(postBeaconState) - if !proto.Equal(pbState, postBeaconState) { - t.Fatal("Post state does not match expected") - } - } else if config.Valid { - err1 := blocks.ValidatePayloadWhenMergeCompletes(preBeaconState, payload) - err2 := blocks.ValidatePayload(preBeaconState, payload) - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err1 == nil && err2 == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } -} - -type ExecutionConfig struct { - Valid bool `json:"execution_valid"` + common.RunExecutionPayloadTest(t, config, version.String(version.Capella), sszToBlockBody, sszToState) } diff --git a/testing/spectest/shared/capella/operations/helpers.go b/testing/spectest/shared/capella/operations/helpers.go index 918fd6c86b57..0f11f910c1ca 100644 --- a/testing/spectest/shared/capella/operations/helpers.go +++ b/testing/spectest/shared/capella/operations/helpers.go @@ -1,88 +1,33 @@ package operations import ( - "context" - "os" - "path" - "strings" - "testing" - - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" ) -type blockOperation func(context.Context, state.BeaconState, interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) - -// RunBlockOperationTest takes in the prestate and the beacon block body, processes it through the -// passed in block operation function and checks the post state with the expected post state. -func RunBlockOperationTest( - t *testing.T, - folderPath string, - body *ethpb.BeaconBlockBodyCapella, - operationFn blockOperation, -) { - preBeaconStateFile, err := util.BazelFileBytes(path.Join(folderPath, "pre.ssz_snappy")) - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preStateBase := ðpb.BeaconStateCapella{} - if err := preStateBase.UnmarshalSSZ(preBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) +func sszToState(b []byte) (state.BeaconState, error) { + base := ðpb.BeaconStateCapella{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } - preState, err := state_native.InitializeFromProtoCapella(preStateBase) - require.NoError(t, err) + return state_native.InitializeFromProtoCapella(base) +} - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(folderPath, "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else if err != nil { - t.Fatal(err) +func sszToBlock(b []byte) (interfaces.SignedBeaconBlock, error) { + base := ðpb.BeaconBlockCapella{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockCapella{Block: base}) +} - helpers.ClearCache() - b := util.NewBeaconBlockCapella() - b.Block.Body = body - wsb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - beaconState, err := operationFn(context.Background(), preState, wsb) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateCapella{} - if err := postBeaconState.UnmarshalSSZ(postBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) - } - pbState, err := state_native.ProtobufBeaconStateCapella(beaconState.ToProtoUnsafe()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return +func sszToBlockBody(b []byte) (interfaces.ReadOnlyBeaconBlockBody, error) { + base := ðpb.BeaconBlockBodyCapella{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewBeaconBlockBody(base) } diff --git a/testing/spectest/shared/capella/operations/proposer_slashing.go b/testing/spectest/shared/capella/operations/proposer_slashing.go index 908a7eaa8ead..793065455b22 100644 --- a/testing/spectest/shared/capella/operations/proposer_slashing.go +++ b/testing/spectest/shared/capella/operations/proposer_slashing.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunProposerSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/proposer_slashing/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/proposer_slashing/pyspec_tests") +func blockWithProposerSlashing(ssz []byte) (interfaces.SignedBeaconBlock, error) { + ps := ðpb.ProposerSlashing{} + if err := ps.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - proposerSlashingFile, err := util.BazelFileBytes(folderPath, "proposer_slashing.ssz_snappy") - require.NoError(t, err) - proposerSlashingSSZ, err := snappy.Decode(nil /* dst */, proposerSlashingFile) - require.NoError(t, err, "Failed to decompress") - proposerSlashing := ðpb.ProposerSlashing{} - require.NoError(t, proposerSlashing.UnmarshalSSZ(proposerSlashingSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockCapella() + b.Block.Body = ðpb.BeaconBlockBodyCapella{ProposerSlashings: []*ethpb.ProposerSlashing{ps}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyCapella{ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessProposerSlashings(ctx, s, b.Block().Body().ProposerSlashings(), validators.SlashValidator) - }) - }) - } +func RunProposerSlashingTest(t *testing.T, config string) { + common.RunProposerSlashingTest(t, config, version.String(version.Capella), blockWithProposerSlashing, sszToState) } diff --git a/testing/spectest/shared/capella/operations/sync_committee.go b/testing/spectest/shared/capella/operations/sync_committee.go index 27c1ea66a029..e95c86723cba 100644 --- a/testing/spectest/shared/capella/operations/sync_committee.go +++ b/testing/spectest/shared/capella/operations/sync_committee.go @@ -1,44 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunSyncCommitteeTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/sync_aggregate/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/sync_aggregate/pyspec_tests") +func blockWithSyncAggregate(ssz []byte) (interfaces.SignedBeaconBlock, error) { + sa := ðpb.SyncAggregate{} + if err := sa.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - syncCommitteeFile, err := util.BazelFileBytes(folderPath, "sync_aggregate.ssz_snappy") - require.NoError(t, err) - syncCommitteeSSZ, err := snappy.Decode(nil /* dst */, syncCommitteeFile) - require.NoError(t, err, "Failed to decompress") - sc := ðpb.SyncAggregate{} - require.NoError(t, sc.UnmarshalSSZ(syncCommitteeSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockCapella() + b.Block.Body = ðpb.BeaconBlockBodyCapella{SyncAggregate: sa} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyCapella{SyncAggregate: sc} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, _, err := altair.ProcessSyncAggregate(context.Background(), s, body.SyncAggregate) - if err != nil { - return nil, err - } - return st, nil - }) - }) - } +func RunSyncCommitteeTest(t *testing.T, config string) { + common.RunSyncCommitteeTest(t, config, version.String(version.Capella), blockWithSyncAggregate, sszToState) } diff --git a/testing/spectest/shared/capella/operations/voluntary_exit.go b/testing/spectest/shared/capella/operations/voluntary_exit.go index c133725c8510..6be69ab56749 100644 --- a/testing/spectest/shared/capella/operations/voluntary_exit.go +++ b/testing/spectest/shared/capella/operations/voluntary_exit.go @@ -1,40 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunVoluntaryExitTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/voluntary_exit/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/voluntary_exit/pyspec_tests") +func blockWithVoluntaryExit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := ðpb.SignedVoluntaryExit{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - exitFile, err := util.BazelFileBytes(folderPath, "voluntary_exit.ssz_snappy") - require.NoError(t, err) - exitSSZ, err := snappy.Decode(nil /* dst */, exitFile) - require.NoError(t, err, "Failed to decompress") - voluntaryExit := ðpb.SignedVoluntaryExit{} - require.NoError(t, voluntaryExit.UnmarshalSSZ(exitSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockCapella() + b.Block.Body = ðpb.BeaconBlockBodyCapella{VoluntaryExits: []*ethpb.SignedVoluntaryExit{e}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyCapella{VoluntaryExits: []*ethpb.SignedVoluntaryExit{voluntaryExit}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessVoluntaryExits(ctx, s, b.Block().Body().VoluntaryExits()) - }) - }) - } +func RunVoluntaryExitTest(t *testing.T, config string) { + common.RunVoluntaryExitTest(t, config, version.String(version.Capella), blockWithVoluntaryExit, sszToState) } diff --git a/testing/spectest/shared/capella/operations/withdrawals.go b/testing/spectest/shared/capella/operations/withdrawals.go index edfb56a8ea61..886739f6e3df 100644 --- a/testing/spectest/shared/capella/operations/withdrawals.go +++ b/testing/spectest/shared/capella/operations/withdrawals.go @@ -1,52 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunWithdrawalsTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "capella", "operations/withdrawals/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "capella", "operations/withdrawals/pyspec_tests") +func blockWithWithdrawals(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := &enginev1.ExecutionPayloadCapella{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - payloadFile, err := util.BazelFileBytes(folderPath, "execution_payload.ssz_snappy") - require.NoError(t, err) - payloadSSZ, err := snappy.Decode(nil /* dst */, payloadFile) - require.NoError(t, err, "Failed to decompress") - payload := &enginev1.ExecutionPayloadCapella{} - require.NoError(t, payload.UnmarshalSSZ(payloadSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockCapella() + b.Block.Body = ðpb.BeaconBlockBodyCapella{ExecutionPayload: e} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyCapella{ExecutionPayload: payload} - RunBlockOperationTest(t, folderPath, body, func(_ context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - payload, err := b.Block().Body().Execution() - if err != nil { - return nil, err - } - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, err - } - p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: withdrawals}) - require.NoError(t, err) - return blocks.ProcessWithdrawals(s, p) - }) - }) - } +func RunWithdrawalsTest(t *testing.T, config string) { + common.RunWithdrawalsTest(t, config, version.String(version.Capella), blockWithWithdrawals, sszToState) } diff --git a/testing/spectest/shared/common/forkchoice/runner.go b/testing/spectest/shared/common/forkchoice/runner.go index c999888c80db..2dbbda1c89e2 100644 --- a/testing/spectest/shared/common/forkchoice/runner.go +++ b/testing/spectest/shared/common/forkchoice/runner.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path" + "slices" "strings" "testing" @@ -16,6 +17,7 @@ import ( state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/beacon-chain/verification" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" @@ -25,6 +27,13 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/util" ) +// These are proposer boost spec tests that assume the clock starts 3 seconds into the slot. +// Example: Tick is 51, which corresponds to 3 seconds into slot 4. +var proposerBoostTests3s = []string{ + "proposer_boost_is_first_block", + "proposer_boost", +} + func init() { transition.SkipSlotCache.Disable() } @@ -89,6 +98,9 @@ func runTest(t *testing.T, config string, fork int, basePath string) { // nolint case version.Electra: beaconState = unmarshalElectraState(t, preBeaconStateSSZ) beaconBlock = unmarshalElectraBlock(t, blockSSZ) + case version.Fulu: + beaconState = unmarshalFuluState(t, preBeaconStateSSZ) + beaconBlock = unmarshalFuluBlock(t, blockSSZ) default: t.Fatalf("unknown fork version: %v", fork) } @@ -97,7 +109,18 @@ func runTest(t *testing.T, config string, fork int, basePath string) { // nolint for _, step := range steps { if step.Tick != nil { - builder.Tick(t, int64(*step.Tick)) + tick := int64(*step.Tick) + // If the test is for proposer boost starting 3 seconds into the slot and the tick aligns with this, + // we provide an additional second buffer. Instead of starting 3 seconds into the slot, we start 2 seconds in to avoid missing the proposer boost. + // A 1-second buffer has proven insufficient during parallel spec test runs, as the likelihood of missing the proposer boost increases significantly, + // often extending to 4 seconds. Starting 2 seconds into the slot ensures close to a 100% pass rate. + if slices.Contains(proposerBoostTests3s, folder.Name()) { + deadline := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot + if uint64(tick)%params.BeaconConfig().SecondsPerSlot == deadline-1 { + tick-- + } + } + builder.Tick(t, tick) } var beaconBlock interfaces.ReadOnlySignedBeaconBlock if step.Block != nil { @@ -118,6 +141,8 @@ func runTest(t *testing.T, config string, fork int, basePath string) { // nolint beaconBlock = unmarshalSignedDenebBlock(t, blockSSZ) case version.Electra: beaconBlock = unmarshalSignedElectraBlock(t, blockSSZ) + case version.Fulu: + beaconBlock = unmarshalSignedFuluBlock(t, blockSSZ) default: t.Fatalf("unknown fork version: %v", fork) } @@ -172,6 +197,129 @@ func runTest(t *testing.T, config string, fork int, basePath string) { // nolint } } +func runBlobStep(t *testing.T, + step Step, + beaconBlock interfaces.ReadOnlySignedBeaconBlock, + fork int, + folder os.DirEntry, + testsFolderPath string, + builder *Builder, +) { + blobs := step.Blobs + proofs := step.Proofs + if blobs != nil && *blobs != "null" { + require.NotNil(t, beaconBlock) + require.Equal(t, true, fork >= version.Deneb) + + block := beaconBlock.Block() + root, err := block.HashTreeRoot() + require.NoError(t, err) + kzgs, err := block.Body().BlobKzgCommitments() + require.NoError(t, err) + + blobsFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*blobs, ".ssz_snappy")) + require.NoError(t, err) + blobsSSZ, err := snappy.Decode(nil /* dst */, blobsFile) + require.NoError(t, err) + sh, err := beaconBlock.Header() + require.NoError(t, err) + requireVerifyExpected := errAssertionForStep(step, verification.ErrBlobInvalid) + for index := 0; index*fieldparams.BlobLength < len(blobsSSZ); index++ { + var proof []byte + if index < len(proofs) { + proofPTR := proofs[index] + require.NotNil(t, proofPTR) + proof, err = hexutil.Decode(*proofPTR) + require.NoError(t, err) + } + + blob := [fieldparams.BlobLength]byte{} + copy(blob[:], blobsSSZ[index*fieldparams.BlobLength:]) + if len(proof) == 0 { + proof = make([]byte, 48) + } + + inclusionProof, err := blocks.MerkleProofKZGCommitment(block.Body(), index) + require.NoError(t, err) + pb := ðpb.BlobSidecar{ + Index: uint64(index), + Blob: blob[:], + KzgCommitment: kzgs[index], + KzgProof: proof, + SignedBlockHeader: sh, + CommitmentInclusionProof: inclusionProof, + } + ro, err := blocks.NewROBlobWithRoot(pb, root) + require.NoError(t, err) + ini, err := builder.vwait.WaitForInitializer(context.Background()) + require.NoError(t, err) + bv := ini.NewBlobVerifier(ro, verification.SpectestBlobSidecarRequirements) + ctx := context.Background() + if err := bv.BlobIndexInBounds(); err != nil { + t.Logf("BlobIndexInBounds error: %s", err.Error()) + } + if err := bv.NotFromFutureSlot(); err != nil { + t.Logf("NotFromFutureSlot error: %s", err.Error()) + } + if err := bv.SlotAboveFinalized(); err != nil { + t.Logf("SlotAboveFinalized error: %s", err.Error()) + } + if err := bv.SidecarInclusionProven(); err != nil { + t.Logf("SidecarInclusionProven error: %s", err.Error()) + } + if err := bv.SidecarKzgProofVerified(); err != nil { + t.Logf("SidecarKzgProofVerified error: %s", err.Error()) + } + if err := bv.ValidProposerSignature(ctx); err != nil { + t.Logf("ValidProposerSignature error: %s", err.Error()) + } + if err := bv.SidecarParentSlotLower(); err != nil { + t.Logf("SidecarParentSlotLower error: %s", err.Error()) + } + if err := bv.SidecarDescendsFromFinalized(); err != nil { + t.Logf("SidecarDescendsFromFinalized error: %s", err.Error()) + } + if err := bv.SidecarProposerExpected(ctx); err != nil { + t.Logf("SidecarProposerExpected error: %s", err.Error()) + } + + vsc, err := bv.VerifiedROBlob() + requireVerifyExpected(t, err) + + if err == nil { + require.NoError(t, builder.service.ReceiveBlob(context.Background(), vsc)) + } + } + } +} + +func errAssertionForStep(step Step, expect error) func(t *testing.T, err error) { + if !*step.Valid { + return func(t *testing.T, err error) { + require.ErrorIs(t, err, expect) + } + } + return func(t *testing.T, err error) { + if err != nil { + require.ErrorIs(t, err, verification.ErrBlobInvalid) + var me verification.VerificationMultiError + ok := errors.As(err, &me) + require.Equal(t, true, ok) + fails := me.Failures() + // we haven't performed any verification, so all the results should be this type + fmsg := make([]string, 0, len(fails)) + for k, v := range fails { + fmsg = append(fmsg, fmt.Sprintf("%s - %s", v.Error(), k.String())) + } + t.Fatal(strings.Join(fmsg, ";")) + } + } +} + +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + func unmarshalPhase0State(t *testing.T, raw []byte) state.BeaconState { base := ðpb.BeaconState{} require.NoError(t, base.UnmarshalSSZ(raw)) @@ -196,6 +344,10 @@ func unmarshalSignedPhase0Block(t *testing.T, raw []byte) interfaces.ReadOnlySig return blk } +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- + func unmarshalAltairState(t *testing.T, raw []byte) state.BeaconState { base := ðpb.BeaconStateAltair{} require.NoError(t, base.UnmarshalSSZ(raw)) @@ -220,6 +372,10 @@ func unmarshalSignedAltairBlock(t *testing.T, raw []byte) interfaces.ReadOnlySig return blk } +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + func unmarshalBellatrixState(t *testing.T, raw []byte) state.BeaconState { base := ðpb.BeaconStateBellatrix{} require.NoError(t, base.UnmarshalSSZ(raw)) @@ -244,6 +400,10 @@ func unmarshalSignedBellatrixBlock(t *testing.T, raw []byte) interfaces.ReadOnly return blk } +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- + func unmarshalCapellaState(t *testing.T, raw []byte) state.BeaconState { base := ðpb.BeaconStateCapella{} require.NoError(t, base.UnmarshalSSZ(raw)) @@ -268,6 +428,10 @@ func unmarshalSignedCapellaBlock(t *testing.T, raw []byte) interfaces.ReadOnlySi return blk } +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + func unmarshalDenebState(t *testing.T, raw []byte) state.BeaconState { base := ðpb.BeaconStateDeneb{} require.NoError(t, base.UnmarshalSSZ(raw)) @@ -292,6 +456,10 @@ func unmarshalSignedDenebBlock(t *testing.T, raw []byte) interfaces.SignedBeacon return blk } +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + func unmarshalElectraState(t *testing.T, raw []byte) state.BeaconState { base := ðpb.BeaconStateElectra{} require.NoError(t, base.UnmarshalSSZ(raw)) @@ -316,121 +484,30 @@ func unmarshalSignedElectraBlock(t *testing.T, raw []byte) interfaces.SignedBeac return blk } -func runBlobStep(t *testing.T, - step Step, - beaconBlock interfaces.ReadOnlySignedBeaconBlock, - fork int, - folder os.DirEntry, - testsFolderPath string, - builder *Builder, -) { - blobs := step.Blobs - proofs := step.Proofs - if blobs != nil && *blobs != "null" { - require.NotNil(t, beaconBlock) - require.Equal(t, true, fork >= version.Deneb) - - block := beaconBlock.Block() - root, err := block.HashTreeRoot() - require.NoError(t, err) - kzgs, err := block.Body().BlobKzgCommitments() - require.NoError(t, err) - - blobsFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*blobs, ".ssz_snappy")) - require.NoError(t, err) - blobsSSZ, err := snappy.Decode(nil /* dst */, blobsFile) - require.NoError(t, err) - sh, err := beaconBlock.Header() - require.NoError(t, err) - requireVerifyExpected := errAssertionForStep(step, verification.ErrBlobInvalid) - for index := 0; index*fieldparams.BlobLength < len(blobsSSZ); index++ { - var proof []byte - if index < len(proofs) { - proofPTR := proofs[index] - require.NotNil(t, proofPTR) - proof, err = hexutil.Decode(*proofPTR) - require.NoError(t, err) - } - - blob := [fieldparams.BlobLength]byte{} - copy(blob[:], blobsSSZ[index*fieldparams.BlobLength:]) - if len(proof) == 0 { - proof = make([]byte, 48) - } - - inclusionProof, err := blocks.MerkleProofKZGCommitment(block.Body(), index) - require.NoError(t, err) - pb := ðpb.BlobSidecar{ - Index: uint64(index), - Blob: blob[:], - KzgCommitment: kzgs[index], - KzgProof: proof, - SignedBlockHeader: sh, - CommitmentInclusionProof: inclusionProof, - } - ro, err := blocks.NewROBlobWithRoot(pb, root) - require.NoError(t, err) - ini, err := builder.vwait.WaitForInitializer(context.Background()) - require.NoError(t, err) - bv := ini.NewBlobVerifier(ro, verification.SpectestSidecarRequirements) - ctx := context.Background() - if err := bv.BlobIndexInBounds(); err != nil { - t.Logf("BlobIndexInBounds error: %s", err.Error()) - } - if err := bv.NotFromFutureSlot(); err != nil { - t.Logf("NotFromFutureSlot error: %s", err.Error()) - } - if err := bv.SlotAboveFinalized(); err != nil { - t.Logf("SlotAboveFinalized error: %s", err.Error()) - } - if err := bv.SidecarInclusionProven(); err != nil { - t.Logf("SidecarInclusionProven error: %s", err.Error()) - } - if err := bv.SidecarKzgProofVerified(); err != nil { - t.Logf("SidecarKzgProofVerified error: %s", err.Error()) - } - if err := bv.ValidProposerSignature(ctx); err != nil { - t.Logf("ValidProposerSignature error: %s", err.Error()) - } - if err := bv.SidecarParentSlotLower(); err != nil { - t.Logf("SidecarParentSlotLower error: %s", err.Error()) - } - if err := bv.SidecarDescendsFromFinalized(); err != nil { - t.Logf("SidecarDescendsFromFinalized error: %s", err.Error()) - } - if err := bv.SidecarProposerExpected(ctx); err != nil { - t.Logf("SidecarProposerExpected error: %s", err.Error()) - } +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- - vsc, err := bv.VerifiedROBlob() - requireVerifyExpected(t, err) +func unmarshalFuluState(t *testing.T, raw []byte) state.BeaconState { + base := ðpb.BeaconStateElectra{} + require.NoError(t, base.UnmarshalSSZ(raw)) + st, err := state_native.InitializeFromProtoFulu(base) + require.NoError(t, err) + return st +} - if err == nil { - require.NoError(t, builder.service.ReceiveBlob(context.Background(), vsc)) - } - } - } +func unmarshalFuluBlock(t *testing.T, raw []byte) interfaces.SignedBeaconBlock { + base := ðpb.BeaconBlockElectra{} + require.NoError(t, base.UnmarshalSSZ(raw)) + blk, err := blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockFulu{Block: base, Signature: make([]byte, fieldparams.BLSSignatureLength)}) + require.NoError(t, err) + return blk } -func errAssertionForStep(step Step, expect error) func(t *testing.T, err error) { - if !*step.Valid { - return func(t *testing.T, err error) { - require.ErrorIs(t, err, expect) - } - } - return func(t *testing.T, err error) { - if err != nil { - require.ErrorIs(t, err, verification.ErrBlobInvalid) - var me verification.VerificationMultiError - ok := errors.As(err, &me) - require.Equal(t, true, ok) - fails := me.Failures() - // we haven't performed any verification, so all the results should be this type - fmsg := make([]string, 0, len(fails)) - for k, v := range fails { - fmsg = append(fmsg, fmt.Sprintf("%s - %s", v.Error(), k.String())) - } - t.Fatal(strings.Join(fmsg, ";")) - } - } +func unmarshalSignedFuluBlock(t *testing.T, raw []byte) interfaces.SignedBeaconBlock { + base := ðpb.SignedBeaconBlockFulu{} + require.NoError(t, base.UnmarshalSSZ(raw)) + blk, err := blocks.NewSignedBeaconBlock(base) + require.NoError(t, err) + return blk } diff --git a/testing/spectest/shared/common/forkchoice/service.go b/testing/spectest/shared/common/forkchoice/service.go index 6395907b9da2..648f6bd42523 100644 --- a/testing/spectest/shared/common/forkchoice/service.go +++ b/testing/spectest/shared/common/forkchoice/service.go @@ -103,7 +103,7 @@ func (m *engineMock) ForkchoiceUpdated(context.Context, *pb.ForkchoiceState, pay return nil, m.latestValidHash, m.payloadStatus } -func (m *engineMock) NewPayload(context.Context, interfaces.ExecutionData, []common.Hash, *common.Hash) ([]byte, error) { +func (m *engineMock) NewPayload(context.Context, interfaces.ExecutionData, []common.Hash, *common.Hash, *pb.ExecutionRequests) ([]byte, error) { return m.latestValidHash, m.payloadStatus } diff --git a/testing/spectest/shared/common/merkle_proof/BUILD.bazel b/testing/spectest/shared/common/merkle_proof/BUILD.bazel index 59e626d299d3..76d0b89398a5 100644 --- a/testing/spectest/shared/common/merkle_proof/BUILD.bazel +++ b/testing/spectest/shared/common/merkle_proof/BUILD.bazel @@ -7,7 +7,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/merkle_proof", visibility = ["//visibility:public"], deps = [ - "//config/fieldparams:go_default_library", + "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//container/trie:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/common/merkle_proof/single_merkle_proof.go b/testing/spectest/shared/common/merkle_proof/single_merkle_proof.go index b7792aab9d8d..09d26c40a26a 100644 --- a/testing/spectest/shared/common/merkle_proof/single_merkle_proof.go +++ b/testing/spectest/shared/common/merkle_proof/single_merkle_proof.go @@ -9,7 +9,7 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/golang/snappy" fssz "github.com/prysmaticlabs/fastssz" - field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" consensus_blocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/container/trie" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -80,7 +80,7 @@ func runSingleMerkleProofTests(t *testing.T, config, forkOrPhase string, unmarsh if err != nil { return } - if index < consensus_blocks.KZGOffset || index > consensus_blocks.KZGOffset+field_params.MaxBlobsPerBlock { + if index < consensus_blocks.KZGOffset || index > uint64(consensus_blocks.KZGOffset+params.BeaconConfig().MaxBlobsPerBlock(0)) { return } localProof, err := consensus_blocks.MerkleProofKZGCommitment(body, int(index-consensus_blocks.KZGOffset)) diff --git a/testing/spectest/shared/common/operations/BUILD.bazel b/testing/spectest/shared/common/operations/BUILD.bazel new file mode 100644 index 000000000000..07b46dee0a20 --- /dev/null +++ b/testing/spectest/shared/common/operations/BUILD.bazel @@ -0,0 +1,46 @@ +load("@prysm//tools/go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + testonly = True, + srcs = [ + "attestation.go", + "attester_slashing.go", + "block_header.go", + "bls_to_execution_changes.go", + "consolidations.go", + "deposit.go", + "deposit_request.go", + "execution_payload.go", + "proposer_slashing.go", + "slashing.go", + "sync_aggregate.go", + "test_runner.go", + "voluntary_exit.go", + "withdrawal_request.go", + "withdrawals.go", + ], + importpath = "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations", + visibility = ["//visibility:public"], + deps = [ + "//beacon-chain/core/altair:go_default_library", + "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/core/electra:go_default_library", + "//beacon-chain/core/helpers:go_default_library", + "//beacon-chain/core/validators:go_default_library", + "//beacon-chain/state:go_default_library", + "//consensus-types/blocks:go_default_library", + "//consensus-types/interfaces:go_default_library", + "//proto/engine/v1:go_default_library", + "//proto/prysm/v1alpha1:go_default_library", + "//testing/require:go_default_library", + "//testing/spectest/utils:go_default_library", + "//testing/util:go_default_library", + "@com_github_golang_snappy//:go_default_library", + "@com_github_google_go_cmp//cmp:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@io_bazel_rules_go//go/tools/bazel:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + "@org_golang_google_protobuf//testing/protocmp:go_default_library", + ], +) diff --git a/testing/spectest/shared/common/operations/attestation.go b/testing/spectest/shared/common/operations/attestation.go new file mode 100644 index 000000000000..f2dac069337a --- /dev/null +++ b/testing/spectest/shared/common/operations/attestation.go @@ -0,0 +1,57 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/pkg/errors" + b "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +// RunAttestationTest executes "operations/attestation" tests. +func RunAttestationTest(t *testing.T, config string, fork string, blockWithAttestation blockWithSSZObject, processBlock ProcessBlock, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/attestation/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/attestation/pyspec_tests") + } + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + attestationFile, err := util.BazelFileBytes(folderPath, "attestation.ssz_snappy") + require.NoError(t, err) + attestationSSZ, err := snappy.Decode(nil /* dst */, attestationFile) + require.NoError(t, err, "Failed to decompress") + blk, err := blockWithAttestation(attestationSSZ) + require.NoError(t, err) + + processAtt := func(ctx context.Context, st state.BeaconState, blk interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + st, err = processBlock(ctx, st, blk.Block()) + if err != nil { + return nil, err + } + aSet, err := b.AttestationSignatureBatch(ctx, st, blk.Block().Body().Attestations()) + if err != nil { + return nil, err + } + verified, err := aSet.Verify() + if err != nil { + return nil, err + } + if !verified { + return nil, errors.New("could not batch verify attestation signature") + } + return st, nil + } + + RunBlockOperationTest(t, folderPath, blk, sszToState, processAtt) + }) + } +} diff --git a/testing/spectest/shared/common/operations/attester_slashing.go b/testing/spectest/shared/common/operations/attester_slashing.go new file mode 100644 index 000000000000..85f2aabc4e35 --- /dev/null +++ b/testing/spectest/shared/common/operations/attester_slashing.go @@ -0,0 +1,17 @@ +package operations + +import ( + "context" + "testing" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + v "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" +) + +func RunAttesterSlashingTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) { + runSlashingTest(t, config, fork, "attester_slashing", block, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + return blocks.ProcessAttesterSlashings(ctx, s, b.Block().Body().AttesterSlashings(), v.SlashValidator) + }) +} diff --git a/testing/spectest/shared/common/operations/block_header.go b/testing/spectest/shared/common/operations/block_header.go new file mode 100644 index 000000000000..c1f01e597ef1 --- /dev/null +++ b/testing/spectest/shared/common/operations/block_header.go @@ -0,0 +1,74 @@ +package operations + +import ( + "context" + "path" + "strings" + "testing" + + "github.com/bazelbuild/rules_go/go/tools/bazel" + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +type SSZToBlock func([]byte) (interfaces.SignedBeaconBlock, error) + +func RunBlockHeaderTest(t *testing.T, config string, fork string, sszToBlock SSZToBlock, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/block_header/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/block_header/pyspec_tests") + } + + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + helpers.ClearCache() + + blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "block.ssz_snappy") + require.NoError(t, err) + blockSSZ, err := snappy.Decode(nil /* dst */, blockFile) + require.NoError(t, err, "Failed to decompress") + block, err := sszToBlock(blockSSZ) + require.NoError(t, err, "Failed to unmarshal") + + preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") + require.NoError(t, err) + preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) + require.NoError(t, err, "Failed to decompress") + preBeaconState, err := sszToState(preBeaconStateSSZ) + require.NoError(t, err) + + // If the post.ssz is not present, it means the test should fail on our end. + postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) + postSSZExists := true + if err != nil && strings.Contains(err.Error(), "could not locate file") { + postSSZExists = false + } else { + require.NoError(t, err) + } + + // Spectest blocks are not signed, so we'll call NoVerify to skip sig verification. + bodyRoot, err := block.Block().Body().HashTreeRoot() + require.NoError(t, err) + pr := block.Block().ParentRoot() + _, err = blocks.ProcessBlockHeaderNoVerify(context.Background(), preBeaconState, block.Block().Slot(), block.Block().ProposerIndex(), pr[:], bodyRoot[:]) + if postSSZExists { + require.NoError(t, err) + comparePostState(t, postSSZFilepath, sszToState, preBeaconState) + } else { + // Note: This doesn't test anything worthwhile. It essentially tests + // that *any* error has occurred, not any specific error. + if err == nil { + t.Fatal("Did not fail when expected") + } + t.Logf("Expected failure; failure reason = %v", err) + return + } + }) + } +} diff --git a/testing/spectest/shared/common/operations/bls_to_execution_changes.go b/testing/spectest/shared/common/operations/bls_to_execution_changes.go new file mode 100644 index 000000000000..2aa38b102eb4 --- /dev/null +++ b/testing/spectest/shared/common/operations/bls_to_execution_changes.go @@ -0,0 +1,57 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func RunBLSToExecutionChangeTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/bls_to_execution_change/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/bls_to_execution_change/pyspec_tests") + } + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + changeFile, err := util.BazelFileBytes(folderPath, "address_change.ssz_snappy") + require.NoError(t, err) + changeSSZ, err := snappy.Decode(nil /* dst */, changeFile) + require.NoError(t, err, "Failed to decompress") + blk, err := block(changeSSZ) + require.NoError(t, err) + RunBlockOperationTest(t, folderPath, blk, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + st, err := blocks.ProcessBLSToExecutionChanges(s, b.Block()) + if err != nil { + return nil, err + } + changes, err := b.Block().Body().BLSToExecutionChanges() + if err != nil { + return nil, err + } + cSet, err := blocks.BLSChangesSignatureBatch(st, changes) + if err != nil { + return nil, err + } + ok, err := cSet.Verify() + if err != nil { + return nil, err + } + if !ok { + return nil, errors.New("signature did not verify") + } + return st, nil + }) + }) + } +} diff --git a/testing/spectest/shared/common/operations/consolidations.go b/testing/spectest/shared/common/operations/consolidations.go new file mode 100644 index 000000000000..81bffa19fdf0 --- /dev/null +++ b/testing/spectest/shared/common/operations/consolidations.go @@ -0,0 +1,39 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func RunConsolidationTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/consolidation_request/pyspec_tests") + require.NotEqual(t, 0, len(testFolders), "missing tests for consolidation operation in folder") + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + consolidationFile, err := util.BazelFileBytes(folderPath, "consolidation_request.ssz_snappy") + require.NoError(t, err) + consolidationSSZ, err := snappy.Decode(nil /* dst */, consolidationFile) + require.NoError(t, err, "Failed to decompress") + blk, err := block(consolidationSSZ) + require.NoError(t, err) + RunBlockOperationTest(t, folderPath, blk, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + er, err := b.Block().Body().ExecutionRequests() + if err != nil { + return nil, err + } + return s, electra.ProcessConsolidationRequests(ctx, s, er.Consolidations) + }) + }) + } +} diff --git a/testing/spectest/shared/common/operations/deposit.go b/testing/spectest/shared/common/operations/deposit.go new file mode 100644 index 000000000000..5cecde94a700 --- /dev/null +++ b/testing/spectest/shared/common/operations/deposit.go @@ -0,0 +1,36 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +type ProcessDeposits func(ctx context.Context, beaconState state.BeaconState, deposits []*ethpb.Deposit) (state.BeaconState, error) + +func RunDepositTest(t *testing.T, config string, fork string, blockWithDeposit blockWithSSZObject, process ProcessDeposits, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/deposit/pyspec_tests") + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + depositFile, err := util.BazelFileBytes(folderPath, "deposit.ssz_snappy") + require.NoError(t, err) + depositSSZ, err := snappy.Decode(nil /* dst */, depositFile) + require.NoError(t, err, "Failed to decompress") + blk, err := blockWithDeposit(depositSSZ) + require.NoError(t, err) + RunBlockOperationTest(t, folderPath, blk, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + return process(ctx, s, b.Block().Body().Deposits()) + }) + }) + } +} diff --git a/testing/spectest/shared/common/operations/deposit_request.go b/testing/spectest/shared/common/operations/deposit_request.go new file mode 100644 index 000000000000..8426033fc71a --- /dev/null +++ b/testing/spectest/shared/common/operations/deposit_request.go @@ -0,0 +1,36 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func RunDepositRequestsTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/deposit_request/pyspec_tests") + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + depositRequestFile, err := util.BazelFileBytes(folderPath, "deposit_request.ssz_snappy") + require.NoError(t, err) + depositRequestSSZ, err := snappy.Decode(nil /* dst */, depositRequestFile) + require.NoError(t, err, "Failed to decompress") + blk, err := block(depositRequestSSZ) + require.NoError(t, err) + RunBlockOperationTest(t, folderPath, blk, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + e, err := b.Block().Body().ExecutionRequests() + require.NoError(t, err, "Failed to get execution requests") + return electra.ProcessDepositRequests(ctx, s, e.Deposits) + }) + }) + } +} diff --git a/testing/spectest/shared/common/operations/execution_payload.go b/testing/spectest/shared/common/operations/execution_payload.go new file mode 100644 index 000000000000..652b500aa496 --- /dev/null +++ b/testing/spectest/shared/common/operations/execution_payload.go @@ -0,0 +1,76 @@ +package operations + +import ( + "path" + "strings" + "testing" + + "github.com/bazelbuild/rules_go/go/tools/bazel" + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +type SSZToBlockBody func([]byte) (interfaces.ReadOnlyBeaconBlockBody, error) + +func RunExecutionPayloadTest(t *testing.T, config string, fork string, sszToBlockBody SSZToBlockBody, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/execution_payload/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/execution_payload/pyspec_tests") + } + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + helpers.ClearCache() + + blockBodyFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "body.ssz_snappy") + require.NoError(t, err) + bodySSZ, err := snappy.Decode(nil /* dst */, blockBodyFile) + require.NoError(t, err, "Failed to decompress") + body, err := sszToBlockBody(bodySSZ) + require.NoError(t, err, "Failed to unmarshal") + + preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") + require.NoError(t, err) + preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) + require.NoError(t, err, "Failed to decompress") + preBeaconState, err := sszToState(preBeaconStateSSZ) + require.NoError(t, err) + + postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) + postSSZExists := true + if err != nil && strings.Contains(err.Error(), "could not locate file") { + postSSZExists = false + } else { + require.NoError(t, err) + } + + file, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "execution.yaml") + require.NoError(t, err) + config := &ExecutionConfig{} + require.NoError(t, utils.UnmarshalYaml(file, config), "Failed to Unmarshal") + + err = blocks.ProcessPayload(preBeaconState, body) + if postSSZExists { + require.NoError(t, err) + comparePostState(t, postSSZFilepath, sszToState, preBeaconState) + } else if config.Valid { + // Note: This doesn't test anything worthwhile. It essentially tests + // that *any* error has occurred, not any specific error. + if err == nil { + t.Fatal("Did not fail when expected") + } + t.Logf("Expected failure; failure reason = %v", err) + return + } + }) + } +} + +type ExecutionConfig struct { + Valid bool `json:"execution_valid"` +} diff --git a/testing/spectest/shared/common/operations/proposer_slashing.go b/testing/spectest/shared/common/operations/proposer_slashing.go new file mode 100644 index 000000000000..dda287e6a16e --- /dev/null +++ b/testing/spectest/shared/common/operations/proposer_slashing.go @@ -0,0 +1,17 @@ +package operations + +import ( + "context" + "testing" + + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + v "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" +) + +func RunProposerSlashingTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) { + runSlashingTest(t, config, fork, "proposer_slashing", block, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + return blocks.ProcessProposerSlashings(ctx, s, b.Block().Body().ProposerSlashings(), v.SlashValidator) + }) +} diff --git a/testing/spectest/shared/common/operations/slashing.go b/testing/spectest/shared/common/operations/slashing.go new file mode 100644 index 000000000000..e4a79b26fda1 --- /dev/null +++ b/testing/spectest/shared/common/operations/slashing.go @@ -0,0 +1,31 @@ +package operations + +import ( + "path" + "testing" + + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func runSlashingTest(t *testing.T, config string, fork string, objName string, block blockWithSSZObject, sszToState SSZToState, operationFn BlockOperation) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/"+objName+"/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/"+objName+"/pyspec_tests") + } + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + slashingFile, err := util.BazelFileBytes(folderPath, objName+".ssz_snappy") + require.NoError(t, err) + slashingSSZ, err := snappy.Decode(nil /* dst */, slashingFile) + require.NoError(t, err, "Failed to decompress") + blk, err := block(slashingSSZ) + require.NoError(t, err) + RunBlockOperationTest(t, folderPath, blk, sszToState, operationFn) + }) + } +} diff --git a/testing/spectest/shared/common/operations/sync_aggregate.go b/testing/spectest/shared/common/operations/sync_aggregate.go new file mode 100644 index 000000000000..8194aed4edbf --- /dev/null +++ b/testing/spectest/shared/common/operations/sync_aggregate.go @@ -0,0 +1,45 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func RunSyncCommitteeTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/sync_aggregate/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/sync_aggregate/pyspec_tests") + } + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + f, err := util.BazelFileBytes(folderPath, "sync_aggregate.ssz_snappy") + require.NoError(t, err) + ssz, err := snappy.Decode(nil /* dst */, f) + require.NoError(t, err, "Failed to decompress") + blk, err := block(ssz) + require.NoError(t, err) + RunBlockOperationTest(t, folderPath, blk, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + sa, err := b.Block().Body().SyncAggregate() + if err != nil { + return nil, err + } + st, _, err := altair.ProcessSyncAggregate(context.Background(), s, sa) + if err != nil { + return nil, err + } + return st, nil + }) + }) + } +} diff --git a/testing/spectest/shared/common/operations/test_runner.go b/testing/spectest/shared/common/operations/test_runner.go new file mode 100644 index 000000000000..1fa5087841b7 --- /dev/null +++ b/testing/spectest/shared/common/operations/test_runner.go @@ -0,0 +1,83 @@ +package operations + +import ( + "context" + "os" + "path" + "strings" + "testing" + + "github.com/bazelbuild/rules_go/go/tools/bazel" + "github.com/golang/snappy" + "github.com/google/go-cmp/cmp" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/util" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" +) + +type blockWithSSZObject func([]byte) (interfaces.SignedBeaconBlock, error) +type BlockOperation func(context.Context, state.BeaconState, interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) +type ProcessBlock func(context.Context, state.BeaconState, interfaces.ReadOnlyBeaconBlock) (state.BeaconState, error) +type SSZToState func([]byte) (state.BeaconState, error) + +// RunBlockOperationTest takes in the prestate and the beacon block body, processes it through the +// passed in block operation function and checks the post state with the expected post state. +func RunBlockOperationTest( + t *testing.T, + folderPath string, + wsb interfaces.SignedBeaconBlock, + sszToState SSZToState, + operationFn BlockOperation, +) { + preBeaconStateFile, err := util.BazelFileBytes(path.Join(folderPath, "pre.ssz_snappy")) + require.NoError(t, err) + preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) + require.NoError(t, err, "Failed to decompress") + preState, err := sszToState(preBeaconStateSSZ) + require.NoError(t, err) + + // If the post.ssz is not present, it means the test should fail on our end. + postSSZFilepath, err := bazel.Runfile(path.Join(folderPath, "post.ssz_snappy")) + postSSZExists := true + if err != nil && strings.Contains(err.Error(), "could not locate file") { + postSSZExists = false + } else if err != nil { + t.Fatal(err) + } + + helpers.ClearCache() + _, err = operationFn(context.Background(), preState, wsb) + if postSSZExists { + require.NoError(t, err) + comparePostState(t, postSSZFilepath, sszToState, preState) + } else { + // Note: This doesn't test anything worthwhile. It essentially tests + // that *any* error has occurred, not any specific error. + if err == nil { + t.Fatal("Did not fail when expected") + } + t.Logf("Expected failure; failure reason = %v", err) + return + } +} + +func comparePostState(t *testing.T, postSSZFilepath string, sszToState SSZToState, want state.BeaconState) { + postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 + require.NoError(t, err) + postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) + require.NoError(t, err, "Failed to decompress") + postBeaconState, err := sszToState(postBeaconStateSSZ) + require.NoError(t, err) + postBeaconStatePb, ok := postBeaconState.ToProtoUnsafe().(proto.Message) + require.Equal(t, true, ok, "post beacon state did not return a proto.Message") + pbState, ok := want.ToProtoUnsafe().(proto.Message) + require.Equal(t, true, ok, "beacon state did not return a proto.Message") + if !proto.Equal(pbState, postBeaconStatePb) { + t.Log(cmp.Diff(postBeaconStatePb, pbState, protocmp.Transform())) + t.Fatal("Post state does not match expected") + } +} diff --git a/testing/spectest/shared/common/operations/voluntary_exit.go b/testing/spectest/shared/common/operations/voluntary_exit.go new file mode 100644 index 000000000000..ec2829d5bda4 --- /dev/null +++ b/testing/spectest/shared/common/operations/voluntary_exit.go @@ -0,0 +1,37 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func RunVoluntaryExitTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/voluntary_exit/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/voluntary_exit/pyspec_tests") + } + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + exitFile, err := util.BazelFileBytes(folderPath, "voluntary_exit.ssz_snappy") + require.NoError(t, err) + exitSSZ, err := snappy.Decode(nil /* dst */, exitFile) + require.NoError(t, err, "Failed to decompress") + blk, err := block(exitSSZ) + require.NoError(t, err) + RunBlockOperationTest(t, folderPath, blk, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + return blocks.ProcessVoluntaryExits(ctx, s, b.Block().Body().VoluntaryExits()) + }) + }) + } +} diff --git a/testing/spectest/shared/common/operations/withdrawal_request.go b/testing/spectest/shared/common/operations/withdrawal_request.go new file mode 100644 index 000000000000..f119c7cb6c04 --- /dev/null +++ b/testing/spectest/shared/common/operations/withdrawal_request.go @@ -0,0 +1,40 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func RunWithdrawalRequestTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/withdrawal_request/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/withdrawal_request/pyspec_tests") + } + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + withdrawalRequestFile, err := util.BazelFileBytes(folderPath, "withdrawal_request.ssz_snappy") + require.NoError(t, err) + withdrawalRequestSSZ, err := snappy.Decode(nil /* dst */, withdrawalRequestFile) + require.NoError(t, err, "Failed to decompress") + blk, err := block(withdrawalRequestSSZ) + require.NoError(t, err) + RunBlockOperationTest(t, folderPath, blk, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + bod := b.Block().Body() + e, err := bod.ExecutionRequests() + require.NoError(t, err) + return electra.ProcessWithdrawalRequests(ctx, s, e.Withdrawals) + }) + }) + } +} diff --git a/testing/spectest/shared/common/operations/withdrawals.go b/testing/spectest/shared/common/operations/withdrawals.go new file mode 100644 index 000000000000..2534576658df --- /dev/null +++ b/testing/spectest/shared/common/operations/withdrawals.go @@ -0,0 +1,50 @@ +package operations + +import ( + "context" + "path" + "testing" + + "github.com/golang/snappy" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/testing/util" +) + +func RunWithdrawalsTest(t *testing.T, config string, fork string, sszToBlock SSZToBlock, sszToState SSZToState) { + require.NoError(t, utils.SetConfig(t, config)) + testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/withdrawals/pyspec_tests") + if len(testFolders) == 0 { + t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/withdrawals/pyspec_tests") + } + for _, folder := range testFolders { + t.Run(folder.Name(), func(t *testing.T) { + folderPath := path.Join(testsFolderPath, folder.Name()) + payloadFile, err := util.BazelFileBytes(folderPath, "execution_payload.ssz_snappy") + require.NoError(t, err) + payloadSSZ, err := snappy.Decode(nil /* dst */, payloadFile) + require.NoError(t, err, "Failed to decompress") + blk, err := sszToBlock(payloadSSZ) + require.NoError(t, err) + + RunBlockOperationTest(t, folderPath, blk, sszToState, func(_ context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { + payload, err := b.Block().Body().Execution() + if err != nil { + return nil, err + } + withdrawals, err := payload.Withdrawals() + if err != nil { + return nil, err + } + p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: withdrawals}) + require.NoError(t, err) + return blocks.ProcessWithdrawals(s, p) + }) + }) + } +} diff --git a/testing/spectest/shared/deneb/epoch_processing/BUILD.bazel b/testing/spectest/shared/deneb/epoch_processing/BUILD.bazel index 6a483739c35f..262b87507ccf 100644 --- a/testing/spectest/shared/deneb/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/deneb/epoch_processing/BUILD.bazel @@ -26,7 +26,6 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", - "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/deneb/epoch_processing/slashings.go b/testing/spectest/shared/deneb/epoch_processing/slashings.go index ac4cd3baf656..71b2bf75e494 100644 --- a/testing/spectest/shared/deneb/epoch_processing/slashings.go +++ b/testing/spectest/shared/deneb/epoch_processing/slashings.go @@ -7,7 +7,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" ) @@ -27,7 +26,6 @@ func RunSlashingsTests(t *testing.T, config string) { } func processSlashingsWrapper(t *testing.T, st state.BeaconState) (state.BeaconState, error) { - st, err := epoch.ProcessSlashings(st, params.BeaconConfig().ProportionalSlashingMultiplierBellatrix) - require.NoError(t, err, "Could not process slashings") + require.NoError(t, epoch.ProcessSlashings(st), "Could not process slashings") return st, nil } diff --git a/testing/spectest/shared/deneb/operations/BUILD.bazel b/testing/spectest/shared/deneb/operations/BUILD.bazel index 7cb96e31f486..43971362c5c1 100644 --- a/testing/spectest/shared/deneb/operations/BUILD.bazel +++ b/testing/spectest/shared/deneb/operations/BUILD.bazel @@ -20,22 +20,14 @@ go_library( visibility = ["//testing/spectest:__subpackages__"], deps = [ "//beacon-chain/core/altair:go_default_library", - "//beacon-chain/core/blocks:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/core/validators:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//testing/require:go_default_library", - "//testing/spectest/utils:go_default_library", + "//runtime/version:go_default_library", + "//testing/spectest/shared/common/operations:go_default_library", "//testing/util:go_default_library", - "@com_github_golang_snappy//:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@io_bazel_rules_go//go/tools/bazel:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/testing/spectest/shared/deneb/operations/attestation.go b/testing/spectest/shared/deneb/operations/attestation.go index 85885818b3ad..2ca496c5b071 100644 --- a/testing/spectest/shared/deneb/operations/attestation.go +++ b/testing/spectest/shared/deneb/operations/attestation.go @@ -1,56 +1,27 @@ package operations import ( - "context" - "errors" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - b "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttestationTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/attestation/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attestationFile, err := util.BazelFileBytes(folderPath, "attestation.ssz_snappy") - require.NoError(t, err) - attestationSSZ, err := snappy.Decode(nil /* dst */, attestationFile) - require.NoError(t, err, "Failed to decompress") - att := ðpb.Attestation{} - require.NoError(t, att.UnmarshalSSZ(attestationSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyDeneb{Attestations: []*ethpb.Attestation{att}} - processAtt := func(ctx context.Context, st state.BeaconState, blk interfaces.SignedBeaconBlock) (state.BeaconState, error) { - st, err = altair.ProcessAttestationsNoVerifySignature(ctx, st, blk.Block()) - if err != nil { - return nil, err - } - aSet, err := b.AttestationSignatureBatch(ctx, st, blk.Block().Body().Attestations()) - if err != nil { - return nil, err - } - verified, err := aSet.Verify() - if err != nil { - return nil, err - } - if !verified { - return nil, errors.New("could not batch verify attestation signature") - } - return st, nil - } - - RunBlockOperationTest(t, folderPath, body, processAtt) - }) +func blockWithAttestation(attestationSSZ []byte) (interfaces.SignedBeaconBlock, error) { + att := ðpb.Attestation{} + if err := att.UnmarshalSSZ(attestationSSZ); err != nil { + return nil, err } + b := util.NewBeaconBlockDeneb() + b.Block.Body = ðpb.BeaconBlockBodyDeneb{Attestations: []*ethpb.Attestation{att}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunAttestationTest(t *testing.T, config string) { + common.RunAttestationTest(t, config, version.String(version.Deneb), blockWithAttestation, altair.ProcessAttestationsNoVerifySignature, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/attester_slashing.go b/testing/spectest/shared/deneb/operations/attester_slashing.go index 7871296412f8..02a1fcaf87be 100644 --- a/testing/spectest/shared/deneb/operations/attester_slashing.go +++ b/testing/spectest/shared/deneb/operations/attester_slashing.go @@ -1,38 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttesterSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/attester_slashing/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attSlashingFile, err := util.BazelFileBytes(folderPath, "attester_slashing.ssz_snappy") - require.NoError(t, err) - attSlashingSSZ, err := snappy.Decode(nil /* dst */, attSlashingFile) - require.NoError(t, err, "Failed to decompress") - attSlashing := ðpb.AttesterSlashing{} - require.NoError(t, attSlashing.UnmarshalSSZ(attSlashingSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyDeneb{AttesterSlashings: []*ethpb.AttesterSlashing{attSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.SignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessAttesterSlashings(ctx, s, b.Block().Body().AttesterSlashings(), validators.SlashValidator) - }) - }) +func blockWithAttesterSlashing(asSSZ []byte) (interfaces.SignedBeaconBlock, error) { + as := ðpb.AttesterSlashing{} + if err := as.UnmarshalSSZ(asSSZ); err != nil { + return nil, err } + b := util.NewBeaconBlockDeneb() + b.Block.Body = ðpb.BeaconBlockBodyDeneb{AttesterSlashings: []*ethpb.AttesterSlashing{as}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunAttesterSlashingTest(t *testing.T, config string) { + common.RunAttesterSlashingTest(t, config, version.String(version.Deneb), blockWithAttesterSlashing, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/block_header.go b/testing/spectest/shared/deneb/operations/block_header.go index db03c9a03bc1..7c5f882e516a 100644 --- a/testing/spectest/shared/deneb/operations/block_header.go +++ b/testing/spectest/shared/deneb/operations/block_header.go @@ -1,83 +1,12 @@ package operations import ( - "context" - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunBlockHeaderTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/block_header/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "block.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockFile) - require.NoError(t, err, "Failed to decompress") - block := ðpb.BeaconBlockDeneb{} - require.NoError(t, block.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateDeneb{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoDeneb(preBeaconStateBase) - require.NoError(t, err) - - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - // Spectest blocks are not signed, so we'll call NoVerify to skip sig verification. - bodyRoot, err := block.Body.HashTreeRoot() - require.NoError(t, err) - beaconState, err := blocks.ProcessBlockHeaderNoVerify(context.Background(), preBeaconState, block.Slot, block.ProposerIndex, block.ParentRoot, bodyRoot[:]) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateDeneb{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateDeneb(beaconState.ToProto()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } + common.RunBlockHeaderTest(t, config, version.String(version.Deneb), sszToBlock, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/bls_to_execution_changes.go b/testing/spectest/shared/deneb/operations/bls_to_execution_changes.go index b7f25c1e9710..6c4601f5318b 100644 --- a/testing/spectest/shared/deneb/operations/bls_to_execution_changes.go +++ b/testing/spectest/shared/deneb/operations/bls_to_execution_changes.go @@ -1,62 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunBLSToExecutionChangeTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/bls_to_execution_change/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "deneb", "operations/bls_to_execution_change/pyspec_tests") +func blockWithBlsChange(ssz []byte) (interfaces.SignedBeaconBlock, error) { + c := ðpb.SignedBLSToExecutionChange{} + if err := c.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - changeFile, err := util.BazelFileBytes(folderPath, "address_change.ssz_snappy") - require.NoError(t, err) - changeSSZ, err := snappy.Decode(nil /* dst */, changeFile) - require.NoError(t, err, "Failed to decompress") - change := ðpb.SignedBLSToExecutionChange{} - require.NoError(t, change.UnmarshalSSZ(changeSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockDeneb() + b.Block.Body = ðpb.BeaconBlockBodyDeneb{BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{c}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyDeneb{ - BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{change}, - } - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.SignedBeaconBlock) (state.BeaconState, error) { - st, err := blocks.ProcessBLSToExecutionChanges(s, b.Block()) - if err != nil { - return nil, err - } - changes, err := b.Block().Body().BLSToExecutionChanges() - if err != nil { - return nil, err - } - cSet, err := blocks.BLSChangesSignatureBatch(st, changes) - if err != nil { - return nil, err - } - ok, err := cSet.Verify() - if err != nil { - return nil, err - } - if !ok { - return nil, errors.New("signature did not verify") - } - return st, nil - }) - }) - } +func RunBLSToExecutionChangeTest(t *testing.T, config string) { + common.RunBLSToExecutionChangeTest(t, config, version.String(version.Deneb), blockWithBlsChange, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/deposit.go b/testing/spectest/shared/deneb/operations/deposit.go index 8a463e923a2f..97a06fc16085 100644 --- a/testing/spectest/shared/deneb/operations/deposit.go +++ b/testing/spectest/shared/deneb/operations/deposit.go @@ -1,38 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunDepositTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/deposit/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - depositFile, err := util.BazelFileBytes(folderPath, "deposit.ssz_snappy") - require.NoError(t, err) - depositSSZ, err := snappy.Decode(nil /* dst */, depositFile) - require.NoError(t, err, "Failed to decompress") - deposit := ðpb.Deposit{} - require.NoError(t, deposit.UnmarshalSSZ(depositSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyDeneb{Deposits: []*ethpb.Deposit{deposit}} - processDepositsFunc := func(ctx context.Context, s state.BeaconState, b interfaces.SignedBeaconBlock) (state.BeaconState, error) { - return altair.ProcessDeposits(ctx, s, b.Block().Body().Deposits()) - } - RunBlockOperationTest(t, folderPath, body, processDepositsFunc) - }) +func blockWithDeposit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + d := ðpb.Deposit{} + if err := d.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockDeneb() + b.Block.Body = ðpb.BeaconBlockBodyDeneb{Deposits: []*ethpb.Deposit{d}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunDepositTest(t *testing.T, config string) { + common.RunDepositTest(t, config, version.String(version.Deneb), blockWithDeposit, altair.ProcessDeposits, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/execution_payload.go b/testing/spectest/shared/deneb/operations/execution_payload.go index d1069e4a600f..c5fc1e5c0647 100644 --- a/testing/spectest/shared/deneb/operations/execution_payload.go +++ b/testing/spectest/shared/deneb/operations/execution_payload.go @@ -1,104 +1,12 @@ package operations import ( - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - blocks2 "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunExecutionPayloadTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/execution_payload/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "deneb", "operations/execution_payload/pyspec_tests") - } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - - blockBodyFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "body.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockBodyFile) - require.NoError(t, err, "Failed to decompress") - body := ðpb.BeaconBlockBodyDeneb{} - require.NoError(t, body.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - b, err := blocks2.NewBeaconBlock(ðpb.BeaconBlockDeneb{Body: body}) - require.NoError(t, err) - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateDeneb{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoDeneb(preBeaconStateBase) - require.NoError(t, err) - - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - payload, err := blocks2.WrappedExecutionPayloadDeneb(body.ExecutionPayload) - require.NoError(t, err) - - file, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "execution.yaml") - require.NoError(t, err) - config := &ExecutionConfig{} - require.NoError(t, utils.UnmarshalYaml(file, config), "Failed to Unmarshal") - - if postSSZExists { - require.NoError(t, blocks.ValidatePayloadWhenMergeCompletes(preBeaconState, payload)) - require.NoError(t, blocks.ValidatePayload(preBeaconState, payload)) - require.NoError(t, transition.VerifyBlobCommitmentCount(b)) - require.NoError(t, preBeaconState.SetLatestExecutionPayloadHeader(payload)) - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateDeneb{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateDeneb(preBeaconState.ToProto()) - require.NoError(t, err) - t.Log(pbState) - t.Log(postBeaconState) - if !proto.Equal(pbState, postBeaconState) { - t.Fatal("Post state does not match expected") - } - } else if config.Valid { - err1 := blocks.ValidatePayloadWhenMergeCompletes(preBeaconState, payload) - err2 := blocks.ValidatePayload(preBeaconState, payload) - err3 := transition.VerifyBlobCommitmentCount(b) - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err1 == nil && err2 == nil && err3 == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } -} - -type ExecutionConfig struct { - Valid bool `json:"execution_valid"` + common.RunExecutionPayloadTest(t, config, version.String(version.Deneb), sszToBlockBody, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/helpers.go b/testing/spectest/shared/deneb/operations/helpers.go index 1cfe64c0ea06..73c822bea2b1 100644 --- a/testing/spectest/shared/deneb/operations/helpers.go +++ b/testing/spectest/shared/deneb/operations/helpers.go @@ -1,85 +1,33 @@ package operations import ( - "context" - "os" - "path" - "strings" - "testing" - - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" ) -type blockOperation func(context.Context, state.BeaconState, interfaces.SignedBeaconBlock) (state.BeaconState, error) - -// RunBlockOperationTest takes in the prestate and the beacon block body, processes it through the -// passed in block operation function and checks the post state with the expected post state. -func RunBlockOperationTest( - t *testing.T, - folderPath string, - body *ethpb.BeaconBlockBodyDeneb, - operationFn blockOperation, -) { - preBeaconStateFile, err := util.BazelFileBytes(path.Join(folderPath, "pre.ssz_snappy")) - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preStateBase := ðpb.BeaconStateDeneb{} - if err := preStateBase.UnmarshalSSZ(preBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) +func sszToState(b []byte) (state.BeaconState, error) { + base := ðpb.BeaconStateDeneb{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } - preState, err := state_native.InitializeFromProtoDeneb(preStateBase) - require.NoError(t, err) + return state_native.InitializeFromProtoDeneb(base) +} - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(folderPath, "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else if err != nil { - t.Fatal(err) +func sszToBlock(b []byte) (interfaces.SignedBeaconBlock, error) { + base := ðpb.BeaconBlockDeneb{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockDeneb{Block: base}) +} - helpers.ClearCache() - b := util.NewBeaconBlockDeneb() - b.Block.Body = body - wsb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - beaconState, err := operationFn(context.Background(), preState, wsb) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateDeneb{} - if err := postBeaconState.UnmarshalSSZ(postBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) - } - pbState, err := state_native.ProtobufBeaconStateDeneb(beaconState.ToProtoUnsafe()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Error("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return +func sszToBlockBody(b []byte) (interfaces.ReadOnlyBeaconBlockBody, error) { + base := ðpb.BeaconBlockBodyDeneb{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewBeaconBlockBody(base) } diff --git a/testing/spectest/shared/deneb/operations/proposer_slashing.go b/testing/spectest/shared/deneb/operations/proposer_slashing.go index e02bc9574bf9..1991db96b49d 100644 --- a/testing/spectest/shared/deneb/operations/proposer_slashing.go +++ b/testing/spectest/shared/deneb/operations/proposer_slashing.go @@ -1,38 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunProposerSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/proposer_slashing/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - proposerSlashingFile, err := util.BazelFileBytes(folderPath, "proposer_slashing.ssz_snappy") - require.NoError(t, err) - proposerSlashingSSZ, err := snappy.Decode(nil /* dst */, proposerSlashingFile) - require.NoError(t, err, "Failed to decompress") - proposerSlashing := ðpb.ProposerSlashing{} - require.NoError(t, proposerSlashing.UnmarshalSSZ(proposerSlashingSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyDeneb{ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.SignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessProposerSlashings(ctx, s, b.Block().Body().ProposerSlashings(), validators.SlashValidator) - }) - }) +func blockWithProposerSlashing(ssz []byte) (interfaces.SignedBeaconBlock, error) { + ps := ðpb.ProposerSlashing{} + if err := ps.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockDeneb() + b.Block.Body = ðpb.BeaconBlockBodyDeneb{ProposerSlashings: []*ethpb.ProposerSlashing{ps}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunProposerSlashingTest(t *testing.T, config string) { + common.RunProposerSlashingTest(t, config, version.String(version.Deneb), blockWithProposerSlashing, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/sync_committee.go b/testing/spectest/shared/deneb/operations/sync_committee.go index a43747cdd3e3..0faff606d68b 100644 --- a/testing/spectest/shared/deneb/operations/sync_committee.go +++ b/testing/spectest/shared/deneb/operations/sync_committee.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunSyncCommitteeTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/sync_aggregate/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - syncCommitteeFile, err := util.BazelFileBytes(folderPath, "sync_aggregate.ssz_snappy") - require.NoError(t, err) - syncCommitteeSSZ, err := snappy.Decode(nil /* dst */, syncCommitteeFile) - require.NoError(t, err, "Failed to decompress") - sc := ðpb.SyncAggregate{} - require.NoError(t, sc.UnmarshalSSZ(syncCommitteeSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyDeneb{SyncAggregate: sc} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.SignedBeaconBlock) (state.BeaconState, error) { - st, _, err := altair.ProcessSyncAggregate(context.Background(), s, body.SyncAggregate) - if err != nil { - return nil, err - } - return st, nil - }) - }) +func blockWithSyncAggregate(ssz []byte) (interfaces.SignedBeaconBlock, error) { + sa := ðpb.SyncAggregate{} + if err := sa.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockDeneb() + b.Block.Body = ðpb.BeaconBlockBodyDeneb{SyncAggregate: sa} + return blocks.NewSignedBeaconBlock(b) +} + +func RunSyncCommitteeTest(t *testing.T, config string) { + common.RunSyncCommitteeTest(t, config, version.String(version.Deneb), blockWithSyncAggregate, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/voluntary_exit.go b/testing/spectest/shared/deneb/operations/voluntary_exit.go index a16ed3a993b7..cbf2b569b3bb 100644 --- a/testing/spectest/shared/deneb/operations/voluntary_exit.go +++ b/testing/spectest/shared/deneb/operations/voluntary_exit.go @@ -1,37 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunVoluntaryExitTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/voluntary_exit/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - exitFile, err := util.BazelFileBytes(folderPath, "voluntary_exit.ssz_snappy") - require.NoError(t, err) - exitSSZ, err := snappy.Decode(nil /* dst */, exitFile) - require.NoError(t, err, "Failed to decompress") - voluntaryExit := ðpb.SignedVoluntaryExit{} - require.NoError(t, voluntaryExit.UnmarshalSSZ(exitSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyDeneb{VoluntaryExits: []*ethpb.SignedVoluntaryExit{voluntaryExit}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.SignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessVoluntaryExits(ctx, s, b.Block().Body().VoluntaryExits()) - }) - }) +func blockWithVoluntaryExit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := ðpb.SignedVoluntaryExit{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockDeneb() + b.Block.Body = ðpb.BeaconBlockBodyDeneb{VoluntaryExits: []*ethpb.SignedVoluntaryExit{e}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunVoluntaryExitTest(t *testing.T, config string) { + common.RunVoluntaryExitTest(t, config, version.String(version.Deneb), blockWithVoluntaryExit, sszToState) } diff --git a/testing/spectest/shared/deneb/operations/withdrawals.go b/testing/spectest/shared/deneb/operations/withdrawals.go index ac8905bc768c..119ef0033d2d 100644 --- a/testing/spectest/shared/deneb/operations/withdrawals.go +++ b/testing/spectest/shared/deneb/operations/withdrawals.go @@ -1,49 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunWithdrawalsTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/withdrawals/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - payloadFile, err := util.BazelFileBytes(folderPath, "execution_payload.ssz_snappy") - require.NoError(t, err) - payloadSSZ, err := snappy.Decode(nil /* dst */, payloadFile) - require.NoError(t, err, "Failed to decompress") - payload := &enginev1.ExecutionPayloadDeneb{} - require.NoError(t, payload.UnmarshalSSZ(payloadSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyDeneb{ExecutionPayload: payload} - RunBlockOperationTest(t, folderPath, body, func(_ context.Context, s state.BeaconState, b interfaces.SignedBeaconBlock) (state.BeaconState, error) { - payload, err := b.Block().Body().Execution() - if err != nil { - return nil, err - } - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, err - } - p, err := consensusblocks.WrappedExecutionPayloadDeneb(&enginev1.ExecutionPayloadDeneb{Withdrawals: withdrawals}) - require.NoError(t, err) - return blocks.ProcessWithdrawals(s, p) - }) - }) +func blockWithWithdrawals(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := &enginev1.ExecutionPayloadDeneb{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockDeneb() + b.Block.Body = ðpb.BeaconBlockBodyDeneb{ExecutionPayload: e} + return blocks.NewSignedBeaconBlock(b) +} + +func RunWithdrawalsTest(t *testing.T, config string) { + common.RunWithdrawalsTest(t, config, version.String(version.Deneb), blockWithWithdrawals, sszToState) } diff --git a/testing/spectest/shared/electra/epoch_processing/BUILD.bazel b/testing/spectest/shared/electra/epoch_processing/BUILD.bazel index b82d6a6ba643..ebf5fbc1cfcc 100644 --- a/testing/spectest/shared/electra/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/electra/epoch_processing/BUILD.bazel @@ -11,8 +11,8 @@ go_library( "inactivity_updates.go", "justification_and_finalization.go", "participation_flag_updates.go", - "pending_balance_updates.go", "pending_consolidations.go", + "pending_deposit_updates.go", "randao_mixes_reset.go", "registry_updates.go", "rewards_and_penalties.go", @@ -28,7 +28,6 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", - "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/electra/epoch_processing/pending_balance_updates.go b/testing/spectest/shared/electra/epoch_processing/pending_deposit_updates.go similarity index 71% rename from testing/spectest/shared/electra/epoch_processing/pending_balance_updates.go rename to testing/spectest/shared/electra/epoch_processing/pending_deposit_updates.go index 89a734373199..c630a4e80849 100644 --- a/testing/spectest/shared/electra/epoch_processing/pending_balance_updates.go +++ b/testing/spectest/shared/electra/epoch_processing/pending_deposit_updates.go @@ -13,23 +13,23 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" ) -func RunPendingBalanceDepositsTests(t *testing.T, config string) { +func RunPendingDepositsTests(t *testing.T, config string) { require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "epoch_processing/pending_balance_deposits/pyspec_tests") + testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "epoch_processing/pending_deposits/pyspec_tests") for _, folder := range testFolders { t.Run(folder.Name(), func(t *testing.T) { folderPath := path.Join(testsFolderPath, folder.Name()) - RunEpochOperationTest(t, folderPath, processPendingBalanceDeposits) + RunEpochOperationTest(t, folderPath, processPendingDeposits) }) } } -func processPendingBalanceDeposits(t *testing.T, st state.BeaconState) (state.BeaconState, error) { +func processPendingDeposits(t *testing.T, st state.BeaconState) (state.BeaconState, error) { // The caller of this method would normally have the precompute balance values for total // active balance for this epoch. For ease of test setup, we will compute total active // balance from the given state. tab, err := helpers.TotalActiveBalance(st) require.NoError(t, err) - return st, electra.ProcessPendingBalanceDeposits(context.TODO(), st, primitives.Gwei(tab)) + return st, electra.ProcessPendingDeposits(context.TODO(), st, primitives.Gwei(tab)) } diff --git a/testing/spectest/shared/electra/epoch_processing/slashings.go b/testing/spectest/shared/electra/epoch_processing/slashings.go index f6c9d61e65ec..6a2818d87f7f 100644 --- a/testing/spectest/shared/electra/epoch_processing/slashings.go +++ b/testing/spectest/shared/electra/epoch_processing/slashings.go @@ -7,7 +7,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" ) @@ -27,7 +26,6 @@ func RunSlashingsTests(t *testing.T, config string) { } func processSlashingsWrapper(t *testing.T, st state.BeaconState) (state.BeaconState, error) { - st, err := electra.ProcessSlashings(st, params.BeaconConfig().ProportionalSlashingMultiplierBellatrix) - require.NoError(t, err, "Could not process slashings") + require.NoError(t, electra.ProcessSlashings(st), "Could not process slashings") return st, nil } diff --git a/testing/spectest/shared/electra/operations/BUILD.bazel b/testing/spectest/shared/electra/operations/BUILD.bazel index 87a8537b8ece..d5d42aab6391 100644 --- a/testing/spectest/shared/electra/operations/BUILD.bazel +++ b/testing/spectest/shared/electra/operations/BUILD.bazel @@ -22,25 +22,15 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/electra/operations", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/electra:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/transition:go_default_library", - "//beacon-chain/core/validators:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//testing/require:go_default_library", - "//testing/spectest/utils:go_default_library", + "//runtime/version:go_default_library", + "//testing/spectest/shared/common/operations:go_default_library", "//testing/util:go_default_library", - "@com_github_golang_snappy//:go_default_library", - "@com_github_google_go_cmp//cmp:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@io_bazel_rules_go//go/tools/bazel:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", - "@org_golang_google_protobuf//testing/protocmp:go_default_library", ], ) diff --git a/testing/spectest/shared/electra/operations/attestation.go b/testing/spectest/shared/electra/operations/attestation.go index ab219b508b46..ceb6d9fca8fd 100644 --- a/testing/spectest/shared/electra/operations/attestation.go +++ b/testing/spectest/shared/electra/operations/attestation.go @@ -1,59 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/pkg/errors" - b "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttestationTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/attestation/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "electra", "operations/attestation/pyspec_tests") +func blockWithAttestation(attestationSSZ []byte) (interfaces.SignedBeaconBlock, error) { + att := ðpb.AttestationElectra{} + if err := att.UnmarshalSSZ(attestationSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attestationFile, err := util.BazelFileBytes(folderPath, "attestation.ssz_snappy") - require.NoError(t, err) - attestationSSZ, err := snappy.Decode(nil /* dst */, attestationFile) - require.NoError(t, err, "Failed to decompress") - att := ðpb.AttestationElectra{} - require.NoError(t, att.UnmarshalSSZ(attestationSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyElectra{Attestations: []*ethpb.AttestationElectra{att}} - processAtt := func(ctx context.Context, st state.BeaconState, blk interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, err = electra.ProcessAttestationsNoVerifySignature(ctx, st, blk.Block()) - if err != nil { - return nil, err - } - aSet, err := b.AttestationSignatureBatch(ctx, st, blk.Block().Body().Attestations()) - if err != nil { - return nil, err - } - verified, err := aSet.Verify() - if err != nil { - return nil, err - } - if !verified { - return nil, errors.New("could not batch verify attestation signature") - } - return st, nil - } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{Attestations: []*ethpb.AttestationElectra{att}} + return blocks.NewSignedBeaconBlock(b) +} - RunBlockOperationTest(t, folderPath, body, processAtt) - }) - } +func RunAttestationTest(t *testing.T, config string) { + common.RunAttestationTest(t, config, version.String(version.Electra), blockWithAttestation, electra.ProcessAttestationsNoVerifySignature, sszToState) } diff --git a/testing/spectest/shared/electra/operations/attester_slashing.go b/testing/spectest/shared/electra/operations/attester_slashing.go index 8fd621330c7e..7ff5d8c626f8 100644 --- a/testing/spectest/shared/electra/operations/attester_slashing.go +++ b/testing/spectest/shared/electra/operations/attester_slashing.go @@ -1,38 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunAttesterSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/attester_slashing/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attSlashingFile, err := util.BazelFileBytes(folderPath, "attester_slashing.ssz_snappy") - require.NoError(t, err) - attSlashingSSZ, err := snappy.Decode(nil /* dst */, attSlashingFile) - require.NoError(t, err, "Failed to decompress") - attSlashing := ðpb.AttesterSlashingElectra{} - require.NoError(t, attSlashing.UnmarshalSSZ(attSlashingSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyElectra{AttesterSlashings: []*ethpb.AttesterSlashingElectra{attSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessAttesterSlashings(ctx, s, b.Block().Body().AttesterSlashings(), validators.SlashValidator) - }) - }) +func blockWithAttesterSlashing(asSSZ []byte) (interfaces.SignedBeaconBlock, error) { + as := ðpb.AttesterSlashingElectra{} + if err := as.UnmarshalSSZ(asSSZ); err != nil { + return nil, err } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{AttesterSlashings: []*ethpb.AttesterSlashingElectra{as}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunAttesterSlashingTest(t *testing.T, config string) { + common.RunAttesterSlashingTest(t, config, version.String(version.Electra), blockWithAttesterSlashing, sszToState) } diff --git a/testing/spectest/shared/electra/operations/block_header.go b/testing/spectest/shared/electra/operations/block_header.go index f0d141e3dc21..7af3c4ed1560 100644 --- a/testing/spectest/shared/electra/operations/block_header.go +++ b/testing/spectest/shared/electra/operations/block_header.go @@ -1,86 +1,12 @@ package operations import ( - "context" - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunBlockHeaderTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/block_header/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "block.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockFile) - require.NoError(t, err, "Failed to decompress") - block := ðpb.BeaconBlockElectra{} - require.NoError(t, block.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateElectra{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoElectra(preBeaconStateBase) - require.NoError(t, err) - - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - // Spectest blocks are not signed, so we'll call NoVerify to skip sig verification. - bodyRoot, err := block.Body.HashTreeRoot() - require.NoError(t, err) - beaconState, err := blocks.ProcessBlockHeaderNoVerify(context.Background(), preBeaconState, block.Slot, block.ProposerIndex, block.ParentRoot, bodyRoot[:]) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateElectra{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateElectra(beaconState.ToProto()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } + common.RunBlockHeaderTest(t, config, version.String(version.Electra), sszToBlock, sszToState) } diff --git a/testing/spectest/shared/electra/operations/bls_to_execution_changes.go b/testing/spectest/shared/electra/operations/bls_to_execution_changes.go index ee033f72d0c7..a30f26d3f035 100644 --- a/testing/spectest/shared/electra/operations/bls_to_execution_changes.go +++ b/testing/spectest/shared/electra/operations/bls_to_execution_changes.go @@ -1,62 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunBLSToExecutionChangeTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/bls_to_execution_change/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "electra", "operations/bls_to_execution_change/pyspec_tests") +func blockWithBlsChange(ssz []byte) (interfaces.SignedBeaconBlock, error) { + c := ðpb.SignedBLSToExecutionChange{} + if err := c.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - changeFile, err := util.BazelFileBytes(folderPath, "address_change.ssz_snappy") - require.NoError(t, err) - changeSSZ, err := snappy.Decode(nil /* dst */, changeFile) - require.NoError(t, err, "Failed to decompress") - change := ðpb.SignedBLSToExecutionChange{} - require.NoError(t, change.UnmarshalSSZ(changeSSZ), "Failed to unmarshal") + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{c}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBodyElectra{ - BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{change}, - } - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, err := blocks.ProcessBLSToExecutionChanges(s, b.Block()) - if err != nil { - return nil, err - } - changes, err := b.Block().Body().BLSToExecutionChanges() - if err != nil { - return nil, err - } - cSet, err := blocks.BLSChangesSignatureBatch(st, changes) - if err != nil { - return nil, err - } - ok, err := cSet.Verify() - if err != nil { - return nil, err - } - if !ok { - return nil, errors.New("signature did not verify") - } - return st, nil - }) - }) - } +func RunBLSToExecutionChangeTest(t *testing.T, config string) { + common.RunBLSToExecutionChangeTest(t, config, version.String(version.Electra), blockWithBlsChange, sszToState) } diff --git a/testing/spectest/shared/electra/operations/consolidations.go b/testing/spectest/shared/electra/operations/consolidations.go index 66091df746ab..25522e61ccc2 100644 --- a/testing/spectest/shared/electra/operations/consolidations.go +++ b/testing/spectest/shared/electra/operations/consolidations.go @@ -1,49 +1,30 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" - eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunConsolidationTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/consolidation_request/pyspec_tests") - require.NotEqual(t, 0, len(testFolders), "missing tests for consolidation operation in folder") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - consolidationFile, err := util.BazelFileBytes(folderPath, "consolidation_request.ssz_snappy") - require.NoError(t, err) - consolidationSSZ, err := snappy.Decode(nil /* dst */, consolidationFile) - require.NoError(t, err, "Failed to decompress") - consolidation := &enginev1.ConsolidationRequest{} - require.NoError(t, consolidation.UnmarshalSSZ(consolidationSSZ), "Failed to unmarshal") - - body := ð.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadElectra{ - ConsolidationRequests: []*enginev1.ConsolidationRequest{consolidation}, - }} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - ed, err := b.Block().Body().Execution() - if err != nil { - return nil, err - } - eed, ok := ed.(interfaces.ExecutionDataElectra) - if !ok { - t.Fatal("block does not have execution data for electra") - } - return s, electra.ProcessConsolidationRequests(ctx, s, eed.ConsolidationRequests()) - }) - }) +func blockWithConsolidation(ssz []byte) (interfaces.SignedBeaconBlock, error) { + cr := &enginev1.ConsolidationRequest{} + if err := cr.UnmarshalSSZ(ssz); err != nil { + return nil, err + } + er := &enginev1.ExecutionRequests{ + Consolidations: []*enginev1.ConsolidationRequest{cr}, } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{ExecutionRequests: er} + return blocks.NewSignedBeaconBlock(b) +} + +func RunConsolidationTest(t *testing.T, config string) { + common.RunConsolidationTest(t, config, version.String(version.Electra), blockWithConsolidation, sszToState) } diff --git a/testing/spectest/shared/electra/operations/deposit.go b/testing/spectest/shared/electra/operations/deposit.go index 254b440a88d1..405671ea2fa9 100644 --- a/testing/spectest/shared/electra/operations/deposit.go +++ b/testing/spectest/shared/electra/operations/deposit.go @@ -1,38 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunDepositTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/deposit/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - depositFile, err := util.BazelFileBytes(folderPath, "deposit.ssz_snappy") - require.NoError(t, err) - depositSSZ, err := snappy.Decode(nil /* dst */, depositFile) - require.NoError(t, err, "Failed to decompress") - deposit := ðpb.Deposit{} - require.NoError(t, deposit.UnmarshalSSZ(depositSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyElectra{Deposits: []*ethpb.Deposit{deposit}} - processDepositsFunc := func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return electra.ProcessDeposits(ctx, s, b.Block().Body().Deposits()) - } - RunBlockOperationTest(t, folderPath, body, processDepositsFunc) - }) +func blockWithDeposit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + d := ðpb.Deposit{} + if err := d.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{Deposits: []*ethpb.Deposit{d}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunDepositTest(t *testing.T, config string) { + common.RunDepositTest(t, config, version.String(version.Electra), blockWithDeposit, electra.ProcessDeposits, sszToState) } diff --git a/testing/spectest/shared/electra/operations/deposit_request.go b/testing/spectest/shared/electra/operations/deposit_request.go index 9f904959b4ea..fbc5b2ff142d 100644 --- a/testing/spectest/shared/electra/operations/deposit_request.go +++ b/testing/spectest/shared/electra/operations/deposit_request.go @@ -1,43 +1,30 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunDepositRequestsTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/deposit_request/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - depositRequestFile, err := util.BazelFileBytes(folderPath, "deposit_request.ssz_snappy") - require.NoError(t, err) - depositRequestSSZ, err := snappy.Decode(nil /* dst */, depositRequestFile) - require.NoError(t, err, "Failed to decompress") - depositRequest := &enginev1.DepositRequest{} - require.NoError(t, depositRequest.UnmarshalSSZ(depositRequestSSZ), "failed to unmarshal") - requests := []*enginev1.DepositRequest{depositRequest} - body := ðpb.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadElectra{DepositRequests: requests}} - processDepositRequestsFunc := func(ctx context.Context, s state.BeaconState, signedBlock interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - e, err := signedBlock.Block().Body().Execution() - require.NoError(t, err, "Failed to get execution") - ee, ok := e.(interfaces.ExecutionDataElectra) - require.Equal(t, true, ok, "Invalid execution payload") - return electra.ProcessDepositRequests(ctx, s, ee.DepositRequests()) - } - RunBlockOperationTest(t, folderPath, body, processDepositRequestsFunc) - }) +func blockWithDepositRequest(ssz []byte) (interfaces.SignedBeaconBlock, error) { + dr := &enginev1.DepositRequest{} + if err := dr.UnmarshalSSZ(ssz); err != nil { + return nil, err + } + er := &enginev1.ExecutionRequests{ + Deposits: []*enginev1.DepositRequest{dr}, } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{ExecutionRequests: er} + return blocks.NewSignedBeaconBlock(b) +} + +func RunDepositRequestsTest(t *testing.T, config string) { + common.RunDepositRequestsTest(t, config, version.String(version.Electra), blockWithDepositRequest, sszToState) } diff --git a/testing/spectest/shared/electra/operations/execution_payload.go b/testing/spectest/shared/electra/operations/execution_payload.go index dc00fc5173eb..ad7b0e97eb15 100644 --- a/testing/spectest/shared/electra/operations/execution_payload.go +++ b/testing/spectest/shared/electra/operations/execution_payload.go @@ -1,105 +1,12 @@ package operations import ( - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - blocks2 "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) func RunExecutionPayloadTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/execution_payload/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "electra", "operations/execution_payload/pyspec_tests") - } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - - blockBodyFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "body.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockBodyFile) - require.NoError(t, err, "Failed to decompress") - body := ðpb.BeaconBlockBodyElectra{} - require.NoError(t, body.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - b, err := blocks2.NewBeaconBlock(ðpb.BeaconBlockElectra{Body: body}) - require.NoError(t, err) - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconStateElectra{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoElectra(preBeaconStateBase) - require.NoError(t, err) - - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - payload, err := blocks2.WrappedExecutionPayloadElectra(body.ExecutionPayload) - require.NoError(t, err) - - file, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "execution.yaml") - require.NoError(t, err) - config := &ExecutionConfig{} - require.NoError(t, utils.UnmarshalYaml(file, config), "Failed to Unmarshal") - - if postSSZExists { - require.NoError(t, blocks.ValidatePayloadWhenMergeCompletes(preBeaconState, payload)) - require.NoError(t, blocks.ValidatePayload(preBeaconState, payload)) - require.NoError(t, transition.VerifyBlobCommitmentCount(b)) - require.NoError(t, preBeaconState.SetLatestExecutionPayloadHeader(payload)) - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateElectra{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStateElectra(preBeaconState.ToProto()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else if config.Valid { - err1 := blocks.ValidatePayloadWhenMergeCompletes(preBeaconState, payload) - err2 := blocks.ValidatePayload(preBeaconState, payload) - err3 := transition.VerifyBlobCommitmentCount(b) - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err1 == nil && err2 == nil && err3 == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } -} - -type ExecutionConfig struct { - Valid bool `json:"execution_valid"` + common.RunExecutionPayloadTest(t, config, version.String(version.Electra), sszToBlockBody, sszToState) } diff --git a/testing/spectest/shared/electra/operations/helpers.go b/testing/spectest/shared/electra/operations/helpers.go index fe42a2c83e6f..64cfad193760 100644 --- a/testing/spectest/shared/electra/operations/helpers.go +++ b/testing/spectest/shared/electra/operations/helpers.go @@ -1,88 +1,33 @@ package operations import ( - "context" - "os" - "path" - "strings" - "testing" - - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" ) -type blockOperation func(context.Context, state.BeaconState, interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) - -// RunBlockOperationTest takes in the prestate and the beacon block body, processes it through the -// passed in block operation function and checks the post state with the expected post state. -func RunBlockOperationTest( - t *testing.T, - folderPath string, - body *ethpb.BeaconBlockBodyElectra, - operationFn blockOperation, -) { - preBeaconStateFile, err := util.BazelFileBytes(path.Join(folderPath, "pre.ssz_snappy")) - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preStateBase := ðpb.BeaconStateElectra{} - if err := preStateBase.UnmarshalSSZ(preBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) +func sszToState(b []byte) (state.BeaconState, error) { + base := ðpb.BeaconStateElectra{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } - preState, err := state_native.InitializeFromProtoElectra(preStateBase) - require.NoError(t, err) + return state_native.InitializeFromProtoElectra(base) +} - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(folderPath, "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else if err != nil { - t.Fatal(err) +func sszToBlock(b []byte) (interfaces.SignedBeaconBlock, error) { + base := ðpb.BeaconBlockElectra{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockElectra{Block: base}) +} - helpers.ClearCache() - b := util.NewBeaconBlockElectra() - b.Block.Body = body - wsb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - beaconState, err := operationFn(context.Background(), preState, wsb) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconStateElectra{} - if err := postBeaconState.UnmarshalSSZ(postBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) - } - pbState, err := state_native.ProtobufBeaconStateElectra(beaconState.ToProtoUnsafe()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Error("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return +func sszToBlockBody(b []byte) (interfaces.ReadOnlyBeaconBlockBody, error) { + base := ðpb.BeaconBlockBodyElectra{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewBeaconBlockBody(base) } diff --git a/testing/spectest/shared/electra/operations/proposer_slashing.go b/testing/spectest/shared/electra/operations/proposer_slashing.go index d31e771cd188..64f11edf4248 100644 --- a/testing/spectest/shared/electra/operations/proposer_slashing.go +++ b/testing/spectest/shared/electra/operations/proposer_slashing.go @@ -1,38 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunProposerSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/proposer_slashing/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - proposerSlashingFile, err := util.BazelFileBytes(folderPath, "proposer_slashing.ssz_snappy") - require.NoError(t, err) - proposerSlashingSSZ, err := snappy.Decode(nil /* dst */, proposerSlashingFile) - require.NoError(t, err, "Failed to decompress") - proposerSlashing := ðpb.ProposerSlashing{} - require.NoError(t, proposerSlashing.UnmarshalSSZ(proposerSlashingSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyElectra{ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessProposerSlashings(ctx, s, b.Block().Body().ProposerSlashings(), validators.SlashValidator) - }) - }) +func blockWithProposerSlashing(ssz []byte) (interfaces.SignedBeaconBlock, error) { + ps := ðpb.ProposerSlashing{} + if err := ps.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{ProposerSlashings: []*ethpb.ProposerSlashing{ps}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunProposerSlashingTest(t *testing.T, config string) { + common.RunProposerSlashingTest(t, config, version.String(version.Electra), blockWithProposerSlashing, sszToState) } diff --git a/testing/spectest/shared/electra/operations/sync_committee.go b/testing/spectest/shared/electra/operations/sync_committee.go index 373cc0046412..b14de68c2f20 100644 --- a/testing/spectest/shared/electra/operations/sync_committee.go +++ b/testing/spectest/shared/electra/operations/sync_committee.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunSyncCommitteeTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/sync_aggregate/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - syncCommitteeFile, err := util.BazelFileBytes(folderPath, "sync_aggregate.ssz_snappy") - require.NoError(t, err) - syncCommitteeSSZ, err := snappy.Decode(nil /* dst */, syncCommitteeFile) - require.NoError(t, err, "Failed to decompress") - sc := ðpb.SyncAggregate{} - require.NoError(t, sc.UnmarshalSSZ(syncCommitteeSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyElectra{SyncAggregate: sc} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, _, err := electra.ProcessSyncAggregate(context.Background(), s, body.SyncAggregate) - if err != nil { - return nil, err - } - return st, nil - }) - }) +func blockWithSyncAggregate(ssz []byte) (interfaces.SignedBeaconBlock, error) { + sa := ðpb.SyncAggregate{} + if err := sa.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{SyncAggregate: sa} + return blocks.NewSignedBeaconBlock(b) +} + +func RunSyncCommitteeTest(t *testing.T, config string) { + common.RunSyncCommitteeTest(t, config, version.String(version.Electra), blockWithSyncAggregate, sszToState) } diff --git a/testing/spectest/shared/electra/operations/voluntary_exit.go b/testing/spectest/shared/electra/operations/voluntary_exit.go index b423c63f3e1b..706e4a9db358 100644 --- a/testing/spectest/shared/electra/operations/voluntary_exit.go +++ b/testing/spectest/shared/electra/operations/voluntary_exit.go @@ -1,37 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunVoluntaryExitTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/voluntary_exit/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - exitFile, err := util.BazelFileBytes(folderPath, "voluntary_exit.ssz_snappy") - require.NoError(t, err) - exitSSZ, err := snappy.Decode(nil /* dst */, exitFile) - require.NoError(t, err, "Failed to decompress") - voluntaryExit := ðpb.SignedVoluntaryExit{} - require.NoError(t, voluntaryExit.UnmarshalSSZ(exitSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBodyElectra{VoluntaryExits: []*ethpb.SignedVoluntaryExit{voluntaryExit}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessVoluntaryExits(ctx, s, b.Block().Body().VoluntaryExits()) - }) - }) +func blockWithVoluntaryExit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := ðpb.SignedVoluntaryExit{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlock() + b.Block.Body = ðpb.BeaconBlockBody{VoluntaryExits: []*ethpb.SignedVoluntaryExit{e}} + return blocks.NewSignedBeaconBlock(b) +} + +func RunVoluntaryExitTest(t *testing.T, config string) { + common.RunVoluntaryExitTest(t, config, version.String(version.Electra), blockWithVoluntaryExit, sszToState) } diff --git a/testing/spectest/shared/electra/operations/withdrawal_request.go b/testing/spectest/shared/electra/operations/withdrawal_request.go index 2f5451a74972..01aaa9472740 100644 --- a/testing/spectest/shared/electra/operations/withdrawal_request.go +++ b/testing/spectest/shared/electra/operations/withdrawal_request.go @@ -1,49 +1,30 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/electra" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunWithdrawalRequestTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/withdrawal_request/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "electra", "operations/withdrawal_request/pyspec_tests") +func blockWithWithdrawalRequest(ssz []byte) (interfaces.SignedBeaconBlock, error) { + wr := &enginev1.WithdrawalRequest{} + if err := wr.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - withdrawalRequestFile, err := util.BazelFileBytes(folderPath, "withdrawal_request.ssz_snappy") - require.NoError(t, err) - withdrawalRequestSSZ, err := snappy.Decode(nil /* dst */, withdrawalRequestFile) - require.NoError(t, err, "Failed to decompress") - withdrawalRequest := &enginev1.WithdrawalRequest{} - require.NoError(t, withdrawalRequest.UnmarshalSSZ(withdrawalRequestSSZ), "Failed to unmarshal") - body := ðpb.BeaconBlockBodyElectra{ExecutionPayload: &enginev1.ExecutionPayloadElectra{ - WithdrawalRequests: []*enginev1.WithdrawalRequest{ - withdrawalRequest, - }, - }} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - bod := b.Block().Body() - e, err := bod.Execution() - require.NoError(t, err) - exe, ok := e.(interfaces.ExecutionDataElectra) - require.Equal(t, true, ok) - return electra.ProcessWithdrawalRequests(ctx, s, exe.WithdrawalRequests()) - }) - }) + er := &enginev1.ExecutionRequests{ + Withdrawals: []*enginev1.WithdrawalRequest{wr}, } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{ExecutionRequests: er} + return blocks.NewSignedBeaconBlock(b) +} + +func RunWithdrawalRequestTest(t *testing.T, config string) { + common.RunWithdrawalRequestTest(t, config, version.String(version.Electra), blockWithWithdrawalRequest, sszToState) } diff --git a/testing/spectest/shared/electra/operations/withdrawals.go b/testing/spectest/shared/electra/operations/withdrawals.go index 5ef4fcd2ee09..51031d615d45 100644 --- a/testing/spectest/shared/electra/operations/withdrawals.go +++ b/testing/spectest/shared/electra/operations/withdrawals.go @@ -1,49 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -func RunWithdrawalsTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", "operations/withdrawals/pyspec_tests") - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - payloadFile, err := util.BazelFileBytes(folderPath, "execution_payload.ssz_snappy") - require.NoError(t, err) - payloadSSZ, err := snappy.Decode(nil /* dst */, payloadFile) - require.NoError(t, err, "Failed to decompress") - payload := &enginev1.ExecutionPayloadElectra{} - require.NoError(t, payload.UnmarshalSSZ(payloadSSZ), "failed to unmarshal") - - body := ðpb.BeaconBlockBodyElectra{ExecutionPayload: payload} - RunBlockOperationTest(t, folderPath, body, func(_ context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - payload, err := b.Block().Body().Execution() - if err != nil { - return nil, err - } - withdrawals, err := payload.Withdrawals() - if err != nil { - return nil, err - } - p, err := consensusblocks.WrappedExecutionPayloadElectra(&enginev1.ExecutionPayloadElectra{Withdrawals: withdrawals}) - require.NoError(t, err) - return blocks.ProcessWithdrawals(s, p) - }) - }) +func blockWithWithdrawals(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := &enginev1.ExecutionPayloadDeneb{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } + b := util.NewBeaconBlockElectra() + b.Block.Body = ðpb.BeaconBlockBodyElectra{ExecutionPayload: e} + return blocks.NewSignedBeaconBlock(b) +} + +func RunWithdrawalsTest(t *testing.T, config string) { + common.RunWithdrawalsTest(t, config, version.String(version.Electra), blockWithWithdrawals, sszToState) } diff --git a/testing/spectest/shared/electra/sanity/BUILD.bazel b/testing/spectest/shared/electra/sanity/BUILD.bazel index f284008577af..59bfab587672 100644 --- a/testing/spectest/shared/electra/sanity/BUILD.bazel +++ b/testing/spectest/shared/electra/sanity/BUILD.bazel @@ -15,6 +15,7 @@ go_library( "//beacon-chain/core/transition:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", + "//config/params:go_default_library", "//consensus-types/blocks:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", diff --git a/testing/spectest/shared/electra/sanity/block_processing.go b/testing/spectest/shared/electra/sanity/block_processing.go index d7fb00c6213a..ab37ce3360a0 100644 --- a/testing/spectest/shared/electra/sanity/block_processing.go +++ b/testing/spectest/shared/electra/sanity/block_processing.go @@ -15,6 +15,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -35,6 +36,11 @@ func RunBlockProcessingTest(t *testing.T, config, folderPath string) { testFolders, testsFolderPath := utils.TestFolders(t, config, "electra", folderPath) for _, folder := range testFolders { t.Run(folder.Name(), func(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.BeaconConfig().Copy() + cfg.ElectraForkEpoch = 0 + params.OverrideBeaconConfig(cfg) + helpers.ClearCache() preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") require.NoError(t, err) diff --git a/testing/spectest/shared/electra/ssz_static/ssz_static.go b/testing/spectest/shared/electra/ssz_static/ssz_static.go index 86522ce4cdbf..84b5c757e95a 100644 --- a/testing/spectest/shared/electra/ssz_static/ssz_static.go +++ b/testing/spectest/shared/electra/ssz_static/ssz_static.go @@ -37,9 +37,9 @@ func UnmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (i var obj interface{} switch folderName { case "ExecutionPayload": - obj = &enginev1.ExecutionPayloadElectra{} + obj = &enginev1.ExecutionPayloadDeneb{} case "ExecutionPayloadHeader": - obj = &enginev1.ExecutionPayloadHeaderElectra{} + obj = &enginev1.ExecutionPayloadHeaderDeneb{} case "Attestation": obj = ðpb.AttestationElectra{} case "AttestationData": @@ -103,6 +103,8 @@ func UnmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (i obj = ðpb.ContributionAndProof{} case "SignedContributionAndProof": obj = ðpb.SignedContributionAndProof{} + case "SingleAttestation": + obj = ðpb.SingleAttestation{} case "SyncAggregate": obj = ðpb.SyncAggregate{} case "SyncAggregatorSelectionData": @@ -141,8 +143,8 @@ func UnmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (i obj = ðpb.BLSToExecutionChange{} case "SignedBLSToExecutionChange": obj = ðpb.SignedBLSToExecutionChange{} - case "PendingBalanceDeposit": - obj = ðpb.PendingBalanceDeposit{} + case "PendingDeposit": + obj = ðpb.PendingDeposit{} case "PendingPartialWithdrawal": obj = ðpb.PendingPartialWithdrawal{} case "PendingConsolidation": @@ -153,6 +155,8 @@ func UnmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (i obj = &enginev1.DepositRequest{} case "ConsolidationRequest": obj = &enginev1.ConsolidationRequest{} + case "ExecutionRequests": + obj = &enginev1.ExecutionRequests{} default: return nil, errors.New("type not found") } diff --git a/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel b/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel index 68e6a1a95491..84be9a021748 100644 --- a/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel +++ b/testing/spectest/shared/phase0/epoch_processing/BUILD.bazel @@ -24,7 +24,6 @@ go_library( "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", - "//config/params:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/require:go_default_library", "//testing/spectest/utils:go_default_library", diff --git a/testing/spectest/shared/phase0/epoch_processing/slashings.go b/testing/spectest/shared/phase0/epoch_processing/slashings.go index cee89bd62ea1..7b443e18d9dd 100644 --- a/testing/spectest/shared/phase0/epoch_processing/slashings.go +++ b/testing/spectest/shared/phase0/epoch_processing/slashings.go @@ -9,7 +9,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch/precompute" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" - "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" ) @@ -32,10 +31,9 @@ func RunSlashingsTests(t *testing.T, config string) { } } -func processSlashingsWrapper(t *testing.T, s state.BeaconState) (state.BeaconState, error) { - s, err := epoch.ProcessSlashings(s, params.BeaconConfig().ProportionalSlashingMultiplier) - require.NoError(t, err, "Could not process slashings") - return s, nil +func processSlashingsWrapper(t *testing.T, st state.BeaconState) (state.BeaconState, error) { + require.NoError(t, epoch.ProcessSlashings(st), "Could not process slashings") + return st, nil } func processSlashingsPrecomputeWrapper(t *testing.T, state state.BeaconState) (state.BeaconState, error) { diff --git a/testing/spectest/shared/phase0/operations/BUILD.bazel b/testing/spectest/shared/phase0/operations/BUILD.bazel index f2a69f1c9e9e..8f69fb427e01 100644 --- a/testing/spectest/shared/phase0/operations/BUILD.bazel +++ b/testing/spectest/shared/phase0/operations/BUILD.bazel @@ -17,21 +17,13 @@ go_library( deps = [ "//beacon-chain/core/altair:go_default_library", "//beacon-chain/core/blocks:go_default_library", - "//beacon-chain/core/helpers:go_default_library", - "//beacon-chain/core/validators:go_default_library", "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//proto/prysm/v1alpha1:go_default_library", - "//testing/require:go_default_library", - "//testing/spectest/utils:go_default_library", + "//runtime/version:go_default_library", + "//testing/spectest/shared/common/operations:go_default_library", "//testing/util:go_default_library", - "@com_github_golang_snappy//:go_default_library", - "@com_github_google_go_cmp//cmp:go_default_library", - "@com_github_pkg_errors//:go_default_library", - "@io_bazel_rules_go//go/tools/bazel:go_default_library", - "@org_golang_google_protobuf//proto:go_default_library", - "@org_golang_google_protobuf//testing/protocmp:go_default_library", ], ) diff --git a/testing/spectest/shared/phase0/operations/attestation.go b/testing/spectest/shared/phase0/operations/attestation.go index 7c2ff9a3352b..173904a68d90 100644 --- a/testing/spectest/shared/phase0/operations/attestation.go +++ b/testing/spectest/shared/phase0/operations/attestation.go @@ -1,59 +1,28 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/pkg/errors" b "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -// RunAttestationTest executes "operations/attestation" tests. -func RunAttestationTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "phase0", "operations/attestation/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "phase0", "operations/attestation/pyspec_tests") +func blockWithAttestation(attestationSSZ []byte) (interfaces.SignedBeaconBlock, error) { + att := ðpb.Attestation{} + if err := att.UnmarshalSSZ(attestationSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attestationFile, err := util.BazelFileBytes(folderPath, "attestation.ssz_snappy") - require.NoError(t, err) - attestationSSZ, err := snappy.Decode(nil /* dst */, attestationFile) - require.NoError(t, err, "Failed to decompress") - att := ðpb.Attestation{} - require.NoError(t, att.UnmarshalSSZ(attestationSSZ), "Failed to unmarshal") - - body := ðpb.BeaconBlockBody{Attestations: []*ethpb.Attestation{att}} - processAtt := func(ctx context.Context, st state.BeaconState, blk interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - st, err = b.ProcessAttestationsNoVerifySignature(ctx, st, blk.Block()) - if err != nil { - return nil, err - } - aSet, err := b.AttestationSignatureBatch(ctx, st, blk.Block().Body().Attestations()) - if err != nil { - return nil, err - } - verified, err := aSet.Verify() - if err != nil { - return nil, err - } - if !verified { - return nil, errors.New("could not batch verify attestation signature") - } - return st, nil - } + b := util.NewBeaconBlock() + b.Block.Body = ðpb.BeaconBlockBody{Attestations: []*ethpb.Attestation{att}} + return blocks.NewSignedBeaconBlock(b) +} - RunBlockOperationTest(t, folderPath, body, processAtt) - }) - } +// RunAttestationTest executes "operations/attestation" tests. +func RunAttestationTest(t *testing.T, config string) { + common.RunAttestationTest(t, config, version.String(version.Phase0), blockWithAttestation, b.ProcessAttestationsNoVerifySignature, sszToState) } diff --git a/testing/spectest/shared/phase0/operations/attester_slashing.go b/testing/spectest/shared/phase0/operations/attester_slashing.go index df86d5116859..9f1d50d6513d 100644 --- a/testing/spectest/shared/phase0/operations/attester_slashing.go +++ b/testing/spectest/shared/phase0/operations/attester_slashing.go @@ -1,42 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - v "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -// RunAttesterSlashingTest executes "operations/attester_slashing" tests. -func RunAttesterSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "phase0", "operations/attester_slashing/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "phase0", "operations/attester_slashing/pyspec_tests") +func blockWithAttesterSlashing(asSSZ []byte) (interfaces.SignedBeaconBlock, error) { + as := ðpb.AttesterSlashing{} + if err := as.UnmarshalSSZ(asSSZ); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - attSlashingFile, err := util.BazelFileBytes(folderPath, "attester_slashing.ssz_snappy") - require.NoError(t, err) - attSlashingSSZ, err := snappy.Decode(nil /* dst */, attSlashingFile) - require.NoError(t, err, "Failed to decompress") - attSlashing := ðpb.AttesterSlashing{} - require.NoError(t, attSlashing.UnmarshalSSZ(attSlashingSSZ), "Failed to unmarshal") + b := util.NewBeaconBlock() + b.Block.Body = ðpb.BeaconBlockBody{AttesterSlashings: []*ethpb.AttesterSlashing{as}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBody{AttesterSlashings: []*ethpb.AttesterSlashing{attSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessAttesterSlashings(ctx, s, b.Block().Body().AttesterSlashings(), v.SlashValidator) - }) - }) - } +func RunAttesterSlashingTest(t *testing.T, config string) { + common.RunAttesterSlashingTest(t, config, version.String(version.Phase0), blockWithAttesterSlashing, sszToState) } diff --git a/testing/spectest/shared/phase0/operations/block_header.go b/testing/spectest/shared/phase0/operations/block_header.go index 0e95a5b66ca7..812f43e8411b 100644 --- a/testing/spectest/shared/phase0/operations/block_header.go +++ b/testing/spectest/shared/phase0/operations/block_header.go @@ -1,92 +1,12 @@ package operations import ( - "context" - "os" - "path" - "strings" "testing" - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" - state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" ) -// RunBlockHeaderTest executes "operations/block_header" tests. func RunBlockHeaderTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "phase0", "operations/block_header/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "phase0", "operations/block_header/pyspec_tests") - } - - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - helpers.ClearCache() - - blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "block.ssz_snappy") - require.NoError(t, err) - blockSSZ, err := snappy.Decode(nil /* dst */, blockFile) - require.NoError(t, err, "Failed to decompress") - block := ðpb.BeaconBlock{} - require.NoError(t, block.UnmarshalSSZ(blockSSZ), "Failed to unmarshal") - - preBeaconStateFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "pre.ssz_snappy") - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preBeaconStateBase := ðpb.BeaconState{} - require.NoError(t, preBeaconStateBase.UnmarshalSSZ(preBeaconStateSSZ), "Failed to unmarshal") - preBeaconState, err := state_native.InitializeFromProtoPhase0(preBeaconStateBase) - require.NoError(t, err) - - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(testsFolderPath, folder.Name(), "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else { - require.NoError(t, err) - } - - // Spectest blocks are not signed, so we'll call NoVerify to skip sig verification. - bodyRoot, err := block.Body.HashTreeRoot() - require.NoError(t, err) - beaconState, err := blocks.ProcessBlockHeaderNoVerify(context.Background(), preBeaconState, block.Slot, block.ProposerIndex, block.ParentRoot, bodyRoot[:]) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconState{} - require.NoError(t, postBeaconState.UnmarshalSSZ(postBeaconStateSSZ), "Failed to unmarshal") - pbState, err := state_native.ProtobufBeaconStatePhase0(beaconState.ToProto()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return - } - }) - } + common.RunBlockHeaderTest(t, config, version.String(version.Phase0), sszToBlock, sszToState) } diff --git a/testing/spectest/shared/phase0/operations/deposit.go b/testing/spectest/shared/phase0/operations/deposit.go index 010fb41208ba..f137c2a8067a 100644 --- a/testing/spectest/shared/phase0/operations/deposit.go +++ b/testing/spectest/shared/phase0/operations/deposit.go @@ -1,42 +1,27 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -// RunDepositTest executes "operations/deposit" tests. -func RunDepositTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "phase0", "operations/deposit/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "phase0", "operations/deposit/pyspec_tests") +func blockWithDeposit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + d := ðpb.Deposit{} + if err := d.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - depositFile, err := util.BazelFileBytes(folderPath, "deposit.ssz_snappy") - require.NoError(t, err) - depositSSZ, err := snappy.Decode(nil /* dst */, depositFile) - require.NoError(t, err, "Failed to decompress") - deposit := ðpb.Deposit{} - require.NoError(t, deposit.UnmarshalSSZ(depositSSZ), "Failed to unmarshal") + b := util.NewBeaconBlock() + b.Block.Body = ðpb.BeaconBlockBody{Deposits: []*ethpb.Deposit{d}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBody{Deposits: []*ethpb.Deposit{deposit}} - processDepositsFunc := func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return altair.ProcessDeposits(ctx, s, b.Block().Body().Deposits()) - } - RunBlockOperationTest(t, folderPath, body, processDepositsFunc) - }) - } +func RunDepositTest(t *testing.T, config string) { + common.RunDepositTest(t, config, version.String(version.Phase0), blockWithDeposit, altair.ProcessDeposits, sszToState) } diff --git a/testing/spectest/shared/phase0/operations/helpers.go b/testing/spectest/shared/phase0/operations/helpers.go index 419dbbb32e9d..262b40a394c2 100644 --- a/testing/spectest/shared/phase0/operations/helpers.go +++ b/testing/spectest/shared/phase0/operations/helpers.go @@ -1,88 +1,25 @@ package operations import ( - "context" - "os" - "path" - "strings" - "testing" - - "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/golang/snappy" - "github.com/google/go-cmp/cmp" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/util" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/testing/protocmp" ) -type blockOperation func(context.Context, state.BeaconState, interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) - -// RunBlockOperationTest takes in the prestate and the beacon block body, processes it through the -// passed in block operation function and checks the post state with the expected post state. -func RunBlockOperationTest( - t *testing.T, - folderPath string, - body *ethpb.BeaconBlockBody, - operationFn blockOperation, -) { - preBeaconStateFile, err := util.BazelFileBytes(path.Join(folderPath, "pre.ssz_snappy")) - require.NoError(t, err) - preBeaconStateSSZ, err := snappy.Decode(nil /* dst */, preBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - preStateBase := ðpb.BeaconState{} - if err := preStateBase.UnmarshalSSZ(preBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) - } - preState, err := state_native.InitializeFromProtoPhase0(preStateBase) - require.NoError(t, err) - - // If the post.ssz is not present, it means the test should fail on our end. - postSSZFilepath, err := bazel.Runfile(path.Join(folderPath, "post.ssz_snappy")) - postSSZExists := true - if err != nil && strings.Contains(err.Error(), "could not locate file") { - postSSZExists = false - } else if err != nil { - t.Fatal(err) +func sszToState(b []byte) (state.BeaconState, error) { + base := ðpb.BeaconState{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return state_native.InitializeFromProtoPhase0(base) +} - helpers.ClearCache() - b := util.NewBeaconBlock() - b.Block.Body = body - wsb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(t, err) - beaconState, err := operationFn(context.Background(), preState, wsb) - if postSSZExists { - require.NoError(t, err) - - postBeaconStateFile, err := os.ReadFile(postSSZFilepath) // #nosec G304 - require.NoError(t, err) - postBeaconStateSSZ, err := snappy.Decode(nil /* dst */, postBeaconStateFile) - require.NoError(t, err, "Failed to decompress") - - postBeaconState := ðpb.BeaconState{} - if err := postBeaconState.UnmarshalSSZ(postBeaconStateSSZ); err != nil { - t.Fatalf("Failed to unmarshal: %v", err) - } - pbState, err := state_native.ProtobufBeaconStatePhase0(beaconState.ToProtoUnsafe()) - require.NoError(t, err) - if !proto.Equal(pbState, postBeaconState) { - t.Log(cmp.Diff(postBeaconState, pbState, protocmp.Transform())) - t.Fatal("Post state does not match expected") - } - } else { - // Note: This doesn't test anything worthwhile. It essentially tests - // that *any* error has occurred, not any specific error. - if err == nil { - t.Fatal("Did not fail when expected") - } - t.Logf("Expected failure; failure reason = %v", err) - return +func sszToBlock(b []byte) (interfaces.SignedBeaconBlock, error) { + base := ðpb.BeaconBlock{} + if err := base.UnmarshalSSZ(b); err != nil { + return nil, err } + return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlock{Block: base}) } diff --git a/testing/spectest/shared/phase0/operations/proposer_slashing.go b/testing/spectest/shared/phase0/operations/proposer_slashing.go index 5c862fbbee74..3511e1e5d216 100644 --- a/testing/spectest/shared/phase0/operations/proposer_slashing.go +++ b/testing/spectest/shared/phase0/operations/proposer_slashing.go @@ -1,42 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - v "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/validators" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -// RunProposerSlashingTest executes "operations/proposer_slashing" tests. -func RunProposerSlashingTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "phase0", "operations/proposer_slashing/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "phase0", "operations/proposer_slashing/pyspec_tests") +func blockWithProposerSlashing(ssz []byte) (interfaces.SignedBeaconBlock, error) { + ps := ðpb.ProposerSlashing{} + if err := ps.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - proposerSlashingFile, err := util.BazelFileBytes(folderPath, "proposer_slashing.ssz_snappy") - require.NoError(t, err) - proposerSlashingSSZ, err := snappy.Decode(nil /* dst */, proposerSlashingFile) - require.NoError(t, err, "Failed to decompress") - proposerSlashing := ðpb.ProposerSlashing{} - require.NoError(t, proposerSlashing.UnmarshalSSZ(proposerSlashingSSZ), "Failed to unmarshal") + b := util.NewBeaconBlock() + b.Block.Body = ðpb.BeaconBlockBody{ProposerSlashings: []*ethpb.ProposerSlashing{ps}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBody{ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessProposerSlashings(ctx, s, b.Block().Body().ProposerSlashings(), v.SlashValidator) - }) - }) - } +func RunProposerSlashingTest(t *testing.T, config string) { + common.RunProposerSlashingTest(t, config, version.String(version.Phase0), blockWithProposerSlashing, sszToState) } diff --git a/testing/spectest/shared/phase0/operations/voluntary_exit.go b/testing/spectest/shared/phase0/operations/voluntary_exit.go index 30a5b8e976d6..4f42065d783c 100644 --- a/testing/spectest/shared/phase0/operations/voluntary_exit.go +++ b/testing/spectest/shared/phase0/operations/voluntary_exit.go @@ -1,41 +1,26 @@ package operations import ( - "context" - "path" "testing" - "github.com/golang/snappy" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks" - "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/testing/spectest/utils" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + common "github.com/prysmaticlabs/prysm/v5/testing/spectest/shared/common/operations" "github.com/prysmaticlabs/prysm/v5/testing/util" ) -// RunVoluntaryExitTest executes "operations/voluntary_exit" tests. -func RunVoluntaryExitTest(t *testing.T, config string) { - require.NoError(t, utils.SetConfig(t, config)) - testFolders, testsFolderPath := utils.TestFolders(t, config, "phase0", "operations/voluntary_exit/pyspec_tests") - if len(testFolders) == 0 { - t.Fatalf("No test folders found for %s/%s/%s", config, "phase0", "operations/voluntary_exit/pyspec_tests") +func blockWithVoluntaryExit(ssz []byte) (interfaces.SignedBeaconBlock, error) { + e := ðpb.SignedVoluntaryExit{} + if err := e.UnmarshalSSZ(ssz); err != nil { + return nil, err } - for _, folder := range testFolders { - t.Run(folder.Name(), func(t *testing.T) { - folderPath := path.Join(testsFolderPath, folder.Name()) - exitFile, err := util.BazelFileBytes(folderPath, "voluntary_exit.ssz_snappy") - require.NoError(t, err) - exitSSZ, err := snappy.Decode(nil /* dst */, exitFile) - require.NoError(t, err, "Failed to decompress") - voluntaryExit := ðpb.SignedVoluntaryExit{} - require.NoError(t, voluntaryExit.UnmarshalSSZ(exitSSZ), "Failed to unmarshal") + b := util.NewBeaconBlock() + b.Block.Body = ðpb.BeaconBlockBody{VoluntaryExits: []*ethpb.SignedVoluntaryExit{e}} + return blocks.NewSignedBeaconBlock(b) +} - body := ðpb.BeaconBlockBody{VoluntaryExits: []*ethpb.SignedVoluntaryExit{voluntaryExit}} - RunBlockOperationTest(t, folderPath, body, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) { - return blocks.ProcessVoluntaryExits(ctx, s, b.Block().Body().VoluntaryExits()) - }) - }) - } +func RunVoluntaryExitTest(t *testing.T, config string) { + common.RunVoluntaryExitTest(t, config, version.String(version.Phase0), blockWithVoluntaryExit, sszToState) } diff --git a/testing/util/BUILD.bazel b/testing/util/BUILD.bazel index 8456b8d17824..1ecd6a009cf3 100644 --- a/testing/util/BUILD.bazel +++ b/testing/util/BUILD.bazel @@ -20,6 +20,8 @@ go_library( "electra_block.go", "electra_state.go", "helpers.go", + "lightclient.go", + "logging.go", "merge.go", "state.go", "sync_aggregate.go", @@ -42,6 +44,7 @@ go_library( "//beacon-chain/state/stateutil:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", + "//consensus-types:go_default_library", "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", @@ -50,22 +53,25 @@ go_library( "//crypto/hash:go_default_library", "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", + "//encoding/ssz:go_default_library", "//network/forks:go_default_library", "//proto/engine/v1:go_default_library", "//proto/eth/v1:go_default_library", - "//proto/eth/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/interop:go_default_library", "//runtime/version:go_default_library", "//testing/assertions:go_default_library", "//testing/require:go_default_library", "//time/slots:go_default_library", + "@com_github_consensys_gnark_crypto//ecc/bls12-381/fr:go_default_library", + "@com_github_crate_crypto_go_kzg_4844//:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", + "@com_github_sirupsen_logrus//hooks/test:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", ], ) @@ -80,6 +86,7 @@ go_test( "deneb_test.go", "deposits_test.go", "helpers_test.go", + "logging_test.go", "state_test.go", ], embed = [":go_default_library"], @@ -98,11 +105,12 @@ go_test( "//encoding/bytesutil:go_default_library", "//encoding/ssz:go_default_library", "//proto/eth/v1:go_default_library", - "//proto/eth/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//time/slots:go_default_library", + "@com_github_pkg_errors//:go_default_library", + "@com_github_sirupsen_logrus//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/testing/util/attestation.go b/testing/util/attestation.go index b0a79d727569..5cdab0231e76 100644 --- a/testing/util/attestation.go +++ b/testing/util/attestation.go @@ -145,6 +145,16 @@ func GenerateAttestations(bState state.BeaconState, privs []bls.SecretKey, numTo return nil, err } headState = genState + case version.Fulu: + pbState, err := state_native.ProtobufBeaconStateFulu(bState.ToProto()) + if err != nil { + return nil, err + } + genState, err := state_native.InitializeFromProtoUnsafeFulu(pbState) + if err != nil { + return nil, err + } + headState = genState default: return nil, fmt.Errorf("state version %s isn't supported", version.String(bState.Version())) } @@ -311,6 +321,17 @@ func HydrateAttestationElectra(a *ethpb.AttestationElectra) *ethpb.AttestationEl return a } +func HydrateSingleAttestation(a *ethpb.SingleAttestation) *ethpb.SingleAttestation { + if a.Signature == nil { + a.Signature = make([]byte, 96) + } + if a.Data == nil { + a.Data = ðpb.AttestationData{} + } + a.Data = HydrateAttestationData(a.Data) + return a +} + // HydrateV1Attestation hydrates a v1 attestation object with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. func HydrateV1Attestation(a *attv1.Attestation) *attv1.Attestation { @@ -381,3 +402,16 @@ func HydrateIndexedAttestation(a *ethpb.IndexedAttestation) *ethpb.IndexedAttest a.Data = HydrateAttestationData(a.Data) return a } + +// HydrateIndexedAttestationElectra hydrates an indexed attestation with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateIndexedAttestationElectra(a *ethpb.IndexedAttestationElectra) *ethpb.IndexedAttestationElectra { + if a.Signature == nil { + a.Signature = make([]byte, 96) + } + if a.Data == nil { + a.Data = ðpb.AttestationData{} + } + a.Data = HydrateAttestationData(a.Data) + return a +} diff --git a/testing/util/block.go b/testing/util/block.go index 80a897f829fe..51de7fe3cfd7 100644 --- a/testing/util/block.go +++ b/testing/util/block.go @@ -2,8 +2,11 @@ package util import ( "context" + rd "crypto/rand" "fmt" + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" @@ -20,7 +23,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" v1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - v2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assertions" @@ -30,30 +32,42 @@ import ( // BlockGenConfig is used to define the requested conditions // for block generation. type BlockGenConfig struct { - NumProposerSlashings uint64 - NumAttesterSlashings uint64 - NumAttestations uint64 - NumDeposits uint64 - NumVoluntaryExits uint64 - NumTransactions uint64 // Only for post Bellatrix blocks - FullSyncAggregate bool - NumBLSChanges uint64 // Only for post Capella blocks + NumProposerSlashings uint64 + NumAttesterSlashings uint64 + NumAttestations uint64 + NumDeposits uint64 + NumVoluntaryExits uint64 + NumTransactions uint64 // Only for post Bellatrix blocks + FullSyncAggregate bool + NumBLSChanges uint64 // Only for post Capella blocks + NumWithdrawals uint64 + NumDepositRequests uint64 // Only for post Electra blocks + NumWithdrawalRequests uint64 // Only for post Electra blocks + NumConsolidationRequests uint64 // Only for post Electra blocks } // DefaultBlockGenConfig returns the block config that utilizes the // current params in the beacon config. func DefaultBlockGenConfig() *BlockGenConfig { return &BlockGenConfig{ - NumProposerSlashings: 0, - NumAttesterSlashings: 0, - NumAttestations: 1, - NumDeposits: 0, - NumVoluntaryExits: 0, - NumTransactions: 0, - NumBLSChanges: 0, + NumProposerSlashings: 0, + NumAttesterSlashings: 0, + NumAttestations: 1, + NumDeposits: 0, + NumVoluntaryExits: 0, + NumTransactions: 0, + NumBLSChanges: 0, + NumWithdrawals: 0, + NumConsolidationRequests: 0, + NumWithdrawalRequests: 0, + NumDepositRequests: 0, } } +// ---------------------------------------------------------------------------- +// Phase 0 +// ---------------------------------------------------------------------------- + // NewBeaconBlock creates a beacon block with minimum marshalable fields. func NewBeaconBlock() *ethpb.SignedBeaconBlock { return ðpb.SignedBeaconBlock{ @@ -609,125 +623,16 @@ func HydrateV1BeaconBlockBody(b *v1.BeaconBlockBody) *v1.BeaconBlockBody { return b } -// HydrateV2AltairSignedBeaconBlock hydrates a signed beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2AltairSignedBeaconBlock(b *v2.SignedBeaconBlockAltair) *v2.SignedBeaconBlockAltair { - if b.Signature == nil { - b.Signature = make([]byte, fieldparams.BLSSignatureLength) - } - b.Message = HydrateV2AltairBeaconBlock(b.Message) - return b -} - -// HydrateV2AltairBeaconBlock hydrates a beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2AltairBeaconBlock(b *v2.BeaconBlockAltair) *v2.BeaconBlockAltair { - if b == nil { - b = &v2.BeaconBlockAltair{} - } - if b.ParentRoot == nil { - b.ParentRoot = make([]byte, fieldparams.RootLength) - } - if b.StateRoot == nil { - b.StateRoot = make([]byte, fieldparams.RootLength) - } - b.Body = HydrateV2AltairBeaconBlockBody(b.Body) - return b -} - -// HydrateV2AltairBeaconBlockBody hydrates a beacon block body with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2AltairBeaconBlockBody(b *v2.BeaconBlockBodyAltair) *v2.BeaconBlockBodyAltair { - if b == nil { - b = &v2.BeaconBlockBodyAltair{} - } - if b.RandaoReveal == nil { - b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) - } - if b.Graffiti == nil { - b.Graffiti = make([]byte, fieldparams.RootLength) - } - if b.Eth1Data == nil { - b.Eth1Data = &v1.Eth1Data{ - DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - } - } - if b.SyncAggregate == nil { - b.SyncAggregate = &v1.SyncAggregate{ - SyncCommitteeBits: make([]byte, 64), - SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), - } - } - return b -} - -// HydrateV2BellatrixSignedBeaconBlock hydrates a signed beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BellatrixSignedBeaconBlock(b *v2.SignedBeaconBlockBellatrix) *v2.SignedBeaconBlockBellatrix { - if b.Signature == nil { - b.Signature = make([]byte, fieldparams.BLSSignatureLength) - } - b.Message = HydrateV2BellatrixBeaconBlock(b.Message) - return b -} - -// HydrateV2BellatrixBeaconBlock hydrates a beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BellatrixBeaconBlock(b *v2.BeaconBlockBellatrix) *v2.BeaconBlockBellatrix { - if b == nil { - b = &v2.BeaconBlockBellatrix{} - } - if b.ParentRoot == nil { - b.ParentRoot = make([]byte, fieldparams.RootLength) - } - if b.StateRoot == nil { - b.StateRoot = make([]byte, fieldparams.RootLength) - } - b.Body = HydrateV2BellatrixBeaconBlockBody(b.Body) - return b +func SaveBlock(tb assertions.AssertionTestingTB, ctx context.Context, db iface.NoHeadAccessDatabase, b interface{}) interfaces.SignedBeaconBlock { + wsb, err := blocks.NewSignedBeaconBlock(b) + require.NoError(tb, err) + require.NoError(tb, db.SaveBlock(ctx, wsb)) + return wsb } -// HydrateV2BellatrixBeaconBlockBody hydrates a beacon block body with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BellatrixBeaconBlockBody(b *v2.BeaconBlockBodyBellatrix) *v2.BeaconBlockBodyBellatrix { - if b == nil { - b = &v2.BeaconBlockBodyBellatrix{} - } - if b.RandaoReveal == nil { - b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) - } - if b.Graffiti == nil { - b.Graffiti = make([]byte, fieldparams.RootLength) - } - if b.Eth1Data == nil { - b.Eth1Data = &v1.Eth1Data{ - DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - } - } - if b.SyncAggregate == nil { - b.SyncAggregate = &v1.SyncAggregate{ - SyncCommitteeBits: make([]byte, 64), - SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), - } - } - if b.ExecutionPayload == nil { - b.ExecutionPayload = &enginev1.ExecutionPayload{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - Transactions: make([][]byte, 0), - } - } - return b -} +// ---------------------------------------------------------------------------- +// Altair +// ---------------------------------------------------------------------------- // HydrateSignedBeaconBlockAltair hydrates a signed beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. @@ -782,6 +687,10 @@ func HydrateBeaconBlockBodyAltair(b *ethpb.BeaconBlockBodyAltair) *ethpb.BeaconB return b } +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + // HydrateSignedBeaconBlockBellatrix hydrates a signed beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. func HydrateSignedBeaconBlockBellatrix(b *ethpb.SignedBeaconBlockBellatrix) *ethpb.SignedBeaconBlockBellatrix { @@ -916,72 +825,9 @@ func HydrateBlindedBeaconBlockBodyBellatrix(b *ethpb.BlindedBeaconBlockBodyBella return b } -// HydrateV2SignedBlindedBeaconBlockBellatrix hydrates a signed blinded beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2SignedBlindedBeaconBlockBellatrix(b *v2.SignedBlindedBeaconBlockBellatrix) *v2.SignedBlindedBeaconBlockBellatrix { - if b.Signature == nil { - b.Signature = make([]byte, fieldparams.BLSSignatureLength) - } - b.Message = HydrateV2BlindedBeaconBlockBellatrix(b.Message) - return b -} - -// HydrateV2BlindedBeaconBlockBellatrix hydrates a blinded beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BlindedBeaconBlockBellatrix(b *v2.BlindedBeaconBlockBellatrix) *v2.BlindedBeaconBlockBellatrix { - if b == nil { - b = &v2.BlindedBeaconBlockBellatrix{} - } - if b.ParentRoot == nil { - b.ParentRoot = make([]byte, fieldparams.RootLength) - } - if b.StateRoot == nil { - b.StateRoot = make([]byte, fieldparams.RootLength) - } - b.Body = HydrateV2BlindedBeaconBlockBodyBellatrix(b.Body) - return b -} - -// HydrateV2BlindedBeaconBlockBodyBellatrix hydrates a blinded beacon block body with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BlindedBeaconBlockBodyBellatrix(b *v2.BlindedBeaconBlockBodyBellatrix) *v2.BlindedBeaconBlockBodyBellatrix { - if b == nil { - b = &v2.BlindedBeaconBlockBodyBellatrix{} - } - if b.RandaoReveal == nil { - b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) - } - if b.Graffiti == nil { - b.Graffiti = make([]byte, 32) - } - if b.Eth1Data == nil { - b.Eth1Data = &v1.Eth1Data{ - DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, 32), - } - } - if b.SyncAggregate == nil { - b.SyncAggregate = &v1.SyncAggregate{ - SyncCommitteeBits: make([]byte, 64), - SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), - } - } - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = &enginev1.ExecutionPayloadHeader{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, 32), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, fieldparams.RootLength), - } - } - return b -} +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- // HydrateSignedBeaconBlockCapella hydrates a signed beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. @@ -1119,80 +965,9 @@ func HydrateBlindedBeaconBlockBodyCapella(b *ethpb.BlindedBeaconBlockBodyCapella return b } -// HydrateV2SignedBlindedBeaconBlockCapella hydrates a signed blinded beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2SignedBlindedBeaconBlockCapella(b *v2.SignedBlindedBeaconBlockCapella) *v2.SignedBlindedBeaconBlockCapella { - if b.Signature == nil { - b.Signature = make([]byte, fieldparams.BLSSignatureLength) - } - b.Message = HydrateV2BlindedBeaconBlockCapella(b.Message) - return b -} - -// HydrateV2BlindedBeaconBlockCapella hydrates a blinded beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BlindedBeaconBlockCapella(b *v2.BlindedBeaconBlockCapella) *v2.BlindedBeaconBlockCapella { - if b == nil { - b = &v2.BlindedBeaconBlockCapella{} - } - if b.ParentRoot == nil { - b.ParentRoot = make([]byte, fieldparams.RootLength) - } - if b.StateRoot == nil { - b.StateRoot = make([]byte, fieldparams.RootLength) - } - b.Body = HydrateV2BlindedBeaconBlockBodyCapella(b.Body) - return b -} - -// HydrateV2BlindedBeaconBlockBodyCapella hydrates a blinded beacon block body with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BlindedBeaconBlockBodyCapella(b *v2.BlindedBeaconBlockBodyCapella) *v2.BlindedBeaconBlockBodyCapella { - if b == nil { - b = &v2.BlindedBeaconBlockBodyCapella{} - } - if b.RandaoReveal == nil { - b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) - } - if b.Graffiti == nil { - b.Graffiti = make([]byte, 32) - } - if b.Eth1Data == nil { - b.Eth1Data = &v1.Eth1Data{ - DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, 32), - } - } - if b.SyncAggregate == nil { - b.SyncAggregate = &v1.SyncAggregate{ - SyncCommitteeBits: make([]byte, 64), - SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), - } - } - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = &enginev1.ExecutionPayloadHeaderCapella{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, 32), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, fieldparams.RootLength), - WithdrawalsRoot: make([]byte, fieldparams.RootLength), - } - } - return b -} - -func SaveBlock(tb assertions.AssertionTestingTB, ctx context.Context, db iface.NoHeadAccessDatabase, b interface{}) interfaces.SignedBeaconBlock { - wsb, err := blocks.NewSignedBeaconBlock(b) - require.NoError(tb, err) - require.NoError(tb, db.SaveBlock(ctx, wsb)) - return wsb -} +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- // HydrateSignedBeaconBlockDeneb hydrates a signed beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. @@ -1207,19 +982,6 @@ func HydrateSignedBeaconBlockDeneb(b *ethpb.SignedBeaconBlockDeneb) *ethpb.Signe return b } -// HydrateSignedBeaconBlockElectra hydrates a signed beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateSignedBeaconBlockElectra(b *ethpb.SignedBeaconBlockElectra) *ethpb.SignedBeaconBlockElectra { - if b == nil { - b = ðpb.SignedBeaconBlockElectra{} - } - if b.Signature == nil { - b.Signature = make([]byte, fieldparams.BLSSignatureLength) - } - b.Block = HydrateBeaconBlockElectra(b.Block) - return b -} - // HydrateSignedBeaconBlockContentsDeneb hydrates a signed beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. func HydrateSignedBeaconBlockContentsDeneb(b *ethpb.SignedBeaconBlockContentsDeneb) *ethpb.SignedBeaconBlockContentsDeneb { @@ -1227,23 +989,6 @@ func HydrateSignedBeaconBlockContentsDeneb(b *ethpb.SignedBeaconBlockContentsDen return b } -// HydrateSignedBeaconBlockContentsElectra hydrates a signed beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateSignedBeaconBlockContentsElectra(b *ethpb.SignedBeaconBlockContentsElectra) *ethpb.SignedBeaconBlockContentsElectra { - b.Block = HydrateSignedBeaconBlockElectra(b.Block) - return b -} - -// HydrateV2SignedBeaconBlockDeneb hydrates a v2 signed beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2SignedBeaconBlockDeneb(b *v2.SignedBeaconBlockDeneb) *v2.SignedBeaconBlockDeneb { - if b.Signature == nil { - b.Signature = make([]byte, fieldparams.BLSSignatureLength) - } - b.Message = HydrateV2BeaconBlockDeneb(b.Message) - return b -} - // HydrateBeaconBlockDeneb hydrates a beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. func HydrateBeaconBlockDeneb(b *ethpb.BeaconBlockDeneb) *ethpb.BeaconBlockDeneb { @@ -1260,38 +1005,6 @@ func HydrateBeaconBlockDeneb(b *ethpb.BeaconBlockDeneb) *ethpb.BeaconBlockDeneb return b } -// HydrateBeaconBlockElectra hydrates a beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateBeaconBlockElectra(b *ethpb.BeaconBlockElectra) *ethpb.BeaconBlockElectra { - if b == nil { - b = ðpb.BeaconBlockElectra{} - } - if b.ParentRoot == nil { - b.ParentRoot = make([]byte, fieldparams.RootLength) - } - if b.StateRoot == nil { - b.StateRoot = make([]byte, fieldparams.RootLength) - } - b.Body = HydrateBeaconBlockBodyElectra(b.Body) - return b -} - -// HydrateV2BeaconBlockDeneb hydrates a v2 beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BeaconBlockDeneb(b *v2.BeaconBlockDeneb) *v2.BeaconBlockDeneb { - if b == nil { - b = &v2.BeaconBlockDeneb{} - } - if b.ParentRoot == nil { - b.ParentRoot = make([]byte, fieldparams.RootLength) - } - if b.StateRoot == nil { - b.StateRoot = make([]byte, fieldparams.RootLength) - } - b.Body = HydrateV2BeaconBlockBodyDeneb(b.Body) - return b -} - // HydrateBeaconBlockBodyDeneb hydrates a beacon block body with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. func HydrateBeaconBlockBodyDeneb(b *ethpb.BeaconBlockBodyDeneb) *ethpb.BeaconBlockBodyDeneb { @@ -1334,22 +1047,32 @@ func HydrateBeaconBlockBodyDeneb(b *ethpb.BeaconBlockBodyDeneb) *ethpb.BeaconBlo return b } -// HydrateBeaconBlockBodyElectra hydrates a beacon block body with correct field length sizes +// HydrateSignedBlindedBeaconBlockDeneb hydrates a signed blinded beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. -func HydrateBeaconBlockBodyElectra(b *ethpb.BeaconBlockBodyElectra) *ethpb.BeaconBlockBodyElectra { +func HydrateSignedBlindedBeaconBlockDeneb(b *ethpb.SignedBlindedBeaconBlockDeneb) *ethpb.SignedBlindedBeaconBlockDeneb { + if b.Signature == nil { + b.Signature = make([]byte, fieldparams.BLSSignatureLength) + } + b.Message = HydrateBlindedBeaconBlockDeneb(b.Message) + return b +} + +// HydrateBlindedBeaconBlockBodyDeneb hydrates a blinded beacon block body with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateBlindedBeaconBlockBodyDeneb(b *ethpb.BlindedBeaconBlockBodyDeneb) *ethpb.BlindedBeaconBlockBodyDeneb { if b == nil { - b = ðpb.BeaconBlockBodyElectra{} + b = ðpb.BlindedBeaconBlockBodyDeneb{} } if b.RandaoReveal == nil { b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) } if b.Graffiti == nil { - b.Graffiti = make([]byte, fieldparams.RootLength) + b.Graffiti = make([]byte, 32) } if b.Eth1Data == nil { b.Eth1Data = ðpb.Eth1Data{ DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, 32), } } if b.SyncAggregate == nil { @@ -1358,32 +1081,85 @@ func HydrateBeaconBlockBodyElectra(b *ethpb.BeaconBlockBodyElectra) *ethpb.Beaco SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), } } - if b.ExecutionPayload == nil { - b.ExecutionPayload = &enginev1.ExecutionPayloadElectra{ - ParentHash: make([]byte, fieldparams.RootLength), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, fieldparams.RootLength), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, fieldparams.RootLength), - Transactions: make([][]byte, 0), - Withdrawals: make([]*enginev1.Withdrawal, 0), - DepositRequests: make([]*enginev1.DepositRequest, 0), - WithdrawalRequests: make([]*enginev1.WithdrawalRequest, 0), - ConsolidationRequests: make([]*enginev1.ConsolidationRequest, 0), + if b.ExecutionPayloadHeader == nil { + b.ExecutionPayloadHeader = &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, fieldparams.RootLength), + WithdrawalsRoot: make([]byte, fieldparams.RootLength), } } return b } -// HydrateV2BeaconBlockBodyDeneb hydrates a v2 beacon block body with correct field length sizes +// HydrateBlindedBeaconBlockDeneb hydrates a blinded beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BeaconBlockBodyDeneb(b *v2.BeaconBlockBodyDeneb) *v2.BeaconBlockBodyDeneb { +func HydrateBlindedBeaconBlockDeneb(b *ethpb.BlindedBeaconBlockDeneb) *ethpb.BlindedBeaconBlockDeneb { if b == nil { - b = &v2.BeaconBlockBodyDeneb{} + b = ðpb.BlindedBeaconBlockDeneb{} + } + if b.ParentRoot == nil { + b.ParentRoot = make([]byte, fieldparams.RootLength) + } + if b.StateRoot == nil { + b.StateRoot = make([]byte, fieldparams.RootLength) + } + b.Body = HydrateBlindedBeaconBlockBodyDeneb(b.Body) + return b +} + +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +// HydrateSignedBeaconBlockElectra hydrates a signed beacon block with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateSignedBeaconBlockElectra(b *ethpb.SignedBeaconBlockElectra) *ethpb.SignedBeaconBlockElectra { + if b == nil { + b = ðpb.SignedBeaconBlockElectra{} + } + if b.Signature == nil { + b.Signature = make([]byte, fieldparams.BLSSignatureLength) + } + b.Block = HydrateBeaconBlockElectra(b.Block) + return b +} + +// HydrateSignedBeaconBlockContentsElectra hydrates a signed beacon block with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateSignedBeaconBlockContentsElectra(b *ethpb.SignedBeaconBlockContentsElectra) *ethpb.SignedBeaconBlockContentsElectra { + b.Block = HydrateSignedBeaconBlockElectra(b.Block) + return b +} + +// HydrateBeaconBlockElectra hydrates a beacon block with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateBeaconBlockElectra(b *ethpb.BeaconBlockElectra) *ethpb.BeaconBlockElectra { + if b == nil { + b = ðpb.BeaconBlockElectra{} + } + if b.ParentRoot == nil { + b.ParentRoot = make([]byte, fieldparams.RootLength) + } + if b.StateRoot == nil { + b.StateRoot = make([]byte, fieldparams.RootLength) + } + b.Body = HydrateBeaconBlockBodyElectra(b.Body) + return b +} + +// HydrateBeaconBlockBodyElectra hydrates a beacon block body with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateBeaconBlockBodyElectra(b *ethpb.BeaconBlockBodyElectra) *ethpb.BeaconBlockBodyElectra { + if b == nil { + b = ðpb.BeaconBlockBodyElectra{} } if b.RandaoReveal == nil { b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) @@ -1392,13 +1168,13 @@ func HydrateV2BeaconBlockBodyDeneb(b *v2.BeaconBlockBodyDeneb) *v2.BeaconBlockBo b.Graffiti = make([]byte, fieldparams.RootLength) } if b.Eth1Data == nil { - b.Eth1Data = &v1.Eth1Data{ + b.Eth1Data = ðpb.Eth1Data{ DepositRoot: make([]byte, fieldparams.RootLength), BlockHash: make([]byte, fieldparams.RootLength), } } if b.SyncAggregate == nil { - b.SyncAggregate = &v1.SyncAggregate{ + b.SyncAggregate = ðpb.SyncAggregate{ SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength), SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), } @@ -1418,17 +1194,26 @@ func HydrateV2BeaconBlockBodyDeneb(b *v2.BeaconBlockBodyDeneb) *v2.BeaconBlockBo Withdrawals: make([]*enginev1.Withdrawal, 0), } } + b.ExecutionRequests = HydrateExecutionRequests(b.ExecutionRequests) return b } -// HydrateSignedBlindedBeaconBlockDeneb hydrates a signed blinded beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateSignedBlindedBeaconBlockDeneb(b *ethpb.SignedBlindedBeaconBlockDeneb) *ethpb.SignedBlindedBeaconBlockDeneb { - if b.Signature == nil { - b.Signature = make([]byte, fieldparams.BLSSignatureLength) +// HydrateExecutionRequests fills the execution requests with the correct field +// lengths +func HydrateExecutionRequests(e *enginev1.ExecutionRequests) *enginev1.ExecutionRequests { + if e == nil { + e = &enginev1.ExecutionRequests{} } - b.Message = HydrateBlindedBeaconBlockDeneb(b.Message) - return b + if e.Deposits == nil { + e.Deposits = make([]*enginev1.DepositRequest, 0) + } + if e.Withdrawals == nil { + e.Withdrawals = make([]*enginev1.WithdrawalRequest, 0) + } + if e.Consolidations == nil { + e.Consolidations = make([]*enginev1.ConsolidationRequest, 0) + } + return e } // HydrateSignedBlindedBeaconBlockElectra hydrates a signed blinded beacon block with correct field length sizes @@ -1441,32 +1226,6 @@ func HydrateSignedBlindedBeaconBlockElectra(b *ethpb.SignedBlindedBeaconBlockEle return b } -// HydrateV2SignedBlindedBeaconBlockDeneb hydrates a signed v2 blinded beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2SignedBlindedBeaconBlockDeneb(b *v2.SignedBlindedBeaconBlockDeneb) *v2.SignedBlindedBeaconBlockDeneb { - if b.Signature == nil { - b.Signature = make([]byte, fieldparams.BLSSignatureLength) - } - b.Message = HydrateV2BlindedBeaconBlockDeneb(b.Message) - return b -} - -// HydrateBlindedBeaconBlockDeneb hydrates a blinded beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateBlindedBeaconBlockDeneb(b *ethpb.BlindedBeaconBlockDeneb) *ethpb.BlindedBeaconBlockDeneb { - if b == nil { - b = ðpb.BlindedBeaconBlockDeneb{} - } - if b.ParentRoot == nil { - b.ParentRoot = make([]byte, fieldparams.RootLength) - } - if b.StateRoot == nil { - b.StateRoot = make([]byte, fieldparams.RootLength) - } - b.Body = HydrateBlindedBeaconBlockBodyDeneb(b.Body) - return b -} - // HydrateBlindedBeaconBlockElectra hydrates a blinded beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. func HydrateBlindedBeaconBlockElectra(b *ethpb.BlindedBeaconBlockElectra) *ethpb.BlindedBeaconBlockElectra { @@ -1483,27 +1242,11 @@ func HydrateBlindedBeaconBlockElectra(b *ethpb.BlindedBeaconBlockElectra) *ethpb return b } -// HydrateV2BlindedBeaconBlockDeneb hydrates a v2 blinded beacon block with correct field length sizes -// to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BlindedBeaconBlockDeneb(b *v2.BlindedBeaconBlockDeneb) *v2.BlindedBeaconBlockDeneb { - if b == nil { - b = &v2.BlindedBeaconBlockDeneb{} - } - if b.ParentRoot == nil { - b.ParentRoot = make([]byte, fieldparams.RootLength) - } - if b.StateRoot == nil { - b.StateRoot = make([]byte, fieldparams.RootLength) - } - b.Body = HydrateV2BlindedBeaconBlockBodyDeneb(b.Body) - return b -} - -// HydrateBlindedBeaconBlockBodyDeneb hydrates a blinded beacon block body with correct field length sizes +// HydrateBlindedBeaconBlockBodyElectra hydrates a blinded beacon block body with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. -func HydrateBlindedBeaconBlockBodyDeneb(b *ethpb.BlindedBeaconBlockBodyDeneb) *ethpb.BlindedBeaconBlockBodyDeneb { +func HydrateBlindedBeaconBlockBodyElectra(b *ethpb.BlindedBeaconBlockBodyElectra) *ethpb.BlindedBeaconBlockBodyElectra { if b == nil { - b = ðpb.BlindedBeaconBlockBodyDeneb{} + b = ðpb.BlindedBeaconBlockBodyElectra{} } if b.RandaoReveal == nil { b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) @@ -1538,25 +1281,101 @@ func HydrateBlindedBeaconBlockBodyDeneb(b *ethpb.BlindedBeaconBlockBodyDeneb) *e WithdrawalsRoot: make([]byte, fieldparams.RootLength), } } + b.ExecutionRequests = HydrateExecutionRequests(b.ExecutionRequests) return b } -// HydrateBlindedBeaconBlockBodyElectra hydrates a blinded beacon block body with correct field length sizes +func generateWithdrawals( + bState state.BeaconState, + privs []bls.SecretKey, + numWithdrawals uint64, +) ([]*enginev1.Withdrawal, error) { + withdrawalRequests := make([]*enginev1.Withdrawal, numWithdrawals) + for i := uint64(0); i < numWithdrawals; i++ { + valIndex, err := randValIndex(bState) + if err != nil { + return nil, err + } + amount := uint64(10000) + bal, err := bState.BalanceAtIndex(valIndex) + if err != nil { + return nil, err + } + amounts := []uint64{ + amount, // some smaller amount + bal, // the entire balance + } + // Get a random index + nBig, err := rd.Int(rd.Reader, big.NewInt(int64(len(amounts)))) + if err != nil { + return nil, err + } + randomIndex := nBig.Uint64() + withdrawalRequests[i] = &enginev1.Withdrawal{ + ValidatorIndex: valIndex, + Address: make([]byte, common.AddressLength), + Amount: amounts[randomIndex], + } + } + return withdrawalRequests, nil +} + +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +// HydrateSignedBeaconBlockFulu hydrates a signed beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. -func HydrateBlindedBeaconBlockBodyElectra(b *ethpb.BlindedBeaconBlockBodyElectra) *ethpb.BlindedBeaconBlockBodyElectra { +func HydrateSignedBeaconBlockFulu(b *ethpb.SignedBeaconBlockFulu) *ethpb.SignedBeaconBlockFulu { if b == nil { - b = ðpb.BlindedBeaconBlockBodyElectra{} + b = ðpb.SignedBeaconBlockFulu{} + } + if b.Signature == nil { + b.Signature = make([]byte, fieldparams.BLSSignatureLength) + } + b.Block = HydrateBeaconBlockFulu(b.Block) + return b +} + +// HydrateSignedBeaconBlockContentsFulu hydrates a signed beacon block with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateSignedBeaconBlockContentsFulu(b *ethpb.SignedBeaconBlockContentsFulu) *ethpb.SignedBeaconBlockContentsFulu { + b.Block = HydrateSignedBeaconBlockFulu(b.Block) + return b +} + +// HydrateBeaconBlockFulu hydrates a beacon block with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateBeaconBlockFulu(b *ethpb.BeaconBlockElectra) *ethpb.BeaconBlockElectra { + if b == nil { + b = ðpb.BeaconBlockElectra{} + } + if b.ParentRoot == nil { + b.ParentRoot = make([]byte, fieldparams.RootLength) + } + if b.StateRoot == nil { + b.StateRoot = make([]byte, fieldparams.RootLength) + } + b.Body = HydrateBeaconBlockBodyFulu(b.Body) + return b +} + +// HydrateBeaconBlockBodyFulu hydrates a beacon block body with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateBeaconBlockBodyFulu(b *ethpb.BeaconBlockBodyElectra) *ethpb.BeaconBlockBodyElectra { + if b == nil { + b = ðpb.BeaconBlockBodyElectra{} } if b.RandaoReveal == nil { b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) } if b.Graffiti == nil { - b.Graffiti = make([]byte, 32) + b.Graffiti = make([]byte, fieldparams.RootLength) } if b.Eth1Data == nil { b.Eth1Data = ðpb.Eth1Data{ DepositRoot: make([]byte, fieldparams.RootLength), - BlockHash: make([]byte, 32), + BlockHash: make([]byte, fieldparams.RootLength), } } if b.SyncAggregate == nil { @@ -1565,32 +1384,56 @@ func HydrateBlindedBeaconBlockBodyElectra(b *ethpb.BlindedBeaconBlockBodyElectra SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), } } - if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = &enginev1.ExecutionPayloadHeaderElectra{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, fieldparams.RootLength), - ReceiptsRoot: make([]byte, fieldparams.RootLength), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, 32), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, fieldparams.RootLength), - WithdrawalsRoot: make([]byte, fieldparams.RootLength), - WithdrawalRequestsRoot: make([]byte, fieldparams.RootLength), - DepositRequestsRoot: make([]byte, fieldparams.RootLength), - ConsolidationRequestsRoot: make([]byte, fieldparams.RootLength), + if b.ExecutionPayload == nil { + b.ExecutionPayload = &enginev1.ExecutionPayloadDeneb{ + ParentHash: make([]byte, fieldparams.RootLength), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, fieldparams.RootLength), + ReceiptsRoot: make([]byte, fieldparams.RootLength), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, fieldparams.RootLength), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, fieldparams.RootLength), + Transactions: make([][]byte, 0), + Withdrawals: make([]*enginev1.Withdrawal, 0), } } + b.ExecutionRequests = HydrateExecutionRequests(b.ExecutionRequests) return b } -// HydrateV2BlindedBeaconBlockBodyDeneb hydrates a blinded v2 beacon block body with correct field length sizes +// HydrateSignedBlindedBeaconBlockFulu hydrates a signed blinded beacon block with correct field length sizes // to comply with fssz marshalling and unmarshalling rules. -func HydrateV2BlindedBeaconBlockBodyDeneb(b *v2.BlindedBeaconBlockBodyDeneb) *v2.BlindedBeaconBlockBodyDeneb { +func HydrateSignedBlindedBeaconBlockFulu(b *ethpb.SignedBlindedBeaconBlockFulu) *ethpb.SignedBlindedBeaconBlockFulu { + if b.Signature == nil { + b.Signature = make([]byte, fieldparams.BLSSignatureLength) + } + b.Message = HydrateBlindedBeaconBlockFulu(b.Message) + return b +} + +// HydrateBlindedBeaconBlockFulu hydrates a blinded beacon block with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateBlindedBeaconBlockFulu(b *ethpb.BlindedBeaconBlockFulu) *ethpb.BlindedBeaconBlockFulu { if b == nil { - b = &v2.BlindedBeaconBlockBodyDeneb{} + b = ðpb.BlindedBeaconBlockFulu{} + } + if b.ParentRoot == nil { + b.ParentRoot = make([]byte, fieldparams.RootLength) + } + if b.StateRoot == nil { + b.StateRoot = make([]byte, fieldparams.RootLength) + } + b.Body = HydrateBlindedBeaconBlockBodyFulu(b.Body) + return b +} + +// HydrateBlindedBeaconBlockBodyFulu hydrates a blinded beacon block body with correct field length sizes +// to comply with fssz marshalling and unmarshalling rules. +func HydrateBlindedBeaconBlockBodyFulu(b *ethpb.BlindedBeaconBlockBodyElectra) *ethpb.BlindedBeaconBlockBodyElectra { + if b == nil { + b = ðpb.BlindedBeaconBlockBodyElectra{} } if b.RandaoReveal == nil { b.RandaoReveal = make([]byte, fieldparams.BLSSignatureLength) @@ -1599,13 +1442,13 @@ func HydrateV2BlindedBeaconBlockBodyDeneb(b *v2.BlindedBeaconBlockBodyDeneb) *v2 b.Graffiti = make([]byte, 32) } if b.Eth1Data == nil { - b.Eth1Data = &v1.Eth1Data{ + b.Eth1Data = ðpb.Eth1Data{ DepositRoot: make([]byte, fieldparams.RootLength), BlockHash: make([]byte, 32), } } if b.SyncAggregate == nil { - b.SyncAggregate = &v1.SyncAggregate{ + b.SyncAggregate = ðpb.SyncAggregate{ SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength), SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), } @@ -1625,5 +1468,6 @@ func HydrateV2BlindedBeaconBlockBodyDeneb(b *v2.BlindedBeaconBlockBodyDeneb) *v2 WithdrawalsRoot: make([]byte, fieldparams.RootLength), } } + b.ExecutionRequests = HydrateExecutionRequests(b.ExecutionRequests) return b } diff --git a/testing/util/block_test.go b/testing/util/block_test.go index 09b1e27c55c9..77e2872af99f 100644 --- a/testing/util/block_test.go +++ b/testing/util/block_test.go @@ -13,7 +13,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpbv1 "github.com/prysmaticlabs/prysm/v5/proto/eth/v1" - ethpbv2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" ethpbalpha "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" ) @@ -216,28 +215,6 @@ func TestHydrateV1SignedBeaconBlock_NoError(t *testing.T) { require.NoError(t, err) } -func TestHydrateV2AltairSignedBeaconBlock_NoError(t *testing.T) { - b := ðpbv2.SignedBeaconBlockAltair{} - b = HydrateV2AltairSignedBeaconBlock(b) - _, err := b.HashTreeRoot() - require.NoError(t, err) - _, err = b.Message.HashTreeRoot() - require.NoError(t, err) - _, err = b.Message.Body.HashTreeRoot() - require.NoError(t, err) -} - -func TestHydrateV2BellatrixSignedBeaconBlock_NoError(t *testing.T) { - b := ðpbv2.SignedBeaconBlockBellatrix{} - b = HydrateV2BellatrixSignedBeaconBlock(b) - _, err := b.HashTreeRoot() - require.NoError(t, err) - _, err = b.Message.HashTreeRoot() - require.NoError(t, err) - _, err = b.Message.Body.HashTreeRoot() - require.NoError(t, err) -} - func TestHydrateSignedBeaconBlockAltair_NoError(t *testing.T) { b := ðpbalpha.SignedBeaconBlockAltair{} b = HydrateSignedBeaconBlockAltair(b) @@ -278,33 +255,6 @@ func TestHydrateBlindedBeaconBlockBodyBellatrix_NoError(t *testing.T) { require.NoError(t, err) } -func TestHydrateV2SignedBlindedBeaconBlockBellatrix_NoError(t *testing.T) { - b := ðpbv2.SignedBlindedBeaconBlockBellatrix{} - b = HydrateV2SignedBlindedBeaconBlockBellatrix(b) - _, err := b.HashTreeRoot() - require.NoError(t, err) - _, err = b.Message.HashTreeRoot() - require.NoError(t, err) - _, err = b.Message.Body.HashTreeRoot() - require.NoError(t, err) -} - -func TestHydrateV2BlindedBeaconBlockBellatrix_NoError(t *testing.T) { - b := ðpbv2.BlindedBeaconBlockBellatrix{} - b = HydrateV2BlindedBeaconBlockBellatrix(b) - _, err := b.HashTreeRoot() - require.NoError(t, err) - _, err = b.Body.HashTreeRoot() - require.NoError(t, err) -} - -func TestHydrateV2BlindedBeaconBlockBodyBellatrix_NoError(t *testing.T) { - b := ðpbv2.BlindedBeaconBlockBodyBellatrix{} - b = HydrateV2BlindedBeaconBlockBodyBellatrix(b) - _, err := b.HashTreeRoot() - require.NoError(t, err) -} - func TestHydrateSignedBeaconBlockCapella_NoError(t *testing.T) { b := ðpbalpha.SignedBeaconBlockCapella{} b = HydrateSignedBeaconBlockCapella(b) @@ -372,3 +322,30 @@ func TestGenerateVoluntaryExits(t *testing.T) { require.NoError(t, err) require.NoError(t, coreBlock.VerifyExitAndSignature(val, beaconState, exit)) } + +func Test_PostDenebPbGenericBlock_ErrorsForPlainBlock(t *testing.T) { + t.Run("Deneb block returns type error", func(t *testing.T) { + eb := NewBeaconBlockDeneb() + b, err := blocks.NewSignedBeaconBlock(eb) + require.NoError(t, err) + + _, err = b.PbGenericBlock() + require.ErrorContains(t, "PbGenericBlock() only supports block content type but got", err) + }) + t.Run("Electra block returns type error", func(t *testing.T) { + eb := NewBeaconBlockElectra() + b, err := blocks.NewSignedBeaconBlock(eb) + require.NoError(t, err) + + _, err = b.PbGenericBlock() + require.ErrorContains(t, "PbGenericBlock() only supports block content type but got", err) + }) + t.Run("Fulu block returns type error", func(t *testing.T) { + eb := NewBeaconBlockFulu() + b, err := blocks.NewSignedBeaconBlock(eb) + require.NoError(t, err) + + _, err = b.PbGenericBlock() + require.ErrorContains(t, "PbGenericBlock() only supports block content type but got", err) + }) +} diff --git a/testing/util/deneb.go b/testing/util/deneb.go index 12a888bf9d11..8899c7e25472 100644 --- a/testing/util/deneb.go +++ b/testing/util/deneb.go @@ -1,10 +1,14 @@ package util import ( + "bytes" + "crypto/sha256" "encoding/binary" "math/big" "testing" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + GoKZG "github.com/crate-crypto/go-kzg-4844" "github.com/ethereum/go-ethereum/common" gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" @@ -19,6 +23,7 @@ import ( ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/time/slots" + "github.com/sirupsen/logrus" ) type DenebBlockGeneratorOption func(*denebBlockGenerator) @@ -197,3 +202,36 @@ func ExtendBlocksPlusBlobs(t *testing.T, blks []blocks.ROBlock, size int) ([]blo return blks, blobs } + +func deterministicRandomness(seed int64) [32]byte { + // Converts an int64 to a byte slice + buf := new(bytes.Buffer) + err := binary.Write(buf, binary.BigEndian, seed) + if err != nil { + logrus.WithError(err).Error("Failed to write int64 to bytes buffer") + return [32]byte{} + } + bytes := buf.Bytes() + + return sha256.Sum256(bytes) +} + +// Returns a serialized random field element in big-endian +func GetRandFieldElement(seed int64) [32]byte { + bytes := deterministicRandomness(seed) + var r fr.Element + r.SetBytes(bytes[:]) + + return GoKZG.SerializeScalar(r) +} + +// Returns a random blob using the passed seed as entropy +func GetRandBlob(seed int64) GoKZG.Blob { + var blob GoKZG.Blob + bytesPerBlob := GoKZG.ScalarsPerBlob * GoKZG.SerializedScalarSize + for i := 0; i < bytesPerBlob; i += GoKZG.SerializedScalarSize { + fieldElementBytes := GetRandFieldElement(seed + int64(i)) + copy(blob[i:i+GoKZG.SerializedScalarSize], fieldElementBytes[:]) + } + return blob +} diff --git a/testing/util/deneb_test.go b/testing/util/deneb_test.go index 87e20db37f1e..7066c8e97bed 100644 --- a/testing/util/deneb_test.go +++ b/testing/util/deneb_test.go @@ -3,13 +3,13 @@ package util import ( "testing" - fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/testing/require" ) func TestInclusionProofs(t *testing.T) { - _, blobs := GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, fieldparams.MaxBlobsPerBlock) + _, blobs := GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, params.BeaconConfig().MaxBlobsPerBlock(0)) for i := range blobs { require.NoError(t, blocks.VerifyKZGInclusionProof(blobs[i])) } diff --git a/testing/util/electra.go b/testing/util/electra.go index dc009427bac1..f37a1da26ac6 100644 --- a/testing/util/electra.go +++ b/testing/util/electra.go @@ -2,7 +2,6 @@ package util import ( "encoding/binary" - "math" "math/big" "testing" @@ -21,22 +20,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/time/slots" ) -// HackElectraMaxuint is helpful for tests that need to set up cases where the electra fork has passed. -// We have unit tests that assert our config matches the upstream config, where the next fork is always -// set to MaxUint64 until the fork epoch is formally set. This creates an issue for tests that want to -// work with slots that are defined to be after electra because converting the max epoch to a slot leads -// to multiplication overflow. -// Monkey patching tests with this function is the simplest workaround in these cases. -func HackElectraMaxuint(t *testing.T) func() { - bc := params.MainnetConfig().Copy() - bc.ElectraForkEpoch = math.MaxUint32 - undo, err := params.SetActiveWithUndo(bc) - require.NoError(t, err) - return func() { - require.NoError(t, undo()) - } -} - type ElectraBlockGeneratorOption func(*electraBlockGenerator) type electraBlockGenerator struct { @@ -47,7 +30,7 @@ type electraBlockGenerator struct { sk bls.SecretKey proposer primitives.ValidatorIndex valRoot []byte - payload *enginev1.ExecutionPayloadElectra + payload *enginev1.ExecutionPayloadDeneb } func WithElectraProposerSigning(idx primitives.ValidatorIndex, sk bls.SecretKey, valRoot []byte) ElectraBlockGeneratorOption { @@ -59,7 +42,7 @@ func WithElectraProposerSigning(idx primitives.ValidatorIndex, sk bls.SecretKey, } } -func WithElectraPayload(p *enginev1.ExecutionPayloadElectra) ElectraBlockGeneratorOption { +func WithElectraPayload(p *enginev1.ExecutionPayloadDeneb) ElectraBlockGeneratorOption { return func(g *electraBlockGenerator) { g.payload = p } @@ -96,33 +79,24 @@ func GenerateTestElectraBlockWithSidecar(t *testing.T, parent [32]byte, slot pri logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength) receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength) parentHash := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength) - g.payload = &enginev1.ExecutionPayloadElectra{ - ParentHash: parentHash, - FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), - StateRoot: stateRoot, - ReceiptsRoot: receiptsRoot, - LogsBloom: logsBloom, - PrevRandao: blockHash[:], - BlockNumber: 0, - GasLimit: 0, - GasUsed: 0, - Timestamp: 0, - ExtraData: make([]byte, 0), - BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength), - BlockHash: blockHash[:], - Transactions: encodedBinaryTxs, - Withdrawals: make([]*enginev1.Withdrawal, 0), - BlobGasUsed: 0, - ExcessBlobGas: 0, - DepositRequests: generateTestDepositRequests(uint64(g.slot), 4), - WithdrawalRequests: generateTestWithdrawalRequests(uint64(g.slot), 4), - ConsolidationRequests: []*enginev1.ConsolidationRequest{ - { - SourceAddress: make([]byte, 20), - SourcePubkey: make([]byte, 48), - TargetPubkey: make([]byte, 48), - }, - }, + g.payload = &enginev1.ExecutionPayloadDeneb{ + ParentHash: parentHash, + FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), + StateRoot: stateRoot, + ReceiptsRoot: receiptsRoot, + LogsBloom: logsBloom, + PrevRandao: blockHash[:], + BlockNumber: 0, + GasLimit: 0, + GasUsed: 0, + Timestamp: 0, + ExtraData: make([]byte, 0), + BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength), + BlockHash: blockHash[:], + Transactions: encodedBinaryTxs, + Withdrawals: make([]*enginev1.Withdrawal, 0), + BlobGasUsed: 0, + ExcessBlobGas: 0, } } @@ -177,31 +151,3 @@ func GenerateTestElectraBlockWithSidecar(t *testing.T, parent [32]byte, slot pri require.NoError(t, err) return rob, sidecars } - -func generateTestDepositRequests(offset, n uint64) []*enginev1.DepositRequest { - r := make([]*enginev1.DepositRequest, n) - var i uint64 - for i = 0; i < n; i++ { - r[i] = &enginev1.DepositRequest{ - Pubkey: make([]byte, 48), - WithdrawalCredentials: make([]byte, 32), - Amount: offset + i, - Signature: make([]byte, 96), - Index: offset + i + 100, - } - } - return r -} - -func generateTestWithdrawalRequests(offset, n uint64) []*enginev1.WithdrawalRequest { - r := make([]*enginev1.WithdrawalRequest, n) - var i uint64 - for i = 0; i < n; i++ { - r[i] = &enginev1.WithdrawalRequest{ - SourceAddress: make([]byte, 20), - ValidatorPubkey: make([]byte, 48), - Amount: offset + i, - } - } - return r -} diff --git a/testing/util/electra_block.go b/testing/util/electra_block.go index e285fdfc2a2c..8ba401722612 100644 --- a/testing/util/electra_block.go +++ b/testing/util/electra_block.go @@ -2,11 +2,15 @@ package util import ( "context" + "crypto/rand" "fmt" + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/prysmaticlabs/go-bitfield" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition" "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" @@ -108,7 +112,6 @@ func GenerateFullBlockElectra( for i := uint64(0); i < numToGen; i++ { newTransactions[i] = bytesutil.Uint64ToBytesLittleEndian(i) } - newWithdrawals := make([]*v1.Withdrawal, 0) random, err := helpers.RandaoMix(bState, time.CurrentEpoch(bState)) if err != nil { @@ -126,12 +129,50 @@ func GenerateFullBlockElectra( return nil, err } + newWithdrawals := make([]*v1.Withdrawal, 0) + if conf.NumWithdrawals > 0 { + newWithdrawals, err = generateWithdrawals(bState, privs, numToGen) + if err != nil { + return nil, errors.Wrapf(err, "failed generating %d withdrawals:", numToGen) + } + } + + depositRequests := make([]*v1.DepositRequest, 0) + if conf.NumDepositRequests > 0 { + depositRequests, err = generateDepositRequests(bState, privs, conf.NumDepositRequests) + if err != nil { + return nil, errors.Wrapf(err, "failed generating %d deposit requests:", conf.NumDepositRequests) + } + } + + withdrawalRequests := make([]*v1.WithdrawalRequest, 0) + if conf.NumWithdrawalRequests > 0 { + withdrawalRequests, err = generateWithdrawalRequests(bState, privs, conf.NumWithdrawalRequests) + if err != nil { + return nil, errors.Wrapf(err, "failed generating %d withdrawal requests:", conf.NumWithdrawalRequests) + } + } + + consolidationRequests := make([]*v1.ConsolidationRequest, 0) + if conf.NumConsolidationRequests > 0 { + consolidationRequests, err = generateConsolidationRequests(bState, privs, conf.NumConsolidationRequests) + if err != nil { + return nil, errors.Wrapf(err, "failed generating %d consolidation requests:", conf.NumConsolidationRequests) + } + } + + executionRequests := &v1.ExecutionRequests{ + Withdrawals: withdrawalRequests, + Deposits: depositRequests, + Consolidations: consolidationRequests, + } + parentExecution, err := stCopy.LatestExecutionPayloadHeader() if err != nil { return nil, err } blockHash := indexToHash(uint64(slot)) - newExecutionPayloadCapella := &v1.ExecutionPayloadElectra{ + newExecutionPayloadElectra := &v1.ExecutionPayloadDeneb{ ParentHash: parentExecution.BlockHash(), FeeRecipient: make([]byte, 20), StateRoot: params.BeaconConfig().ZeroHash[:], @@ -208,8 +249,9 @@ func GenerateFullBlockElectra( Deposits: newDeposits, Graffiti: make([]byte, fieldparams.RootLength), SyncAggregate: newSyncAggregate, - ExecutionPayload: newExecutionPayloadCapella, + ExecutionPayload: newExecutionPayloadElectra, BlsToExecutionChanges: changes, + ExecutionRequests: executionRequests, }, } @@ -221,3 +263,132 @@ func GenerateFullBlockElectra( return ðpb.SignedBeaconBlockElectra{Block: block, Signature: signature.Marshal()}, nil } + +func generateWithdrawalRequests( + bState state.BeaconState, + privs []bls.SecretKey, + numRequests uint64, +) ([]*v1.WithdrawalRequest, error) { + withdrawalRequests := make([]*v1.WithdrawalRequest, numRequests) + for i := uint64(0); i < numRequests; i++ { + valIndex, err := randValIndex(bState) + if err != nil { + return nil, err + } + // Get a random index + nBig, err := rand.Int(rand.Reader, big.NewInt(60000)) + if err != nil { + return nil, err + } + amount := nBig.Uint64() // random amount created + bal, err := bState.BalanceAtIndex(valIndex) + if err != nil { + return nil, err + } + amounts := []uint64{ + amount, // some smaller amount + bal, // the entire balance + } + // Get a random index + nBig, err = rand.Int(rand.Reader, big.NewInt(int64(len(amounts)))) + if err != nil { + return nil, err + } + randomIndex := nBig.Uint64() + withdrawalRequests[i] = &v1.WithdrawalRequest{ + ValidatorPubkey: privs[valIndex].PublicKey().Marshal(), + SourceAddress: make([]byte, common.AddressLength), + Amount: amounts[randomIndex], + } + } + return withdrawalRequests, nil +} + +func generateDepositRequests( + bState state.BeaconState, + privs []bls.SecretKey, + numRequests uint64, +) ([]*v1.DepositRequest, error) { + depositRequests := make([]*v1.DepositRequest, numRequests) + for i := uint64(0); i < numRequests; i++ { + valIndex, err := randValIndex(bState) + if err != nil { + return nil, err + } + // Get a random index + nBig, err := rand.Int(rand.Reader, big.NewInt(60000)) + if err != nil { + return nil, err + } + amount := nBig.Uint64() // random amount created + prefixes := []byte{params.BeaconConfig().CompoundingWithdrawalPrefixByte, 0, params.BeaconConfig().BLSWithdrawalPrefixByte} + withdrawalCred := make([]byte, 32) + // Get a random index + nBig, err = rand.Int(rand.Reader, big.NewInt(int64(len(prefixes)))) + if err != nil { + return nil, err + } + randPrefixIndex := nBig.Uint64() + withdrawalCred[0] = prefixes[randPrefixIndex] + + depositMessage := ðpb.DepositMessage{ + PublicKey: privs[valIndex].PublicKey().Marshal(), + Amount: amount, + WithdrawalCredentials: withdrawalCred, + } + domain, err := signing.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil) + if err != nil { + return nil, err + } + sr, err := signing.ComputeSigningRoot(depositMessage, domain) + if err != nil { + return nil, err + } + sig := privs[i].Sign(sr[:]) + depositRequests[i] = &v1.DepositRequest{ + Pubkey: depositMessage.PublicKey, + Index: uint64(valIndex), + WithdrawalCredentials: depositMessage.WithdrawalCredentials, + Amount: depositMessage.Amount, + Signature: sig.Marshal(), + } + } + return depositRequests, nil +} + +func generateConsolidationRequests( + bState state.BeaconState, + privs []bls.SecretKey, + numRequests uint64, +) ([]*v1.ConsolidationRequest, error) { + consolidationRequests := make([]*v1.ConsolidationRequest, numRequests) + for i := uint64(0); i < numRequests; i++ { + valIndex, err := randValIndex(bState) + if err != nil { + return nil, err + } + valIndex2, err := randValIndex(bState) + if err != nil { + return nil, err + } + source, err := randomAddress() + if err != nil { + return nil, err + } + consolidationRequests[i] = &v1.ConsolidationRequest{ + TargetPubkey: privs[valIndex2].PublicKey().Marshal(), + SourceAddress: source.Bytes(), + SourcePubkey: privs[valIndex].PublicKey().Marshal(), + } + } + return consolidationRequests, nil +} + +func randomAddress() (common.Address, error) { + b := make([]byte, 20) + _, err := rand.Read(b) + if err != nil { + return common.Address{}, err + } + return common.BytesToAddress(b), nil +} diff --git a/testing/util/electra_state.go b/testing/util/electra_state.go index 437d2e62d6f5..f05d349ef9c1 100644 --- a/testing/util/electra_state.go +++ b/testing/util/electra_state.go @@ -71,14 +71,14 @@ func genesisBeaconStateElectra(ctx context.Context, deposits []*ethpb.Deposit, g return buildGenesisBeaconStateElectra(genesisTime, st, st.Eth1Data()) } -// emptyGenesisStateDeneb returns an empty genesis state in Electra format. +// emptyGenesisStateElectra returns an empty genesis state in Electra format. func emptyGenesisStateElectra() (state.BeaconState, error) { st := ðpb.BeaconStateElectra{ // Misc fields. Slot: 0, Fork: ðpb.Fork{ - PreviousVersion: params.BeaconConfig().BellatrixForkVersion, - CurrentVersion: params.BeaconConfig().DenebForkVersion, + PreviousVersion: params.BeaconConfig().DenebForkVersion, + CurrentVersion: params.BeaconConfig().ElectraForkVersion, Epoch: 0, }, // Validator registry fields. @@ -96,7 +96,7 @@ func emptyGenesisStateElectra() (state.BeaconState, error) { Eth1DataVotes: []*ethpb.Eth1Data{}, Eth1DepositIndex: 0, - LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderElectra{}, + LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{}, DepositBalanceToConsume: primitives.Gwei(0), ExitBalanceToConsume: primitives.Gwei(0), @@ -209,7 +209,7 @@ func buildGenesisBeaconStateElectra(genesisTime uint64, preState state.BeaconSta ExitBalanceToConsume: helpers.ActivationExitChurnLimit(primitives.Gwei(tab)), EarliestConsolidationEpoch: helpers.ActivationExitEpoch(slots.ToEpoch(preState.Slot())), ConsolidationBalanceToConsume: helpers.ConsolidationChurnLimit(primitives.Gwei(tab)), - PendingBalanceDeposits: make([]*ethpb.PendingBalanceDeposit, 0), + PendingDeposits: make([]*ethpb.PendingDeposit, 0), PendingPartialWithdrawals: make([]*ethpb.PendingPartialWithdrawal, 0), PendingConsolidations: make([]*ethpb.PendingConsolidation, 0), } @@ -226,20 +226,22 @@ func buildGenesisBeaconStateElectra(genesisTime uint64, preState state.BeaconSta SyncCommitteeBits: scBits[:], SyncCommitteeSignature: make([]byte, 96), }, - ExecutionPayload: &enginev1.ExecutionPayloadElectra{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, 32), - ReceiptsRoot: make([]byte, 32), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, 32), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - Transactions: make([][]byte, 0), - Withdrawals: make([]*enginev1.Withdrawal, 0), - DepositRequests: make([]*enginev1.DepositRequest, 0), - WithdrawalRequests: make([]*enginev1.WithdrawalRequest, 0), + ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + Transactions: make([][]byte, 0), + }, + ExecutionRequests: &enginev1.ExecutionRequests{ + Deposits: make([]*enginev1.DepositRequest, 0), + Withdrawals: make([]*enginev1.WithdrawalRequest, 0), + Consolidations: make([]*enginev1.ConsolidationRequest, 0), }, }).HashTreeRoot() if err != nil { @@ -271,21 +273,18 @@ func buildGenesisBeaconStateElectra(genesisTime uint64, preState state.BeaconSta AggregatePubkey: aggregated.Marshal(), } - st.LatestExecutionPayloadHeader = &enginev1.ExecutionPayloadHeaderElectra{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, 32), - ReceiptsRoot: make([]byte, 32), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, 32), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, 32), - WithdrawalsRoot: make([]byte, 32), - DepositRequestsRoot: make([]byte, 32), - WithdrawalRequestsRoot: make([]byte, 32), - ConsolidationRequestsRoot: make([]byte, 32), + st.LatestExecutionPayloadHeader = &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, 32), + WithdrawalsRoot: make([]byte, 32), } return state_native.InitializeFromProtoElectra(st) diff --git a/testing/util/helpers.go b/testing/util/helpers.go index b207813a0861..163e06fbcda5 100644 --- a/testing/util/helpers.go +++ b/testing/util/helpers.go @@ -4,6 +4,7 @@ import ( "context" "encoding/binary" "fmt" + "math" "testing" "github.com/pkg/errors" @@ -19,6 +20,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/crypto/rand" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/testing/require" ) // RandaoReveal returns a signature of the requested epoch using the beacon proposer private key. @@ -149,3 +152,28 @@ func Random32Bytes(t *testing.T) []byte { } return b } + +// HackForksMaxuint is helpful for tests that need to set up cases for some future forks. +// We have unit tests that assert our config matches the upstream config, where some forks epoch are always +// set to MaxUint64 until they are formally set. This creates an issue for tests that want to +// work with slots that are defined to be after these forks because converting the max epoch to a slot leads +// to multiplication overflow. +// Monkey patching tests with this function is the simplest workaround in these cases. +func HackForksMaxuint(t *testing.T, forksVersion []int) func() { + bc := params.MainnetConfig().Copy() + for _, forkVersion := range forksVersion { + switch forkVersion { + case version.Electra: + bc.ElectraForkEpoch = math.MaxUint32 - 1 + case version.Fulu: + bc.FuluForkEpoch = math.MaxUint32 + default: + t.Fatalf("unsupported fork version %d", forkVersion) + } + } + undo, err := params.SetActiveWithUndo(bc) + require.NoError(t, err) + return func() { + require.NoError(t, undo()) + } +} diff --git a/testing/util/lightclient.go b/testing/util/lightclient.go new file mode 100644 index 000000000000..5223359dc9da --- /dev/null +++ b/testing/util/lightclient.go @@ -0,0 +1,1127 @@ +package util + +import ( + "context" + "testing" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/state" + fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/config/params" + consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types" + "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" + "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/encoding/ssz" + v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" + "github.com/prysmaticlabs/prysm/v5/testing/require" +) + +type TestLightClient struct { + T *testing.T + Ctx context.Context + State state.BeaconState + Block interfaces.ReadOnlySignedBeaconBlock + AttestedState state.BeaconState + AttestedBlock interfaces.ReadOnlySignedBeaconBlock + FinalizedBlock interfaces.ReadOnlySignedBeaconBlock +} + +func NewTestLightClient(t *testing.T) *TestLightClient { + return &TestLightClient{T: t} +} + +func (l *TestLightClient) SetupTestCapella(blinded bool) *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + + attestedState, err := NewBeaconStateCapella() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockCapella()) + require.NoError(l.T, err) + finalizedBlock.SetSlot(primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch))) + finalizedHeader, err := finalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: params.BeaconConfig().CapellaForkEpoch, + Root: finalizedRoot[:], + })) + + parent := NewBeaconBlockCapella() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateCapella() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + var signedBlock interfaces.SignedBeaconBlock + if blinded { + block := NewBlindedBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } else { + block := NewBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } + + l.State = state + l.AttestedState = attestedState + l.AttestedBlock = signedParent + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = finalizedBlock + + return l +} + +func (l *TestLightClient) SetupTestCapellaFinalizedBlockAltair(blinded bool) *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(params.BeaconConfig().CapellaForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + + attestedState, err := NewBeaconStateCapella() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockAltair()) + require.NoError(l.T, err) + finalizedBlock.SetSlot(1) + finalizedHeader, err := finalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: params.BeaconConfig().AltairForkEpoch - 10, + Root: finalizedRoot[:], + })) + + parent := NewBeaconBlockCapella() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateCapella() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + var signedBlock interfaces.SignedBeaconBlock + if blinded { + block := NewBlindedBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } else { + block := NewBeaconBlockCapella() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } + + l.State = state + l.AttestedState = attestedState + l.AttestedBlock = signedParent + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = finalizedBlock + + return l +} + +func (l *TestLightClient) SetupTestAltair() *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(uint64(params.BeaconConfig().AltairForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)).Add(1) + + attestedState, err := NewBeaconStateAltair() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedState, err := NewBeaconStateAltair() + require.NoError(l.T, err) + err = finalizedState.SetSlot(1) + require.NoError(l.T, err) + finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + SignedFinalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockAltair()) + require.NoError(l.T, err) + SignedFinalizedBlock.SetSlot(1) + SignedFinalizedBlock.SetStateRoot(finalizedStateRoot[:]) + finalizedHeader, err := SignedFinalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + finalizedCheckpoint := ðpb.Checkpoint{ + Epoch: params.BeaconConfig().AltairForkEpoch - 10, + Root: finalizedRoot[:], + } + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(finalizedCheckpoint)) + + parent := NewBeaconBlockAltair() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateAltair() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + block := NewBeaconBlockAltair() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + l.State = state + l.AttestedState = attestedState + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = SignedFinalizedBlock + l.AttestedBlock = signedParent + + return l +} + +func (l *TestLightClient) SetupTestBellatrix() *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(params.BeaconConfig().BellatrixForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + + attestedState, err := NewBeaconStateBellatrix() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockBellatrix()) + require.NoError(l.T, err) + finalizedBlock.SetSlot(1) + finalizedHeader, err := finalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: params.BeaconConfig().BellatrixForkEpoch - 10, + Root: finalizedRoot[:], + })) + + parent := NewBeaconBlockBellatrix() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateBellatrix() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + block := NewBeaconBlockBellatrix() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err := blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + l.State = state + l.AttestedState = attestedState + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = finalizedBlock + l.AttestedBlock = signedParent + + return l +} + +func (l *TestLightClient) SetupTestDeneb(blinded bool) *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + + attestedState, err := NewBeaconStateDeneb() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockDeneb()) + require.NoError(l.T, err) + finalizedBlock.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch))) + finalizedHeader, err := finalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: params.BeaconConfig().DenebForkEpoch, + Root: finalizedRoot[:], + })) + + parent := NewBeaconBlockDeneb() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateDeneb() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + var signedBlock interfaces.SignedBeaconBlock + if blinded { + block := NewBlindedBeaconBlockDeneb() + block.Message.Slot = slot + block.Message.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Message.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } else { + block := NewBeaconBlockDeneb() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } + + l.State = state + l.AttestedState = attestedState + l.AttestedBlock = signedParent + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = finalizedBlock + + return l +} + +func (l *TestLightClient) SetupTestElectra(blinded bool) *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + finalizedBlockSlot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)) + + attestedState, err := NewBeaconStateElectra() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockDeneb()) + require.NoError(l.T, err) + finalizedBlock.SetSlot(finalizedBlockSlot) + finalizedHeader, err := finalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: params.BeaconConfig().ElectraForkEpoch, + Root: finalizedRoot[:], + })) + + parent := NewBeaconBlockElectra() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateElectra() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + var signedBlock interfaces.SignedBeaconBlock + if blinded { + block := NewBlindedBeaconBlockElectra() + block.Message.Slot = slot + block.Message.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Message.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } else { + block := NewBeaconBlockElectra() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } + + l.State = state + l.AttestedState = attestedState + l.AttestedBlock = signedParent + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = finalizedBlock + + return l +} + +func (l *TestLightClient) SetupTestFulu(blinded bool) *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(params.BeaconConfig().FuluForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + + attestedState, err := NewBeaconStateFulu() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockFulu()) + require.NoError(l.T, err) + finalizedBlock.SetSlot(1) + finalizedHeader, err := finalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: params.BeaconConfig().FuluForkEpoch - 10, + Root: finalizedRoot[:], + })) + + parent := NewBeaconBlockFulu() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateFulu() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + var signedBlock interfaces.SignedBeaconBlock + if blinded { + block := NewBlindedBeaconBlockFulu() + block.Message.Slot = slot + block.Message.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Message.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } else { + block := NewBeaconBlockFulu() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } + + l.State = state + l.AttestedState = attestedState + l.AttestedBlock = signedParent + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = finalizedBlock + + return l +} + +func (l *TestLightClient) SetupTestDenebFinalizedBlockCapella(blinded bool) *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + + attestedState, err := NewBeaconStateDeneb() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockCapella()) + require.NoError(l.T, err) + finalizedBlock.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Sub(15)) + finalizedHeader, err := finalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: params.BeaconConfig().DenebForkEpoch - 1, + Root: finalizedRoot[:], + })) + + parent := NewBeaconBlockDeneb() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateDeneb() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + var signedBlock interfaces.SignedBeaconBlock + if blinded { + block := NewBlindedBeaconBlockDeneb() + block.Message.Slot = slot + block.Message.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Message.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } else { + block := NewBeaconBlockDeneb() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } + + l.State = state + l.AttestedState = attestedState + l.AttestedBlock = signedParent + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = finalizedBlock + + return l +} + +func (l *TestLightClient) SetupTestElectraFinalizedBlockDeneb(blinded bool) *TestLightClient { + ctx := context.Background() + + slot := primitives.Slot(params.BeaconConfig().ElectraForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)).Add(1) + finalizedBlockSlot := primitives.Slot(params.BeaconConfig().DenebForkEpoch * primitives.Epoch(params.BeaconConfig().SlotsPerEpoch)) + + attestedState, err := NewBeaconStateElectra() + require.NoError(l.T, err) + err = attestedState.SetSlot(slot) + require.NoError(l.T, err) + + finalizedBlock, err := blocks.NewSignedBeaconBlock(NewBeaconBlockDeneb()) + require.NoError(l.T, err) + finalizedBlock.SetSlot(finalizedBlockSlot) + finalizedHeader, err := finalizedBlock.Header() + require.NoError(l.T, err) + finalizedRoot, err := finalizedHeader.Header.HashTreeRoot() + require.NoError(l.T, err) + + require.NoError(l.T, attestedState.SetFinalizedCheckpoint(ðpb.Checkpoint{ + Epoch: params.BeaconConfig().DenebForkEpoch, + Root: finalizedRoot[:], + })) + + parent := NewBeaconBlockElectra() + parent.Block.Slot = slot + + signedParent, err := blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + parentHeader, err := signedParent.Header() + require.NoError(l.T, err) + attestedHeader := parentHeader.Header + + err = attestedState.SetLatestBlockHeader(attestedHeader) + require.NoError(l.T, err) + attestedStateRoot, err := attestedState.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + parent.Block.StateRoot = attestedStateRoot[:] + signedParent, err = blocks.NewSignedBeaconBlock(parent) + require.NoError(l.T, err) + + state, err := NewBeaconStateElectra() + require.NoError(l.T, err) + err = state.SetSlot(slot) + require.NoError(l.T, err) + + parentRoot, err := signedParent.Block().HashTreeRoot() + require.NoError(l.T, err) + + var signedBlock interfaces.SignedBeaconBlock + if blinded { + block := NewBlindedBeaconBlockElectra() + block.Message.Slot = slot + block.Message.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Message.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } else { + block := NewBeaconBlockElectra() + block.Block.Slot = slot + block.Block.ParentRoot = parentRoot[:] + + for i := uint64(0); i < params.BeaconConfig().MinSyncCommitteeParticipants; i++ { + block.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true) + } + + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + + h, err := signedBlock.Header() + require.NoError(l.T, err) + + err = state.SetLatestBlockHeader(h.Header) + require.NoError(l.T, err) + stateRoot, err := state.HashTreeRoot(ctx) + require.NoError(l.T, err) + + // get a new signed block so the root is updated with the new state root + block.Block.StateRoot = stateRoot[:] + signedBlock, err = blocks.NewSignedBeaconBlock(block) + require.NoError(l.T, err) + } + + l.State = state + l.AttestedState = attestedState + l.AttestedBlock = signedParent + l.Block = signedBlock + l.Ctx = ctx + l.FinalizedBlock = finalizedBlock + + return l +} + +func (l *TestLightClient) CheckAttestedHeader(header interfaces.LightClientHeader) { + updateAttestedHeaderBeacon := header.Beacon() + testAttestedHeader, err := l.AttestedBlock.Header() + require.NoError(l.T, err) + require.Equal(l.T, l.AttestedBlock.Block().Slot(), updateAttestedHeaderBeacon.Slot, "Attested block slot is not equal") + require.Equal(l.T, testAttestedHeader.Header.ProposerIndex, updateAttestedHeaderBeacon.ProposerIndex, "Attested block proposer index is not equal") + require.DeepSSZEqual(l.T, testAttestedHeader.Header.ParentRoot, updateAttestedHeaderBeacon.ParentRoot, "Attested block parent root is not equal") + require.DeepSSZEqual(l.T, testAttestedHeader.Header.BodyRoot, updateAttestedHeaderBeacon.BodyRoot, "Attested block body root is not equal") + + attestedStateRoot, err := l.AttestedState.HashTreeRoot(l.Ctx) + require.NoError(l.T, err) + require.DeepSSZEqual(l.T, attestedStateRoot[:], updateAttestedHeaderBeacon.StateRoot, "Attested block state root is not equal") + + if l.AttestedBlock.Version() == version.Capella { + payloadInterface, err := l.AttestedBlock.Block().Body().Execution() + require.NoError(l.T, err) + transactionsRoot, err := payloadInterface.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payloadInterface.Transactions() + require.NoError(l.T, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(l.T, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(l.T, err) + } + withdrawalsRoot, err := payloadInterface.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payloadInterface.Withdrawals() + require.NoError(l.T, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(l.T, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(l.T, err) + } + execution := &v11.ExecutionPayloadHeaderCapella{ + ParentHash: payloadInterface.ParentHash(), + FeeRecipient: payloadInterface.FeeRecipient(), + StateRoot: payloadInterface.StateRoot(), + ReceiptsRoot: payloadInterface.ReceiptsRoot(), + LogsBloom: payloadInterface.LogsBloom(), + PrevRandao: payloadInterface.PrevRandao(), + BlockNumber: payloadInterface.BlockNumber(), + GasLimit: payloadInterface.GasLimit(), + GasUsed: payloadInterface.GasUsed(), + Timestamp: payloadInterface.Timestamp(), + ExtraData: payloadInterface.ExtraData(), + BaseFeePerGas: payloadInterface.BaseFeePerGas(), + BlockHash: payloadInterface.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + updateAttestedHeaderExecution, err := header.Execution() + require.NoError(l.T, err) + require.DeepSSZEqual(l.T, execution, updateAttestedHeaderExecution.Proto(), "Attested Block Execution is not equal") + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.AttestedBlock.Block()) + require.NoError(l.T, err) + updateAttestedHeaderExecutionBranch, err := header.ExecutionBranch() + require.NoError(l.T, err) + for i, leaf := range updateAttestedHeaderExecutionBranch { + require.DeepSSZEqual(l.T, executionPayloadProof[i], leaf[:], "Leaf is not equal") + } + } + + if l.AttestedBlock.Version() == version.Deneb { + payloadInterface, err := l.AttestedBlock.Block().Body().Execution() + require.NoError(l.T, err) + transactionsRoot, err := payloadInterface.TransactionsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + transactions, err := payloadInterface.Transactions() + require.NoError(l.T, err) + transactionsRootArray, err := ssz.TransactionsRoot(transactions) + require.NoError(l.T, err) + transactionsRoot = transactionsRootArray[:] + } else { + require.NoError(l.T, err) + } + withdrawalsRoot, err := payloadInterface.WithdrawalsRoot() + if errors.Is(err, consensus_types.ErrUnsupportedField) { + withdrawals, err := payloadInterface.Withdrawals() + require.NoError(l.T, err) + withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload) + require.NoError(l.T, err) + withdrawalsRoot = withdrawalsRootArray[:] + } else { + require.NoError(l.T, err) + } + execution := &v11.ExecutionPayloadHeaderDeneb{ + ParentHash: payloadInterface.ParentHash(), + FeeRecipient: payloadInterface.FeeRecipient(), + StateRoot: payloadInterface.StateRoot(), + ReceiptsRoot: payloadInterface.ReceiptsRoot(), + LogsBloom: payloadInterface.LogsBloom(), + PrevRandao: payloadInterface.PrevRandao(), + BlockNumber: payloadInterface.BlockNumber(), + GasLimit: payloadInterface.GasLimit(), + GasUsed: payloadInterface.GasUsed(), + Timestamp: payloadInterface.Timestamp(), + ExtraData: payloadInterface.ExtraData(), + BaseFeePerGas: payloadInterface.BaseFeePerGas(), + BlockHash: payloadInterface.BlockHash(), + TransactionsRoot: transactionsRoot, + WithdrawalsRoot: withdrawalsRoot, + } + + updateAttestedHeaderExecution, err := header.Execution() + require.NoError(l.T, err) + require.DeepSSZEqual(l.T, execution, updateAttestedHeaderExecution.Proto(), "Attested Block Execution is not equal") + + executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.AttestedBlock.Block()) + require.NoError(l.T, err) + updateAttestedHeaderExecutionBranch, err := header.ExecutionBranch() + require.NoError(l.T, err) + for i, leaf := range updateAttestedHeaderExecutionBranch { + require.DeepSSZEqual(l.T, executionPayloadProof[i], leaf[:], "Leaf is not equal") + } + } +} + +func (l *TestLightClient) CheckSyncAggregate(sa *ethpb.SyncAggregate) { + syncAggregate, err := l.Block.Block().Body().SyncAggregate() + require.NoError(l.T, err) + require.DeepSSZEqual(l.T, syncAggregate.SyncCommitteeBits, sa.SyncCommitteeBits, "SyncAggregate bits is not equal") + require.DeepSSZEqual(l.T, syncAggregate.SyncCommitteeSignature, sa.SyncCommitteeSignature, "SyncAggregate signature is not equal") +} diff --git a/testing/util/logging.go b/testing/util/logging.go new file mode 100644 index 000000000000..a4da28453d0b --- /dev/null +++ b/testing/util/logging.go @@ -0,0 +1,90 @@ +package util + +import ( + "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus/hooks/test" +) + +// ComparableHook is an interface that allows hooks to be uniquely identified +// so that tests can safely unregister them as part of cleanup. +type ComparableHook interface { + logrus.Hook + Equal(other logrus.Hook) bool +} + +// UnregisterHook removes a hook that implements the HookIdentifier interface +// from all levels of the given logger. +func UnregisterHook(logger *logrus.Logger, unregister ComparableHook) { + found := false + replace := make(logrus.LevelHooks) + for lvl, hooks := range logger.Hooks { + for _, h := range hooks { + if unregister.Equal(h) { + found = true + continue + } + replace[lvl] = append(replace[lvl], h) + } + } + if !found { + return + } + logger.ReplaceHooks(replace) +} + +var highestLevel logrus.Level + +// RegisterHookWithUndo adds a hook to the logger and +// returns a function that can be called to remove it. This is intended to be used in tests +// to ensure that test hooks are removed after the test is complete. +func RegisterHookWithUndo(logger *logrus.Logger, hook ComparableHook) func() { + level := logger.Level + logger.AddHook(hook) + // set level to highest possible to ensure that hook is called for all log levels + logger.SetLevel(highestLevel) + return func() { + UnregisterHook(logger, hook) + logger.SetLevel(level) + } +} + +// NewChannelEntryWriter creates a new ChannelEntryWriter. +// The channel argument will be sent all log entries. +// Note that if this is an unbuffered channel, it is the responsibility +// of the code using it to make sure that it is drained appropriately, +// or calls to the logger can block. +func NewChannelEntryWriter(c chan *logrus.Entry) *ChannelEntryWriter { + return &ChannelEntryWriter{c: c} +} + +// ChannelEntryWriter embeds/wraps the test.Hook struct +// and adds a channel to receive log entries every time the +// Fire method of the Hook interface is called. +type ChannelEntryWriter struct { + test.Hook + c chan *logrus.Entry +} + +// Fire delegates to the embedded test.Hook Fire method after +// sending the log entry to the channel. +func (c *ChannelEntryWriter) Fire(e *logrus.Entry) error { + if c.c != nil { + c.c <- e + } + return c.Hook.Fire(e) +} + +func (c *ChannelEntryWriter) Equal(other logrus.Hook) bool { + return c == other +} + +var _ logrus.Hook = &ChannelEntryWriter{} +var _ ComparableHook = &ChannelEntryWriter{} + +func init() { + for _, level := range logrus.AllLevels { + if level > highestLevel { + highestLevel = level + } + } +} diff --git a/testing/util/logging_test.go b/testing/util/logging_test.go new file mode 100644 index 000000000000..d596abbfc466 --- /dev/null +++ b/testing/util/logging_test.go @@ -0,0 +1,78 @@ +package util + +import ( + "testing" + "time" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/sirupsen/logrus" +) + +func TestUnregister(t *testing.T) { + logger := logrus.New() + logger.SetLevel(logrus.PanicLevel) // set to lowest log level to test level override in + assertNoHooks(t, logger) + c := make(chan *logrus.Entry, 1) + tl := NewChannelEntryWriter(c) + undo := RegisterHookWithUndo(logger, tl) + assertRegistered(t, logger, tl) + logger.Trace("test") + select { + case <-c: + default: + t.Fatalf("Expected log entry, got none") + } + undo() + assertNoHooks(t, logger) + require.Equal(t, logrus.PanicLevel, logger.Level) +} + +var logTestErr = errors.New("test") + +func TestChannelEntryWriter(t *testing.T) { + logger := logrus.New() + c := make(chan *logrus.Entry) + tl := NewChannelEntryWriter(c) + logger.AddHook(tl) + msg := "test" + go func() { + logger.WithError(logTestErr).Info(msg) + }() + select { + case e := <-c: + gotErr := e.Data[logrus.ErrorKey] + if gotErr == nil { + t.Fatalf("Expected error in log entry, got nil") + } + ge, ok := gotErr.(error) + require.Equal(t, true, ok, "Expected error in log entry to be of type error, got %T", gotErr) + require.ErrorIs(t, ge, logTestErr) + require.Equal(t, msg, e.Message) + require.Equal(t, logrus.InfoLevel, e.Level) + case <-time.After(10 * time.Millisecond): + t.Fatalf("Timed out waiting for log entry") + } +} + +func assertNoHooks(t *testing.T, logger *logrus.Logger) { + for lvl, hooks := range logger.Hooks { + for _, hook := range hooks { + t.Fatalf("Expected no hooks, got %v at level %s", hook, lvl.String()) + } + } +} + +func assertRegistered(t *testing.T, logger *logrus.Logger, hook ComparableHook) { + for _, lvl := range hook.Levels() { + registered := logger.Hooks[lvl] + found := false + for _, h := range registered { + if hook.Equal(h) { + found = true + break + } + } + require.Equal(t, true, found, "Expected hook %v to be registered at level %s, but it was not", hook, lvl.String()) + } +} diff --git a/testing/util/merge.go b/testing/util/merge.go index 85bf2c82a807..d911e5a12380 100644 --- a/testing/util/merge.go +++ b/testing/util/merge.go @@ -1,10 +1,13 @@ package util import ( - v2 "github.com/prysmaticlabs/prysm/v5/proto/eth/v2" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) +// ---------------------------------------------------------------------------- +// Bellatrix +// ---------------------------------------------------------------------------- + // NewBeaconBlockBellatrix creates a beacon block with minimum marshalable fields. func NewBeaconBlockBellatrix() *ethpb.SignedBeaconBlockBellatrix { return HydrateSignedBeaconBlockBellatrix(ðpb.SignedBeaconBlockBellatrix{}) @@ -15,10 +18,9 @@ func NewBlindedBeaconBlockBellatrix() *ethpb.SignedBlindedBeaconBlockBellatrix { return HydrateSignedBlindedBeaconBlockBellatrix(ðpb.SignedBlindedBeaconBlockBellatrix{}) } -// NewBlindedBeaconBlockBellatrixV2 creates a blinded beacon block with minimum marshalable fields. -func NewBlindedBeaconBlockBellatrixV2() *v2.SignedBlindedBeaconBlockBellatrix { - return HydrateV2SignedBlindedBeaconBlockBellatrix(&v2.SignedBlindedBeaconBlockBellatrix{}) -} +// ---------------------------------------------------------------------------- +// Capella +// ---------------------------------------------------------------------------- // NewBeaconBlockCapella creates a beacon block with minimum marshalable fields. func NewBeaconBlockCapella() *ethpb.SignedBeaconBlockCapella { @@ -30,16 +32,15 @@ func NewBlindedBeaconBlockCapella() *ethpb.SignedBlindedBeaconBlockCapella { return HydrateSignedBlindedBeaconBlockCapella(ðpb.SignedBlindedBeaconBlockCapella{}) } +// ---------------------------------------------------------------------------- +// Deneb +// ---------------------------------------------------------------------------- + // NewBeaconBlockDeneb creates a beacon block with minimum marshalable fields. func NewBeaconBlockDeneb() *ethpb.SignedBeaconBlockDeneb { return HydrateSignedBeaconBlockDeneb(ðpb.SignedBeaconBlockDeneb{}) } -// NewBeaconBlockElectra creates a beacon block with minimum marshalable fields. -func NewBeaconBlockElectra() *ethpb.SignedBeaconBlockElectra { - return HydrateSignedBeaconBlockElectra(ðpb.SignedBeaconBlockElectra{}) -} - // NewBeaconBlockContentsDeneb creates a beacon block with minimum marshalable fields. func NewBeaconBlockContentsDeneb() *ethpb.SignedBeaconBlockContentsDeneb { return HydrateSignedBeaconBlockContentsDeneb(ðpb.SignedBeaconBlockContentsDeneb{}) @@ -50,6 +51,15 @@ func NewBlindedBeaconBlockDeneb() *ethpb.SignedBlindedBeaconBlockDeneb { return HydrateSignedBlindedBeaconBlockDeneb(ðpb.SignedBlindedBeaconBlockDeneb{}) } +// ---------------------------------------------------------------------------- +// Electra +// ---------------------------------------------------------------------------- + +// NewBeaconBlockElectra creates a beacon block with minimum marshalable fields. +func NewBeaconBlockElectra() *ethpb.SignedBeaconBlockElectra { + return HydrateSignedBeaconBlockElectra(ðpb.SignedBeaconBlockElectra{}) +} + // NewBeaconBlockContentsElectra creates a beacon block with minimum marshalable fields. func NewBeaconBlockContentsElectra() *ethpb.SignedBeaconBlockContentsElectra { return HydrateSignedBeaconBlockContentsElectra(ðpb.SignedBeaconBlockContentsElectra{}) @@ -60,7 +70,21 @@ func NewBlindedBeaconBlockElectra() *ethpb.SignedBlindedBeaconBlockElectra { return HydrateSignedBlindedBeaconBlockElectra(ðpb.SignedBlindedBeaconBlockElectra{}) } -// NewBlindedBeaconBlockCapellaV2 creates a blinded beacon block with minimum marshalable fields. -func NewBlindedBeaconBlockCapellaV2() *v2.SignedBlindedBeaconBlockCapella { - return HydrateV2SignedBlindedBeaconBlockCapella(&v2.SignedBlindedBeaconBlockCapella{}) +// ---------------------------------------------------------------------------- +// Fulu +// ---------------------------------------------------------------------------- + +// NewBeaconBlockFulu creates a beacon block with minimum marshalable fields. +func NewBeaconBlockFulu() *ethpb.SignedBeaconBlockFulu { + return HydrateSignedBeaconBlockFulu(ðpb.SignedBeaconBlockFulu{}) +} + +// NewBeaconBlockContentsFulu creates a beacon block with minimum marshalable fields. +func NewBeaconBlockContentsFulu() *ethpb.SignedBeaconBlockContentsFulu { + return HydrateSignedBeaconBlockContentsFulu(ðpb.SignedBeaconBlockContentsFulu{}) +} + +// NewBlindedBeaconBlockFulu creates a blinded beacon block with minimum marshalable fields. +func NewBlindedBeaconBlockFulu() *ethpb.SignedBlindedBeaconBlockFulu { + return HydrateSignedBlindedBeaconBlockFulu(ðpb.SignedBlindedBeaconBlockFulu{}) } diff --git a/testing/util/state.go b/testing/util/state.go index b0f4838860b4..f8ccd026b38c 100644 --- a/testing/util/state.go +++ b/testing/util/state.go @@ -424,21 +424,18 @@ func NewBeaconStateElectra(options ...func(state *ethpb.BeaconStateElectra) erro Pubkeys: pubkeys, AggregatePubkey: make([]byte, 48), }, - LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderElectra{ - ParentHash: make([]byte, 32), - FeeRecipient: make([]byte, 20), - StateRoot: make([]byte, 32), - ReceiptsRoot: make([]byte, 32), - LogsBloom: make([]byte, 256), - PrevRandao: make([]byte, 32), - ExtraData: make([]byte, 0), - BaseFeePerGas: make([]byte, 32), - BlockHash: make([]byte, 32), - TransactionsRoot: make([]byte, 32), - WithdrawalsRoot: make([]byte, 32), - DepositRequestsRoot: make([]byte, 32), - WithdrawalRequestsRoot: make([]byte, 32), - ConsolidationRequestsRoot: make([]byte, 32), + LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, 32), + WithdrawalsRoot: make([]byte, 32), }, } @@ -457,6 +454,74 @@ func NewBeaconStateElectra(options ...func(state *ethpb.BeaconStateElectra) erro return st.Copy(), nil } +// NewBeaconStateFulu creates a beacon state with minimum marshalable fields. +func NewBeaconStateFulu(options ...func(state *ethpb.BeaconStateElectra) error) (state.BeaconState, error) { + pubkeys := make([][]byte, 512) + for i := range pubkeys { + pubkeys[i] = make([]byte, 48) + } + + seed := ðpb.BeaconStateElectra{ + BlockRoots: filledByteSlice2D(uint64(params.BeaconConfig().SlotsPerHistoricalRoot), 32), + StateRoots: filledByteSlice2D(uint64(params.BeaconConfig().SlotsPerHistoricalRoot), 32), + Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), + RandaoMixes: filledByteSlice2D(uint64(params.BeaconConfig().EpochsPerHistoricalVector), 32), + Validators: make([]*ethpb.Validator, 0), + CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, fieldparams.RootLength), + BlockHash: make([]byte, 32), + }, + Fork: ðpb.Fork{ + PreviousVersion: make([]byte, 4), + CurrentVersion: make([]byte, 4), + }, + Eth1DataVotes: make([]*ethpb.Eth1Data, 0), + HistoricalRoots: make([][]byte, 0), + JustificationBits: bitfield.Bitvector4{0x0}, + FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + LatestBlockHeader: HydrateBeaconHeader(ðpb.BeaconBlockHeader{}), + PreviousJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, fieldparams.RootLength)}, + PreviousEpochParticipation: make([]byte, 0), + CurrentEpochParticipation: make([]byte, 0), + CurrentSyncCommittee: ðpb.SyncCommittee{ + Pubkeys: pubkeys, + AggregatePubkey: make([]byte, 48), + }, + NextSyncCommittee: ðpb.SyncCommittee{ + Pubkeys: pubkeys, + AggregatePubkey: make([]byte, 48), + }, + LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + ExtraData: make([]byte, 0), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, 32), + WithdrawalsRoot: make([]byte, 32), + }, + } + + for _, opt := range options { + err := opt(seed) + if err != nil { + return nil, err + } + } + + var st, err = state_native.InitializeFromProtoUnsafeFulu(seed) + if err != nil { + return nil, err + } + + return st.Copy(), nil +} + // SSZ will fill 2D byte slices with their respective values, so we must fill these in too for round // trip testing. func filledByteSlice2D(length, innerLen uint64) [][]byte { diff --git a/testing/validator-mock/validator_client_mock.go b/testing/validator-mock/validator_client_mock.go index cd4f21b5b044..274ebb39d6c7 100644 --- a/testing/validator-mock/validator_client_mock.go +++ b/testing/validator-mock/validator_client_mock.go @@ -238,7 +238,7 @@ func (mr *MockValidatorClientMockRecorder) ProposeAttestation(arg0, arg1 any) *g } // ProposeAttestationElectra mocks base method. -func (m *MockValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.AttestationElectra) (*eth.AttestResponse, error) { +func (m *MockValidatorClient) ProposeAttestationElectra(arg0 context.Context, arg1 *eth.SingleAttestation) (*eth.AttestResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ProposeAttestationElectra", arg0, arg1) ret0, _ := ret[0].(*eth.AttestResponse) @@ -501,21 +501,6 @@ func (mr *MockValidatorClientMockRecorder) ValidatorStatus(arg0, arg1 any) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorStatus", reflect.TypeOf((*MockValidatorClient)(nil).ValidatorStatus), arg0, arg1) } -// WaitForActivation mocks base method. -func (m *MockValidatorClient) WaitForActivation(arg0 context.Context, arg1 *eth.ValidatorActivationRequest) (eth.BeaconNodeValidator_WaitForActivationClient, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "WaitForActivation", arg0, arg1) - ret0, _ := ret[0].(eth.BeaconNodeValidator_WaitForActivationClient) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// WaitForActivation indicates an expected call of WaitForActivation. -func (mr *MockValidatorClientMockRecorder) WaitForActivation(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitForActivation", reflect.TypeOf((*MockValidatorClient)(nil).WaitForActivation), arg0, arg1) -} - // WaitForChainStart mocks base method. func (m *MockValidatorClient) WaitForChainStart(arg0 context.Context, arg1 *emptypb.Empty) (*eth.ChainStartResponse, error) { m.ctrl.T.Helper() diff --git a/third_party/com_github_grpc_ecosystem_grpc_gateway_v2.patch b/third_party/com_github_grpc_ecosystem_grpc_gateway_v2.patch deleted file mode 100644 index e7b94f9794da..000000000000 --- a/third_party/com_github_grpc_ecosystem_grpc_gateway_v2.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/internal/descriptor/apiconfig/BUILD.bazel b/internal/descriptor/apiconfig/BUILD.bazel -index 80dc57a2..76d4374f 100644 ---- a/internal/descriptor/apiconfig/BUILD.bazel -+++ b/internal/descriptor/apiconfig/BUILD.bazel -@@ -11,6 +11,7 @@ proto_library( - ], - deps = [ - "@go_googleapis//google/api:annotations_proto", -+ "@go_googleapis//google/api:http_proto", - ], - ) - diff --git a/third_party/com_github_grpc_ecosystem_grpc_gateway_v2_fix_emptypb.patch b/third_party/com_github_grpc_ecosystem_grpc_gateway_v2_fix_emptypb.patch deleted file mode 100644 index 707ee5da4b7c..000000000000 --- a/third_party/com_github_grpc_ecosystem_grpc_gateway_v2_fix_emptypb.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/protoc-gen-grpc-gateway/internal/gengateway/template.go b/protoc-gen-grpc-gateway/internal/gengateway/template.go -index 6d3476df..6392af9a 100644 ---- a/protoc-gen-grpc-gateway/internal/gengateway/template.go -+++ b/protoc-gen-grpc-gateway/internal/gengateway/template.go -@@ -243,8 +243,7 @@ It translates gRPC into RESTful JSON APIs. - package {{.GoPkg.Name}} - import ( - github_com_prysmaticlabs_prysm_v4_consensus_types_primitives "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" -- emptypb "github.com/golang/protobuf/ptypes/empty" -- "github.com/golang/protobuf/ptypes/empty" -+ "google.golang.org/protobuf/types/known/emptypb" - {{range $i := .Imports}}{{if $i | printf "%q" | ne "github.com/golang/protobuf/ptypes/empty"}}{{$i | printf "%s\n"}}{{end}}{{end}} - ) - -@@ -257,7 +256,6 @@ var _ = utilities.NewDoubleArray - var _ = metadata.Join - var _ = github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Epoch(0) - var _ = emptypb.Empty{} --var _ = empty.Empty{} - `)) - - handlerTemplate = template.Must(template.New("handler").Parse(` diff --git a/third_party/com_github_grpc_ecosystem_grpc_gateway_v2_prysm_v5.patch b/third_party/com_github_grpc_ecosystem_grpc_gateway_v2_prysm_v5.patch deleted file mode 100644 index 8d568a4b1b26..000000000000 --- a/third_party/com_github_grpc_ecosystem_grpc_gateway_v2_prysm_v5.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/protoc-gen-grpc-gateway/internal/gengateway/template.go b/protoc-gen-grpc-gateway/internal/gengateway/template.go -index 6392af9..2d28493 100644 ---- a/protoc-gen-grpc-gateway/internal/gengateway/template.go -+++ b/protoc-gen-grpc-gateway/internal/gengateway/template.go -@@ -152,13 +152,13 @@ type trailerParams struct { - func typeFromName(name string) string { - lowerName := strings.ToLower(name) - if strings.Contains(lowerName, "epoch") { -- return "github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Epoch" -+ return "github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch" - } else if strings.Contains(lowerName, "slot") { -- return "github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Slot" -+ return "github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot" - } else if strings.Contains(lowerName, "committee") { -- return "github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.CommitteeIndex" -+ return "github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.CommitteeIndex" - } else if strings.Contains(lowerName, "index") { -- return "github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.ValidatorIndex" -+ return "github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex" - } - return "" - } -@@ -242,7 +242,7 @@ It translates gRPC into RESTful JSON APIs. - */{{end}} - package {{.GoPkg.Name}} - import ( -- github_com_prysmaticlabs_prysm_v4_consensus_types_primitives "github.com/prysmaticlabs/prysm/v4/consensus-types/primitives" -+ github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - "google.golang.org/protobuf/types/known/emptypb" - {{range $i := .Imports}}{{if $i | printf "%q" | ne "github.com/golang/protobuf/ptypes/empty"}}{{$i | printf "%s\n"}}{{end}}{{end}} - ) -@@ -254,7 +254,7 @@ var _ status.Status - var _ = runtime.String - var _ = utilities.NewDoubleArray - var _ = metadata.Join --var _ = github_com_prysmaticlabs_prysm_v4_consensus_types_primitives.Epoch(0) -+var _ = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Epoch(0) - var _ = emptypb.Empty{} - `)) - diff --git a/third_party/com_github_karalabe_hid.patch b/third_party/com_github_karalabe_hid.patch new file mode 100644 index 000000000000..3768703835b9 --- /dev/null +++ b/third_party/com_github_karalabe_hid.patch @@ -0,0 +1,77 @@ +diff --git a/BUILD.bazel b/BUILD.bazel +index 9be80a1..0e78457 100755 +--- a/BUILD.bazel ++++ b/BUILD.bazel +@@ -8,58 +8,7 @@ go_library( + srcs = [ + "hid.go", + "hid_disabled.go", +- "hid_enabled.go", +- "wchar.go", + ], +- cgo = True, +- clinkopts = select({ +- "@io_bazel_rules_go//go/platform:darwin": [ +- "-framework CoreFoundation -framework IOKit -lobjc", +- ], +- "@io_bazel_rules_go//go/platform:freebsd": [ +- "-lusb", +- ], +- "@io_bazel_rules_go//go/platform:linux": [ +- "-lrt", +- ], +- "@io_bazel_rules_go//go/platform:windows": [ +- "-lsetupapi", +- ], +- "//conditions:default": [], +- }), +- copts = select({ +- "@io_bazel_rules_go//go/platform:android": [ +- "-DDEFAULT_VISIBILITY=", +- "-DPOLL_NFDS_TYPE=int", +- "-Ihidapi/hidapi", +- "-Ilibusb/libusb -DOS_LINUX -D_GNU_SOURCE -DHAVE_SYS_TIME_H -DHAVE_CLOCK_GETTIME", +- ], +- "@io_bazel_rules_go//go/platform:darwin": [ +- "-DDEFAULT_VISIBILITY=", +- "-DOS_DARWIN -DHAVE_SYS_TIME_H", +- "-DPOLL_NFDS_TYPE=int", +- "-Ihidapi/hidapi", +- ], +- "@io_bazel_rules_go//go/platform:freebsd": [ +- "-DDEFAULT_VISIBILITY=", +- "-DOS_FREEBSD", +- "-DPOLL_NFDS_TYPE=int", +- "-Ihidapi/hidapi", +- ], +- "@io_bazel_rules_go//go/platform:linux": [ +- "-DDEFAULT_VISIBILITY=", +- "-DPOLL_NFDS_TYPE=int", +- "-Ihidapi/hidapi", +- "-Ilibusb/libusb -DOS_LINUX -D_GNU_SOURCE -DHAVE_SYS_TIME_H -DHAVE_CLOCK_GETTIME", +- ], +- "@io_bazel_rules_go//go/platform:windows": [ +- "-DDEFAULT_VISIBILITY=", +- "-DOS_WINDOWS", +- "-DPOLL_NFDS_TYPE=int", +- "-Ihidapi/hidapi", +- ], +- "//conditions:default": [], +- }), + importpath = "github.com/karalabe/hid", + visibility = ["//visibility:public"], + ) +diff --git a/hid_disabled.go b/hid_disabled.go +index fa2c504..0091853 100644 +--- a/hid_disabled.go ++++ b/hid_disabled.go +@@ -4,9 +4,6 @@ + // This file is released under the 3-clause BSD license. Note however that Linux + // support depends on libusb, released under GNU LGPL 2.1 or later. + +-//go:build (!freebsd && !linux && !darwin && !windows) || ios || !cgo +-// +build !freebsd,!linux,!darwin,!windows ios !cgo +- + package hid + + // Supported returns whether this platform is supported by the HID library or not. diff --git a/third_party/usb/AUTHORS b/third_party/hid/AUTHORS similarity index 100% rename from third_party/usb/AUTHORS rename to third_party/hid/AUTHORS diff --git a/third_party/usb/BUILD.bazel b/third_party/hid/BUILD.bazel similarity index 82% rename from third_party/usb/BUILD.bazel rename to third_party/hid/BUILD.bazel index a8a9d019ec2f..5618968123af 100644 --- a/third_party/usb/BUILD.bazel +++ b/third_party/hid/BUILD.bazel @@ -1,6 +1,6 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") -# gazelle:prefix github.com/karalabe/usb +# gazelle:prefix github.com/karalabe/hid go_library( name = "go_default_library", @@ -10,7 +10,7 @@ go_library( "usb.go", "usb_disabled.go", ], - importpath = "github.com/karalabe/usb", + importpath = "github.com/karalabe/hid", visibility = ["@com_github_ethereum_go_ethereum//:__subpackages__"], ) diff --git a/third_party/usb/LICENSE b/third_party/hid/LICENSE similarity index 100% rename from third_party/usb/LICENSE rename to third_party/hid/LICENSE diff --git a/third_party/usb/README.md b/third_party/hid/README.md similarity index 100% rename from third_party/usb/README.md rename to third_party/hid/README.md diff --git a/third_party/usb/hid_disabled.go b/third_party/hid/hid_disabled.go similarity index 99% rename from third_party/usb/hid_disabled.go rename to third_party/hid/hid_disabled.go index e8134ecb5fc2..bfc1e8e9f023 100644 --- a/third_party/usb/hid_disabled.go +++ b/third_party/hid/hid_disabled.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Lesser General Public License along // with the library. If not, see . -package usb +package hid // HidDevice is a live HID USB connected device handle. On platforms that this file // implements, the type lacks the actual HID device and all methods are noop. diff --git a/third_party/usb/raw_disabled.go b/third_party/hid/raw_disabled.go similarity index 99% rename from third_party/usb/raw_disabled.go rename to third_party/hid/raw_disabled.go index e00fa5878f11..bb11dbb7fcd7 100644 --- a/third_party/usb/raw_disabled.go +++ b/third_party/hid/raw_disabled.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Lesser General Public License along // with the library. If not, see . -package usb +package hid // RawDevice is a live raw USB connected device handle. On platforms that this file // implements, the type lacks the actual USB device and all methods are noop. diff --git a/third_party/usb/usb.go b/third_party/hid/usb.go similarity index 97% rename from third_party/usb/usb.go rename to third_party/hid/usb.go index 96a1e2502c1b..4aa13353fe1c 100644 --- a/third_party/usb/usb.go +++ b/third_party/hid/usb.go @@ -13,8 +13,8 @@ // You should have received a copy of the GNU Lesser General Public License along // with the library. If not, see . -// Package usb provide interfaces for generic USB devices. -package usb +// Package hid provide interfaces for generic USB devices. +package hid import "errors" diff --git a/third_party/usb/usb_disabled.go b/third_party/hid/usb_disabled.go similarity index 99% rename from third_party/usb/usb_disabled.go rename to third_party/hid/usb_disabled.go index 6e4a30037a81..4f56a6a3ebe2 100644 --- a/third_party/usb/usb_disabled.go +++ b/third_party/hid/usb_disabled.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Lesser General Public License along // with the library. If not, see . -package usb +package hid // Supported returns whether this platform is supported by the USB library or not. // The goal of this method is to allow programmatically handling platforms that do diff --git a/third_party/usb/usb_test.go b/third_party/hid/usb_test.go similarity index 99% rename from third_party/usb/usb_test.go rename to third_party/hid/usb_test.go index c238c0af432f..c05e21785cb0 100644 --- a/third_party/usb/usb_test.go +++ b/third_party/hid/usb_test.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Lesser General Public License along // with the library. If not, see . -package usb +package hid import ( "os" diff --git a/time/slots/BUILD.bazel b/time/slots/BUILD.bazel index ca39ef4fded9..779cf851e64e 100644 --- a/time/slots/BUILD.bazel +++ b/time/slots/BUILD.bazel @@ -13,6 +13,7 @@ go_library( "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", "//math:go_default_library", + "//runtime/version:go_default_library", "//time:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", @@ -32,6 +33,7 @@ go_test( deps = [ "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//time:go_default_library", diff --git a/time/slots/slottime.go b/time/slots/slottime.go index 03c857bdac36..412ad33d366a 100644 --- a/time/slots/slottime.go +++ b/time/slots/slottime.go @@ -9,7 +9,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" mathutil "github.com/prysmaticlabs/prysm/v5/math" + "github.com/prysmaticlabs/prysm/v5/runtime/version" prysmTime "github.com/prysmaticlabs/prysm/v5/time" + "github.com/sirupsen/logrus" ) // MaxSlotBuffer specifies the max buffer given to slots from @@ -80,6 +82,27 @@ func ToEpoch(slot primitives.Slot) primitives.Epoch { return primitives.Epoch(slot.DivSlot(params.BeaconConfig().SlotsPerEpoch)) } +// ToForkVersion translates a slot into it's corresponding version. +func ToForkVersion(slot primitives.Slot) int { + epoch := ToEpoch(slot) + switch { + case epoch >= params.BeaconConfig().FuluForkEpoch: + return version.Fulu + case epoch >= params.BeaconConfig().ElectraForkEpoch: + return version.Electra + case epoch >= params.BeaconConfig().DenebForkEpoch: + return version.Deneb + case epoch >= params.BeaconConfig().CapellaForkEpoch: + return version.Capella + case epoch >= params.BeaconConfig().BellatrixForkEpoch: + return version.Bellatrix + case epoch >= params.BeaconConfig().AltairForkEpoch: + return version.Altair + default: + return version.Phase0 + } +} + // EpochStart returns the first slot number of the // current epoch. // @@ -263,8 +286,9 @@ func SyncCommitteePeriodStartEpoch(e primitives.Epoch) (primitives.Epoch, error) // SecondsSinceSlotStart returns the number of seconds elapsed since the // given slot start time func SecondsSinceSlotStart(s primitives.Slot, genesisTime, timeStamp uint64) (uint64, error) { - if timeStamp < genesisTime+uint64(s)*params.BeaconConfig().SecondsPerSlot { - return 0, errors.New("could not compute seconds since slot start: invalid timestamp") + limit := genesisTime + uint64(s)*params.BeaconConfig().SecondsPerSlot + if timeStamp < limit { + return 0, fmt.Errorf("could not compute seconds since slot %d start: invalid timestamp, got %d < want %d", s, timeStamp, limit) } return timeStamp - genesisTime - uint64(s)*params.BeaconConfig().SecondsPerSlot, nil } @@ -286,3 +310,25 @@ func WithinVotingWindow(genesisTime uint64, slot primitives.Slot) bool { func MaxSafeEpoch() primitives.Epoch { return primitives.Epoch(math.MaxUint64 / uint64(params.BeaconConfig().SlotsPerEpoch)) } + +// SecondsUntilNextEpochStart returns how many seconds until the next Epoch start from the current time and slot +func SecondsUntilNextEpochStart(genesisTimeSec uint64) (uint64, error) { + currentSlot := CurrentSlot(genesisTimeSec) + firstSlotOfNextEpoch, err := EpochStart(ToEpoch(currentSlot) + 1) + if err != nil { + return 0, err + } + nextEpochStartTime, err := ToTime(genesisTimeSec, firstSlotOfNextEpoch) + if err != nil { + return 0, err + } + es := nextEpochStartTime.Unix() + n := time.Now().Unix() + waitTime := uint64(es - n) + log.WithFields(logrus.Fields{ + "current_slot": currentSlot, + "next_epoch_start_slot": firstSlotOfNextEpoch, + "is_epoch_start": IsEpochStart(currentSlot), + }).Debugf("%d seconds until next epoch", waitTime) + return waitTime, nil +} diff --git a/time/slots/slottime_test.go b/time/slots/slottime_test.go index 1ecaeed761cf..0cc1bbf6c56a 100644 --- a/time/slots/slottime_test.go +++ b/time/slots/slottime_test.go @@ -7,6 +7,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" prysmTime "github.com/prysmaticlabs/prysm/v5/time" @@ -607,3 +608,96 @@ func TestWithinVotingWindow(t *testing.T) { genesisTime = uint64(time.Now().Add(-40 * time.Second).Unix()) require.Equal(t, false, WithinVotingWindow(genesisTime, 3)) } + +func TestSecondsUntilNextEpochStart(t *testing.T) { + secondsInEpoch := uint64(params.BeaconConfig().SlotsPerEpoch) * params.BeaconConfig().SecondsPerSlot + // try slot 3 + genesisTime := uint64(time.Now().Add(-39 * time.Second).Unix()) + waitTime, err := SecondsUntilNextEpochStart(genesisTime) + require.NoError(t, err) + require.Equal(t, secondsInEpoch-(params.BeaconConfig().SecondsPerSlot*3)-3, waitTime) + // try slot 34 + genesisTime = uint64(time.Now().Add(time.Duration(-1*int(secondsInEpoch)-int(params.BeaconConfig().SecondsPerSlot*2)-5) * time.Second).Unix()) + waitTime, err = SecondsUntilNextEpochStart(genesisTime) + require.NoError(t, err) + require.Equal(t, secondsInEpoch-(params.BeaconConfig().SecondsPerSlot*2)-5, waitTime) + + // check if waitTime is correctly EpochStart + n := time.Now().Add(-39 * time.Second) + genesisTime = uint64(n.Unix()) + waitTime, err = SecondsUntilNextEpochStart(genesisTime) + require.NoError(t, err) + require.Equal(t, secondsInEpoch-39, waitTime) + newGenesisTime := uint64(n.Add(time.Duration(-1*int(waitTime)) * time.Second).Unix()) + currentSlot := CurrentSlot(newGenesisTime) + require.Equal(t, true, IsEpochStart(currentSlot)) + +} + +func TestToForkVersion(t *testing.T) { + t.Run("Fulu fork version", func(t *testing.T) { + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.FuluForkEpoch = 100 + params.OverrideBeaconConfig(config) + + slot, err := EpochStart(params.BeaconConfig().FuluForkEpoch) + require.NoError(t, err) + + result := ToForkVersion(slot) + require.Equal(t, version.Fulu, result) + }) + + t.Run("Electra fork version", func(t *testing.T) { + params.SetupTestConfigCleanup(t) + config := params.BeaconConfig() + config.ElectraForkEpoch = 100 + params.OverrideBeaconConfig(config) + + slot, err := EpochStart(params.BeaconConfig().ElectraForkEpoch) + require.NoError(t, err) + + result := ToForkVersion(slot) + require.Equal(t, version.Electra, result) + }) + + t.Run("Deneb fork version", func(t *testing.T) { + slot, err := EpochStart(params.BeaconConfig().DenebForkEpoch) + require.NoError(t, err) + + result := ToForkVersion(slot) + require.Equal(t, version.Deneb, result) + }) + + t.Run("Capella fork version", func(t *testing.T) { + slot, err := EpochStart(params.BeaconConfig().CapellaForkEpoch) + require.NoError(t, err) + + result := ToForkVersion(slot) + require.Equal(t, version.Capella, result) + }) + + t.Run("Bellatrix fork version", func(t *testing.T) { + slot, err := EpochStart(params.BeaconConfig().BellatrixForkEpoch) + require.NoError(t, err) + + result := ToForkVersion(slot) + require.Equal(t, version.Bellatrix, result) + }) + + t.Run("Altair fork version", func(t *testing.T) { + slot, err := EpochStart(params.BeaconConfig().AltairForkEpoch) + require.NoError(t, err) + + result := ToForkVersion(slot) + require.Equal(t, version.Altair, result) + }) + + t.Run("Phase0 fork version", func(t *testing.T) { + slot, err := EpochStart(params.BeaconConfig().AltairForkEpoch) + require.NoError(t, err) + + result := ToForkVersion(slot - 1) + require.Equal(t, version.Phase0, result) + }) +} diff --git a/time/slots/slotutil_test.go b/time/slots/slotutil_test.go index 78729c6d7ac7..58d1f8d9f575 100644 --- a/time/slots/slotutil_test.go +++ b/time/slots/slotutil_test.go @@ -2,6 +2,7 @@ package slots import ( "io" + "os" "testing" "github.com/sirupsen/logrus" @@ -11,5 +12,5 @@ func TestMain(m *testing.M) { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(io.Discard) - m.Run() + os.Exit(m.Run()) } diff --git a/tools/analyzers/comparesame/analyzer.go b/tools/analyzers/comparesame/analyzer.go index 44e69be60efb..e063f228a56c 100644 --- a/tools/analyzers/comparesame/analyzer.go +++ b/tools/analyzers/comparesame/analyzer.go @@ -47,10 +47,10 @@ func run(pass *analysis.Pass) (interface{}, error) { case token.EQL, token.NEQ, token.GEQ, token.LEQ, token.GTR, token.LSS: var xBuf, yBuf bytes.Buffer if err := printer.Fprint(&xBuf, pass.Fset, expr.X); err != nil { - pass.Reportf(expr.X.Pos(), err.Error()) + pass.Reportf(expr.X.Pos(), "error=%s", err) } if err := printer.Fprint(&yBuf, pass.Fset, expr.Y); err != nil { - pass.Reportf(expr.Y.Pos(), err.Error()) + pass.Reportf(expr.Y.Pos(), "error=%s", err) } if xBuf.String() == yBuf.String() { switch expr.Op { diff --git a/tools/analyzers/cryptorand/analyzer.go b/tools/analyzers/cryptorand/analyzer.go index 6abe13b84a25..937e44af05c7 100644 --- a/tools/analyzers/cryptorand/analyzer.go +++ b/tools/analyzers/cryptorand/analyzer.go @@ -4,7 +4,6 @@ package cryptorand import ( "errors" - "fmt" "go/ast" "strings" @@ -62,8 +61,8 @@ func run(pass *analysis.Pass) (interface{}, error) { for pkg, path := range aliases { for _, fn := range disallowedFns { if isPkgDot(stmt.Fun, pkg, fn) { - pass.Reportf(node.Pos(), fmt.Sprintf( - "%s: %s.%s() (from %s)", errWeakCrypto.Error(), pkg, fn, path)) + pass.Reportf(node.Pos(), + "%s: %s.%s() (from %s)", errWeakCrypto.Error(), pkg, fn, path) } } } diff --git a/tools/analyzers/errcheck/BUILD.bazel b/tools/analyzers/errcheck/BUILD.bazel index b6049a7ca0b0..dfc7ef7bec29 100644 --- a/tools/analyzers/errcheck/BUILD.bazel +++ b/tools/analyzers/errcheck/BUILD.bazel @@ -1,23 +1,9 @@ -load("@prysm//tools/go:def.bzl", "go_library", "go_test") +load("@prysm//tools/go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["analyzer.go"], importpath = "github.com/prysmaticlabs/prysm/v5/tools/analyzers/errcheck", visibility = ["//visibility:public"], - deps = [ - "@org_golang_x_tools//go/analysis:go_default_library", - "@org_golang_x_tools//go/analysis/passes/inspect:go_default_library", - "@org_golang_x_tools//go/ast/inspector:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["embedded_walker_test.go"], - embed = [":go_default_library"], - deps = [ - "//testing/assert:go_default_library", - "//testing/require:go_default_library", - ], + deps = ["@com_github_kisielk_errcheck//errcheck:go_default_library"], ) diff --git a/tools/analyzers/errcheck/analyzer.go b/tools/analyzers/errcheck/analyzer.go index 0b1804b9b142..5a4faf566555 100644 --- a/tools/analyzers/errcheck/analyzer.go +++ b/tools/analyzers/errcheck/analyzer.go @@ -3,443 +3,7 @@ package errcheck import ( - "errors" - "fmt" - "go/ast" - "go/token" - "go/types" - - "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/passes/inspect" - "golang.org/x/tools/go/ast/inspector" + analyzer "github.com/kisielk/errcheck/errcheck" ) -// Doc explaining the tool. -const Doc = "This tool enforces all errors must be handled and that type assertions test that " + - "the type implements the given interface to prevent runtime panics." - -// Analyzer runs static analysis. -var Analyzer = &analysis.Analyzer{ - Name: "errcheck", - Doc: Doc, - Requires: []*analysis.Analyzer{inspect.Analyzer}, - Run: run, -} - -var exclusions = make(map[string]bool) - -func init() { - for _, exc := range [...]string{ - // bytes - "(*bytes.Buffer).Write", - "(*bytes.Buffer).WriteByte", - "(*bytes.Buffer).WriteRune", - "(*bytes.Buffer).WriteString", - - // fmt - "fmt.Errorf", - "fmt.Print", - "fmt.Printf", - "fmt.Println", - "fmt.Fprint(*bytes.Buffer)", - "fmt.Fprintf(*bytes.Buffer)", - "fmt.Fprintln(*bytes.Buffer)", - "fmt.Fprint(*strings.Builder)", - "fmt.Fprintf(*strings.Builder)", - "fmt.Fprintln(*strings.Builder)", - "fmt.Fprint(os.Stderr)", - "fmt.Fprintf(os.Stderr)", - "fmt.Fprintln(os.Stderr)", - - // math/rand - "math/rand.Read", - "(*math/rand.Rand).Read", - - // hash - "(hash.Hash).Write", - } { - exclusions[exc] = true - } -} - -func run(pass *analysis.Pass) (interface{}, error) { - inspection, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) - if !ok { - return nil, errors.New("analyzer is not type *inspector.Inspector") - } - - nodeFilter := []ast.Node{ - (*ast.CallExpr)(nil), - (*ast.ExprStmt)(nil), - (*ast.GoStmt)(nil), - (*ast.DeferStmt)(nil), - (*ast.AssignStmt)(nil), - } - - inspection.Preorder(nodeFilter, func(node ast.Node) { - switch stmt := node.(type) { - case *ast.ExprStmt: - if call, ok := stmt.X.(*ast.CallExpr); ok { - if !ignoreCall(pass, call) && callReturnsError(pass, call) { - reportUnhandledError(pass, call.Lparen, call) - } - } - case *ast.GoStmt: - if !ignoreCall(pass, stmt.Call) && callReturnsError(pass, stmt.Call) { - reportUnhandledError(pass, stmt.Call.Lparen, stmt.Call) - } - case *ast.DeferStmt: - if !ignoreCall(pass, stmt.Call) && callReturnsError(pass, stmt.Call) { - reportUnhandledError(pass, stmt.Call.Lparen, stmt.Call) - } - case *ast.AssignStmt: - if len(stmt.Rhs) == 1 { - // single value on rhs; check against lhs identifiers - if call, ok := stmt.Rhs[0].(*ast.CallExpr); ok { - if ignoreCall(pass, call) { - break - } - isError := errorsByArg(pass, call) - for i := 0; i < len(stmt.Lhs); i++ { - if id, ok := stmt.Lhs[i].(*ast.Ident); ok { - // We shortcut calls to recover() because errorsByArg can't - // check its return types for errors since it returns interface{}. - if id.Name == "_" && (isRecover(pass, call) || isError[i]) { - reportUnhandledError(pass, id.NamePos, call) - } - } - } - } else if assert, ok := stmt.Rhs[0].(*ast.TypeAssertExpr); ok { - if assert.Type == nil { - // type switch - break - } - if len(stmt.Lhs) < 2 { - // assertion result not read - reportUnhandledTypeAssertion(pass, stmt.Rhs[0].Pos()) - } else if id, ok := stmt.Lhs[1].(*ast.Ident); ok && id.Name == "_" { - // assertion result ignored - reportUnhandledTypeAssertion(pass, id.NamePos) - } - } - } else { - // multiple value on rhs; in this case a call can't return - // multiple values. Assume len(stmt.Lhs) == len(stmt.Rhs) - for i := 0; i < len(stmt.Lhs); i++ { - if id, ok := stmt.Lhs[i].(*ast.Ident); ok { - if call, ok := stmt.Rhs[i].(*ast.CallExpr); ok { - if ignoreCall(pass, call) { - continue - } - if id.Name == "_" && callReturnsError(pass, call) { - reportUnhandledError(pass, id.NamePos, call) - } - } else if assert, ok := stmt.Rhs[i].(*ast.TypeAssertExpr); ok { - if assert.Type == nil { - // Shouldn't happen anyway, no multi assignment in type switches - continue - } - reportUnhandledError(pass, id.NamePos, nil) - } - } - } - } - default: - } - }) - - return nil, nil -} - -func reportUnhandledError(pass *analysis.Pass, pos token.Pos, call *ast.CallExpr) { - pass.Reportf(pos, "Unhandled error for function call %s", fullName(pass, call)) -} - -func reportUnhandledTypeAssertion(pass *analysis.Pass, pos token.Pos) { - pass.Reportf(pos, "Unhandled type assertion check. You must test whether or not an "+ - "interface implements the asserted type.") -} - -func fullName(pass *analysis.Pass, call *ast.CallExpr) string { - _, fn, ok := selectorAndFunc(pass, call) - if !ok { - return "" - } - return fn.FullName() -} - -// selectorAndFunc tries to get the selector and function from call expression. -// For example, given the call expression representing "a.b()", the selector -// is "a.b" and the function is "b" itself. -// -// The final return value will be true if it is able to do extract a selector -// from the call and look up the function object it refers to. -// -// If the call does not include a selector (like if it is a plain "f()" function call) -// then the final return value will be false. -func selectorAndFunc(pass *analysis.Pass, call *ast.CallExpr) (*ast.SelectorExpr, *types.Func, bool) { - if call == nil || call.Fun == nil { - return nil, nil, false - } - sel, ok := call.Fun.(*ast.SelectorExpr) - if !ok { - return nil, nil, false - } - - fn, ok := pass.TypesInfo.ObjectOf(sel.Sel).(*types.Func) - if !ok { - return nil, nil, false - } - - return sel, fn, true - -} - -func ignoreCall(pass *analysis.Pass, call *ast.CallExpr) bool { - for _, name := range namesForExcludeCheck(pass, call) { - if exclusions[name] { - return true - } - } - return false -} - -var errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) - -func isErrorType(t types.Type) bool { - return types.Implements(t, errorType) -} - -func callReturnsError(pass *analysis.Pass, call *ast.CallExpr) bool { - if isRecover(pass, call) { - return true - } - - for _, isError := range errorsByArg(pass, call) { - if isError { - return true - } - } - - return false -} - -// errorsByArg returns a slice s such that -// len(s) == number of return types of call -// s[i] == true iff return type at position i from left is an error type -func errorsByArg(pass *analysis.Pass, call *ast.CallExpr) []bool { - switch t := pass.TypesInfo.Types[call].Type.(type) { - case *types.Named: - // Single return - return []bool{isErrorType(t)} - case *types.Pointer: - // Single return via pointer - return []bool{isErrorType(t)} - case *types.Tuple: - // Multiple returns - s := make([]bool, t.Len()) - for i := 0; i < t.Len(); i++ { - switch et := t.At(i).Type().(type) { - case *types.Named: - // Single return - s[i] = isErrorType(et) - case *types.Pointer: - // Single return via pointer - s[i] = isErrorType(et) - default: - s[i] = false - } - } - return s - } - return []bool{false} -} - -func isRecover(pass *analysis.Pass, call *ast.CallExpr) bool { - if fun, ok := call.Fun.(*ast.Ident); ok { - if _, ok := pass.TypesInfo.Uses[fun].(*types.Builtin); ok { - return fun.Name == "recover" - } - } - return false -} - -func namesForExcludeCheck(pass *analysis.Pass, call *ast.CallExpr) []string { - sel, fn, ok := selectorAndFunc(pass, call) - if !ok { - return nil - } - - name := fullName(pass, call) - if name == "" { - return nil - } - - // This will be missing for functions without a receiver (like fmt.Printf), - // so just fall back to the function's fullName in that case. - selection, ok := pass.TypesInfo.Selections[sel] - if !ok { - return []string{name} - } - - // This will return with ok false if the function isn't defined - // on an interface, so just fall back to the fullName. - ts, ok := walkThroughEmbeddedInterfaces(selection) - if !ok { - return []string{name} - } - - result := make([]string, len(ts)) - for i, t := range ts { - // Like in fullName, vendored packages will have /vendor/ in their name, - // thus not matching vendored standard library packages. If we - // want to support vendored stdlib packages, we need to implement - // additional logic here. - result[i] = fmt.Sprintf("(%s).%s", t.String(), fn.Name()) - } - return result -} - -// walkThroughEmbeddedInterfaces returns a slice of Interfaces that -// we need to walk through in order to reach the actual definition, -// in an Interface, of the method selected by the given selection. -// -// false will be returned in the second return value if: -// - the right side of the selection is not a function -// - the actual definition of the function is not in an Interface -// -// The returned slice will contain all the interface types that need -// to be walked through to reach the actual definition. -// -// For example, say we have: -// -// type Inner interface {Method()} -// type Middle interface {Inner} -// type Outer interface {Middle} -// type T struct {Outer} -// type U struct {T} -// type V struct {U} -// -// And then the selector: -// -// V.Method -// -// We'll return [Outer, Middle, Inner] by first walking through the embedded structs -// until we reach the Outer interface, then descending through the embedded interfaces -// until we find the one that actually explicitly defines Method. -func walkThroughEmbeddedInterfaces(sel *types.Selection) ([]types.Type, bool) { - fn, ok := sel.Obj().(*types.Func) - if !ok { - return nil, false - } - - // Start off at the receiver. - currentT := sel.Recv() - - // First, we can walk through any Struct fields provided - // by the selection Index() method. We ignore the last - // index because it would give the method itself. - indexes := sel.Index() - for _, fieldIndex := range indexes[:len(indexes)-1] { - currentT = typeAtFieldIndex(currentT, fieldIndex) - } - - // Now currentT is either a type implementing the actual function, - // an Invalid type (if the receiver is a package), or an interface. - // - // If it's not an Interface, then we're done, as this function - // only cares about Interface-defined functions. - // - // If it is an Interface, we potentially need to continue digging until - // we find the Interface that actually explicitly defines the function. - interfaceT, ok := maybeUnname(currentT).(*types.Interface) - if !ok { - return nil, false - } - - // The first interface we pass through is this one we've found. We return the possibly - // wrapping types.Named because it is more useful to work with for callers. - result := []types.Type{currentT} - - // If this interface itself explicitly defines the given method - // then we're done digging. - for !explicitlyDefinesMethod(interfaceT, fn) { - // Otherwise, we find which of the embedded interfaces _does_ - // define the method, add it to our list, and loop. - namedInterfaceT, ok := embeddedInterfaceDefiningMethod(interfaceT, fn) - if !ok { - // This should be impossible as long as we type-checked: either the - // interface or one of its embedded ones must implement the method... - panic(fmt.Sprintf("either %v or one of its embedded interfaces must implement %v", currentT, fn)) - } - result = append(result, namedInterfaceT) - interfaceT, ok = namedInterfaceT.Underlying().(*types.Interface) - if !ok { - panic(fmt.Sprintf("either %v or one of its embedded interfaces must implement %v", currentT, fn)) - } - } - - return result, true -} - -func typeAtFieldIndex(startingAt types.Type, fieldIndex int) types.Type { - t := maybeUnname(maybeDereference(startingAt)) - s, ok := t.(*types.Struct) - if !ok { - panic(fmt.Sprintf("cannot get Field of a type that is not a struct, got a %T", t)) - } - - return s.Field(fieldIndex).Type() -} - -// embeddedInterfaceDefiningMethod searches through any embedded interfaces of the -// passed interface searching for one that defines the given function. If found, the -// types.Named wrapping that interface will be returned along with true in the second value. -// -// If no such embedded interface is found, nil and false are returned. -func embeddedInterfaceDefiningMethod(interfaceT *types.Interface, fn *types.Func) (*types.Named, bool) { - for i := 0; i < interfaceT.NumEmbeddeds(); i++ { - embedded, ok := interfaceT.EmbeddedType(i).(*types.Named) - if !ok { - return nil, false - } - if definesMethod(embedded.Underlying().(*types.Interface), fn) { - return embedded, true - } - } - return nil, false -} - -func explicitlyDefinesMethod(interfaceT *types.Interface, fn *types.Func) bool { - for i := 0; i < interfaceT.NumExplicitMethods(); i++ { - if interfaceT.ExplicitMethod(i) == fn { - return true - } - } - return false -} - -func definesMethod(interfaceT *types.Interface, fn *types.Func) bool { - for i := 0; i < interfaceT.NumMethods(); i++ { - if interfaceT.Method(i) == fn { - return true - } - } - return false -} - -func maybeDereference(t types.Type) types.Type { - p, ok := t.(*types.Pointer) - if ok { - return p.Elem() - } - return t -} - -func maybeUnname(t types.Type) types.Type { - n, ok := t.(*types.Named) - if ok { - return n.Underlying() - } - return t -} +var Analyzer = analyzer.Analyzer diff --git a/tools/analyzers/errcheck/embedded_walker_test.go b/tools/analyzers/errcheck/embedded_walker_test.go deleted file mode 100644 index 247d4c783c82..000000000000 --- a/tools/analyzers/errcheck/embedded_walker_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package errcheck - -import ( - "go/ast" - "go/parser" - "go/token" - "go/types" - "testing" - - "github.com/prysmaticlabs/prysm/v5/testing/assert" - "github.com/prysmaticlabs/prysm/v5/testing/require" -) - -const commonSrc = ` -package p - -type Inner struct {} -func (Inner) Method() - -type Outer struct {Inner} -type OuterP struct {*Inner} - -type InnerInterface interface { - Method() -} - -type OuterInterface interface {InnerInterface} -type MiddleInterfaceStruct struct {OuterInterface} -type OuterInterfaceStruct struct {MiddleInterfaceStruct} - -var c = ` - -type testCase struct { - selector string - expectedOk bool - expected []string -} - -func TestWalkThroughEmbeddedInterfaces(t *testing.T) { - cases := []testCase{ - {"Inner{}.Method", false, nil}, - {"(&Inner{}).Method", false, nil}, - {"Outer{}.Method", false, nil}, - {"InnerInterface.Method", true, []string{"test.InnerInterface"}}, - {"OuterInterface.Method", true, []string{"test.OuterInterface", "test.InnerInterface"}}, - {"OuterInterfaceStruct.Method", true, []string{"test.OuterInterface", "test.InnerInterface"}}, - } - - for _, c := range cases { - fset := token.NewFileSet() - f, err := parser.ParseFile(fset, "test", commonSrc+c.selector, 0) - require.NoError(t, err) - - conf := types.Config{} - info := types.Info{ - Selections: make(map[*ast.SelectorExpr]*types.Selection), - } - _, err = conf.Check("test", fset, []*ast.File{f}, &info) - require.NoError(t, err) - ast.Inspect(f, func(n ast.Node) bool { - s, ok := n.(*ast.SelectorExpr) - if ok { - selection, ok := info.Selections[s] - require.Equal(t, true, ok, "No selection!") - ts, ok := walkThroughEmbeddedInterfaces(selection) - if ok != c.expectedOk { - t.Errorf("expected ok %v got %v", c.expectedOk, ok) - return false - } - if !ok { - return false - } - - require.Equal(t, len(c.expected), len(ts)) - for i, e := range c.expected { - assert.Equal(t, e, ts[i].String(), "mismatch at index %d", i) - } - } - return true - }) - } -} diff --git a/tools/analyzers/maligned/analyzer.go b/tools/analyzers/maligned/analyzer.go index 1b4d4c9fb230..29f727400601 100644 --- a/tools/analyzers/maligned/analyzer.go +++ b/tools/analyzers/maligned/analyzer.go @@ -35,7 +35,7 @@ func run(pass *analysis.Pass) (interface{}, error) { inspection.Preorder(nodeFilter, func(node ast.Node) { if s, ok := node.(*ast.StructType); ok { if err := malign(node.Pos(), pass.TypesInfo.Types[s].Type.(*types.Struct)); err != nil { - pass.Reportf(node.Pos(), err.Error()) + pass.Reportf(node.Pos(), "error=%s", err) } } }) diff --git a/tools/analyzers/properpermissions/analyzer.go b/tools/analyzers/properpermissions/analyzer.go index fe5ffc3736b0..ac3dd8f04d65 100644 --- a/tools/analyzers/properpermissions/analyzer.go +++ b/tools/analyzers/properpermissions/analyzer.go @@ -6,7 +6,6 @@ package properpermissions import ( "errors" - "fmt" "go/ast" "golang.org/x/tools/go/analysis" @@ -75,13 +74,11 @@ func run(pass *analysis.Pass) (interface{}, error) { if isPkgDot(stmt.Fun, alias, fn) { pass.Reportf( node.Pos(), - fmt.Sprintf( - "%v: %s.%s() (from %s)", - errUnsafePackage, - alias, - fn, - pkg, - ), + "%v: %s.%s() (from %s)", + errUnsafePackage, + alias, + fn, + pkg, ) } } diff --git a/tools/analyzers/recursivelock/analyzer.go b/tools/analyzers/recursivelock/analyzer.go index 6434515765c0..d521c2a2e0e6 100644 --- a/tools/analyzers/recursivelock/analyzer.go +++ b/tools/analyzers/recursivelock/analyzer.go @@ -236,30 +236,24 @@ func checkForRecLocks(node ast.Node, pass *analysis.Pass, inspect *inspector.Ins if lockTracker.rLockSelector.isRelated(selMap, 0) { pass.Reportf( node.Pos(), - fmt.Sprintf( - "%v", - errNestedMixedLock, - ), + "%v", + errNestedMixedLock, ) } if lockTracker.rLockSelector.isEqual(selMap, 0) { pass.Reportf( node.Pos(), - fmt.Sprintf( - "%v", - lockmode.ErrorFound(), - ), + "%v", + lockmode.ErrorFound(), ) } else { if stack := hasNestedlock(lockTracker.rLockSelector, lockTracker.goroutinePos, selMap, call, inspect, pass, make(map[string]bool), lockmode.UnLockName()); stack != "" { pass.Reportf( node.Pos(), - fmt.Sprintf( - "%v\n%v", - lockmode.ErrorFound(), - stack, - ), + "%v\n%v", + lockmode.ErrorFound(), + stack, ) } } diff --git a/tools/analyzers/shadowpredecl/analyzer.go b/tools/analyzers/shadowpredecl/analyzer.go index 19fdc47cfbc8..1dfc8766e59a 100644 --- a/tools/analyzers/shadowpredecl/analyzer.go +++ b/tools/analyzers/shadowpredecl/analyzer.go @@ -6,6 +6,7 @@ import ( "errors" "go/ast" "go/token" + "slices" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -100,10 +101,5 @@ func inspectFunctionParams(pass *analysis.Pass, paramList []*ast.Field) { } func shadows(name string) bool { - for _, identifier := range predeclared { - if identifier == name { - return true - } - } - return false + return slices.Contains(predeclared, name) } diff --git a/tools/bootnode/bootnode.go b/tools/bootnode/bootnode.go index a95e5c2ad9f2..2a41f1755e74 100644 --- a/tools/bootnode/bootnode.go +++ b/tools/bootnode/bootnode.go @@ -81,9 +81,7 @@ func main() { logrus.SetLevel(logrus.DebugLevel) // Geth specific logging. - glogger := gethlog.NewGlogHandler(gethlog.StreamHandler(os.Stderr, gethlog.TerminalFormat(false))) - glogger.Verbosity(gethlog.LvlTrace) - gethlog.Root().SetHandler(glogger) + gethlog.SetDefault(gethlog.NewLogger(gethlog.NewTerminalHandlerWithLevel(os.Stderr, gethlog.LvlTrace, true))) log.Debug("Debug logging enabled.") } diff --git a/tools/bootnode/bootnode_test.go b/tools/bootnode/bootnode_test.go index 6474fa244806..a9548f78d193 100644 --- a/tools/bootnode/bootnode_test.go +++ b/tools/bootnode/bootnode_test.go @@ -5,6 +5,7 @@ import ( "crypto/rand" "fmt" "io" + "os" "testing" "time" @@ -23,7 +24,7 @@ func TestMain(m *testing.M) { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(io.Discard) - m.Run() + os.Exit(m.Run()) } func TestBootnode_OK(t *testing.T) { @@ -31,10 +32,13 @@ func TestBootnode_OK(t *testing.T) { require.NoError(t, err) privKey := extractPrivateKey() cfg := discover.Config{ - PrivateKey: privKey, + PrivateKey: privKey, + PingInterval: 100 * time.Millisecond, + NoFindnodeLivenessCheck: true, } listener := createListener(ipAddr, 4000, cfg) defer listener.Close() + time.Sleep(5 * time.Second) cfg.PrivateKey = extractPrivateKey() bootNode, err := enode.Parse(enode.ValidSchemes, listener.Self().String()) diff --git a/tools/pcli/main.go b/tools/pcli/main.go index 65667e118931..810748af5697 100644 --- a/tools/pcli/main.go +++ b/tools/pcli/main.go @@ -299,7 +299,7 @@ var stateTransitionCommand = &cli.Command{ func main() { customFormatter := new(prefixed.TextFormatter) - customFormatter.TimestampFormat = "2006-01-02 15:04:05" + customFormatter.TimestampFormat = time.DateTime customFormatter.FullTimestamp = true log.SetFormatter(customFormatter) app := cli.App{} diff --git a/tools/prysm_image.bzl b/tools/prysm_image.bzl index fa98bb6b6d0a..44814784cec8 100644 --- a/tools/prysm_image.bzl +++ b/tools/prysm_image.bzl @@ -14,6 +14,7 @@ def prysm_image_upload( srcs = [binary], symlinks = symlinks, tags = tags, + extension = "tar.gz", ) oci_image( diff --git a/validator/accounts/testing/mock.go b/validator/accounts/testing/mock.go index e98a0592a12a..a95d5b77e6c7 100644 --- a/validator/accounts/testing/mock.go +++ b/validator/accounts/testing/mock.go @@ -204,7 +204,7 @@ func (*Validator) HasProposerSettings() bool { } // PushProposerSettings for mocking -func (_ *Validator) PushProposerSettings(_ context.Context, _ keymanager.IKeymanager, _ primitives.Slot) error { +func (_ *Validator) PushProposerSettings(_ context.Context, _ keymanager.IKeymanager, _ primitives.Slot, _ bool) error { panic("implement me") } @@ -214,7 +214,7 @@ func (_ *Validator) SetPubKeyToValidatorIndexMap(_ context.Context, _ keymanager } // SignValidatorRegistrationRequest for mocking -func (_ *Validator) SignValidatorRegistrationRequest(_ context.Context, _ iface2.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) { +func (_ *Validator) SignValidatorRegistrationRequest(_ context.Context, _ iface2.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool, error) { panic("implement me") } diff --git a/validator/accounts/wallet/wallet.go b/validator/accounts/wallet/wallet.go index 1ebcab12d48c..8dd3f853cb5f 100644 --- a/validator/accounts/wallet/wallet.go +++ b/validator/accounts/wallet/wallet.go @@ -119,9 +119,7 @@ func IsValid(walletDir string) (bool, error) { } f, err := os.Open(expanded) // #nosec G304 if err != nil { - if strings.Contains(err.Error(), "no such file") || - strings.Contains(err.Error(), "cannot find the file") || - strings.Contains(err.Error(), "cannot find the path") { + if os.IsNotExist(err) { return false, nil } return false, err diff --git a/validator/client/BUILD.bazel b/validator/client/BUILD.bazel index 6c9fbce2acd5..269f6e4b8298 100644 --- a/validator/client/BUILD.bazel +++ b/validator/client/BUILD.bazel @@ -42,13 +42,13 @@ go_library( "//consensus-types/blocks:go_default_library", "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", - "//consensus-types/validator:go_default_library", "//crypto/bls:go_default_library", "//crypto/hash:go_default_library", "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//math:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", @@ -85,7 +85,8 @@ go_library( "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_opencensus_go//plugin/ocgrpc:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp//:go_default_library", + "@io_opentelemetry_go_otel_trace//:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//credentials:go_default_library", @@ -143,7 +144,6 @@ go_test( "//runtime:go_default_library", "//runtime/version:go_default_library", "//testing/assert:go_default_library", - "//testing/mock:go_default_library", "//testing/require:go_default_library", "//testing/util:go_default_library", "//testing/validator-mock:go_default_library", @@ -168,15 +168,12 @@ go_test( "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", - "@com_github_stretchr_testify//mock:go_default_library", "@com_github_tyler_smith_go_bip39//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library", "@com_github_wealdtech_go_eth2_util//:go_default_library", "@in_gopkg_d4l3k_messagediff_v1//:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", - "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//metadata:go_default_library", - "@org_golang_google_grpc//status:go_default_library", "@org_golang_google_protobuf//types/known/emptypb:go_default_library", "@org_uber_go_mock//gomock:go_default_library", ], diff --git a/validator/client/aggregate.go b/validator/client/aggregate.go index ca45c5dd1284..380a78990d39 100644 --- a/validator/client/aggregate.go +++ b/validator/client/aggregate.go @@ -13,13 +13,13 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/runtime/version" prysmTime "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" - "go.opencensus.io/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -32,7 +32,7 @@ func (v *validator) SubmitAggregateAndProof(ctx context.Context, slot primitives ctx, span := trace.StartSpan(ctx, "validator.SubmitAggregateAndProof") defer span.End() - span.AddAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey))) + span.SetAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey))) fmtKey := fmt.Sprintf("%#x", pubKey[:]) duty, err := v.duty(pubKey) @@ -88,6 +88,7 @@ func (v *validator) SubmitAggregateAndProof(ctx context.Context, slot primitives PublicKey: pubKey[:], SlotSignature: slotSig, } + // TODO: look at renaming SubmitAggregateSelectionProof functions as they are GET beacon API var agg ethpb.AggregateAttAndProof if postElectra { res, err := v.validatorClient.SubmitAggregateSelectionProofElectra(ctx, aggSelectionRequest, duty.ValidatorIndex, uint64(len(duty.Committee))) diff --git a/validator/client/attest.go b/validator/client/attest.go index 024bfaa0e813..cd74fb2d181c 100644 --- a/validator/client/attest.go +++ b/validator/client/attest.go @@ -17,13 +17,13 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" prysmTime "github.com/prysmaticlabs/prysm/v5/time" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/prysmaticlabs/prysm/v5/validator/client/iface" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) var failedAttLocalProtectionErr = "attempted to make slashable attestation, rejected by local slashing protection" @@ -35,7 +35,7 @@ var failedAttLocalProtectionErr = "attempted to make slashable attestation, reje func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot, pubKey [fieldparams.BLSPubkeyLength]byte) { ctx, span := trace.StartSpan(ctx, "validator.SubmitAttestation") defer span.End() - span.AddAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey))) + span.SetAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey))) v.waitOneThirdOrValidBlock(ctx, slot) @@ -122,52 +122,46 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot, return } - var indexInCommittee uint64 - var found bool - for i, vID := range duty.Committee { - if vID == duty.ValidatorIndex { - indexInCommittee = uint64(i) - found = true - break - } - } - if !found { - log.Errorf("Validator ID %d not found in committee of %v", duty.ValidatorIndex, duty.Committee) - if v.emitAccountMetrics { - ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc() - } + // Send the attestation to the beacon node. + if err := v.db.SlashableAttestationCheck(ctx, indexedAtt, pubKey, signingRoot, v.emitAccountMetrics, ValidatorAttestFailVec); err != nil { + log.WithError(err).Error("Failed attestation slashing protection check") + log.WithFields( + attestationLogFields(pubKey, indexedAtt), + ).Debug("Attempted slashable attestation details") + tracing.AnnotateError(span, err) return } - // TODO: Extend to Electra - phase0Att, ok := indexedAtt.(*ethpb.IndexedAttestation) - if ok { - // Send the attestation to the beacon node. - if err := v.db.SlashableAttestationCheck(ctx, phase0Att, pubKey, signingRoot, v.emitAccountMetrics, ValidatorAttestFailVec); err != nil { - log.WithError(err).Error("Failed attestation slashing protection check") - log.WithFields( - attestationLogFields(pubKey, indexedAtt), - ).Debug("Attempted slashable attestation details") - tracing.AnnotateError(span, err) - return - } - } - - aggregationBitfield := bitfield.NewBitlist(uint64(len(duty.Committee))) - aggregationBitfield.SetBitAt(indexInCommittee, true) - committeeBits := primitives.NewAttestationCommitteeBits() + var aggregationBitfield bitfield.Bitlist var attResp *ethpb.AttestResponse if postElectra { - attestation := ðpb.AttestationElectra{ - Data: data, - AggregationBits: aggregationBitfield, - CommitteeBits: committeeBits, - Signature: sig, + attestation := ðpb.SingleAttestation{ + Data: data, + AttesterIndex: duty.ValidatorIndex, + CommitteeId: duty.CommitteeIndex, + Signature: sig, } - attestation.CommitteeBits.SetBitAt(uint64(req.CommitteeIndex), true) attResp, err = v.validatorClient.ProposeAttestationElectra(ctx, attestation) } else { + var indexInCommittee uint64 + var found bool + for i, vID := range duty.Committee { + if vID == duty.ValidatorIndex { + indexInCommittee = uint64(i) + found = true + break + } + } + if !found { + log.Errorf("Validator ID %d not found in committee of %v", duty.ValidatorIndex, duty.Committee) + if v.emitAccountMetrics { + ValidatorAttestFailVec.WithLabelValues(fmtKey).Inc() + } + return + } + aggregationBitfield = bitfield.NewBitlist(uint64(len(duty.Committee))) + aggregationBitfield.SetBitAt(indexInCommittee, true) attestation := ðpb.Attestation{ Data: data, AggregationBits: aggregationBitfield, @@ -193,18 +187,19 @@ func (v *validator) SubmitAttestation(ctx context.Context, slot primitives.Slot, return } - span.AddAttributes( + span.SetAttributes( trace.Int64Attribute("slot", int64(slot)), // lint:ignore uintcast -- This conversion is OK for tracing. trace.StringAttribute("attestationHash", fmt.Sprintf("%#x", attResp.AttestationDataRoot)), trace.StringAttribute("blockRoot", fmt.Sprintf("%#x", data.BeaconBlockRoot)), trace.Int64Attribute("justifiedEpoch", int64(data.Source.Epoch)), trace.Int64Attribute("targetEpoch", int64(data.Target.Epoch)), - trace.StringAttribute("aggregationBitfield", fmt.Sprintf("%#x", aggregationBitfield)), ) if postElectra { - span.AddAttributes(trace.StringAttribute("committeeBitfield", fmt.Sprintf("%#x", committeeBits))) + span.SetAttributes(trace.Int64Attribute("attesterIndex", int64(duty.ValidatorIndex))) + span.SetAttributes(trace.Int64Attribute("committeeIndex", int64(duty.CommitteeIndex))) } else { - span.AddAttributes(trace.Int64Attribute("committeeIndex", int64(data.CommitteeIndex))) + span.SetAttributes(trace.StringAttribute("aggregationBitfield", fmt.Sprintf("%#x", aggregationBitfield))) + span.SetAttributes(trace.Int64Attribute("committeeIndex", int64(data.CommitteeIndex))) } if v.emitAccountMetrics { diff --git a/validator/client/attest_test.go b/validator/client/attest_test.go index 68a5b2cce7ec..4ed02f666e6c 100644 --- a/validator/client/attest_test.go +++ b/validator/client/attest_test.go @@ -222,11 +222,11 @@ func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) { gomock.Any(), // epoch ).Times(2).Return(ðpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/) - var generatedAttestation *ethpb.AttestationElectra + var generatedAttestation *ethpb.SingleAttestation m.validatorClient.EXPECT().ProposeAttestationElectra( gomock.Any(), // ctx - gomock.AssignableToTypeOf(ðpb.AttestationElectra{}), - ).Do(func(_ context.Context, att *ethpb.AttestationElectra) { + gomock.AssignableToTypeOf(ðpb.SingleAttestation{}), + ).Do(func(_ context.Context, att *ethpb.SingleAttestation) { generatedAttestation = att }).Return(ðpb.AttestResponse{}, nil /* error */) @@ -236,15 +236,15 @@ func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) { aggregationBitfield.SetBitAt(4, true) committeeBits := primitives.NewAttestationCommitteeBits() committeeBits.SetBitAt(5, true) - expectedAttestation := ðpb.AttestationElectra{ + expectedAttestation := ðpb.SingleAttestation{ Data: ðpb.AttestationData{ BeaconBlockRoot: beaconBlockRoot[:], Target: ðpb.Checkpoint{Root: targetRoot[:]}, Source: ðpb.Checkpoint{Root: sourceRoot[:], Epoch: 3}, }, - AggregationBits: aggregationBitfield, - CommitteeBits: committeeBits, - Signature: make([]byte, 96), + AttesterIndex: validatorIndex, + CommitteeId: 5, + Signature: make([]byte, 96), } root, err := signing.ComputeSigningRoot(expectedAttestation.Data, make([]byte, 32)) diff --git a/validator/client/beacon-api/BUILD.bazel b/validator/client/beacon-api/BUILD.bazel index 7ee6a6ac4f2e..be42a93cd877 100644 --- a/validator/client/beacon-api/BUILD.bazel +++ b/validator/client/beacon-api/BUILD.bazel @@ -3,7 +3,6 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "activation.go", "attestation_data.go", "beacon_api_beacon_chain_client.go", "beacon_api_helpers.go", @@ -51,6 +50,7 @@ go_library( "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", "//encoding/bytesutil:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/forks:go_default_library", "//network/httputil:go_default_library", "//proto/engine/v1:go_default_library", @@ -64,7 +64,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_protobuf//types/known/timestamppb:go_default_library", "@org_golang_x_sync//errgroup:go_default_library", @@ -75,7 +74,6 @@ go_test( name = "go_default_test", size = "small", srcs = [ - "activation_test.go", "attestation_data_test.go", "beacon_api_beacon_chain_client_test.go", "beacon_api_helpers_test.go", @@ -99,8 +97,12 @@ go_test( "propose_beacon_block_blinded_bellatrix_test.go", "propose_beacon_block_blinded_capella_test.go", "propose_beacon_block_blinded_deneb_test.go", + "propose_beacon_block_blinded_electra_test.go", + "propose_beacon_block_blinded_fulu_test.go", "propose_beacon_block_capella_test.go", "propose_beacon_block_deneb_test.go", + "propose_beacon_block_electra_test.go", + "propose_beacon_block_fulu_test.go", "propose_beacon_block_phase0_test.go", "propose_beacon_block_test.go", "propose_exit_test.go", @@ -121,6 +123,7 @@ go_test( deps = [ "//api:go_default_library", "//api/server/structs:go_default_library", + "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/rpc/eth/shared/testing:go_default_library", "//config/params:go_default_library", "//consensus-types/primitives:go_default_library", @@ -129,6 +132,7 @@ go_test( "//network/httputil:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", "//time/slots:go_default_library", diff --git a/validator/client/beacon-api/activation.go b/validator/client/beacon-api/activation.go deleted file mode 100644 index 9e1671ec11fa..000000000000 --- a/validator/client/beacon-api/activation.go +++ /dev/null @@ -1,121 +0,0 @@ -package beacon_api - -import ( - "context" - "strconv" - "time" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/config/params" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "google.golang.org/grpc" -) - -func (c *beaconApiValidatorClient) waitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error) { - return &waitForActivationClient{ - ctx: ctx, - beaconApiValidatorClient: c, - ValidatorActivationRequest: in, - }, nil -} - -type waitForActivationClient struct { - grpc.ClientStream - ctx context.Context - *beaconApiValidatorClient - *ethpb.ValidatorActivationRequest - lastRecvTime time.Time -} - -func computeWaitElements(now, lastRecvTime time.Time) (time.Duration, time.Time) { - nextRecvTime := lastRecvTime.Add(time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second) - - if lastRecvTime.IsZero() { - nextRecvTime = now - } - - if nextRecvTime.Before(now) { - return time.Duration(0), now - } - - return nextRecvTime.Sub(now), nextRecvTime -} - -func (c *waitForActivationClient) Recv() (*ethpb.ValidatorActivationResponse, error) { - waitDuration, nextRecvTime := computeWaitElements(time.Now(), c.lastRecvTime) - - select { - case <-time.After(waitDuration): - c.lastRecvTime = nextRecvTime - - // Represents the target set of keys - stringTargetPubKeysToPubKeys := make(map[string][]byte, len(c.ValidatorActivationRequest.PublicKeys)) - stringTargetPubKeys := make([]string, len(c.ValidatorActivationRequest.PublicKeys)) - - // Represents the set of keys actually returned by the beacon node - stringRetrievedPubKeys := make(map[string]struct{}) - - // Contains all keys in targetPubKeys but not in retrievedPubKeys - var missingPubKeys [][]byte - - var statuses []*ethpb.ValidatorActivationResponse_Status - - for index, publicKey := range c.ValidatorActivationRequest.PublicKeys { - stringPubKey := hexutil.Encode(publicKey) - stringTargetPubKeysToPubKeys[stringPubKey] = publicKey - stringTargetPubKeys[index] = stringPubKey - } - - stateValidators, err := c.stateValidatorsProvider.StateValidators(c.ctx, stringTargetPubKeys, nil, nil) - if err != nil { - return nil, errors.Wrap(err, "failed to get state validators") - } - - for _, data := range stateValidators.Data { - pubkey, err := hexutil.Decode(data.Validator.Pubkey) - if err != nil { - return nil, errors.Wrap(err, "failed to parse validator public key") - } - - stringRetrievedPubKeys[data.Validator.Pubkey] = struct{}{} - - index, err := strconv.ParseUint(data.Index, 10, 64) - if err != nil { - return nil, errors.Wrap(err, "failed to parse validator index") - } - - validatorStatus, ok := beaconAPITogRPCValidatorStatus[data.Status] - if !ok { - return nil, errors.New("invalid validator status: " + data.Status) - } - - statuses = append(statuses, ðpb.ValidatorActivationResponse_Status{ - PublicKey: pubkey, - Index: primitives.ValidatorIndex(index), - Status: ðpb.ValidatorStatusResponse{Status: validatorStatus}, - }) - } - - for stringTargetPubKey, targetPubKey := range stringTargetPubKeysToPubKeys { - if _, ok := stringRetrievedPubKeys[stringTargetPubKey]; !ok { - missingPubKeys = append(missingPubKeys, targetPubKey) - } - } - - for _, missingPubKey := range missingPubKeys { - statuses = append(statuses, ðpb.ValidatorActivationResponse_Status{ - PublicKey: missingPubKey, - Index: primitives.ValidatorIndex(^uint64(0)), - Status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}, - }) - } - - return ðpb.ValidatorActivationResponse{ - Statuses: statuses, - }, nil - case <-c.ctx.Done(): - return nil, errors.New("context canceled") - } -} diff --git a/validator/client/beacon-api/activation_test.go b/validator/client/beacon-api/activation_test.go deleted file mode 100644 index 1088734fc30b..000000000000 --- a/validator/client/beacon-api/activation_test.go +++ /dev/null @@ -1,315 +0,0 @@ -package beacon_api - -import ( - "bytes" - "context" - "encoding/json" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v5/api/server/structs" - "github.com/prysmaticlabs/prysm/v5/config/params" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/testing/assert" - "github.com/prysmaticlabs/prysm/v5/testing/require" - "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" - "go.uber.org/mock/gomock" -) - -func TestComputeWaitElements_LastRecvTimeZero(t *testing.T) { - now := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC) - lastRecvTime := time.Time{} - - waitDuration, nextRecvTime := computeWaitElements(now, lastRecvTime) - - assert.Equal(t, time.Duration(0), waitDuration) - assert.Equal(t, now, nextRecvTime) -} - -func TestComputeWaitElements_LastRecvTimeNotZero(t *testing.T) { - delay := 10 - now := time.Date(2022, 1, 1, 0, 0, delay, 0, time.UTC) - lastRecvTime := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC) - secondsPerSlot := params.BeaconConfig().SecondsPerSlot - - waitDuration, nextRecvTime := computeWaitElements(now, lastRecvTime) - - assert.Equal(t, time.Duration(secondsPerSlot-uint64(delay))*time.Second, waitDuration) - assert.Equal(t, time.Date(2022, 1, 1, 0, 0, int(secondsPerSlot), 0, time.UTC), nextRecvTime) -} - -func TestComputeWaitElements_Longest(t *testing.T) { - now := time.Date(2022, 1, 1, 0, 0, 20, 0, time.UTC) - lastRecvTime := time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC) - - waitDuration, nextRecvTime := computeWaitElements(now, lastRecvTime) - - assert.Equal(t, 0*time.Second, waitDuration) - assert.Equal(t, now, nextRecvTime) -} - -func TestActivation_Nominal(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - stringPubKeys := []string{ - "0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing - "0x80000e851c0f53c3246ff726d7ff7766661ca5e12a07c45c114d208d54f0f8233d4380b2e9aff759d69795d1df905526", // active_exiting - "0x424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", // does not exist - "0x800015473bdc3a7f45ef8eb8abc598bc20021e55ad6e6ad1d745aaef9730dd2c28ec08bf42df18451de94dd4a6d24ec5", // exited_slashed - } - - pubKeys := make([][]byte, len(stringPubKeys)) - for i, stringPubKey := range stringPubKeys { - pubKey, err := hexutil.Decode(stringPubKey) - require.NoError(t, err) - - pubKeys[i] = pubKey - } - - wantedStatuses := []*ethpb.ValidatorActivationResponse_Status{ - { - PublicKey: pubKeys[0], - Index: 55293, - Status: ðpb.ValidatorStatusResponse{ - Status: ethpb.ValidatorStatus_ACTIVE, - }, - }, - { - PublicKey: pubKeys[1], - Index: 11877, - Status: ðpb.ValidatorStatusResponse{ - Status: ethpb.ValidatorStatus_EXITING, - }, - }, - { - PublicKey: pubKeys[3], - Index: 210439, - Status: ðpb.ValidatorStatusResponse{ - Status: ethpb.ValidatorStatus_EXITED, - }, - }, - { - PublicKey: pubKeys[2], - Index: 18446744073709551615, - Status: ðpb.ValidatorStatusResponse{ - Status: ethpb.ValidatorStatus_UNKNOWN_STATUS, - }, - }, - } - - stateValidatorsResponseJson := structs.GetValidatorsResponse{} - - // Instantiate a cancellable context. - ctx, cancel := context.WithCancel(context.Background()) - - jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) - - req := &structs.GetValidatorsRequest{ - Ids: stringPubKeys, - Statuses: []string{}, - } - reqBytes, err := json.Marshal(req) - require.NoError(t, err) - - // Get does not return any result for non existing key - jsonRestHandler.EXPECT().Post( - gomock.Any(), - "/eth/v1/beacon/states/head/validators", - nil, - bytes.NewBuffer(reqBytes), - &stateValidatorsResponseJson, - ).Return( - nil, - ).SetArg( - 4, - structs.GetValidatorsResponse{ - Data: []*structs.ValidatorContainer{ - { - Index: "55293", - Status: "active_ongoing", - Validator: &structs.Validator{ - Pubkey: stringPubKeys[0], - }, - }, - { - Index: "11877", - Status: "active_exiting", - Validator: &structs.Validator{ - Pubkey: stringPubKeys[1], - }, - }, - { - Index: "210439", - Status: "exited_slashed", - Validator: &structs.Validator{ - Pubkey: stringPubKeys[3], - }, - }, - }, - }, - ).Times(1) - - validatorClient := beaconApiValidatorClient{ - stateValidatorsProvider: beaconApiStateValidatorsProvider{ - jsonRestHandler: jsonRestHandler, - }, - } - - waitForActivation, err := validatorClient.WaitForActivation( - ctx, - ðpb.ValidatorActivationRequest{ - PublicKeys: pubKeys, - }, - ) - assert.NoError(t, err) - - // This first call to `Recv` should return immediately - resp, err := waitForActivation.Recv() - require.NoError(t, err) - assert.DeepEqual(t, wantedStatuses, resp.Statuses) - - // Cancel the context after 1 second - go func(ctx context.Context) { - time.Sleep(time.Second) - cancel() - }(ctx) - - // This second call to `Recv` should return after ~12 seconds, but is interrupted by the cancel - _, err = waitForActivation.Recv() - - assert.ErrorContains(t, "context canceled", err) -} - -func TestActivation_InvalidData(t *testing.T) { - testCases := []struct { - name string - data []*structs.ValidatorContainer - expectedErrorMessage string - }{ - { - name: "bad validator public key", - data: []*structs.ValidatorContainer{ - { - Index: "55293", - Status: "active_ongoing", - Validator: &structs.Validator{ - Pubkey: "NotAPubKey", - }, - }, - }, - expectedErrorMessage: "failed to parse validator public key", - }, - { - name: "bad validator index", - data: []*structs.ValidatorContainer{ - { - Index: "NotAnIndex", - Status: "active_ongoing", - Validator: &structs.Validator{ - Pubkey: stringPubKey, - }, - }, - }, - expectedErrorMessage: "failed to parse validator index", - }, - { - name: "invalid validator status", - data: []*structs.ValidatorContainer{ - { - Index: "12345", - Status: "NotAStatus", - Validator: &structs.Validator{ - Pubkey: stringPubKey, - }, - }, - }, - expectedErrorMessage: "invalid validator status: NotAStatus", - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, - func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - ctx := context.Background() - - jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) - jsonRestHandler.EXPECT().Post( - gomock.Any(), - gomock.Any(), - gomock.Any(), - gomock.Any(), - gomock.Any(), - ).Return( - nil, - ).SetArg( - 4, - structs.GetValidatorsResponse{ - Data: testCase.data, - }, - ).Times(1) - - validatorClient := beaconApiValidatorClient{ - stateValidatorsProvider: beaconApiStateValidatorsProvider{ - jsonRestHandler: jsonRestHandler, - }, - } - - waitForActivation, err := validatorClient.WaitForActivation( - ctx, - ðpb.ValidatorActivationRequest{}, - ) - assert.NoError(t, err) - - _, err = waitForActivation.Recv() - assert.ErrorContains(t, testCase.expectedErrorMessage, err) - }, - ) - } -} - -func TestActivation_JsonResponseError(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - ctx := context.Background() - - jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) - jsonRestHandler.EXPECT().Post( - gomock.Any(), - gomock.Any(), - gomock.Any(), - gomock.Any(), - gomock.Any(), - ).Return( - errors.New("some specific json error"), - ).Times(1) - - jsonRestHandler.EXPECT().Get( - gomock.Any(), - gomock.Any(), - gomock.Any(), - ).Return( - errors.New("some specific json error"), - ).Times(1) - - validatorClient := beaconApiValidatorClient{ - stateValidatorsProvider: beaconApiStateValidatorsProvider{ - jsonRestHandler: jsonRestHandler, - }, - } - - waitForActivation, err := validatorClient.WaitForActivation( - ctx, - ðpb.ValidatorActivationRequest{}, - ) - assert.NoError(t, err) - - _, err = waitForActivation.Recv() - assert.ErrorContains(t, "failed to get state validators", err) -} diff --git a/validator/client/beacon-api/beacon_api_validator_client.go b/validator/client/beacon-api/beacon_api_validator_client.go index 56dad0c777eb..e0f923bbc713 100644 --- a/validator/client/beacon-api/beacon_api_validator_client.go +++ b/validator/client/beacon-api/beacon_api_validator_client.go @@ -11,9 +11,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/api/client/event" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/validator/client/iface" - "go.opencensus.io/trace" ) type ValidatorClientOpt func(*beaconApiValidatorClient) @@ -154,8 +154,13 @@ func (c *beaconApiValidatorClient) ProposeAttestation(ctx context.Context, in *e }) } -func (c *beaconApiValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) { - return nil, errors.New("ProposeAttestationElectra is not implemented") +func (c *beaconApiValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { + ctx, span := trace.StartSpan(ctx, "beacon-api.ProposeAttestationElectra") + defer span.End() + + return wrapInMetrics[*ethpb.AttestResponse]("ProposeAttestationElectra", func() (*ethpb.AttestResponse, error) { + return c.proposeAttestationElectra(ctx, in) + }) } func (c *beaconApiValidatorClient) ProposeBeaconBlock(ctx context.Context, in *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) { @@ -190,7 +195,12 @@ func (c *beaconApiValidatorClient) SubmitAggregateSelectionProof(ctx context.Con } func (c *beaconApiValidatorClient) SubmitAggregateSelectionProofElectra(ctx context.Context, in *ethpb.AggregateSelectionRequest, index primitives.ValidatorIndex, committeeLength uint64) (*ethpb.AggregateSelectionElectraResponse, error) { - return nil, errors.New("SubmitAggregateSelectionProofElectra is not implemented") + ctx, span := trace.StartSpan(ctx, "beacon-api.SubmitAggregateSelectionProofElectra") + defer span.End() + + return wrapInMetrics[*ethpb.AggregateSelectionElectraResponse]("SubmitAggregateSelectionProofElectra", func() (*ethpb.AggregateSelectionElectraResponse, error) { + return c.submitAggregateSelectionProofElectra(ctx, in, index, committeeLength) + }) } func (c *beaconApiValidatorClient) SubmitSignedAggregateSelectionProof(ctx context.Context, in *ethpb.SignedAggregateSubmitRequest) (*ethpb.SignedAggregateSubmitResponse, error) { @@ -203,7 +213,12 @@ func (c *beaconApiValidatorClient) SubmitSignedAggregateSelectionProof(ctx conte } func (c *beaconApiValidatorClient) SubmitSignedAggregateSelectionProofElectra(ctx context.Context, in *ethpb.SignedAggregateSubmitElectraRequest) (*ethpb.SignedAggregateSubmitResponse, error) { - return nil, errors.New("SubmitSignedAggregateSelectionProofElectra is not implemented") + ctx, span := trace.StartSpan(ctx, "beacon-api.SubmitSignedAggregateSelectionProofElectra") + defer span.End() + + return wrapInMetrics[*ethpb.SignedAggregateSubmitResponse]("SubmitSignedAggregateSelectionProofElectra", func() (*ethpb.SignedAggregateSubmitResponse, error) { + return c.submitSignedAggregateSelectionProofElectra(ctx, in) + }) } func (c *beaconApiValidatorClient) SubmitSignedContributionAndProof(ctx context.Context, in *ethpb.SignedContributionAndProof) (*empty.Empty, error) { @@ -258,13 +273,6 @@ func (c *beaconApiValidatorClient) ValidatorStatus(ctx context.Context, in *ethp return c.validatorStatus(ctx, in) } -func (c *beaconApiValidatorClient) WaitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error) { - ctx, span := trace.StartSpan(ctx, "beacon-api.WaitForActivation") - defer span.End() - - return c.waitForActivation(ctx, in) -} - // Deprecated: Do not use. func (c *beaconApiValidatorClient) WaitForChainStart(ctx context.Context, _ *empty.Empty) (*ethpb.ChainStartResponse, error) { return c.waitForChainStart(ctx) diff --git a/validator/client/beacon-api/beacon_api_validator_client_test.go b/validator/client/beacon-api/beacon_api_validator_client_test.go index 63599d9f2f82..5e8521a68163 100644 --- a/validator/client/beacon-api/beacon_api_validator_client_test.go +++ b/validator/client/beacon-api/beacon_api_validator_client_test.go @@ -139,7 +139,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockValid(t *testing.T) { jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", map[string]string{"Eth-Consensus-Version": "phase0"}, gomock.Any(), nil, @@ -175,7 +175,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockError(t *testing.T) { jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", map[string]string{"Eth-Consensus-Version": "phase0"}, gomock.Any(), nil, diff --git a/validator/client/beacon-api/beacon_block_json_helpers.go b/validator/client/beacon-api/beacon_block_json_helpers.go index a72de11e2e91..c3e5ab552dfb 100644 --- a/validator/client/beacon-api/beacon_block_json_helpers.go +++ b/validator/client/beacon-api/beacon_block_json_helpers.go @@ -51,6 +51,14 @@ func jsonifyAttestations(attestations []*ethpb.Attestation) []*structs.Attestati return jsonAttestations } +func jsonifySingleAttestations(attestations []*ethpb.SingleAttestation) []*structs.SingleAttestation { + jsonAttestations := make([]*structs.SingleAttestation, len(attestations)) + for index, attestation := range attestations { + jsonAttestations[index] = jsonifySingleAttestation(attestation) + } + return jsonAttestations +} + func jsonifyAttesterSlashings(attesterSlashings []*ethpb.AttesterSlashing) []*structs.AttesterSlashing { jsonAttesterSlashings := make([]*structs.AttesterSlashing, len(attesterSlashings)) for index, attesterSlashing := range attesterSlashings { @@ -164,6 +172,24 @@ func jsonifyAttestation(attestation *ethpb.Attestation) *structs.Attestation { } } +func jsonifyAttestationElectra(attestation *ethpb.AttestationElectra) *structs.AttestationElectra { + return &structs.AttestationElectra{ + AggregationBits: hexutil.Encode(attestation.AggregationBits), + Data: jsonifyAttestationData(attestation.Data), + Signature: hexutil.Encode(attestation.Signature), + CommitteeBits: hexutil.Encode(attestation.CommitteeBits), + } +} + +func jsonifySingleAttestation(attestation *ethpb.SingleAttestation) *structs.SingleAttestation { + return &structs.SingleAttestation{ + CommitteeIndex: uint64ToString(attestation.CommitteeId), + AttesterIndex: uint64ToString(attestation.AttesterIndex), + Data: jsonifyAttestationData(attestation.Data), + Signature: hexutil.Encode(attestation.Signature), + } +} + func jsonifySignedAggregateAndProof(signedAggregateAndProof *ethpb.SignedAggregateAttestationAndProof) *structs.SignedAggregateAttestationAndProof { return &structs.SignedAggregateAttestationAndProof{ Message: &structs.AggregateAttestationAndProof{ @@ -175,6 +201,17 @@ func jsonifySignedAggregateAndProof(signedAggregateAndProof *ethpb.SignedAggrega } } +func jsonifySignedAggregateAndProofElectra(signedAggregateAndProof *ethpb.SignedAggregateAttestationAndProofElectra) *structs.SignedAggregateAttestationAndProofElectra { + return &structs.SignedAggregateAttestationAndProofElectra{ + Message: &structs.AggregateAttestationAndProofElectra{ + AggregatorIndex: uint64ToString(signedAggregateAndProof.Message.AggregatorIndex), + Aggregate: jsonifyAttestationElectra(signedAggregateAndProof.Message.Aggregate), + SelectionProof: hexutil.Encode(signedAggregateAndProof.Message.SelectionProof), + }, + Signature: hexutil.Encode(signedAggregateAndProof.Signature), + } +} + func jsonifyWithdrawals(withdrawals []*enginev1.Withdrawal) []*structs.Withdrawal { jsonWithdrawals := make([]*structs.Withdrawal, len(withdrawals)) for index, withdrawal := range withdrawals { diff --git a/validator/client/beacon-api/beacon_block_proto_helpers.go b/validator/client/beacon-api/beacon_block_proto_helpers.go index dc5c40d0e1cf..52d6bd4d1e87 100644 --- a/validator/client/beacon-api/beacon_block_proto_helpers.go +++ b/validator/client/beacon-api/beacon_block_proto_helpers.go @@ -197,6 +197,39 @@ func convertAttestationToProto(jsonAttestation *structs.Attestation) (*ethpb.Att }, nil } +func convertAttestationElectraToProto(jsonAttestation *structs.AttestationElectra) (*ethpb.AttestationElectra, error) { + if jsonAttestation == nil { + return nil, errors.New("json attestation is nil") + } + + aggregationBits, err := hexutil.Decode(jsonAttestation.AggregationBits) + if err != nil { + return nil, errors.Wrapf(err, "failed to decode aggregation bits `%s`", jsonAttestation.AggregationBits) + } + + attestationData, err := convertAttestationDataToProto(jsonAttestation.Data) + if err != nil { + return nil, errors.Wrap(err, "failed to get attestation data") + } + + signature, err := hexutil.Decode(jsonAttestation.Signature) + if err != nil { + return nil, errors.Wrapf(err, "failed to decode attestation signature `%s`", jsonAttestation.Signature) + } + + committeeBits, err := hexutil.Decode(jsonAttestation.CommitteeBits) + if err != nil { + return nil, errors.Wrapf(err, "failed to decode committee bits `%s`", jsonAttestation.CommitteeBits) + } + + return ðpb.AttestationElectra{ + AggregationBits: aggregationBits, + Data: attestationData, + Signature: signature, + CommitteeBits: committeeBits, + }, nil +} + func convertAttestationsToProto(jsonAttestations []*structs.Attestation) ([]*ethpb.Attestation, error) { var attestations []*ethpb.Attestation for index, jsonAttestation := range jsonAttestations { diff --git a/validator/client/beacon-api/doppelganger.go b/validator/client/beacon-api/doppelganger.go index 2fa3887156f6..f5a27ae43198 100644 --- a/validator/client/beacon-api/doppelganger.go +++ b/validator/client/beacon-api/doppelganger.go @@ -220,7 +220,7 @@ func buildResponse( func (c *beaconApiValidatorClient) indexToLiveness(ctx context.Context, epoch primitives.Epoch, indexes []string) (map[string]bool, error) { livenessResponse, err := c.liveness(ctx, epoch, indexes) if err != nil || livenessResponse.Data == nil { - return nil, errors.Wrapf(err, fmt.Sprintf("failed to get liveness for epoch %d", epoch)) + return nil, errors.Wrapf(err, "failed to get liveness for epoch %d", epoch) } indexToLiveness := make(map[string]bool, len(livenessResponse.Data)) diff --git a/validator/client/beacon-api/get_beacon_block.go b/validator/client/beacon-api/get_beacon_block.go index 16de0e5b9598..3af8f1763474 100644 --- a/validator/client/beacon-api/get_beacon_block.go +++ b/validator/client/beacon-api/get_beacon_block.go @@ -69,8 +69,15 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti blinded = produceBlockV3ResponseJson.ExecutionPayloadBlinded decoder = json.NewDecoder(bytes.NewReader(produceBlockV3ResponseJson.Data)) } + return processBlockResponse(ver, blinded, decoder) +} +// nolint: gocognit +func processBlockResponse(ver string, isBlinded bool, decoder *json.Decoder) (*ethpb.GenericBeaconBlock, error) { var response *ethpb.GenericBeaconBlock + if decoder == nil { + return nil, errors.New("no produce block json decoder found") + } switch ver { case version.String(version.Phase0): jsonPhase0Block := structs.BeaconBlock{} @@ -93,7 +100,7 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti } response = genericBlock case version.String(version.Bellatrix): - if blinded { + if isBlinded { jsonBellatrixBlock := structs.BlindedBeaconBlockBellatrix{} if err := decoder.Decode(&jsonBellatrixBlock); err != nil { return nil, errors.Wrap(err, "failed to decode blinded bellatrix block response json") @@ -115,7 +122,7 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti response = genericBlock } case version.String(version.Capella): - if blinded { + if isBlinded { jsonCapellaBlock := structs.BlindedBeaconBlockCapella{} if err := decoder.Decode(&jsonCapellaBlock); err != nil { return nil, errors.Wrap(err, "failed to decode blinded capella block response json") @@ -137,7 +144,7 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti response = genericBlock } case version.String(version.Deneb): - if blinded { + if isBlinded { jsonDenebBlock := structs.BlindedBeaconBlockDeneb{} if err := decoder.Decode(&jsonDenebBlock); err != nil { return nil, errors.Wrap(err, "failed to decode blinded deneb block response json") @@ -158,6 +165,50 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti } response = genericBlock } + case version.String(version.Electra): + if isBlinded { + jsonElectraBlock := structs.BlindedBeaconBlockElectra{} + if err := decoder.Decode(&jsonElectraBlock); err != nil { + return nil, errors.Wrap(err, "failed to decode blinded electra block response json") + } + genericBlock, err := jsonElectraBlock.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get blinded electra block") + } + response = genericBlock + } else { + jsonElectraBlockContents := structs.BeaconBlockContentsElectra{} + if err := decoder.Decode(&jsonElectraBlockContents); err != nil { + return nil, errors.Wrap(err, "failed to decode electra block response json") + } + genericBlock, err := jsonElectraBlockContents.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get electra block") + } + response = genericBlock + } + case version.String(version.Fulu): + if isBlinded { + jsonFuluBlock := structs.BlindedBeaconBlockFulu{} + if err := decoder.Decode(&jsonFuluBlock); err != nil { + return nil, errors.Wrap(err, "failed to decode blinded fulu block response json") + } + genericBlock, err := jsonFuluBlock.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get blinded fulu block") + } + response = genericBlock + } else { + jsonFuluBlockContents := structs.BeaconBlockContentsFulu{} + if err := decoder.Decode(&jsonFuluBlockContents); err != nil { + return nil, errors.Wrap(err, "failed to decode fulu block response json") + } + genericBlock, err := jsonFuluBlockContents.ToGeneric() + if err != nil { + return nil, errors.Wrap(err, "failed to get fulu block") + } + response = genericBlock + } default: return nil, errors.Errorf("unsupported consensus version `%s`", ver) } diff --git a/validator/client/beacon-api/get_beacon_block_test.go b/validator/client/beacon-api/get_beacon_block_test.go index 68efd0196d89..2e31fee13b61 100644 --- a/validator/client/beacon-api/get_beacon_block_test.go +++ b/validator/client/beacon-api/get_beacon_block_test.go @@ -500,6 +500,96 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) { assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) } +func TestGetBeaconBlock_ElectraValid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := testhelpers.GenerateProtoElectraBeaconBlockContents() + block := testhelpers.GenerateJsonElectraBeaconBlockContents() + bytes, err := json.Marshal(block) + require.NoError(t, err) + + const slot = primitives.Slot(1) + randaoReveal := []byte{2} + graffiti := []byte{3} + + ctx := context.Background() + + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &structs.ProduceBlockV3Response{}, + ).SetArg( + 2, + structs.ProduceBlockV3Response{ + Version: "electra", + ExecutionPayloadBlinded: false, + Data: bytes, + }, + ).Return( + nil, + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti) + require.NoError(t, err) + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_Electra{ + Electra: proto, + }, + IsBlinded: false, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + +func TestGetBeaconBlock_BlindedElectraValid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + proto := testhelpers.GenerateProtoBlindedElectraBeaconBlock() + block := testhelpers.GenerateJsonBlindedElectraBeaconBlock() + bytes, err := json.Marshal(block) + require.NoError(t, err) + + const slot = primitives.Slot(1) + randaoReveal := []byte{2} + graffiti := []byte{3} + + ctx := context.Background() + + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)), + &structs.ProduceBlockV3Response{}, + ).SetArg( + 2, + structs.ProduceBlockV3Response{ + Version: "electra", + ExecutionPayloadBlinded: true, + Data: bytes, + }, + ).Return( + nil, + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti) + require.NoError(t, err) + + expectedBeaconBlock := ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_BlindedElectra{ + BlindedElectra: proto, + }, + IsBlinded: true, + } + + assert.DeepEqual(t, expectedBeaconBlock, beaconBlock) +} + func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() diff --git a/validator/client/beacon-api/propose_attestation.go b/validator/client/beacon-api/propose_attestation.go index be543d14ed6f..7b78e99b25a8 100644 --- a/validator/client/beacon-api/propose_attestation.go +++ b/validator/client/beacon-api/propose_attestation.go @@ -4,29 +4,51 @@ import ( "bytes" "context" "encoding/json" + "net/http" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" ) func (c *beaconApiValidatorClient) proposeAttestation(ctx context.Context, attestation *ethpb.Attestation) (*ethpb.AttestResponse, error) { - if err := checkNilAttestation(attestation); err != nil { + if err := helpers.ValidateNilAttestation(attestation); err != nil { return nil, err } - marshalledAttestation, err := json.Marshal(jsonifyAttestations([]*ethpb.Attestation{attestation})) if err != nil { return nil, err } - if err = c.jsonRestHandler.Post( + headers := map[string]string{"Eth-Consensus-Version": version.String(attestation.Version())} + err = c.jsonRestHandler.Post( ctx, - "/eth/v1/beacon/pool/attestations", - nil, + "/eth/v2/beacon/pool/attestations", + headers, bytes.NewBuffer(marshalledAttestation), nil, - ); err != nil { - return nil, err + ) + errJson := &httputil.DefaultJsonError{} + if err != nil { + // TODO: remove this when v2 becomes default + if !errors.As(err, &errJson) { + return nil, err + } + if errJson.Code != http.StatusNotFound { + return nil, errJson + } + log.Debug("Endpoint /eth/v2/beacon/pool/attestations is not supported, falling back to older endpoints for submit attestation.") + if err = c.jsonRestHandler.Post( + ctx, + "/eth/v1/beacon/pool/attestations", + nil, + bytes.NewBuffer(marshalledAttestation), + nil, + ); err != nil { + return nil, err + } } attestationDataRoot, err := attestation.Data.HashTreeRoot() @@ -37,27 +59,29 @@ func (c *beaconApiValidatorClient) proposeAttestation(ctx context.Context, attes return ðpb.AttestResponse{AttestationDataRoot: attestationDataRoot[:]}, nil } -// checkNilAttestation returns error if attestation or any field of attestation is nil. -func checkNilAttestation(attestation *ethpb.Attestation) error { - if attestation == nil { - return errors.New("attestation is nil") - } - - if attestation.Data == nil { - return errors.New("attestation data is nil") +func (c *beaconApiValidatorClient) proposeAttestationElectra(ctx context.Context, attestation *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { + if err := helpers.ValidateNilAttestation(attestation); err != nil { + return nil, err } - - if attestation.Data.Source == nil || attestation.Data.Target == nil { - return errors.New("source/target in attestation data is nil") + marshalledAttestation, err := json.Marshal(jsonifySingleAttestations([]*ethpb.SingleAttestation{attestation})) + if err != nil { + return nil, err } - - if len(attestation.AggregationBits) == 0 { - return errors.New("attestation aggregation bits is empty") + headers := map[string]string{"Eth-Consensus-Version": version.String(attestation.Version())} + if err = c.jsonRestHandler.Post( + ctx, + "/eth/v2/beacon/pool/attestations", + headers, + bytes.NewBuffer(marshalledAttestation), + nil, + ); err != nil { + return nil, err } - if len(attestation.Signature) == 0 { - return errors.New("attestation signature is empty") + attestationDataRoot, err := attestation.Data.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "failed to compute attestation data root") } - return nil + return ðpb.AttestResponse{AttestationDataRoot: attestationDataRoot[:]}, nil } diff --git a/validator/client/beacon-api/propose_attestation_test.go b/validator/client/beacon-api/propose_attestation_test.go index be6064a0323e..250fc2c2f8f7 100644 --- a/validator/client/beacon-api/propose_attestation_test.go +++ b/validator/client/beacon-api/propose_attestation_test.go @@ -5,9 +5,13 @@ import ( "context" "encoding/json" "errors" + "net/http" "testing" + "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" @@ -56,7 +60,7 @@ func TestProposeAttestation(t *testing.T) { AggregationBits: testhelpers.FillByteSlice(4, 74), Signature: testhelpers.FillByteSlice(96, 82), }, - expectedErrorMessage: "attestation data is nil", + expectedErrorMessage: "attestation is nil", }, { name: "nil source checkpoint", @@ -67,7 +71,7 @@ func TestProposeAttestation(t *testing.T) { }, Signature: testhelpers.FillByteSlice(96, 82), }, - expectedErrorMessage: "source/target in attestation data is nil", + expectedErrorMessage: "attestation's source can't be nil", }, { name: "nil target checkpoint", @@ -78,7 +82,7 @@ func TestProposeAttestation(t *testing.T) { }, Signature: testhelpers.FillByteSlice(96, 82), }, - expectedErrorMessage: "source/target in attestation data is nil", + expectedErrorMessage: "attestation's target can't be nil", }, { name: "nil aggregation bits", @@ -89,18 +93,195 @@ func TestProposeAttestation(t *testing.T) { }, Signature: testhelpers.FillByteSlice(96, 82), }, - expectedErrorMessage: "attestation aggregation bits is empty", + expectedErrorMessage: "attestation's bitfield can't be nil", }, { - name: "nil signature", - attestation: ðpb.Attestation{ - AggregationBits: testhelpers.FillByteSlice(4, 74), + name: "bad request", + attestation: attestation, + expectedErrorMessage: "bad request", + endpointError: errors.New("bad request"), + endpointCall: 1, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + var marshalledAttestations []byte + if helpers.ValidateNilAttestation(test.attestation) == nil { + b, err := json.Marshal(jsonifyAttestations([]*ethpb.Attestation{test.attestation})) + require.NoError(t, err) + marshalledAttestations = b + } + + ctx := context.Background() + + headers := map[string]string{"Eth-Consensus-Version": version.String(test.attestation.Version())} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/beacon/pool/attestations", + headers, + bytes.NewBuffer(marshalledAttestations), + nil, + ).Return( + test.endpointError, + ).Times(test.endpointCall) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + proposeResponse, err := validatorClient.proposeAttestation(ctx, test.attestation) + if test.expectedErrorMessage != "" { + require.ErrorContains(t, test.expectedErrorMessage, err) + return + } + + require.NoError(t, err) + require.NotNil(t, proposeResponse) + + expectedAttestationDataRoot, err := attestation.Data.HashTreeRoot() + require.NoError(t, err) + + // Make sure that the attestation data root is set + assert.DeepEqual(t, expectedAttestationDataRoot[:], proposeResponse.AttestationDataRoot) + }) + } +} + +func TestProposeAttestationFallBack(t *testing.T) { + attestation := ðpb.Attestation{ + AggregationBits: testhelpers.FillByteSlice(4, 74), + Data: ðpb.AttestationData{ + Slot: 75, + CommitteeIndex: 76, + BeaconBlockRoot: testhelpers.FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 78, + Root: testhelpers.FillByteSlice(32, 79), + }, + Target: ðpb.Checkpoint{ + Epoch: 80, + Root: testhelpers.FillByteSlice(32, 81), + }, + }, + Signature: testhelpers.FillByteSlice(96, 82), + } + + ctrl := gomock.NewController(t) + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + var marshalledAttestations []byte + if helpers.ValidateNilAttestation(attestation) == nil { + b, err := json.Marshal(jsonifyAttestations([]*ethpb.Attestation{attestation})) + require.NoError(t, err) + marshalledAttestations = b + } + + ctx := context.Background() + headers := map[string]string{"Eth-Consensus-Version": version.String(attestation.Version())} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/beacon/pool/attestations", + headers, + bytes.NewBuffer(marshalledAttestations), + nil, + ).Return( + &httputil.DefaultJsonError{ + Code: http.StatusNotFound, + }, + ).Times(1) + + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v1/beacon/pool/attestations", + nil, + bytes.NewBuffer(marshalledAttestations), + nil, + ).Return( + nil, + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + proposeResponse, err := validatorClient.proposeAttestation(ctx, attestation) + + require.NoError(t, err) + require.NotNil(t, proposeResponse) + + expectedAttestationDataRoot, err := attestation.Data.HashTreeRoot() + require.NoError(t, err) + + // Make sure that the attestation data root is set + assert.DeepEqual(t, expectedAttestationDataRoot[:], proposeResponse.AttestationDataRoot) +} + +func TestProposeAttestationElectra(t *testing.T) { + attestation := ðpb.SingleAttestation{ + AttesterIndex: 74, + Data: ðpb.AttestationData{ + Slot: 75, + CommitteeIndex: 76, + BeaconBlockRoot: testhelpers.FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 78, + Root: testhelpers.FillByteSlice(32, 79), + }, + Target: ðpb.Checkpoint{ + Epoch: 80, + Root: testhelpers.FillByteSlice(32, 81), + }, + }, + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeId: 83, + } + + tests := []struct { + name string + attestation *ethpb.SingleAttestation + expectedErrorMessage string + endpointError error + endpointCall int + }{ + { + name: "valid", + attestation: attestation, + endpointCall: 1, + }, + { + name: "nil attestation", + expectedErrorMessage: "attestation is nil", + }, + { + name: "nil attestation data", + attestation: ðpb.SingleAttestation{ + AttesterIndex: 74, + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeId: 83, + }, + expectedErrorMessage: "attestation is nil", + }, + { + name: "nil source checkpoint", + attestation: ðpb.SingleAttestation{ + AttesterIndex: 74, Data: ðpb.AttestationData{ - Source: ðpb.Checkpoint{}, Target: ðpb.Checkpoint{}, }, + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeId: 83, + }, + expectedErrorMessage: "attestation's source can't be nil", + }, + { + name: "nil target checkpoint", + attestation: ðpb.SingleAttestation{ + AttesterIndex: 74, + Data: ðpb.AttestationData{ + Source: ðpb.Checkpoint{}, + }, + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeId: 83, }, - expectedErrorMessage: "attestation signature is empty", + expectedErrorMessage: "attestation's target can't be nil", }, { name: "bad request", @@ -117,18 +298,18 @@ func TestProposeAttestation(t *testing.T) { jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) var marshalledAttestations []byte - if checkNilAttestation(test.attestation) == nil { - b, err := json.Marshal(jsonifyAttestations([]*ethpb.Attestation{test.attestation})) + if helpers.ValidateNilAttestation(test.attestation) == nil { + b, err := json.Marshal(jsonifySingleAttestations([]*ethpb.SingleAttestation{test.attestation})) require.NoError(t, err) marshalledAttestations = b } ctx := context.Background() - + headers := map[string]string{"Eth-Consensus-Version": version.String(test.attestation.Version())} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/pool/attestations", - nil, + "/eth/v2/beacon/pool/attestations", + headers, bytes.NewBuffer(marshalledAttestations), nil, ).Return( @@ -136,7 +317,7 @@ func TestProposeAttestation(t *testing.T) { ).Times(test.endpointCall) validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} - proposeResponse, err := validatorClient.proposeAttestation(ctx, test.attestation) + proposeResponse, err := validatorClient.proposeAttestationElectra(ctx, test.attestation) if test.expectedErrorMessage != "" { require.ErrorContains(t, test.expectedErrorMessage, err) return diff --git a/validator/client/beacon-api/propose_beacon_block.go b/validator/client/beacon-api/propose_beacon_block.go index b6d91a447e49..06e4ad1c8406 100644 --- a/validator/client/beacon-api/propose_beacon_block.go +++ b/validator/client/beacon-api/propose_beacon_block.go @@ -14,6 +14,7 @@ import ( ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) +// nolint:gocognit func (c *beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) { var consensusVersion string var beaconBlockRoot [32]byte @@ -120,16 +121,72 @@ func (c *beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *e if err != nil { return nil, errors.Wrap(err, "failed to marshal blinded deneb beacon block contents") } + case *ethpb.GenericSignedBeaconBlock_Electra: + consensusVersion = "electra" + beaconBlockRoot, err = blockType.Electra.Block.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "failed to compute block root for electra beacon block") + } + signedBlock, err := structs.SignedBeaconBlockContentsElectraFromConsensus(blockType.Electra) + if err != nil { + return nil, errors.Wrap(err, "failed to convert electra beacon block contents") + } + marshalledSignedBeaconBlockJson, err = json.Marshal(signedBlock) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal electra beacon block contents") + } + case *ethpb.GenericSignedBeaconBlock_BlindedElectra: + blinded = true + consensusVersion = "electra" + beaconBlockRoot, err = blockType.BlindedElectra.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "failed to compute block root for blinded electra beacon block") + } + signedBlock, err := structs.SignedBlindedBeaconBlockElectraFromConsensus(blockType.BlindedElectra) + if err != nil { + return nil, errors.Wrap(err, "failed to convert blinded electra beacon block contents") + } + marshalledSignedBeaconBlockJson, err = json.Marshal(signedBlock) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal blinded electra beacon block contents") + } + case *ethpb.GenericSignedBeaconBlock_Fulu: + consensusVersion = "fulu" + beaconBlockRoot, err = blockType.Fulu.Block.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "failed to compute block root for fulu beacon block") + } + signedBlock, err := structs.SignedBeaconBlockContentsFuluFromConsensus(blockType.Fulu) + if err != nil { + return nil, errors.Wrap(err, "failed to convert fulu beacon block contents") + } + marshalledSignedBeaconBlockJson, err = json.Marshal(signedBlock) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal fulu beacon block contents") + } + case *ethpb.GenericSignedBeaconBlock_BlindedFulu: + blinded = true + consensusVersion = "fulu" + beaconBlockRoot, err = blockType.BlindedFulu.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "failed to compute block root for blinded fulu beacon block") + } + signedBlock, err := structs.SignedBlindedBeaconBlockFuluFromConsensus(blockType.BlindedFulu) + if err != nil { + return nil, errors.Wrap(err, "failed to convert blinded fulu beacon block contents") + } + marshalledSignedBeaconBlockJson, err = json.Marshal(signedBlock) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal blinded fulu beacon block contents") + } default: return nil, errors.Errorf("unsupported block type %T", in.Block) } - var endpoint string + endpoint := "/eth/v2/beacon/blocks" if blinded { - endpoint = "/eth/v1/beacon/blinded_blocks" - } else { - endpoint = "/eth/v1/beacon/blocks" + endpoint = "/eth/v2/beacon/blinded_blocks" } headers := map[string]string{"Eth-Consensus-Version": consensusVersion} diff --git a/validator/client/beacon-api/propose_beacon_block_altair_test.go b/validator/client/beacon-api/propose_beacon_block_altair_test.go index 540fc2435bc3..46fb29baba3b 100644 --- a/validator/client/beacon-api/propose_beacon_block_altair_test.go +++ b/validator/client/beacon-api/propose_beacon_block_altair_test.go @@ -59,7 +59,7 @@ func TestProposeBeaconBlock_Altair(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "altair"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_bellatrix_test.go b/validator/client/beacon-api/propose_beacon_block_bellatrix_test.go index a154b25e74e6..8bb5c773dbb0 100644 --- a/validator/client/beacon-api/propose_beacon_block_bellatrix_test.go +++ b/validator/client/beacon-api/propose_beacon_block_bellatrix_test.go @@ -76,7 +76,7 @@ func TestProposeBeaconBlock_Bellatrix(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "bellatrix"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_bellatrix_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_bellatrix_test.go index 7f32a5b39ba3..12bf428ea270 100644 --- a/validator/client/beacon-api/propose_beacon_block_blinded_bellatrix_test.go +++ b/validator/client/beacon-api/propose_beacon_block_blinded_bellatrix_test.go @@ -77,7 +77,7 @@ func TestProposeBeaconBlock_BlindedBellatrix(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "bellatrix"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blinded_blocks", + "/eth/v2/beacon/blinded_blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_capella_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_capella_test.go index f858bdacaaf1..9ea5144bb6f7 100644 --- a/validator/client/beacon-api/propose_beacon_block_blinded_capella_test.go +++ b/validator/client/beacon-api/propose_beacon_block_blinded_capella_test.go @@ -79,7 +79,7 @@ func TestProposeBeaconBlock_BlindedCapella(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "capella"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blinded_blocks", + "/eth/v2/beacon/blinded_blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_deneb_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_deneb_test.go index 06601363a7f9..c5da35c264d5 100644 --- a/validator/client/beacon-api/propose_beacon_block_blinded_deneb_test.go +++ b/validator/client/beacon-api/propose_beacon_block_blinded_deneb_test.go @@ -15,7 +15,6 @@ import ( ) func TestProposeBeaconBlock_BlindedDeneb(t *testing.T) { - t.Skip("TODO: Fix this in the beacon-API PR") ctrl := gomock.NewController(t) defer ctrl.Finish() jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) @@ -32,7 +31,7 @@ func TestProposeBeaconBlock_BlindedDeneb(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "deneb"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blinded_blocks", + "/eth/v2/beacon/blinded_blocks", headers, bytes.NewBuffer(denebBytes), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_electra_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_electra_test.go new file mode 100644 index 000000000000..00ac93e2362a --- /dev/null +++ b/validator/client/beacon-api/propose_beacon_block_blinded_electra_test.go @@ -0,0 +1,50 @@ +package beacon_api + +import ( + "bytes" + "context" + "encoding/json" + "testing" + + "github.com/prysmaticlabs/prysm/v5/api/server/structs" + rpctesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared/testing" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" + "go.uber.org/mock/gomock" +) + +func TestProposeBeaconBlock_BlindedElectra(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + var block structs.SignedBlindedBeaconBlockElectra + err := json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &block) + require.NoError(t, err) + genericSignedBlock, err := block.ToGeneric() + require.NoError(t, err) + + electraBytes, err := json.Marshal(block) + require.NoError(t, err) + // Make sure that what we send in the POST body is the marshalled version of the protobuf block + headers := map[string]string{"Eth-Consensus-Version": "electra"} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/beacon/blinded_blocks", + headers, + bytes.NewBuffer(electraBytes), + nil, + ) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + proposeResponse, err := validatorClient.proposeBeaconBlock(context.Background(), genericSignedBlock) + assert.NoError(t, err) + require.NotNil(t, proposeResponse) + + expectedBlockRoot, err := genericSignedBlock.GetBlindedElectra().HashTreeRoot() + require.NoError(t, err) + + // Make sure that the block root is set + assert.DeepEqual(t, expectedBlockRoot[:], proposeResponse.BlockRoot) +} diff --git a/validator/client/beacon-api/propose_beacon_block_blinded_fulu_test.go b/validator/client/beacon-api/propose_beacon_block_blinded_fulu_test.go new file mode 100644 index 000000000000..7a70c21e0f4e --- /dev/null +++ b/validator/client/beacon-api/propose_beacon_block_blinded_fulu_test.go @@ -0,0 +1,50 @@ +package beacon_api + +import ( + "bytes" + "context" + "encoding/json" + "testing" + + "github.com/prysmaticlabs/prysm/v5/api/server/structs" + rpctesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared/testing" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" + "go.uber.org/mock/gomock" +) + +func TestProposeBeaconBlock_BlindedFulu(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + var block structs.SignedBlindedBeaconBlockFulu + err := json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &block) + require.NoError(t, err) + genericSignedBlock, err := block.ToGeneric() + require.NoError(t, err) + + fuluBytes, err := json.Marshal(block) + require.NoError(t, err) + // Make sure that what we send in the POST body is the marshalled version of the protobuf block + headers := map[string]string{"Eth-Consensus-Version": "fulu"} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/beacon/blinded_blocks", + headers, + bytes.NewBuffer(fuluBytes), + nil, + ) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + proposeResponse, err := validatorClient.proposeBeaconBlock(context.Background(), genericSignedBlock) + assert.NoError(t, err) + require.NotNil(t, proposeResponse) + + expectedBlockRoot, err := genericSignedBlock.GetBlindedFulu().HashTreeRoot() + require.NoError(t, err) + + // Make sure that the block root is set + assert.DeepEqual(t, expectedBlockRoot[:], proposeResponse.BlockRoot) +} diff --git a/validator/client/beacon-api/propose_beacon_block_capella_test.go b/validator/client/beacon-api/propose_beacon_block_capella_test.go index 733edfd5cceb..acc57e28bacd 100644 --- a/validator/client/beacon-api/propose_beacon_block_capella_test.go +++ b/validator/client/beacon-api/propose_beacon_block_capella_test.go @@ -76,7 +76,7 @@ func TestProposeBeaconBlock_Capella(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "capella"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_deneb_test.go b/validator/client/beacon-api/propose_beacon_block_deneb_test.go index 1caf7504fa21..31128aa82bc1 100644 --- a/validator/client/beacon-api/propose_beacon_block_deneb_test.go +++ b/validator/client/beacon-api/propose_beacon_block_deneb_test.go @@ -15,8 +15,6 @@ import ( ) func TestProposeBeaconBlock_Deneb(t *testing.T) { - t.Skip("TODO: Fix this in the beacon-API PR") - ctrl := gomock.NewController(t) defer ctrl.Finish() jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) @@ -33,7 +31,7 @@ func TestProposeBeaconBlock_Deneb(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "deneb"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(denebBytes), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_electra_test.go b/validator/client/beacon-api/propose_beacon_block_electra_test.go new file mode 100644 index 000000000000..d7d2a949d7e3 --- /dev/null +++ b/validator/client/beacon-api/propose_beacon_block_electra_test.go @@ -0,0 +1,50 @@ +package beacon_api + +import ( + "bytes" + "context" + "encoding/json" + "testing" + + "github.com/prysmaticlabs/prysm/v5/api/server/structs" + rpctesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared/testing" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" + "go.uber.org/mock/gomock" +) + +func TestProposeBeaconBlock_Electra(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + var blockContents structs.SignedBeaconBlockContentsElectra + err := json.Unmarshal([]byte(rpctesting.ElectraBlockContents), &blockContents) + require.NoError(t, err) + genericSignedBlock, err := blockContents.ToGeneric() + require.NoError(t, err) + + electraBytes, err := json.Marshal(blockContents) + require.NoError(t, err) + // Make sure that what we send in the POST body is the marshalled version of the protobuf block + headers := map[string]string{"Eth-Consensus-Version": "electra"} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/beacon/blocks", + headers, + bytes.NewBuffer(electraBytes), + nil, + ) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + proposeResponse, err := validatorClient.proposeBeaconBlock(context.Background(), genericSignedBlock) + assert.NoError(t, err) + require.NotNil(t, proposeResponse) + + expectedBlockRoot, err := genericSignedBlock.GetElectra().Block.HashTreeRoot() + require.NoError(t, err) + + // Make sure that the block root is set + assert.DeepEqual(t, expectedBlockRoot[:], proposeResponse.BlockRoot) +} diff --git a/validator/client/beacon-api/propose_beacon_block_fulu_test.go b/validator/client/beacon-api/propose_beacon_block_fulu_test.go new file mode 100644 index 000000000000..fb760e6a34e2 --- /dev/null +++ b/validator/client/beacon-api/propose_beacon_block_fulu_test.go @@ -0,0 +1,50 @@ +package beacon_api + +import ( + "bytes" + "context" + "encoding/json" + "testing" + + "github.com/prysmaticlabs/prysm/v5/api/server/structs" + rpctesting "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared/testing" + "github.com/prysmaticlabs/prysm/v5/testing/assert" + "github.com/prysmaticlabs/prysm/v5/testing/require" + "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" + "go.uber.org/mock/gomock" +) + +func TestProposeBeaconBlock_Fulu(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + var blockContents structs.SignedBeaconBlockContentsFulu + err := json.Unmarshal([]byte(rpctesting.FuluBlockContents), &blockContents) + require.NoError(t, err) + genericSignedBlock, err := blockContents.ToGeneric() + require.NoError(t, err) + + fuluBytes, err := json.Marshal(blockContents) + require.NoError(t, err) + // Make sure that what we send in the POST body is the marshalled version of the protobuf block + headers := map[string]string{"Eth-Consensus-Version": "fulu"} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/beacon/blocks", + headers, + bytes.NewBuffer(fuluBytes), + nil, + ) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + proposeResponse, err := validatorClient.proposeBeaconBlock(context.Background(), genericSignedBlock) + assert.NoError(t, err) + require.NotNil(t, proposeResponse) + + expectedBlockRoot, err := genericSignedBlock.GetFulu().Block.HashTreeRoot() + require.NoError(t, err) + + // Make sure that the block root is set + assert.DeepEqual(t, expectedBlockRoot[:], proposeResponse.BlockRoot) +} diff --git a/validator/client/beacon-api/propose_beacon_block_phase0_test.go b/validator/client/beacon-api/propose_beacon_block_phase0_test.go index aa63c28d1159..140461f40015 100644 --- a/validator/client/beacon-api/propose_beacon_block_phase0_test.go +++ b/validator/client/beacon-api/propose_beacon_block_phase0_test.go @@ -55,7 +55,7 @@ func TestProposeBeaconBlock_Phase0(t *testing.T) { headers := map[string]string{"Eth-Consensus-Version": "phase0"} jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/beacon/blocks", + "/eth/v2/beacon/blocks", headers, bytes.NewBuffer(marshalledBlock), nil, diff --git a/validator/client/beacon-api/propose_beacon_block_test.go b/validator/client/beacon-api/propose_beacon_block_test.go index 33e165748ff1..23c37e8c0e25 100644 --- a/validator/client/beacon-api/propose_beacon_block_test.go +++ b/validator/client/beacon-api/propose_beacon_block_test.go @@ -51,7 +51,7 @@ func TestProposeBeaconBlock_Error(t *testing.T) { { name: "phase0", consensusVersion: "phase0", - endpoint: "/eth/v1/beacon/blocks", + endpoint: "/eth/v2/beacon/blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedPhase0Block(), }, @@ -59,7 +59,7 @@ func TestProposeBeaconBlock_Error(t *testing.T) { { name: "altair", consensusVersion: "altair", - endpoint: "/eth/v1/beacon/blocks", + endpoint: "/eth/v2/beacon/blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedAltairBlock(), }, @@ -67,7 +67,7 @@ func TestProposeBeaconBlock_Error(t *testing.T) { { name: "bellatrix", consensusVersion: "bellatrix", - endpoint: "/eth/v1/beacon/blocks", + endpoint: "/eth/v2/beacon/blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedBellatrixBlock(), }, @@ -75,15 +75,23 @@ func TestProposeBeaconBlock_Error(t *testing.T) { { name: "blinded bellatrix", consensusVersion: "bellatrix", - endpoint: "/eth/v1/beacon/blinded_blocks", + endpoint: "/eth/v2/beacon/blinded_blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedBlindedBellatrixBlock(), }, }, + { + name: "capella", + consensusVersion: "capella", + endpoint: "/eth/v2/beacon/blocks", + block: ðpb.GenericSignedBeaconBlock{ + Block: generateSignedCapellaBlock(), + }, + }, { name: "blinded capella", consensusVersion: "capella", - endpoint: "/eth/v1/beacon/blinded_blocks", + endpoint: "/eth/v2/beacon/blinded_blocks", block: ðpb.GenericSignedBeaconBlock{ Block: generateSignedBlindedCapellaBlock(), }, diff --git a/validator/client/beacon-api/status.go b/validator/client/beacon-api/status.go index e0055b34a599..3e04a8b97b54 100644 --- a/validator/client/beacon-api/status.go +++ b/validator/client/beacon-api/status.go @@ -50,6 +50,10 @@ func (c *beaconApiValidatorClient) validatorsStatusResponse(ctx context.Context, []*ethpb.ValidatorStatusResponse, error, ) { + // if no parameters are provided we should just return an empty response + if len(inPubKeys) == 0 && len(inIndexes) == 0 { + return [][]byte{}, []primitives.ValidatorIndex{}, []*ethpb.ValidatorStatusResponse{}, nil + } // Represents the target set of keys stringTargetPubKeysToPubKeys := make(map[string][]byte, len(inPubKeys)) stringTargetPubKeys := make([]string, len(inPubKeys)) @@ -78,6 +82,7 @@ func (c *beaconApiValidatorClient) validatorsStatusResponse(ctx context.Context, return nil, nil, nil, errors.Wrap(err, "failed to get state validators") } + // TODO: we should remove this API call validatorsCountResponse, err := c.prysmChainClient.ValidatorCount(ctx, "head", nil) if err != nil && !errors.Is(err, iface.ErrNotSupported) { return nil, nil, nil, errors.Wrap(err, "failed to get total validator count") diff --git a/validator/client/beacon-api/status_test.go b/validator/client/beacon-api/status_test.go index abff246c8f3e..d8a7370abb84 100644 --- a/validator/client/beacon-api/status_test.go +++ b/validator/client/beacon-api/status_test.go @@ -215,32 +215,23 @@ func TestMultipleValidatorStatus_Nominal(t *testing.T) { assert.DeepEqual(t, &expectedValidatorStatusResponse, actualValidatorStatusResponse) } -func TestMultipleValidatorStatus_Error(t *testing.T) { +func TestMultipleValidatorStatus_No_Keys(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() ctx := context.Background() stateValidatorsProvider := mock.NewMockStateValidatorsProvider(ctrl) - stateValidatorsProvider.EXPECT().StateValidators( - gomock.Any(), - gomock.Any(), - []primitives.ValidatorIndex{}, - nil, - ).Return( - &structs.GetValidatorsResponse{}, - errors.New("a specific error"), - ).Times(1) - validatorClient := beaconApiValidatorClient{stateValidatorsProvider: stateValidatorsProvider} - _, err := validatorClient.MultipleValidatorStatus( + resp, err := validatorClient.MultipleValidatorStatus( ctx, ðpb.MultipleValidatorStatusRequest{ PublicKeys: [][]byte{}, }, ) - require.ErrorContains(t, "failed to get validators status response", err) + require.NoError(t, err) + require.DeepEqual(t, ðpb.MultipleValidatorStatusResponse{}, resp) } func TestGetValidatorsStatusResponse_Nominal_SomeActiveValidators(t *testing.T) { diff --git a/validator/client/beacon-api/submit_aggregate_selection_proof.go b/validator/client/beacon-api/submit_aggregate_selection_proof.go index 3aeda87136d6..da0ae21843f7 100644 --- a/validator/client/beacon-api/submit_aggregate_selection_proof.go +++ b/validator/client/beacon-api/submit_aggregate_selection_proof.go @@ -2,6 +2,8 @@ package beacon_api import ( "context" + "encoding/json" + "net/http" "net/url" "strconv" @@ -10,6 +12,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" ) @@ -19,6 +22,71 @@ func (c *beaconApiValidatorClient) submitAggregateSelectionProof( index primitives.ValidatorIndex, committeeLength uint64, ) (*ethpb.AggregateSelectionResponse, error) { + attestationDataRoot, err := c.getAttestationDataRootFromRequest(ctx, in, committeeLength) + if err != nil { + return nil, err + } + + aggregateAttestationResponse, err := c.aggregateAttestation(ctx, in.Slot, attestationDataRoot, in.CommitteeIndex) + if err != nil { + return nil, err + } + + var attData *structs.Attestation + if err := json.Unmarshal(aggregateAttestationResponse.Data, &attData); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal aggregate attestation data") + } + + aggregatedAttestation, err := convertAttestationToProto(attData) + if err != nil { + return nil, errors.Wrap(err, "failed to convert aggregate attestation json to proto") + } + + return ðpb.AggregateSelectionResponse{ + AggregateAndProof: ðpb.AggregateAttestationAndProof{ + AggregatorIndex: index, + Aggregate: aggregatedAttestation, + SelectionProof: in.SlotSignature, + }, + }, nil +} + +func (c *beaconApiValidatorClient) submitAggregateSelectionProofElectra( + ctx context.Context, + in *ethpb.AggregateSelectionRequest, + index primitives.ValidatorIndex, + committeeLength uint64, +) (*ethpb.AggregateSelectionElectraResponse, error) { + attestationDataRoot, err := c.getAttestationDataRootFromRequest(ctx, in, committeeLength) + if err != nil { + return nil, err + } + + aggregateAttestationResponse, err := c.aggregateAttestationElectra(ctx, in.Slot, attestationDataRoot, in.CommitteeIndex) + if err != nil { + return nil, err + } + + var attData *structs.AttestationElectra + if err := json.Unmarshal(aggregateAttestationResponse.Data, &attData); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal aggregate attestation electra data") + } + + aggregatedAttestation, err := convertAttestationElectraToProto(attData) + if err != nil { + return nil, errors.Wrap(err, "failed to convert aggregate attestation json to proto") + } + + return ðpb.AggregateSelectionElectraResponse{ + AggregateAndProof: ðpb.AggregateAttestationAndProofElectra{ + AggregatorIndex: index, + Aggregate: aggregatedAttestation, + SelectionProof: in.SlotSignature, + }, + }, nil +} + +func (c *beaconApiValidatorClient) getAttestationDataRootFromRequest(ctx context.Context, in *ethpb.AggregateSelectionRequest, committeeLength uint64) ([]byte, error) { isOptimistic, err := c.isOptimistic(ctx) if err != nil { return nil, err @@ -46,35 +114,56 @@ func (c *beaconApiValidatorClient) submitAggregateSelectionProof( if err != nil { return nil, errors.Wrap(err, "failed to calculate attestation data root") } + return attestationDataRoot[:], nil +} - aggregateAttestationResponse, err := c.aggregateAttestation(ctx, in.Slot, attestationDataRoot[:]) - if err != nil { - return nil, err - } +func (c *beaconApiValidatorClient) aggregateAttestation( + ctx context.Context, + slot primitives.Slot, + attestationDataRoot []byte, + committeeIndex primitives.CommitteeIndex, +) (*structs.AggregateAttestationResponse, error) { + params := url.Values{} + params.Add("slot", strconv.FormatUint(uint64(slot), 10)) + params.Add("attestation_data_root", hexutil.Encode(attestationDataRoot)) + params.Add("committee_index", strconv.FormatUint(uint64(committeeIndex), 10)) + endpoint := buildURL("/eth/v2/validator/aggregate_attestation", params) - aggregatedAttestation, err := convertAttestationToProto(aggregateAttestationResponse.Data) + var aggregateAttestationResponse structs.AggregateAttestationResponse + err := c.jsonRestHandler.Get(ctx, endpoint, &aggregateAttestationResponse) + errJson := &httputil.DefaultJsonError{} if err != nil { - return nil, errors.Wrap(err, "failed to convert aggregate attestation json to proto") + // TODO: remove this when v2 becomes default + if !errors.As(err, &errJson) { + return nil, err + } + if errJson.Code != http.StatusNotFound { + return nil, errJson + } + log.Debug("Endpoint /eth/v2/validator/aggregate_attestation is not supported, falling back to older endpoints for get aggregated attestation.") + params = url.Values{} + params.Add("slot", strconv.FormatUint(uint64(slot), 10)) + params.Add("attestation_data_root", hexutil.Encode(attestationDataRoot)) + oldEndpoint := buildURL("/eth/v1/validator/aggregate_attestation", params) + if err = c.jsonRestHandler.Get(ctx, oldEndpoint, &aggregateAttestationResponse); err != nil { + return nil, err + } } - return ðpb.AggregateSelectionResponse{ - AggregateAndProof: ðpb.AggregateAttestationAndProof{ - AggregatorIndex: index, - Aggregate: aggregatedAttestation, - SelectionProof: in.SlotSignature, - }, - }, nil + return &aggregateAttestationResponse, nil } -func (c *beaconApiValidatorClient) aggregateAttestation( +func (c *beaconApiValidatorClient) aggregateAttestationElectra( ctx context.Context, slot primitives.Slot, attestationDataRoot []byte, + committeeIndex primitives.CommitteeIndex, ) (*structs.AggregateAttestationResponse, error) { params := url.Values{} params.Add("slot", strconv.FormatUint(uint64(slot), 10)) params.Add("attestation_data_root", hexutil.Encode(attestationDataRoot)) - endpoint := buildURL("/eth/v1/validator/aggregate_attestation", params) + params.Add("committee_index", strconv.FormatUint(uint64(committeeIndex), 10)) + endpoint := buildURL("/eth/v2/validator/aggregate_attestation", params) var aggregateAttestationResponse structs.AggregateAttestationResponse if err := c.jsonRestHandler.Get(ctx, endpoint, &aggregateAttestationResponse); err != nil { diff --git a/validator/client/beacon-api/submit_aggregate_selection_proof_test.go b/validator/client/beacon-api/submit_aggregate_selection_proof_test.go index f8cdcb1111d9..e5a3a0797567 100644 --- a/validator/client/beacon-api/submit_aggregate_selection_proof_test.go +++ b/validator/client/beacon-api/submit_aggregate_selection_proof_test.go @@ -2,13 +2,16 @@ package beacon_api import ( "context" + "encoding/json" "errors" "fmt" + "net/http" "testing" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -22,7 +25,7 @@ func TestSubmitAggregateSelectionProof(t *testing.T) { pubkeyStr = "0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13" syncingEndpoint = "/eth/v1/node/syncing" attestationDataEndpoint = "/eth/v1/validator/attestation_data" - aggregateAttestationEndpoint = "/eth/v1/validator/aggregate_attestation" + aggregateAttestationEndpoint = "/eth/v2/validator/aggregate_attestation" validatorIndex = primitives.ValidatorIndex(55293) slotSignature = "0x8776a37d6802c4797d113169c5fcfda50e68a32058eb6356a6f00d06d7da64c841a00c7c38b9b94a204751eca53707bd03523ce4797827d9bacff116a6e776a20bbccff4b683bf5201b610797ed0502557a58a65c8395f8a1649b976c3112d15" slot = primitives.Slot(123) @@ -124,15 +127,18 @@ func TestSubmitAggregateSelectionProof(t *testing.T) { test.attestationDataErr, ).Times(test.attestationDataCalled) + attestationJSON, err := json.Marshal(jsonifyAttestation(aggregateAttestation)) + require.NoError(t, err) + // Call attestation data to get attestation data root to query aggregate attestation. jsonRestHandler.EXPECT().Get( gomock.Any(), - fmt.Sprintf("%s?attestation_data_root=%s&slot=%d", aggregateAttestationEndpoint, hexutil.Encode(attestationDataRootBytes[:]), slot), + fmt.Sprintf("%s?attestation_data_root=%s&committee_index=%d&slot=%d", aggregateAttestationEndpoint, hexutil.Encode(attestationDataRootBytes[:]), committeeIndex, slot), &structs.AggregateAttestationResponse{}, ).SetArg( 2, structs.AggregateAttestationResponse{ - Data: jsonifyAttestation(aggregateAttestation), + Data: attestationJSON, }, ).Return( test.aggregateAttestationErr, @@ -181,3 +187,295 @@ func TestSubmitAggregateSelectionProof(t *testing.T) { }) } } + +func TestSubmitAggregateSelectionProofFallBack(t *testing.T) { + const ( + pubkeyStr = "0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13" + syncingEndpoint = "/eth/v1/node/syncing" + attestationDataEndpoint = "/eth/v1/validator/attestation_data" + aggregateAttestationEndpoint = "/eth/v1/validator/aggregate_attestation" + aggregateAttestationV2Endpoint = "/eth/v2/validator/aggregate_attestation" + validatorIndex = primitives.ValidatorIndex(55293) + slotSignature = "0x8776a37d6802c4797d113169c5fcfda50e68a32058eb6356a6f00d06d7da64c841a00c7c38b9b94a204751eca53707bd03523ce4797827d9bacff116a6e776a20bbccff4b683bf5201b610797ed0502557a58a65c8395f8a1649b976c3112d15" + slot = primitives.Slot(123) + committeeIndex = primitives.CommitteeIndex(1) + committeesAtSlot = uint64(1) + ) + + attestationDataResponse := generateValidAttestation(uint64(slot), uint64(committeeIndex)) + attestationDataProto, err := attestationDataResponse.Data.ToConsensus() + require.NoError(t, err) + attestationDataRootBytes, err := attestationDataProto.HashTreeRoot() + require.NoError(t, err) + + aggregateAttestation := ðpb.Attestation{ + AggregationBits: testhelpers.FillByteSlice(4, 74), + Data: attestationDataProto, + Signature: testhelpers.FillByteSlice(96, 82), + } + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + ctx := context.Background() + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + // Call node syncing endpoint to check if head is optimistic. + jsonRestHandler.EXPECT().Get( + gomock.Any(), + syncingEndpoint, + &structs.SyncStatusResponse{}, + ).SetArg( + 2, + structs.SyncStatusResponse{ + Data: &structs.SyncStatusResponseData{ + IsOptimistic: false, + }, + }, + ).Return( + nil, + ).Times(1) + + // Call attestation data to get attestation data root to query aggregate attestation. + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("%s?committee_index=%d&slot=%d", attestationDataEndpoint, committeeIndex, slot), + &structs.GetAttestationDataResponse{}, + ).SetArg( + 2, + attestationDataResponse, + ).Return( + nil, + ).Times(1) + + attestationJSON, err := json.Marshal(jsonifyAttestation(aggregateAttestation)) + require.NoError(t, err) + + // Call attestation data to get attestation data root to query aggregate attestation. + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("%s?attestation_data_root=%s&committee_index=%d&slot=%d", aggregateAttestationV2Endpoint, hexutil.Encode(attestationDataRootBytes[:]), committeeIndex, slot), + &structs.AggregateAttestationResponse{}, + ).Return( + &httputil.DefaultJsonError{ + Code: http.StatusNotFound, + }, + ).Times(1) + + // Call attestation data to get attestation data root to query aggregate attestation. + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("%s?attestation_data_root=%s&slot=%d", aggregateAttestationEndpoint, hexutil.Encode(attestationDataRootBytes[:]), slot), + &structs.AggregateAttestationResponse{}, + ).SetArg( + 2, + structs.AggregateAttestationResponse{ + Data: attestationJSON, + }, + ).Return( + nil, + ).Times(1) + + pubkey, err := hexutil.Decode(pubkeyStr) + require.NoError(t, err) + + slotSignatureBytes, err := hexutil.Decode(slotSignature) + require.NoError(t, err) + + expectedResponse := ðpb.AggregateSelectionResponse{ + AggregateAndProof: ðpb.AggregateAttestationAndProof{ + AggregatorIndex: primitives.ValidatorIndex(55293), + Aggregate: aggregateAttestation, + SelectionProof: slotSignatureBytes, + }, + } + + validatorClient := &beaconApiValidatorClient{ + jsonRestHandler: jsonRestHandler, + stateValidatorsProvider: beaconApiStateValidatorsProvider{ + jsonRestHandler: jsonRestHandler, + }, + dutiesProvider: beaconApiDutiesProvider{ + jsonRestHandler: jsonRestHandler, + }, + } + + actualResponse, err := validatorClient.submitAggregateSelectionProof(ctx, ðpb.AggregateSelectionRequest{ + Slot: slot, + CommitteeIndex: committeeIndex, + PublicKey: pubkey, + SlotSignature: slotSignatureBytes, + }, validatorIndex, committeesAtSlot) + + require.NoError(t, err) + assert.DeepEqual(t, expectedResponse, actualResponse) + +} + +func TestSubmitAggregateSelectionProofElectra(t *testing.T) { + const ( + pubkeyStr = "0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13" + syncingEndpoint = "/eth/v1/node/syncing" + attestationDataEndpoint = "/eth/v1/validator/attestation_data" + aggregateAttestationEndpoint = "/eth/v2/validator/aggregate_attestation" + validatorIndex = primitives.ValidatorIndex(55293) + slotSignature = "0x8776a37d6802c4797d113169c5fcfda50e68a32058eb6356a6f00d06d7da64c841a00c7c38b9b94a204751eca53707bd03523ce4797827d9bacff116a6e776a20bbccff4b683bf5201b610797ed0502557a58a65c8395f8a1649b976c3112d15" + slot = primitives.Slot(123) + committeeIndex = primitives.CommitteeIndex(1) + committeesAtSlot = uint64(1) + ) + + attestationDataResponse := generateValidAttestation(uint64(slot), uint64(committeeIndex)) + attestationDataProto, err := attestationDataResponse.Data.ToConsensus() + require.NoError(t, err) + attestationDataRootBytes, err := attestationDataProto.HashTreeRoot() + require.NoError(t, err) + + aggregateAttestation := ðpb.AttestationElectra{ + AggregationBits: testhelpers.FillByteSlice(4, 74), + Data: attestationDataProto, + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeBits: testhelpers.FillByteSlice(8, 83), + } + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + tests := []struct { + name string + isOptimistic bool + syncingErr error + attestationDataErr error + aggregateAttestationErr error + attestationDataCalled int + aggregateAttestationCalled int + expectedErrorMsg string + committeesAtSlot uint64 + }{ + { + name: "success", + attestationDataCalled: 1, + aggregateAttestationCalled: 1, + }, + { + name: "head is optimistic", + isOptimistic: true, + expectedErrorMsg: "the node is currently optimistic and cannot serve validators", + }, + { + name: "syncing error", + syncingErr: errors.New("bad request"), + expectedErrorMsg: "failed to get syncing status", + }, + { + name: "attestation data error", + attestationDataCalled: 1, + attestationDataErr: errors.New("bad request"), + expectedErrorMsg: fmt.Sprintf("failed to get attestation data for slot=%d and committee_index=%d", slot, committeeIndex), + }, + { + name: "aggregate attestation error", + attestationDataCalled: 1, + aggregateAttestationCalled: 1, + aggregateAttestationErr: errors.New("bad request"), + expectedErrorMsg: "bad request", + }, + { + name: "validator is not an aggregator", + committeesAtSlot: 64, + expectedErrorMsg: "validator is not an aggregator", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ctx := context.Background() + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + + // Call node syncing endpoint to check if head is optimistic. + jsonRestHandler.EXPECT().Get( + gomock.Any(), + syncingEndpoint, + &structs.SyncStatusResponse{}, + ).SetArg( + 2, + structs.SyncStatusResponse{ + Data: &structs.SyncStatusResponseData{ + IsOptimistic: test.isOptimistic, + }, + }, + ).Return( + test.syncingErr, + ).Times(1) + + // Call attestation data to get attestation data root to query aggregate attestation. + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("%s?committee_index=%d&slot=%d", attestationDataEndpoint, committeeIndex, slot), + &structs.GetAttestationDataResponse{}, + ).SetArg( + 2, + attestationDataResponse, + ).Return( + test.attestationDataErr, + ).Times(test.attestationDataCalled) + + attestationJSON, err := json.Marshal(jsonifyAttestationElectra(aggregateAttestation)) + require.NoError(t, err) + + // Call attestation data to get attestation data root to query aggregate attestation. + jsonRestHandler.EXPECT().Get( + gomock.Any(), + fmt.Sprintf("%s?attestation_data_root=%s&committee_index=%d&slot=%d", aggregateAttestationEndpoint, hexutil.Encode(attestationDataRootBytes[:]), committeeIndex, slot), + &structs.AggregateAttestationResponse{}, + ).SetArg( + 2, + structs.AggregateAttestationResponse{ + Data: attestationJSON, + }, + ).Return( + test.aggregateAttestationErr, + ).Times(test.aggregateAttestationCalled) + + pubkey, err := hexutil.Decode(pubkeyStr) + require.NoError(t, err) + + slotSignatureBytes, err := hexutil.Decode(slotSignature) + require.NoError(t, err) + + expectedResponse := ðpb.AggregateSelectionElectraResponse{ + AggregateAndProof: ðpb.AggregateAttestationAndProofElectra{ + AggregatorIndex: primitives.ValidatorIndex(55293), + Aggregate: aggregateAttestation, + SelectionProof: slotSignatureBytes, + }, + } + + validatorClient := &beaconApiValidatorClient{ + jsonRestHandler: jsonRestHandler, + stateValidatorsProvider: beaconApiStateValidatorsProvider{ + jsonRestHandler: jsonRestHandler, + }, + dutiesProvider: beaconApiDutiesProvider{ + jsonRestHandler: jsonRestHandler, + }, + } + + committees := committeesAtSlot + if test.committeesAtSlot != 0 { + committees = test.committeesAtSlot + } + actualResponse, err := validatorClient.submitAggregateSelectionProofElectra(ctx, ðpb.AggregateSelectionRequest{ + Slot: slot, + CommitteeIndex: committeeIndex, + PublicKey: pubkey, + SlotSignature: slotSignatureBytes, + }, validatorIndex, committees) + if test.expectedErrorMsg == "" { + require.NoError(t, err) + assert.DeepEqual(t, expectedResponse, actualResponse) + } else { + require.ErrorContains(t, test.expectedErrorMsg, err) + } + }) + } +} diff --git a/validator/client/beacon-api/submit_signed_aggregate_proof.go b/validator/client/beacon-api/submit_signed_aggregate_proof.go index 9ebca667a63f..7f553d9b2be5 100644 --- a/validator/client/beacon-api/submit_signed_aggregate_proof.go +++ b/validator/client/beacon-api/submit_signed_aggregate_proof.go @@ -4,10 +4,13 @@ import ( "bytes" "context" "encoding/json" + "net/http" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/server/structs" + "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" ) func (c *beaconApiValidatorClient) submitSignedAggregateSelectionProof(ctx context.Context, in *ethpb.SignedAggregateSubmitRequest) (*ethpb.SignedAggregateSubmitResponse, error) { @@ -15,8 +18,44 @@ func (c *beaconApiValidatorClient) submitSignedAggregateSelectionProof(ctx conte if err != nil { return nil, errors.Wrap(err, "failed to marshal SignedAggregateAttestationAndProof") } + headers := map[string]string{"Eth-Consensus-Version": version.String(in.SignedAggregateAndProof.Version())} + err = c.jsonRestHandler.Post(ctx, "/eth/v2/validator/aggregate_and_proofs", headers, bytes.NewBuffer(body), nil) + errJson := &httputil.DefaultJsonError{} + if err != nil { + // TODO: remove this when v2 becomes default + if !errors.As(err, &errJson) { + return nil, err + } + if errJson.Code != http.StatusNotFound { + return nil, errJson + } + log.Debug("Endpoint /eth/v2/validator/aggregate_and_proofs is not supported, falling back to older endpoints for publish aggregate and proofs.") + if err = c.jsonRestHandler.Post( + ctx, + "/eth/v1/validator/aggregate_and_proofs", + nil, + bytes.NewBuffer(body), + nil, + ); err != nil { + return nil, err + } + } + + attestationDataRoot, err := in.SignedAggregateAndProof.Message.Aggregate.Data.HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "failed to compute attestation data root") + } + + return ðpb.SignedAggregateSubmitResponse{AttestationDataRoot: attestationDataRoot[:]}, nil +} - if err = c.jsonRestHandler.Post(ctx, "/eth/v1/validator/aggregate_and_proofs", nil, bytes.NewBuffer(body), nil); err != nil { +func (c *beaconApiValidatorClient) submitSignedAggregateSelectionProofElectra(ctx context.Context, in *ethpb.SignedAggregateSubmitElectraRequest) (*ethpb.SignedAggregateSubmitResponse, error) { + body, err := json.Marshal([]*structs.SignedAggregateAttestationAndProofElectra{jsonifySignedAggregateAndProofElectra(in.SignedAggregateAndProof)}) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal SignedAggregateAttestationAndProofElectra") + } + headers := map[string]string{"Eth-Consensus-Version": version.String(in.SignedAggregateAndProof.Version())} + if err = c.jsonRestHandler.Post(ctx, "/eth/v2/validator/aggregate_and_proofs", headers, bytes.NewBuffer(body), nil); err != nil { return nil, err } diff --git a/validator/client/beacon-api/submit_signed_aggregate_proof_test.go b/validator/client/beacon-api/submit_signed_aggregate_proof_test.go index 1251d3d4d604..c25822d5cfa2 100644 --- a/validator/client/beacon-api/submit_signed_aggregate_proof_test.go +++ b/validator/client/beacon-api/submit_signed_aggregate_proof_test.go @@ -4,11 +4,14 @@ import ( "bytes" "context" "encoding/json" + "net/http" "testing" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api/server/structs" + "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock" @@ -25,12 +28,12 @@ func TestSubmitSignedAggregateSelectionProof_Valid(t *testing.T) { require.NoError(t, err) ctx := context.Background() - + headers := map[string]string{"Eth-Consensus-Version": version.String(signedAggregateAndProof.Message.Version())} jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/validator/aggregate_and_proofs", - nil, + "/eth/v2/validator/aggregate_and_proofs", + headers, bytes.NewBuffer(marshalledSignedAggregateSignedAndProof), nil, ).Return( @@ -57,11 +60,12 @@ func TestSubmitSignedAggregateSelectionProof_BadRequest(t *testing.T) { require.NoError(t, err) ctx := context.Background() + headers := map[string]string{"Eth-Consensus-Version": version.String(signedAggregateAndProof.Message.Version())} jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) jsonRestHandler.EXPECT().Post( gomock.Any(), - "/eth/v1/validator/aggregate_and_proofs", - nil, + "/eth/v2/validator/aggregate_and_proofs", + headers, bytes.NewBuffer(marshalledSignedAggregateSignedAndProof), nil, ).Return( @@ -75,6 +79,110 @@ func TestSubmitSignedAggregateSelectionProof_BadRequest(t *testing.T) { assert.ErrorContains(t, "bad request", err) } +func TestSubmitSignedAggregateSelectionProof_Fallback(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + signedAggregateAndProof := generateSignedAggregateAndProofJson() + marshalledSignedAggregateSignedAndProof, err := json.Marshal([]*structs.SignedAggregateAttestationAndProof{jsonifySignedAggregateAndProof(signedAggregateAndProof)}) + require.NoError(t, err) + + ctx := context.Background() + + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + headers := map[string]string{"Eth-Consensus-Version": version.String(signedAggregateAndProof.Message.Version())} + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/validator/aggregate_and_proofs", + headers, + bytes.NewBuffer(marshalledSignedAggregateSignedAndProof), + nil, + ).Return( + &httputil.DefaultJsonError{ + Code: http.StatusNotFound, + }, + ).Times(1) + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v1/validator/aggregate_and_proofs", + nil, + bytes.NewBuffer(marshalledSignedAggregateSignedAndProof), + nil, + ).Return( + nil, + ).Times(1) + + attestationDataRoot, err := signedAggregateAndProof.Message.Aggregate.Data.HashTreeRoot() + require.NoError(t, err) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + resp, err := validatorClient.submitSignedAggregateSelectionProof(ctx, ðpb.SignedAggregateSubmitRequest{ + SignedAggregateAndProof: signedAggregateAndProof, + }) + require.NoError(t, err) + assert.DeepEqual(t, attestationDataRoot[:], resp.AttestationDataRoot) +} + +func TestSubmitSignedAggregateSelectionProofElectra_Valid(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + signedAggregateAndProofElectra := generateSignedAggregateAndProofElectraJson() + marshalledSignedAggregateSignedAndProofElectra, err := json.Marshal([]*structs.SignedAggregateAttestationAndProofElectra{jsonifySignedAggregateAndProofElectra(signedAggregateAndProofElectra)}) + require.NoError(t, err) + + ctx := context.Background() + headers := map[string]string{"Eth-Consensus-Version": version.String(signedAggregateAndProofElectra.Message.Version())} + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/validator/aggregate_and_proofs", + headers, + bytes.NewBuffer(marshalledSignedAggregateSignedAndProofElectra), + nil, + ).Return( + nil, + ).Times(1) + + attestationDataRoot, err := signedAggregateAndProofElectra.Message.Aggregate.Data.HashTreeRoot() + require.NoError(t, err) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + resp, err := validatorClient.submitSignedAggregateSelectionProofElectra(ctx, ðpb.SignedAggregateSubmitElectraRequest{ + SignedAggregateAndProof: signedAggregateAndProofElectra, + }) + require.NoError(t, err) + assert.DeepEqual(t, attestationDataRoot[:], resp.AttestationDataRoot) +} + +func TestSubmitSignedAggregateSelectionProofElectra_BadRequest(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + signedAggregateAndProofElectra := generateSignedAggregateAndProofElectraJson() + marshalledSignedAggregateSignedAndProofElectra, err := json.Marshal([]*structs.SignedAggregateAttestationAndProofElectra{jsonifySignedAggregateAndProofElectra(signedAggregateAndProofElectra)}) + require.NoError(t, err) + + ctx := context.Background() + headers := map[string]string{"Eth-Consensus-Version": version.String(signedAggregateAndProofElectra.Message.Version())} + jsonRestHandler := mock.NewMockJsonRestHandler(ctrl) + jsonRestHandler.EXPECT().Post( + gomock.Any(), + "/eth/v2/validator/aggregate_and_proofs", + headers, + bytes.NewBuffer(marshalledSignedAggregateSignedAndProofElectra), + nil, + ).Return( + errors.New("bad request"), + ).Times(1) + + validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler} + _, err = validatorClient.submitSignedAggregateSelectionProofElectra(ctx, ðpb.SignedAggregateSubmitElectraRequest{ + SignedAggregateAndProof: signedAggregateAndProofElectra, + }) + assert.ErrorContains(t, "bad request", err) +} + func generateSignedAggregateAndProofJson() *ethpb.SignedAggregateAttestationAndProof { return ðpb.SignedAggregateAttestationAndProof{ Message: ðpb.AggregateAttestationAndProof{ @@ -101,3 +209,31 @@ func generateSignedAggregateAndProofJson() *ethpb.SignedAggregateAttestationAndP Signature: testhelpers.FillByteSlice(96, 82), } } + +func generateSignedAggregateAndProofElectraJson() *ethpb.SignedAggregateAttestationAndProofElectra { + return ðpb.SignedAggregateAttestationAndProofElectra{ + Message: ðpb.AggregateAttestationAndProofElectra{ + AggregatorIndex: 72, + Aggregate: ðpb.AttestationElectra{ + AggregationBits: testhelpers.FillByteSlice(4, 74), + Data: ðpb.AttestationData{ + Slot: 75, + CommitteeIndex: 76, + BeaconBlockRoot: testhelpers.FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 78, + Root: testhelpers.FillByteSlice(32, 79), + }, + Target: ðpb.Checkpoint{ + Epoch: 80, + Root: testhelpers.FillByteSlice(32, 81), + }, + }, + Signature: testhelpers.FillByteSlice(96, 82), + CommitteeBits: testhelpers.FillByteSlice(8, 83), + }, + SelectionProof: testhelpers.FillByteSlice(96, 84), + }, + Signature: testhelpers.FillByteSlice(96, 85), + } +} diff --git a/validator/client/beacon-api/test-helpers/BUILD.bazel b/validator/client/beacon-api/test-helpers/BUILD.bazel index 725b3f5907b6..e8527eed9dcf 100644 --- a/validator/client/beacon-api/test-helpers/BUILD.bazel +++ b/validator/client/beacon-api/test-helpers/BUILD.bazel @@ -8,6 +8,7 @@ go_library( "bellatrix_beacon_block_test_helpers.go", "capella_beacon_block_test_helpers.go", "deneb_beacon_block_test_helpers.go", + "electra_beacon_block_test_helpers.go", "phase0_beacon_block_test_helpers.go", "test_helpers.go", ], diff --git a/validator/client/beacon-api/test-helpers/electra_beacon_block_test_helpers.go b/validator/client/beacon-api/test-helpers/electra_beacon_block_test_helpers.go new file mode 100644 index 000000000000..3cd0640931ea --- /dev/null +++ b/validator/client/beacon-api/test-helpers/electra_beacon_block_test_helpers.go @@ -0,0 +1,1012 @@ +package test_helpers + +import ( + "github.com/prysmaticlabs/prysm/v5/api/server/structs" + "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" +) + +func GenerateProtoElectraBeaconBlockContents() *ethpb.BeaconBlockContentsElectra { + return ðpb.BeaconBlockContentsElectra{ + Block: ðpb.BeaconBlockElectra{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: FillByteSlice(32, 3), + StateRoot: FillByteSlice(32, 4), + Body: ðpb.BeaconBlockBodyElectra{ + RandaoReveal: FillByteSlice(96, 5), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: FillByteSlice(32, 6), + DepositCount: 7, + BlockHash: FillByteSlice(32, 8), + }, + Graffiti: FillByteSlice(32, 9), + ProposerSlashings: []*ethpb.ProposerSlashing{ + { + Header_1: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 10, + ProposerIndex: 11, + ParentRoot: FillByteSlice(32, 12), + StateRoot: FillByteSlice(32, 13), + BodyRoot: FillByteSlice(32, 14), + }, + Signature: FillByteSlice(96, 15), + }, + Header_2: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 16, + ProposerIndex: 17, + ParentRoot: FillByteSlice(32, 18), + StateRoot: FillByteSlice(32, 19), + BodyRoot: FillByteSlice(32, 20), + }, + Signature: FillByteSlice(96, 21), + }, + }, + { + Header_1: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 22, + ProposerIndex: 23, + ParentRoot: FillByteSlice(32, 24), + StateRoot: FillByteSlice(32, 25), + BodyRoot: FillByteSlice(32, 26), + }, + Signature: FillByteSlice(96, 27), + }, + Header_2: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 28, + ProposerIndex: 29, + ParentRoot: FillByteSlice(32, 30), + StateRoot: FillByteSlice(32, 31), + BodyRoot: FillByteSlice(32, 32), + }, + Signature: FillByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*ethpb.AttesterSlashingElectra{ + { + Attestation_1: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{34, 35}, + Data: ðpb.AttestationData{ + Slot: 36, + CommitteeIndex: 37, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 39, + Root: FillByteSlice(32, 40), + }, + Target: ðpb.Checkpoint{ + Epoch: 41, + Root: FillByteSlice(32, 42), + }, + }, + Signature: FillByteSlice(96, 43), + }, + Attestation_2: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{44, 45}, + Data: ðpb.AttestationData{ + Slot: 46, + CommitteeIndex: 47, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 49, + Root: FillByteSlice(32, 50), + }, + Target: ðpb.Checkpoint{ + Epoch: 51, + Root: FillByteSlice(32, 52), + }, + }, + Signature: FillByteSlice(96, 53), + }, + }, + }, + Attestations: []*ethpb.AttestationElectra{ + { + AggregationBits: FillByteSlice(4, 74), + Data: ðpb.AttestationData{ + Slot: 75, + CommitteeIndex: 76, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 78, + Root: FillByteSlice(32, 79), + }, + Target: ðpb.Checkpoint{ + Epoch: 80, + Root: FillByteSlice(32, 81), + }, + }, + Signature: FillByteSlice(96, 82), + CommitteeBits: FillByteSlice(8, 82), + }, + { + AggregationBits: FillByteSlice(4, 83), + Data: ðpb.AttestationData{ + Slot: 84, + CommitteeIndex: 85, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 87, + Root: FillByteSlice(32, 88), + }, + Target: ðpb.Checkpoint{ + Epoch: 89, + Root: FillByteSlice(32, 90), + }, + }, + Signature: FillByteSlice(96, 91), + CommitteeBits: FillByteSlice(8, 91), + }, + }, + Deposits: []*ethpb.Deposit{ + { + Proof: FillByteArraySlice(33, FillByteSlice(32, 92)), + Data: ðpb.Deposit_Data{ + PublicKey: FillByteSlice(48, 94), + WithdrawalCredentials: FillByteSlice(32, 95), + Amount: 96, + Signature: FillByteSlice(96, 97), + }, + }, + { + Proof: FillByteArraySlice(33, FillByteSlice(32, 98)), + Data: ðpb.Deposit_Data{ + PublicKey: FillByteSlice(48, 100), + WithdrawalCredentials: FillByteSlice(32, 101), + Amount: 102, + Signature: FillByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*ethpb.SignedVoluntaryExit{ + { + Exit: ðpb.VoluntaryExit{ + Epoch: 104, + ValidatorIndex: 105, + }, + Signature: FillByteSlice(96, 106), + }, + { + Exit: ðpb.VoluntaryExit{ + Epoch: 107, + ValidatorIndex: 108, + }, + Signature: FillByteSlice(96, 109), + }, + }, + SyncAggregate: ðpb.SyncAggregate{ + SyncCommitteeBits: FillByteSlice(64, 110), + SyncCommitteeSignature: FillByteSlice(96, 111), + }, + ExecutionPayload: &enginev1.ExecutionPayloadDeneb{ + ParentHash: FillByteSlice(32, 112), + FeeRecipient: FillByteSlice(20, 113), + StateRoot: FillByteSlice(32, 114), + ReceiptsRoot: FillByteSlice(32, 115), + LogsBloom: FillByteSlice(256, 116), + PrevRandao: FillByteSlice(32, 117), + BlockNumber: 118, + GasLimit: 119, + GasUsed: 120, + Timestamp: 121, + ExtraData: FillByteSlice(32, 122), + BaseFeePerGas: FillByteSlice(32, 123), + BlockHash: FillByteSlice(32, 124), + Transactions: [][]byte{ + FillByteSlice(32, 125), + FillByteSlice(32, 126), + }, + Withdrawals: []*enginev1.Withdrawal{ + { + Index: 127, + ValidatorIndex: 128, + Address: FillByteSlice(20, 129), + Amount: 130, + }, + { + Index: 131, + ValidatorIndex: 132, + Address: FillByteSlice(20, 133), + Amount: 134, + }, + }, + BlobGasUsed: 135, + ExcessBlobGas: 136, + }, + BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{ + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 137, + FromBlsPubkey: FillByteSlice(48, 138), + ToExecutionAddress: FillByteSlice(20, 139), + }, + Signature: FillByteSlice(96, 140), + }, + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 141, + FromBlsPubkey: FillByteSlice(48, 142), + ToExecutionAddress: FillByteSlice(20, 143), + }, + Signature: FillByteSlice(96, 144), + }, + }, + BlobKzgCommitments: [][]byte{FillByteSlice(48, 145), FillByteSlice(48, 146)}, + ExecutionRequests: &enginev1.ExecutionRequests{ + Deposits: []*enginev1.DepositRequest{{ + Pubkey: FillByteSlice(48, 147), + WithdrawalCredentials: FillByteSlice(32, 148), + Amount: 149, + Signature: FillByteSlice(96, 150), + Index: 151, + }}, + Withdrawals: []*enginev1.WithdrawalRequest{ + { + SourceAddress: FillByteSlice(20, 152), + ValidatorPubkey: FillByteSlice(48, 153), + Amount: 154, + }, + }, + Consolidations: []*enginev1.ConsolidationRequest{ + { + SourceAddress: FillByteSlice(20, 155), + SourcePubkey: FillByteSlice(48, 156), + TargetPubkey: FillByteSlice(48, 157), + }, + }, + }, + }, + }, + KzgProofs: [][]byte{FillByteSlice(48, 158)}, + Blobs: [][]byte{FillByteSlice(131072, 159)}, + } +} + +func GenerateProtoBlindedElectraBeaconBlock() *ethpb.BlindedBeaconBlockElectra { + return ðpb.BlindedBeaconBlockElectra{ + Slot: 1, + ProposerIndex: 2, + ParentRoot: FillByteSlice(32, 3), + StateRoot: FillByteSlice(32, 4), + Body: ðpb.BlindedBeaconBlockBodyElectra{ + RandaoReveal: FillByteSlice(96, 5), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: FillByteSlice(32, 6), + DepositCount: 7, + BlockHash: FillByteSlice(32, 8), + }, + Graffiti: FillByteSlice(32, 9), + ProposerSlashings: []*ethpb.ProposerSlashing{ + { + Header_1: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 10, + ProposerIndex: 11, + ParentRoot: FillByteSlice(32, 12), + StateRoot: FillByteSlice(32, 13), + BodyRoot: FillByteSlice(32, 14), + }, + Signature: FillByteSlice(96, 15), + }, + Header_2: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 16, + ProposerIndex: 17, + ParentRoot: FillByteSlice(32, 18), + StateRoot: FillByteSlice(32, 19), + BodyRoot: FillByteSlice(32, 20), + }, + Signature: FillByteSlice(96, 21), + }, + }, + { + Header_1: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 22, + ProposerIndex: 23, + ParentRoot: FillByteSlice(32, 24), + StateRoot: FillByteSlice(32, 25), + BodyRoot: FillByteSlice(32, 26), + }, + Signature: FillByteSlice(96, 27), + }, + Header_2: ðpb.SignedBeaconBlockHeader{ + Header: ðpb.BeaconBlockHeader{ + Slot: 28, + ProposerIndex: 29, + ParentRoot: FillByteSlice(32, 30), + StateRoot: FillByteSlice(32, 31), + BodyRoot: FillByteSlice(32, 32), + }, + Signature: FillByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*ethpb.AttesterSlashingElectra{ + { + Attestation_1: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{34, 35}, + Data: ðpb.AttestationData{ + Slot: 36, + CommitteeIndex: 37, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 39, + Root: FillByteSlice(32, 40), + }, + Target: ðpb.Checkpoint{ + Epoch: 41, + Root: FillByteSlice(32, 42), + }, + }, + Signature: FillByteSlice(96, 43), + }, + Attestation_2: ðpb.IndexedAttestationElectra{ + AttestingIndices: []uint64{44, 45}, + Data: ðpb.AttestationData{ + Slot: 46, + CommitteeIndex: 47, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 49, + Root: FillByteSlice(32, 50), + }, + Target: ðpb.Checkpoint{ + Epoch: 51, + Root: FillByteSlice(32, 52), + }, + }, + Signature: FillByteSlice(96, 53), + }, + }, + }, + Attestations: []*ethpb.AttestationElectra{ + { + AggregationBits: FillByteSlice(4, 74), + Data: ðpb.AttestationData{ + Slot: 75, + CommitteeIndex: 76, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 78, + Root: FillByteSlice(32, 79), + }, + Target: ðpb.Checkpoint{ + Epoch: 80, + Root: FillByteSlice(32, 81), + }, + }, + Signature: FillByteSlice(96, 82), + CommitteeBits: FillByteSlice(8, 82), + }, + { + AggregationBits: FillByteSlice(4, 83), + Data: ðpb.AttestationData{ + Slot: 84, + CommitteeIndex: 85, + BeaconBlockRoot: FillByteSlice(32, 38), + Source: ðpb.Checkpoint{ + Epoch: 87, + Root: FillByteSlice(32, 88), + }, + Target: ðpb.Checkpoint{ + Epoch: 89, + Root: FillByteSlice(32, 90), + }, + }, + Signature: FillByteSlice(96, 91), + CommitteeBits: FillByteSlice(8, 91), + }, + }, + Deposits: []*ethpb.Deposit{ + { + Proof: FillByteArraySlice(33, FillByteSlice(32, 92)), + Data: ðpb.Deposit_Data{ + PublicKey: FillByteSlice(48, 94), + WithdrawalCredentials: FillByteSlice(32, 95), + Amount: 96, + Signature: FillByteSlice(96, 97), + }, + }, + { + Proof: FillByteArraySlice(33, FillByteSlice(32, 98)), + Data: ðpb.Deposit_Data{ + PublicKey: FillByteSlice(48, 100), + WithdrawalCredentials: FillByteSlice(32, 101), + Amount: 102, + Signature: FillByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*ethpb.SignedVoluntaryExit{ + { + Exit: ðpb.VoluntaryExit{ + Epoch: 104, + ValidatorIndex: 105, + }, + Signature: FillByteSlice(96, 106), + }, + { + Exit: ðpb.VoluntaryExit{ + Epoch: 107, + ValidatorIndex: 108, + }, + Signature: FillByteSlice(96, 109), + }, + }, + SyncAggregate: ðpb.SyncAggregate{ + SyncCommitteeBits: FillByteSlice(64, 110), + SyncCommitteeSignature: FillByteSlice(96, 111), + }, + ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderDeneb{ + ParentHash: FillByteSlice(32, 112), + FeeRecipient: FillByteSlice(20, 113), + StateRoot: FillByteSlice(32, 114), + ReceiptsRoot: FillByteSlice(32, 115), + LogsBloom: FillByteSlice(256, 116), + PrevRandao: FillByteSlice(32, 117), + BlockNumber: 118, + GasLimit: 119, + GasUsed: 120, + Timestamp: 121, + ExtraData: FillByteSlice(32, 122), + BaseFeePerGas: FillByteSlice(32, 123), + BlockHash: FillByteSlice(32, 124), + TransactionsRoot: FillByteSlice(32, 125), + WithdrawalsRoot: FillByteSlice(32, 126), + BlobGasUsed: 127, + ExcessBlobGas: 128, + }, + BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{ + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 129, + FromBlsPubkey: FillByteSlice(48, 130), + ToExecutionAddress: FillByteSlice(20, 131), + }, + Signature: FillByteSlice(96, 132), + }, + { + Message: ðpb.BLSToExecutionChange{ + ValidatorIndex: 133, + FromBlsPubkey: FillByteSlice(48, 134), + ToExecutionAddress: FillByteSlice(20, 135), + }, + Signature: FillByteSlice(96, 136), + }, + }, + BlobKzgCommitments: [][]byte{FillByteSlice(48, 137), FillByteSlice(48, 138)}, + ExecutionRequests: &enginev1.ExecutionRequests{ + Deposits: []*enginev1.DepositRequest{{ + Pubkey: FillByteSlice(48, 139), + WithdrawalCredentials: FillByteSlice(32, 140), + Amount: 141, + Signature: FillByteSlice(96, 142), + Index: 143, + }}, + Withdrawals: []*enginev1.WithdrawalRequest{ + { + SourceAddress: FillByteSlice(20, 144), + ValidatorPubkey: FillByteSlice(48, 145), + Amount: 146, + }, + }, + Consolidations: []*enginev1.ConsolidationRequest{ + { + SourceAddress: FillByteSlice(20, 147), + SourcePubkey: FillByteSlice(48, 148), + TargetPubkey: FillByteSlice(48, 149), + }, + }, + }, + }, + } +} + +func GenerateJsonElectraBeaconBlockContents() *structs.BeaconBlockContentsElectra { + return &structs.BeaconBlockContentsElectra{ + Block: &structs.BeaconBlockElectra{ + Slot: "1", + ProposerIndex: "2", + ParentRoot: FillEncodedByteSlice(32, 3), + StateRoot: FillEncodedByteSlice(32, 4), + Body: &structs.BeaconBlockBodyElectra{ + RandaoReveal: FillEncodedByteSlice(96, 5), + Eth1Data: &structs.Eth1Data{ + DepositRoot: FillEncodedByteSlice(32, 6), + DepositCount: "7", + BlockHash: FillEncodedByteSlice(32, 8), + }, + Graffiti: FillEncodedByteSlice(32, 9), + ProposerSlashings: []*structs.ProposerSlashing{ + { + SignedHeader1: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "10", + ProposerIndex: "11", + ParentRoot: FillEncodedByteSlice(32, 12), + StateRoot: FillEncodedByteSlice(32, 13), + BodyRoot: FillEncodedByteSlice(32, 14), + }, + Signature: FillEncodedByteSlice(96, 15), + }, + SignedHeader2: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "16", + ProposerIndex: "17", + ParentRoot: FillEncodedByteSlice(32, 18), + StateRoot: FillEncodedByteSlice(32, 19), + BodyRoot: FillEncodedByteSlice(32, 20), + }, + Signature: FillEncodedByteSlice(96, 21), + }, + }, + { + SignedHeader1: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "22", + ProposerIndex: "23", + ParentRoot: FillEncodedByteSlice(32, 24), + StateRoot: FillEncodedByteSlice(32, 25), + BodyRoot: FillEncodedByteSlice(32, 26), + }, + Signature: FillEncodedByteSlice(96, 27), + }, + SignedHeader2: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "28", + ProposerIndex: "29", + ParentRoot: FillEncodedByteSlice(32, 30), + StateRoot: FillEncodedByteSlice(32, 31), + BodyRoot: FillEncodedByteSlice(32, 32), + }, + Signature: FillEncodedByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*structs.AttesterSlashingElectra{ + { + Attestation1: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"34", "35"}, + Data: &structs.AttestationData{ + Slot: "36", + CommitteeIndex: "37", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "39", + Root: FillEncodedByteSlice(32, 40), + }, + Target: &structs.Checkpoint{ + Epoch: "41", + Root: FillEncodedByteSlice(32, 42), + }, + }, + Signature: FillEncodedByteSlice(96, 43), + }, + Attestation2: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"44", "45"}, + Data: &structs.AttestationData{ + Slot: "46", + CommitteeIndex: "47", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "49", + Root: FillEncodedByteSlice(32, 50), + }, + Target: &structs.Checkpoint{ + Epoch: "51", + Root: FillEncodedByteSlice(32, 52), + }, + }, + Signature: FillEncodedByteSlice(96, 53), + }, + }, + }, + Attestations: []*structs.AttestationElectra{ + { + AggregationBits: FillEncodedByteSlice(4, 74), + Data: &structs.AttestationData{ + Slot: "75", + CommitteeIndex: "76", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "78", + Root: FillEncodedByteSlice(32, 79), + }, + Target: &structs.Checkpoint{ + Epoch: "80", + Root: FillEncodedByteSlice(32, 81), + }, + }, + Signature: FillEncodedByteSlice(96, 82), + CommitteeBits: FillEncodedByteSlice(8, 82), + }, + { + AggregationBits: FillEncodedByteSlice(4, 83), + Data: &structs.AttestationData{ + Slot: "84", + CommitteeIndex: "85", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "87", + Root: FillEncodedByteSlice(32, 88), + }, + Target: &structs.Checkpoint{ + Epoch: "89", + Root: FillEncodedByteSlice(32, 90), + }, + }, + Signature: FillEncodedByteSlice(96, 91), + CommitteeBits: FillEncodedByteSlice(8, 91), + }, + }, + Deposits: []*structs.Deposit{ + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 92)), + Data: &structs.DepositData{ + Pubkey: FillEncodedByteSlice(48, 94), + WithdrawalCredentials: FillEncodedByteSlice(32, 95), + Amount: "96", + Signature: FillEncodedByteSlice(96, 97), + }, + }, + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 98)), + Data: &structs.DepositData{ + Pubkey: FillEncodedByteSlice(48, 100), + WithdrawalCredentials: FillEncodedByteSlice(32, 101), + Amount: "102", + Signature: FillEncodedByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*structs.SignedVoluntaryExit{ + { + Message: &structs.VoluntaryExit{ + Epoch: "104", + ValidatorIndex: "105", + }, + Signature: FillEncodedByteSlice(96, 106), + }, + { + Message: &structs.VoluntaryExit{ + Epoch: "107", + ValidatorIndex: "108", + }, + Signature: FillEncodedByteSlice(96, 109), + }, + }, + SyncAggregate: &structs.SyncAggregate{ + SyncCommitteeBits: FillEncodedByteSlice(64, 110), + SyncCommitteeSignature: FillEncodedByteSlice(96, 111), + }, + ExecutionPayload: &structs.ExecutionPayloadDeneb{ + ParentHash: FillEncodedByteSlice(32, 112), + FeeRecipient: FillEncodedByteSlice(20, 113), + StateRoot: FillEncodedByteSlice(32, 114), + ReceiptsRoot: FillEncodedByteSlice(32, 115), + LogsBloom: FillEncodedByteSlice(256, 116), + PrevRandao: FillEncodedByteSlice(32, 117), + BlockNumber: "118", + GasLimit: "119", + GasUsed: "120", + Timestamp: "121", + ExtraData: FillEncodedByteSlice(32, 122), + BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(FillByteSlice(32, 123)).String(), + BlockHash: FillEncodedByteSlice(32, 124), + Transactions: []string{ + FillEncodedByteSlice(32, 125), + FillEncodedByteSlice(32, 126), + }, + Withdrawals: []*structs.Withdrawal{ + { + WithdrawalIndex: "127", + ValidatorIndex: "128", + ExecutionAddress: FillEncodedByteSlice(20, 129), + Amount: "130", + }, + { + WithdrawalIndex: "131", + ValidatorIndex: "132", + ExecutionAddress: FillEncodedByteSlice(20, 133), + Amount: "134", + }, + }, + BlobGasUsed: "135", + ExcessBlobGas: "136", + }, + BLSToExecutionChanges: []*structs.SignedBLSToExecutionChange{ + { + Message: &structs.BLSToExecutionChange{ + ValidatorIndex: "137", + FromBLSPubkey: FillEncodedByteSlice(48, 138), + ToExecutionAddress: FillEncodedByteSlice(20, 139), + }, + Signature: FillEncodedByteSlice(96, 140), + }, + { + Message: &structs.BLSToExecutionChange{ + ValidatorIndex: "141", + FromBLSPubkey: FillEncodedByteSlice(48, 142), + ToExecutionAddress: FillEncodedByteSlice(20, 143), + }, + Signature: FillEncodedByteSlice(96, 144), + }, + }, + BlobKzgCommitments: []string{FillEncodedByteSlice(48, 145), FillEncodedByteSlice(48, 146)}, + ExecutionRequests: &structs.ExecutionRequests{ + Deposits: []*structs.DepositRequest{{ + Pubkey: FillEncodedByteSlice(48, 147), + WithdrawalCredentials: FillEncodedByteSlice(32, 148), + Amount: "149", + Signature: FillEncodedByteSlice(96, 150), + Index: "151", + }}, + Withdrawals: []*structs.WithdrawalRequest{ + { + SourceAddress: FillEncodedByteSlice(20, 152), + ValidatorPubkey: FillEncodedByteSlice(48, 153), + Amount: "154", + }, + }, + Consolidations: []*structs.ConsolidationRequest{ + { + SourceAddress: FillEncodedByteSlice(20, 155), + SourcePubkey: FillEncodedByteSlice(48, 156), + TargetPubkey: FillEncodedByteSlice(48, 157), + }, + }, + }, + }, + }, + KzgProofs: []string{FillEncodedByteSlice(48, 158)}, + Blobs: []string{FillEncodedByteSlice(131072, 159)}, + } +} + +func GenerateJsonBlindedElectraBeaconBlock() *structs.BlindedBeaconBlockElectra { + return &structs.BlindedBeaconBlockElectra{ + Slot: "1", + ProposerIndex: "2", + ParentRoot: FillEncodedByteSlice(32, 3), + StateRoot: FillEncodedByteSlice(32, 4), + Body: &structs.BlindedBeaconBlockBodyElectra{ + RandaoReveal: FillEncodedByteSlice(96, 5), + Eth1Data: &structs.Eth1Data{ + DepositRoot: FillEncodedByteSlice(32, 6), + DepositCount: "7", + BlockHash: FillEncodedByteSlice(32, 8), + }, + Graffiti: FillEncodedByteSlice(32, 9), + ProposerSlashings: []*structs.ProposerSlashing{ + { + SignedHeader1: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "10", + ProposerIndex: "11", + ParentRoot: FillEncodedByteSlice(32, 12), + StateRoot: FillEncodedByteSlice(32, 13), + BodyRoot: FillEncodedByteSlice(32, 14), + }, + Signature: FillEncodedByteSlice(96, 15), + }, + SignedHeader2: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "16", + ProposerIndex: "17", + ParentRoot: FillEncodedByteSlice(32, 18), + StateRoot: FillEncodedByteSlice(32, 19), + BodyRoot: FillEncodedByteSlice(32, 20), + }, + Signature: FillEncodedByteSlice(96, 21), + }, + }, + { + SignedHeader1: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "22", + ProposerIndex: "23", + ParentRoot: FillEncodedByteSlice(32, 24), + StateRoot: FillEncodedByteSlice(32, 25), + BodyRoot: FillEncodedByteSlice(32, 26), + }, + Signature: FillEncodedByteSlice(96, 27), + }, + SignedHeader2: &structs.SignedBeaconBlockHeader{ + Message: &structs.BeaconBlockHeader{ + Slot: "28", + ProposerIndex: "29", + ParentRoot: FillEncodedByteSlice(32, 30), + StateRoot: FillEncodedByteSlice(32, 31), + BodyRoot: FillEncodedByteSlice(32, 32), + }, + Signature: FillEncodedByteSlice(96, 33), + }, + }, + }, + AttesterSlashings: []*structs.AttesterSlashingElectra{ + { + Attestation1: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"34", "35"}, + Data: &structs.AttestationData{ + Slot: "36", + CommitteeIndex: "37", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "39", + Root: FillEncodedByteSlice(32, 40), + }, + Target: &structs.Checkpoint{ + Epoch: "41", + Root: FillEncodedByteSlice(32, 42), + }, + }, + Signature: FillEncodedByteSlice(96, 43), + }, + Attestation2: &structs.IndexedAttestationElectra{ + AttestingIndices: []string{"44", "45"}, + Data: &structs.AttestationData{ + Slot: "46", + CommitteeIndex: "47", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "49", + Root: FillEncodedByteSlice(32, 50), + }, + Target: &structs.Checkpoint{ + Epoch: "51", + Root: FillEncodedByteSlice(32, 52), + }, + }, + Signature: FillEncodedByteSlice(96, 53), + }, + }, + }, + Attestations: []*structs.AttestationElectra{ + { + AggregationBits: FillEncodedByteSlice(4, 74), + Data: &structs.AttestationData{ + Slot: "75", + CommitteeIndex: "76", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "78", + Root: FillEncodedByteSlice(32, 79), + }, + Target: &structs.Checkpoint{ + Epoch: "80", + Root: FillEncodedByteSlice(32, 81), + }, + }, + Signature: FillEncodedByteSlice(96, 82), + CommitteeBits: FillEncodedByteSlice(8, 82), + }, + { + AggregationBits: FillEncodedByteSlice(4, 83), + Data: &structs.AttestationData{ + Slot: "84", + CommitteeIndex: "85", + BeaconBlockRoot: FillEncodedByteSlice(32, 38), + Source: &structs.Checkpoint{ + Epoch: "87", + Root: FillEncodedByteSlice(32, 88), + }, + Target: &structs.Checkpoint{ + Epoch: "89", + Root: FillEncodedByteSlice(32, 90), + }, + }, + Signature: FillEncodedByteSlice(96, 91), + CommitteeBits: FillEncodedByteSlice(8, 91), + }, + }, + Deposits: []*structs.Deposit{ + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 92)), + Data: &structs.DepositData{ + Pubkey: FillEncodedByteSlice(48, 94), + WithdrawalCredentials: FillEncodedByteSlice(32, 95), + Amount: "96", + Signature: FillEncodedByteSlice(96, 97), + }, + }, + { + Proof: FillEncodedByteArraySlice(33, FillEncodedByteSlice(32, 98)), + Data: &structs.DepositData{ + Pubkey: FillEncodedByteSlice(48, 100), + WithdrawalCredentials: FillEncodedByteSlice(32, 101), + Amount: "102", + Signature: FillEncodedByteSlice(96, 103), + }, + }, + }, + VoluntaryExits: []*structs.SignedVoluntaryExit{ + { + Message: &structs.VoluntaryExit{ + Epoch: "104", + ValidatorIndex: "105", + }, + Signature: FillEncodedByteSlice(96, 106), + }, + { + Message: &structs.VoluntaryExit{ + Epoch: "107", + ValidatorIndex: "108", + }, + Signature: FillEncodedByteSlice(96, 109), + }, + }, + SyncAggregate: &structs.SyncAggregate{ + SyncCommitteeBits: FillEncodedByteSlice(64, 110), + SyncCommitteeSignature: FillEncodedByteSlice(96, 111), + }, + ExecutionPayloadHeader: &structs.ExecutionPayloadHeaderDeneb{ + ParentHash: FillEncodedByteSlice(32, 112), + FeeRecipient: FillEncodedByteSlice(20, 113), + StateRoot: FillEncodedByteSlice(32, 114), + ReceiptsRoot: FillEncodedByteSlice(32, 115), + LogsBloom: FillEncodedByteSlice(256, 116), + PrevRandao: FillEncodedByteSlice(32, 117), + BlockNumber: "118", + GasLimit: "119", + GasUsed: "120", + Timestamp: "121", + ExtraData: FillEncodedByteSlice(32, 122), + BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(FillByteSlice(32, 123)).String(), + BlockHash: FillEncodedByteSlice(32, 124), + TransactionsRoot: FillEncodedByteSlice(32, 125), + WithdrawalsRoot: FillEncodedByteSlice(32, 126), + BlobGasUsed: "127", + ExcessBlobGas: "128", + }, + BLSToExecutionChanges: []*structs.SignedBLSToExecutionChange{ + { + Message: &structs.BLSToExecutionChange{ + ValidatorIndex: "129", + FromBLSPubkey: FillEncodedByteSlice(48, 130), + ToExecutionAddress: FillEncodedByteSlice(20, 131), + }, + Signature: FillEncodedByteSlice(96, 132), + }, + { + Message: &structs.BLSToExecutionChange{ + ValidatorIndex: "133", + FromBLSPubkey: FillEncodedByteSlice(48, 134), + ToExecutionAddress: FillEncodedByteSlice(20, 135), + }, + Signature: FillEncodedByteSlice(96, 136), + }, + }, + BlobKzgCommitments: []string{FillEncodedByteSlice(48, 137), FillEncodedByteSlice(48, 138)}, + ExecutionRequests: &structs.ExecutionRequests{ + Deposits: []*structs.DepositRequest{{ + Pubkey: FillEncodedByteSlice(48, 139), + WithdrawalCredentials: FillEncodedByteSlice(32, 140), + Amount: "141", + Signature: FillEncodedByteSlice(96, 142), + Index: "143", + }}, + Withdrawals: []*structs.WithdrawalRequest{ + { + SourceAddress: FillEncodedByteSlice(20, 144), + ValidatorPubkey: FillEncodedByteSlice(48, 145), + Amount: "146", + }, + }, + Consolidations: []*structs.ConsolidationRequest{ + { + SourceAddress: FillEncodedByteSlice(20, 147), + SourcePubkey: FillEncodedByteSlice(48, 148), + TargetPubkey: FillEncodedByteSlice(48, 149), + }, + }, + }, + }, + } +} diff --git a/validator/client/grpc-api/BUILD.bazel b/validator/client/grpc-api/BUILD.bazel index 3fdd649792ae..3dd77c8311cb 100644 --- a/validator/client/grpc-api/BUILD.bazel +++ b/validator/client/grpc-api/BUILD.bazel @@ -19,13 +19,13 @@ go_library( "//beacon-chain/state/state-native:go_default_library", "//consensus-types/primitives:go_default_library", "//consensus-types/validator:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/eth/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//validator/client/iface:go_default_library", "@com_github_golang_protobuf//ptypes/empty", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_grpc//:go_default_library", ], ) diff --git a/validator/client/grpc-api/grpc_validator_client.go b/validator/client/grpc-api/grpc_validator_client.go index c03d504dff80..4e9cdd4d3cd9 100644 --- a/validator/client/grpc-api/grpc_validator_client.go +++ b/validator/client/grpc-api/grpc_validator_client.go @@ -11,10 +11,10 @@ import ( eventClient "github.com/prysmaticlabs/prysm/v5/api/client/event" "github.com/prysmaticlabs/prysm/v5/api/server/structs" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/validator/client/iface" log "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "google.golang.org/grpc" ) @@ -71,7 +71,7 @@ func (c *grpcValidatorClient) ProposeAttestation(ctx context.Context, in *ethpb. return c.beaconNodeValidatorClient.ProposeAttestation(ctx, in) } -func (c *grpcValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) { +func (c *grpcValidatorClient) ProposeAttestationElectra(ctx context.Context, in *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) { return c.beaconNodeValidatorClient.ProposeAttestationElectra(ctx, in) } @@ -127,10 +127,6 @@ func (c *grpcValidatorClient) ValidatorStatus(ctx context.Context, in *ethpb.Val return c.beaconNodeValidatorClient.ValidatorStatus(ctx, in) } -func (c *grpcValidatorClient) WaitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error) { - return c.beaconNodeValidatorClient.WaitForActivation(ctx, in) -} - // Deprecated: Do not use. func (c *grpcValidatorClient) WaitForChainStart(ctx context.Context, in *empty.Empty) (*ethpb.ChainStartResponse, error) { stream, err := c.beaconNodeValidatorClient.WaitForChainStart(ctx, in) diff --git a/validator/client/iface/validator.go b/validator/client/iface/validator.go index 647ef06a2faa..354e92a5bf4e 100644 --- a/validator/client/iface/validator.go +++ b/validator/client/iface/validator.go @@ -57,8 +57,8 @@ type Validator interface { Keymanager() (keymanager.IKeymanager, error) HandleKeyReload(ctx context.Context, currentKeys [][fieldparams.BLSPubkeyLength]byte) (bool, error) CheckDoppelGanger(ctx context.Context) error - PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot) error - SignValidatorRegistrationRequest(ctx context.Context, signer SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) + PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot, forceFullPush bool) error + SignValidatorRegistrationRequest(ctx context.Context, signer SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool /* isCached */, error) StartEventStream(ctx context.Context, topics []string, eventsChan chan<- *event.Event) EventStreamIsRunning() bool ProcessEvent(event *event.Event) diff --git a/validator/client/iface/validator_client.go b/validator/client/iface/validator_client.go index 71388211f9d8..5ff21ca6486e 100644 --- a/validator/client/iface/validator_client.go +++ b/validator/client/iface/validator_client.go @@ -124,7 +124,6 @@ type ValidatorClient interface { Duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.DutiesResponse, error) DomainData(ctx context.Context, in *ethpb.DomainRequest) (*ethpb.DomainResponse, error) WaitForChainStart(ctx context.Context, in *empty.Empty) (*ethpb.ChainStartResponse, error) - WaitForActivation(ctx context.Context, in *ethpb.ValidatorActivationRequest) (ethpb.BeaconNodeValidator_WaitForActivationClient, error) ValidatorIndex(ctx context.Context, in *ethpb.ValidatorIndexRequest) (*ethpb.ValidatorIndexResponse, error) ValidatorStatus(ctx context.Context, in *ethpb.ValidatorStatusRequest) (*ethpb.ValidatorStatusResponse, error) MultipleValidatorStatus(ctx context.Context, in *ethpb.MultipleValidatorStatusRequest) (*ethpb.MultipleValidatorStatusResponse, error) @@ -134,7 +133,7 @@ type ValidatorClient interface { FeeRecipientByPubKey(ctx context.Context, in *ethpb.FeeRecipientByPubKeyRequest) (*ethpb.FeeRecipientByPubKeyResponse, error) AttestationData(ctx context.Context, in *ethpb.AttestationDataRequest) (*ethpb.AttestationData, error) ProposeAttestation(ctx context.Context, in *ethpb.Attestation) (*ethpb.AttestResponse, error) - ProposeAttestationElectra(ctx context.Context, in *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) + ProposeAttestationElectra(ctx context.Context, in *ethpb.SingleAttestation) (*ethpb.AttestResponse, error) SubmitAggregateSelectionProof(ctx context.Context, in *ethpb.AggregateSelectionRequest, index primitives.ValidatorIndex, committeeLength uint64) (*ethpb.AggregateSelectionResponse, error) SubmitAggregateSelectionProofElectra(ctx context.Context, in *ethpb.AggregateSelectionRequest, _ primitives.ValidatorIndex, _ uint64) (*ethpb.AggregateSelectionElectraResponse, error) SubmitSignedAggregateSelectionProof(ctx context.Context, in *ethpb.SignedAggregateSubmitRequest) (*ethpb.SignedAggregateSubmitResponse, error) diff --git a/validator/client/key_reload.go b/validator/client/key_reload.go index ab01e89f9306..52ae4006adbc 100644 --- a/validator/client/key_reload.go +++ b/validator/client/key_reload.go @@ -3,49 +3,18 @@ package client import ( "context" - "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - validator2 "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" - eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/validator/client/iface" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ) // HandleKeyReload makes sure the validator keeps operating correctly after a change to the underlying keys. // It is also responsible for logging out information about the new state of keys. -func (v *validator) HandleKeyReload(ctx context.Context, currentKeys [][fieldparams.BLSPubkeyLength]byte) (anyActive bool, err error) { +func (v *validator) HandleKeyReload(ctx context.Context, currentKeys [][fieldparams.BLSPubkeyLength]byte) (bool, error) { ctx, span := trace.StartSpan(ctx, "validator.HandleKeyReload") defer span.End() - - statusRequestKeys := make([][]byte, len(currentKeys)) - for i := range currentKeys { - statusRequestKeys[i] = currentKeys[i][:] - } - resp, err := v.validatorClient.MultipleValidatorStatus(ctx, ð.MultipleValidatorStatusRequest{ - PublicKeys: statusRequestKeys, - }) - if err != nil { + if err := v.updateValidatorStatusCache(ctx, currentKeys); err != nil { return false, err } - statuses := make([]*validatorStatus, len(resp.Statuses)) - for i, s := range resp.Statuses { - statuses[i] = &validatorStatus{ - publicKey: resp.PublicKeys[i], - status: s, - index: resp.Indices[i], - } - } - - // "-1" indicates that validator count endpoint is not supported by the beacon node. - var valCount int64 = -1 - valCounts, err := v.prysmChainClient.ValidatorCount(ctx, "head", []validator2.Status{validator2.Active}) - if err != nil && !errors.Is(err, iface.ErrNotSupported) { - return false, errors.Wrap(err, "could not get active validator count") - } - - if len(valCounts) > 0 { - valCount = int64(valCounts[0].Count) - } - return v.checkAndLogValidatorStatus(statuses, valCount), nil + return v.checkAndLogValidatorStatus(), nil } diff --git a/validator/client/key_reload_test.go b/validator/client/key_reload_test.go index df8e0435e1a0..f9abd2ffc8be 100644 --- a/validator/client/key_reload_test.go +++ b/validator/client/key_reload_test.go @@ -6,12 +6,10 @@ import ( "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - validator2 "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/assert" "github.com/prysmaticlabs/prysm/v5/testing/require" validatormock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock" - "github.com/prysmaticlabs/prysm/v5/validator/client/iface" "github.com/prysmaticlabs/prysm/v5/validator/client/testutil" logTest "github.com/sirupsen/logrus/hooks/test" "go.uber.org/mock/gomock" @@ -36,6 +34,7 @@ func TestValidator_HandleKeyReload(t *testing.T) { genesisTime: 1, chainClient: chainClient, prysmChainClient: prysmChainClient, + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), } resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:], active.pub[:]}) @@ -47,11 +46,6 @@ func TestValidator_HandleKeyReload(t *testing.T) { PublicKeys: [][]byte{inactive.pub[:], active.pub[:]}, }, ).Return(resp, nil) - prysmChainClient.EXPECT().ValidatorCount( - gomock.Any(), - "head", - []validator2.Status{validator2.Active}, - ).Return([]iface.ValidatorCount{}, nil) anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{inactive.pub, active.pub}) require.NoError(t, err) @@ -73,6 +67,7 @@ func TestValidator_HandleKeyReload(t *testing.T) { genesisTime: 1, chainClient: chainClient, prysmChainClient: prysmChainClient, + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), } resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]}) @@ -83,11 +78,6 @@ func TestValidator_HandleKeyReload(t *testing.T) { PublicKeys: [][]byte{kp.pub[:]}, }, ).Return(resp, nil) - prysmChainClient.EXPECT().ValidatorCount( - gomock.Any(), - "head", - []validator2.Status{validator2.Active}, - ).Return([]iface.ValidatorCount{}, nil) anyActive, err := v.HandleKeyReload(context.Background(), [][fieldparams.BLSPubkeyLength]byte{kp.pub}) require.NoError(t, err) @@ -103,6 +93,7 @@ func TestValidator_HandleKeyReload(t *testing.T) { validatorClient: client, km: newMockKeymanager(t, kp), genesisTime: 1, + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), } client.EXPECT().MultipleValidatorStatus( diff --git a/validator/client/metrics.go b/validator/client/metrics.go index d8ea5f91e852..7d17dfe44ec2 100644 --- a/validator/client/metrics.go +++ b/validator/client/metrics.go @@ -16,7 +16,7 @@ import ( ) var ( - // ValidatorStatusesGaugeVec used to track validator statuses by public key. + // ValidatorStatusesGaugeVec used to track validator statuses by public key and validator index. ValidatorStatusesGaugeVec = promauto.NewGaugeVec( prometheus.GaugeOpts{ Namespace: "validator", @@ -24,7 +24,7 @@ var ( Help: "validator statuses: 0 UNKNOWN, 1 DEPOSITED, 2 PENDING, 3 ACTIVE, 4 EXITING, 5 SLASHING, 6 EXITED", }, []string{ - "pubkey", + "pubkey", "index", }, ) // ValidatorAggSuccessVec used to count successful aggregations. diff --git a/validator/client/propose.go b/validator/client/propose.go index 656f7d38da4a..08bf10d4a6ba 100644 --- a/validator/client/propose.go +++ b/validator/client/propose.go @@ -20,6 +20,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/crypto/rand" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/runtime/version" @@ -27,7 +28,6 @@ import ( "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/prysmaticlabs/prysm/v5/validator/client/iface" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) @@ -56,7 +56,7 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK defer lock.Unlock() fmtKey := fmt.Sprintf("%#x", pubKey[:]) - span.AddAttributes(trace.StringAttribute("validator", fmtKey)) + span.SetAttributes(trace.StringAttribute("validator", fmtKey)) log := log.WithField("pubkey", fmt.Sprintf("%#x", bytesutil.Trunc(pubKey[:]))) // Sign randao reveal, it's used to request block from beacon node @@ -148,6 +148,12 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK log.WithError(err).Error("Failed to build generic signed block") return } + case version.Fulu: + genericSignedBlock, err = buildGenericSignedBlockFuluWithBlobs(pb, b) + if err != nil { + log.WithError(err).Error("Failed to build generic signed block") + return + } default: log.Errorf("Unsupported block version %s", version.String(blk.Version())) } @@ -171,28 +177,36 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK return } - span.AddAttributes( + span.SetAttributes( trace.StringAttribute("blockRoot", fmt.Sprintf("%#x", blkResp.BlockRoot)), trace.Int64Attribute("numDeposits", int64(len(blk.Block().Body().Deposits()))), trace.Int64Attribute("numAttestations", int64(len(blk.Block().Body().Attestations()))), ) + if err := logProposedBlock(log, blk, blkResp.BlockRoot); err != nil { + log.WithError(err).Error("Failed to log proposed block") + } + + if v.emitAccountMetrics { + ValidatorProposeSuccessVec.WithLabelValues(fmtKey).Inc() + } +} + +func logProposedBlock(log *logrus.Entry, blk interfaces.SignedBeaconBlock, blkRoot []byte) error { if blk.Version() >= version.Bellatrix { p, err := blk.Block().Body().Execution() if err != nil { - log.WithError(err).Error("Failed to get execution payload") - return + return errors.Wrap(err, "failed to get execution payload") } log = log.WithFields(logrus.Fields{ "payloadHash": fmt.Sprintf("%#x", bytesutil.Trunc(p.BlockHash())), "parentHash": fmt.Sprintf("%#x", bytesutil.Trunc(p.ParentHash())), - "blockNumber": p.BlockNumber, + "blockNumber": p.BlockNumber(), }) if !blk.IsBlinded() { txs, err := p.Transactions() if err != nil { - log.WithError(err).Error("Failed to get execution payload transactions") - return + return errors.Wrap(err, "failed to get execution payload transactions") } log = log.WithField("txCount", len(txs)) } @@ -202,36 +216,32 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK if blk.Version() >= version.Capella && !blk.IsBlinded() { withdrawals, err := p.Withdrawals() if err != nil { - log.WithError(err).Error("Failed to get execution payload withdrawals") - return + return errors.Wrap(err, "failed to get execution payload withdrawals") } log = log.WithField("withdrawalCount", len(withdrawals)) } if blk.Version() >= version.Deneb { kzgs, err := blk.Block().Body().BlobKzgCommitments() if err != nil { - log.WithError(err).Error("Failed to get blob KZG commitments") - return + return errors.Wrap(err, "failed to get kzg commitments") } else if len(kzgs) != 0 { log = log.WithField("kzgCommitmentCount", len(kzgs)) } } } - blkRoot := fmt.Sprintf("%#x", bytesutil.Trunc(blkResp.BlockRoot)) + br := fmt.Sprintf("%#x", bytesutil.Trunc(blkRoot)) graffiti := blk.Block().Body().Graffiti() log.WithFields(logrus.Fields{ "slot": blk.Block().Slot(), - "blockRoot": blkRoot, + "blockRoot": br, "attestationCount": len(blk.Block().Body().Attestations()), "depositCount": len(blk.Block().Body().Deposits()), "graffiti": string(graffiti[:]), "fork": version.String(blk.Block().Version()), }).Info("Submitted new block") - if v.emitAccountMetrics { - ValidatorProposeSuccessVec.WithLabelValues(fmtKey).Inc() - } + return nil } func buildGenericSignedBlockDenebWithBlobs(pb proto.Message, b *ethpb.GenericBeaconBlock) (*ethpb.GenericSignedBeaconBlock, error) { @@ -266,6 +276,22 @@ func buildGenericSignedBlockElectraWithBlobs(pb proto.Message, b *ethpb.GenericB }, nil } +func buildGenericSignedBlockFuluWithBlobs(pb proto.Message, b *ethpb.GenericBeaconBlock) (*ethpb.GenericSignedBeaconBlock, error) { + fuluBlock, ok := pb.(*ethpb.SignedBeaconBlockFulu) + if !ok { + return nil, errors.New("could cast to fulu block") + } + return ðpb.GenericSignedBeaconBlock{ + Block: ðpb.GenericSignedBeaconBlock_Fulu{ + Fulu: ðpb.SignedBeaconBlockContentsFulu{ + Block: fuluBlock, + KzgProofs: b.GetFulu().KzgProofs, + Blobs: b.GetFulu().Blobs, + }, + }, + }, nil +} + // ProposeExit performs a voluntary exit on a validator. // The exit is signed by the validator before being sent to the beacon node for broadcasting. func ProposeExit( @@ -287,7 +313,7 @@ func ProposeExit( return errors.Wrap(err, "failed to propose voluntary exit") } - span.AddAttributes( + span.SetAttributes( trace.StringAttribute("exitRoot", fmt.Sprintf("%#x", exitResp.ExitRoot)), ) return nil diff --git a/validator/client/propose_test.go b/validator/client/propose_test.go index ab75d9ec2013..96075035f109 100644 --- a/validator/client/propose_test.go +++ b/validator/client/propose_test.go @@ -665,6 +665,19 @@ func testProposeBlock(t *testing.T, graffiti []byte) { }, }, }, + { + name: "fulu block", + version: version.Fulu, + block: ðpb.GenericBeaconBlock{ + Block: ðpb.GenericBeaconBlock_Fulu{ + Fulu: func() *ethpb.BeaconBlockContentsFulu { + blk := util.NewBeaconBlockContentsFulu() + blk.Block.Block.Body.Graffiti = graffiti + return ðpb.BeaconBlockContentsFulu{Block: blk.Block.Block, KzgProofs: blk.KzgProofs, Blobs: blk.Blobs} + }(), + }, + }, + }, } for _, tt := range tests { diff --git a/validator/client/registration.go b/validator/client/registration.go index fa5ca997f841..528b6f5e485f 100644 --- a/validator/client/registration.go +++ b/validator/client/registration.go @@ -10,10 +10,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/validator/client/iface" - "go.opencensus.io/trace" ) // SubmitValidatorRegistrations signs validator registration objects and submits it to the beacon node by batch of validatorRegsBatchSize size maximum. @@ -52,7 +52,7 @@ func SubmitValidatorRegistrations( } if lastErr == nil { - log.Infoln("Submitted builder validator registration settings for custom builders") + log.Debugln("Submitted builder validator registration settings for custom builders") } else { log.WithError(lastErr).Warn("Could not submit all signed registrations to beacon node") } @@ -93,24 +93,21 @@ func signValidatorRegistration(ctx context.Context, signer iface.SigningFunc, re } // SignValidatorRegistrationRequest compares and returns either the cached validator registration request or signs a new one. -func (v *validator) SignValidatorRegistrationRequest(ctx context.Context, signer iface.SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) { - ctx, span := trace.StartSpan(ctx, "validator.SignValidatorRegistrationRequest") - defer span.End() - +func (v *validator) SignValidatorRegistrationRequest(ctx context.Context, signer iface.SigningFunc, newValidatorRegistration *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool /* isCached */, error) { signedReg, ok := v.signedValidatorRegistrations[bytesutil.ToBytes48(newValidatorRegistration.Pubkey)] if ok && isValidatorRegistrationSame(signedReg.Message, newValidatorRegistration) { - return signedReg, nil + return signedReg, true, nil } else { sig, err := signValidatorRegistration(ctx, signer, newValidatorRegistration) if err != nil { - return nil, err + return nil, false, err } newRequest := ðpb.SignedValidatorRegistrationV1{ Message: newValidatorRegistration, Signature: sig, } v.signedValidatorRegistrations[bytesutil.ToBytes48(newValidatorRegistration.Pubkey)] = newRequest - return newRequest, nil + return newRequest, false, nil } } diff --git a/validator/client/registration_test.go b/validator/client/registration_test.go index f8c77b22494e..bd954317d202 100644 --- a/validator/client/registration_test.go +++ b/validator/client/registration_test.go @@ -10,7 +10,6 @@ import ( "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" - "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" @@ -172,7 +171,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) { }, validatorSetter: func(t *testing.T) *validator { v := validator{ - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, genesisTime: 0, @@ -200,7 +199,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) { }, validatorSetter: func(t *testing.T) *validator { v := validator{ - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, genesisTime: 0, @@ -228,7 +227,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) { }, validatorSetter: func(t *testing.T) *validator { v := validator{ - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, genesisTime: 0, @@ -256,7 +255,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) { }, validatorSetter: func(t *testing.T) *validator { v := validator{ - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, genesisTime: 0, @@ -272,7 +271,7 @@ func TestValidator_SignValidatorRegistrationRequest(t *testing.T) { startingReq, ok := v.signedValidatorRegistrations[bytesutil.ToBytes48(tt.arg.Pubkey)] - got, err := v.SignValidatorRegistrationRequest(ctx, m.signfunc, tt.arg) + got, _, err := v.SignValidatorRegistrationRequest(ctx, m.signfunc, tt.arg) require.NoError(t, err) if tt.isCached { require.DeepEqual(t, got, v.signedValidatorRegistrations[bytesutil.ToBytes48(tt.arg.Pubkey)]) diff --git a/validator/client/runner.go b/validator/client/runner.go index 34bc8273496c..49129f6528dc 100644 --- a/validator/client/runner.go +++ b/validator/client/runner.go @@ -14,9 +14,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + prysmTrace "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/prysmaticlabs/prysm/v5/validator/client/iface" - "go.opencensus.io/trace" + "go.opentelemetry.io/otel/trace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -61,15 +62,13 @@ func run(ctx context.Context, v iface.Validator) { log.Warn("Validator client started without proposer settings such as fee recipient" + " and will continue to use settings provided in the beacon node.") } - if err := v.PushProposerSettings(ctx, km, headSlot); err != nil { + if err := v.PushProposerSettings(ctx, km, headSlot, true); err != nil { log.WithError(err).Fatal("Failed to update proposer settings") } for { - ctx, span := trace.StartSpan(ctx, "validator.processSlot") select { case <-ctx.Done(): log.Info("Context canceled, stopping validator") - span.End() sub.Unsubscribe() close(accountsChangedChan) return // Exit if context is canceled. @@ -77,16 +76,20 @@ func run(ctx context.Context, v iface.Validator) { if !healthTracker.IsHealthy() { continue } - span.AddAttributes(trace.Int64Attribute("slot", int64(slot))) // lint:ignore uintcast -- This conversion is OK for tracing. deadline := v.SlotDeadline(slot) slotCtx, cancel := context.WithDeadline(ctx, deadline) + + var span trace.Span + slotCtx, span = prysmTrace.StartSpan(slotCtx, "validator.processSlot") + span.SetAttributes(prysmTrace.Int64Attribute("slot", int64(slot))) // lint:ignore uintcast -- This conversion is OK for tracing. + log := log.WithField("slot", slot) log.WithField("deadline", deadline).Debug("Set deadline for proposals and attestations") // Keep trying to update assignments if they are nil or if we are past an // epoch transition in the beacon node's state. - if err := v.UpdateDuties(ctx, slot); err != nil { + if err := v.UpdateDuties(slotCtx, slot); err != nil { handleAssignmentError(err, slot) cancel() span.End() @@ -96,18 +99,18 @@ func run(ctx context.Context, v iface.Validator) { // call push proposer settings often to account for the following edge cases: // proposer is activated at the start of epoch and tries to propose immediately // account has changed in the middle of an epoch - if err := v.PushProposerSettings(ctx, km, slot); err != nil { + if err := v.PushProposerSettings(slotCtx, km, slot, false); err != nil { log.WithError(err).Warn("Failed to update proposer settings") } // Start fetching domain data for the next epoch. if slots.IsEpochEnd(slot) { - go v.UpdateDomainDataCaches(ctx, slot+1) + go v.UpdateDomainDataCaches(slotCtx, slot+1) } var wg sync.WaitGroup - allRoles, err := v.RolesAt(ctx, slot) + allRoles, err := v.RolesAt(slotCtx, slot) if err != nil { log.WithError(err).Error("Could not get validator roles") cancel() @@ -136,6 +139,9 @@ func run(ctx context.Context, v iface.Validator) { } func onAccountsChanged(ctx context.Context, v iface.Validator, current [][48]byte, ac chan [][fieldparams.BLSPubkeyLength]byte) { + ctx, span := prysmTrace.StartSpan(ctx, "validator.accountsChanged") + defer span.End() + anyActive, err := v.HandleKeyReload(ctx, current) if err != nil { log.WithError(err).Error("Could not properly handle reloaded keys") @@ -150,7 +156,7 @@ func onAccountsChanged(ctx context.Context, v iface.Validator, current [][48]byt } func initializeValidatorAndGetHeadSlot(ctx context.Context, v iface.Validator) (primitives.Slot, error) { - ctx, span := trace.StartSpan(ctx, "validator.initializeValidatorAndGetHeadSlot") + ctx, span := prysmTrace.StartSpan(ctx, "validator.initializeValidatorAndGetHeadSlot") defer span.End() ticker := time.NewTicker(backOffPeriod) @@ -225,7 +231,7 @@ func initializeValidatorAndGetHeadSlot(ctx context.Context, v iface.Validator) ( return headSlot, nil } -func performRoles(slotCtx context.Context, allRoles map[[48]byte][]iface.ValidatorRole, v iface.Validator, slot primitives.Slot, wg *sync.WaitGroup, span *trace.Span) { +func performRoles(slotCtx context.Context, allRoles map[[48]byte][]iface.ValidatorRole, v iface.Validator, slot primitives.Slot, wg *sync.WaitGroup, span trace.Span) { for pubKey, roles := range allRoles { wg.Add(len(roles)) for _, role := range roles { @@ -315,7 +321,7 @@ func runHealthCheckRoutine(ctx context.Context, v iface.Validator, eventsChan ch log.WithError(err).Error("Could not get canonical head slot") return } - if err := v.PushProposerSettings(ctx, km, slot); err != nil { + if err := v.PushProposerSettings(ctx, km, slot, true); err != nil { log.WithError(err).Warn("Failed to update proposer settings") } } diff --git a/validator/client/service.go b/validator/client/service.go index 31c039cf5219..63ff04227a4a 100644 --- a/validator/client/service.go +++ b/validator/client/service.go @@ -33,6 +33,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/validator/keymanager/local" remoteweb3signer "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer" "go.opencensus.io/plugin/ocgrpc" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) @@ -173,7 +174,7 @@ func (v *ValidatorService) Start() { return } restHandler := beaconApi.NewBeaconApiJsonRestHandler( - http.Client{Timeout: v.conn.GetBeaconApiTimeout()}, + http.Client{Timeout: v.conn.GetBeaconApiTimeout(), Transport: otelhttp.NewTransport(http.DefaultTransport)}, hosts[0], ) @@ -184,7 +185,7 @@ func (v *ValidatorService) Start() { startBalances: make(map[[fieldparams.BLSPubkeyLength]byte]uint64), prevEpochBalances: make(map[[fieldparams.BLSPubkeyLength]byte]uint64), blacklistedPubkeys: slashablePublicKeys, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), wallet: v.wallet, walletInitializedChan: make(chan *wallet.Wallet, 1), walletInitializedFeed: v.walletInitializedFeed, diff --git a/validator/client/sync_committee.go b/validator/client/sync_committee.go index f32b1ce0fede..0d67eedbd3d6 100644 --- a/validator/client/sync_committee.go +++ b/validator/client/sync_committee.go @@ -16,19 +16,19 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/prysmaticlabs/prysm/v5/validator/client/iface" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" ) // SubmitSyncCommitteeMessage submits the sync committee message to the beacon chain. func (v *validator) SubmitSyncCommitteeMessage(ctx context.Context, slot primitives.Slot, pubKey [fieldparams.BLSPubkeyLength]byte) { ctx, span := trace.StartSpan(ctx, "validator.SubmitSyncCommitteeMessage") defer span.End() - span.AddAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey))) + span.SetAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey))) v.waitOneThirdOrValidBlock(ctx, slot) @@ -98,7 +98,7 @@ func (v *validator) SubmitSyncCommitteeMessage(ctx context.Context, slot primiti func (v *validator) SubmitSignedContributionAndProof(ctx context.Context, slot primitives.Slot, pubKey [fieldparams.BLSPubkeyLength]byte) { ctx, span := trace.StartSpan(ctx, "validator.SubmitSignedContributionAndProof") defer span.End() - span.AddAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey))) + span.SetAttributes(trace.StringAttribute("validator", fmt.Sprintf("%#x", pubKey))) duty, err := v.duty(pubKey) if err != nil { diff --git a/validator/client/testutil/mock_validator.go b/validator/client/testutil/mock_validator.go index 0e462c1c6203..e6a48d5b91c5 100644 --- a/validator/client/testutil/mock_validator.go +++ b/validator/client/testutil/mock_validator.go @@ -254,7 +254,7 @@ func (*FakeValidator) HasProposerSettings() bool { } // PushProposerSettings for mocking -func (fv *FakeValidator) PushProposerSettings(ctx context.Context, _ keymanager.IKeymanager, _ primitives.Slot) error { +func (fv *FakeValidator) PushProposerSettings(ctx context.Context, _ keymanager.IKeymanager, _ primitives.Slot, _ bool) error { time.Sleep(fv.ProposerSettingWait) if errors.Is(ctx.Err(), context.DeadlineExceeded) { log.Error("deadline exceeded") @@ -276,8 +276,8 @@ func (*FakeValidator) SetPubKeyToValidatorIndexMap(_ context.Context, _ keymanag } // SignValidatorRegistrationRequest for mocking -func (*FakeValidator) SignValidatorRegistrationRequest(_ context.Context, _ iface.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, error) { - return nil, nil +func (*FakeValidator) SignValidatorRegistrationRequest(_ context.Context, _ iface.SigningFunc, _ *ethpb.ValidatorRegistrationV1) (*ethpb.SignedValidatorRegistrationV1, bool, error) { + return nil, false, nil } // ProposerSettings for mocking diff --git a/validator/client/validator.go b/validator/client/validator.go index b89c9e88fcd9..a342b7966d34 100644 --- a/validator/client/validator.go +++ b/validator/client/validator.go @@ -10,7 +10,6 @@ import ( "encoding/json" "fmt" "io" - "math" "strconv" "strings" "sync" @@ -35,11 +34,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/crypto/hash" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/time/slots" accountsiface "github.com/prysmaticlabs/prysm/v5/validator/accounts/iface" "github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet" - beaconapi "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api" "github.com/prysmaticlabs/prysm/v5/validator/client/iface" "github.com/prysmaticlabs/prysm/v5/validator/db" dbCommon "github.com/prysmaticlabs/prysm/v5/validator/db/common" @@ -48,10 +47,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/validator/keymanager/local" remoteweb3signer "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" - "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/emptypb" ) @@ -77,7 +73,7 @@ type validator struct { startBalances map[[fieldparams.BLSPubkeyLength]byte]uint64 prevEpochBalances map[[fieldparams.BLSPubkeyLength]byte]uint64 blacklistedPubkeys map[[fieldparams.BLSPubkeyLength]byte]bool - pubkeyToValidatorIndex map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex + pubkeyToStatus map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus wallet *wallet.Wallet walletInitializedChan chan *wallet.Wallet walletInitializedFeed *event.Feed @@ -352,10 +348,10 @@ func (v *validator) WaitForSync(ctx context.Context) error { } } -func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, activeValCount int64) bool { +func (v *validator) checkAndLogValidatorStatus() bool { nonexistentIndex := primitives.ValidatorIndex(^uint64(0)) - var validatorActivated bool - for _, s := range statuses { + var someAreActive bool + for _, s := range v.pubkeyToStatus { fields := logrus.Fields{ "pubkey": fmt.Sprintf("%#x", bytesutil.Trunc(s.publicKey)), "status": s.status.Status.String(), @@ -365,36 +361,18 @@ func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, acti } log := log.WithFields(fields) if v.emitAccountMetrics { - fmtKey := fmt.Sprintf("%#x", s.publicKey) - ValidatorStatusesGaugeVec.WithLabelValues(fmtKey).Set(float64(s.status.Status)) + fmtKey, fmtIndex := fmt.Sprintf("%#x", s.publicKey), fmt.Sprintf("%#x", s.index) + ValidatorStatusesGaugeVec.WithLabelValues(fmtKey, fmtIndex).Set(float64(s.status.Status)) } switch s.status.Status { case ethpb.ValidatorStatus_UNKNOWN_STATUS: log.Info("Waiting for deposit to be observed by beacon node") case ethpb.ValidatorStatus_DEPOSITED: - if s.status.PositionInActivationQueue != 0 { - log.WithField( - "positionInActivationQueue", s.status.PositionInActivationQueue, - ).Info("Deposit processed, entering activation queue after finalization") - } + log.Info("Validator deposited, entering activation queue after finalization") case ethpb.ValidatorStatus_PENDING: - if activeValCount >= 0 && s.status.ActivationEpoch == params.BeaconConfig().FarFutureEpoch { - activationsPerEpoch := - uint64(math.Max(float64(params.BeaconConfig().MinPerEpochChurnLimit), float64(uint64(activeValCount)/params.BeaconConfig().ChurnLimitQuotient))) - secondsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().SecondsPerSlot)) - expectedWaitingTime := - time.Duration((s.status.PositionInActivationQueue+activationsPerEpoch)/activationsPerEpoch*secondsPerEpoch) * time.Second - log.WithFields(logrus.Fields{ - "positionInActivationQueue": s.status.PositionInActivationQueue, - "expectedWaitingTime": expectedWaitingTime.String(), - }).Info("Waiting to be assigned activation epoch") - } else if s.status.ActivationEpoch != params.BeaconConfig().FarFutureEpoch { - log.WithFields(logrus.Fields{ - "activationEpoch": s.status.ActivationEpoch, - }).Info("Waiting for activation") - } + log.Info("Waiting for activation... Check validator queue status in a block explorer") case ethpb.ValidatorStatus_ACTIVE, ethpb.ValidatorStatus_EXITING: - validatorActivated = true + someAreActive = true log.WithFields(logrus.Fields{ "index": s.index, }).Info("Validator activated") @@ -404,11 +382,11 @@ func (v *validator) checkAndLogValidatorStatus(statuses []*validatorStatus, acti log.Warn("Invalid Eth1 deposit") default: log.WithFields(logrus.Fields{ - "activationEpoch": s.status.ActivationEpoch, + "status": s.status.Status.String(), }).Info("Validator status") } } - return validatorActivated + return someAreActive } // CanonicalHeadSlot returns the slot of canonical block currently found in the @@ -992,7 +970,7 @@ func (v *validator) logDuties(slot primitives.Slot, currentEpochDuties []*ethpb. for _, duty := range currentEpochDuties { pubkey := fmt.Sprintf("%#x", duty.PublicKey) if v.emitAccountMetrics { - ValidatorStatusesGaugeVec.WithLabelValues(pubkey).Set(float64(duty.Status)) + ValidatorStatusesGaugeVec.WithLabelValues(pubkey, fmt.Sprintf("%#x", duty.ValidatorIndex)).Set(float64(duty.Status)) } // Only interested in validators who are attesting/proposing. @@ -1102,7 +1080,7 @@ func (v *validator) SetProposerSettings(ctx context.Context, settings *proposer. } // PushProposerSettings calls the prepareBeaconProposer RPC to set the fee recipient and also the register validator API if using a custom builder. -func (v *validator) PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot) error { +func (v *validator) PushProposerSettings(ctx context.Context, km keymanager.IKeymanager, slot primitives.Slot, forceFullPush bool) error { ctx, span := trace.StartSpan(ctx, "validator.PushProposerSettings") defer span.End() @@ -1143,7 +1121,7 @@ func (v *validator) PushProposerSettings(ctx context.Context, km keymanager.IKey }); err != nil { return err } - signedRegReqs := v.buildSignedRegReqs(ctx, filteredKeys, km.Sign) + signedRegReqs := v.buildSignedRegReqs(ctx, filteredKeys, km.Sign, slot, forceFullPush) if len(signedRegReqs) > 0 { go func() { if err := SubmitValidatorRegistrations(ctx, v.validatorClient, signedRegReqs, v.validatorsRegBatchSize); err != nil { @@ -1212,44 +1190,31 @@ func (v *validator) ChangeHost() { func (v *validator) filterAndCacheActiveKeys(ctx context.Context, pubkeys [][fieldparams.BLSPubkeyLength]byte, slot primitives.Slot) ([][fieldparams.BLSPubkeyLength]byte, error) { ctx, span := trace.StartSpan(ctx, "validator.filterAndCacheActiveKeys") defer span.End() - + isEpochStart := slots.IsEpochStart(slot) filteredKeys := make([][fieldparams.BLSPubkeyLength]byte, 0) - statusRequestKeys := make([][]byte, 0) - for _, k := range pubkeys { - _, ok := v.pubkeyToValidatorIndex[k] - // Get validator index from RPC server if not found. - if !ok { - i, ok, err := v.validatorIndex(ctx, k) - if err != nil { - return nil, err - } - if !ok { // Nothing we can do if RPC server doesn't have validator index. - continue - } - v.pubkeyToValidatorIndex[k] = i - } - copiedk := k - statusRequestKeys = append(statusRequestKeys, copiedk[:]) + if len(pubkeys) == 0 { + return filteredKeys, nil } - resp, err := v.validatorClient.MultipleValidatorStatus(ctx, ðpb.MultipleValidatorStatusRequest{ - PublicKeys: statusRequestKeys, - }) - if err != nil { - return nil, err + var err error + // repopulate the statuses if epoch start or if a new key is added missing the cache + if isEpochStart || len(v.pubkeyToStatus) != len(pubkeys) /* cache not populated or updated correctly */ { + if err = v.updateValidatorStatusCache(ctx, pubkeys); err != nil { + return nil, errors.Wrap(err, "failed to update validator status cache") + } } - for i, s := range resp.Statuses { + for k, s := range v.pubkeyToStatus { currEpoch := primitives.Epoch(slot / params.BeaconConfig().SlotsPerEpoch) - currActivating := s.Status == ethpb.ValidatorStatus_PENDING && currEpoch >= s.ActivationEpoch + currActivating := s.status.Status == ethpb.ValidatorStatus_PENDING && currEpoch >= s.status.ActivationEpoch - active := s.Status == ethpb.ValidatorStatus_ACTIVE - exiting := s.Status == ethpb.ValidatorStatus_EXITING + active := s.status.Status == ethpb.ValidatorStatus_ACTIVE + exiting := s.status.Status == ethpb.ValidatorStatus_EXITING if currActivating || active || exiting { - filteredKeys = append(filteredKeys, bytesutil.ToBytes48(resp.PublicKeys[i])) + filteredKeys = append(filteredKeys, k) } else { log.WithFields(logrus.Fields{ - "pubkey": hexutil.Encode(resp.PublicKeys[i]), - "status": s.Status.String(), + "pubkey": hexutil.Encode(s.publicKey), + "status": s.status.Status.String(), }).Debugf("Skipping non-active status key.") } } @@ -1257,11 +1222,55 @@ func (v *validator) filterAndCacheActiveKeys(ctx context.Context, pubkeys [][fie return filteredKeys, nil } +// updateValidatorStatusCache updates the validator statuses cache, a map of keys currently used by the validator client +func (v *validator) updateValidatorStatusCache(ctx context.Context, pubkeys [][fieldparams.BLSPubkeyLength]byte) error { + if len(pubkeys) == 0 { + v.pubkeyToStatus = make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus, 0) + return nil + } + statusRequestKeys := make([][]byte, 0) + for _, k := range pubkeys { + statusRequestKeys = append(statusRequestKeys, k[:]) + } + resp, err := v.validatorClient.MultipleValidatorStatus(ctx, ðpb.MultipleValidatorStatusRequest{ + PublicKeys: statusRequestKeys, + }) + if err != nil { + return err + } + if resp == nil { + return errors.New("response is nil") + } + if len(resp.Statuses) != len(resp.PublicKeys) { + return fmt.Errorf("expected %d pubkeys in status, received %d", len(resp.Statuses), len(resp.PublicKeys)) + } + if len(resp.Statuses) != len(resp.Indices) { + return fmt.Errorf("expected %d indices in status, received %d", len(resp.Statuses), len(resp.Indices)) + } + + pubkeyToStatus := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus, len(resp.Statuses)) + for i, s := range resp.Statuses { + pubkeyToStatus[bytesutil.ToBytes48(resp.PublicKeys[i])] = &validatorStatus{ + publicKey: resp.PublicKeys[i], + status: s, + index: resp.Indices[i], + } + } + v.pubkeyToStatus = pubkeyToStatus + + return nil +} + func (v *validator) buildPrepProposerReqs(activePubkeys [][fieldparams.BLSPubkeyLength]byte) ([]*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer, error) { var prepareProposerReqs []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer for _, k := range activePubkeys { + s, ok := v.pubkeyToStatus[k] + if !ok { + continue + } + // Default case: Define fee recipient to burn address - var feeRecipient common.Address + feeRecipient := common.HexToAddress(params.BeaconConfig().EthBurnAddressHex) // If fee recipient is defined in default configuration, use it if v.ProposerSettings() != nil && v.ProposerSettings().DefaultConfig != nil && v.ProposerSettings().DefaultConfig.FeeRecipientConfig != nil { @@ -1277,13 +1286,8 @@ func (v *validator) buildPrepProposerReqs(activePubkeys [][fieldparams.BLSPubkey } } - validatorIndex, ok := v.pubkeyToValidatorIndex[k] - if !ok { - continue - } - prepareProposerReqs = append(prepareProposerReqs, ðpb.PrepareBeaconProposerRequest_FeeRecipientContainer{ - ValidatorIndex: validatorIndex, + ValidatorIndex: s.index, FeeRecipient: feeRecipient[:], }) } @@ -1294,27 +1298,36 @@ func (v *validator) buildSignedRegReqs( ctx context.Context, activePubkeys [][fieldparams.BLSPubkeyLength]byte, signer iface.SigningFunc, + slot primitives.Slot, + forceFullPush bool, ) []*ethpb.SignedValidatorRegistrationV1 { ctx, span := trace.StartSpan(ctx, "validator.buildSignedRegReqs") defer span.End() - var signedValRegRegs []*ethpb.SignedValidatorRegistrationV1 + var signedValRegRequests []*ethpb.SignedValidatorRegistrationV1 if v.ProposerSettings() == nil { - return signedValRegRegs + return signedValRegRequests } // if the timestamp is pre-genesis, don't create registrations if v.genesisTime > uint64(time.Now().UTC().Unix()) { - return signedValRegRegs + return signedValRegRequests } + + if v.ProposerSettings().DefaultConfig != nil && v.ProposerSettings().DefaultConfig.FeeRecipientConfig == nil && v.ProposerSettings().DefaultConfig.BuilderConfig != nil { + log.Warn("Builder is `enabled` in default config but will be ignored because no fee recipient was provided!") + } + for i, k := range activePubkeys { + // map is populated before this function in buildPrepProposerReq + _, ok := v.pubkeyToStatus[k] + if !ok { + continue + } + feeRecipient := common.HexToAddress(params.BeaconConfig().EthBurnAddressHex) gasLimit := params.BeaconConfig().DefaultBuilderGasLimit enabled := false - if v.ProposerSettings().DefaultConfig != nil && v.ProposerSettings().DefaultConfig.FeeRecipientConfig == nil && v.ProposerSettings().DefaultConfig.BuilderConfig != nil { - log.Warn("Builder is `enabled` in default config but will be ignored because no fee recipient was provided!") - } - if v.ProposerSettings().DefaultConfig != nil && v.ProposerSettings().DefaultConfig.FeeRecipientConfig != nil { defaultConfig := v.ProposerSettings().DefaultConfig feeRecipient = defaultConfig.FeeRecipientConfig.FeeRecipient // Use cli defaultBuilderConfig for fee recipient. @@ -1346,12 +1359,6 @@ func (v *validator) buildSignedRegReqs( continue } - // map is populated before this function in buildPrepProposerReq - _, ok := v.pubkeyToValidatorIndex[k] - if !ok { - continue - } - req := ðpb.ValidatorRegistrationV1{ FeeRecipient: feeRecipient[:], GasLimit: gasLimit, @@ -1359,7 +1366,7 @@ func (v *validator) buildSignedRegReqs( Pubkey: activePubkeys[i][:], } - signedReq, err := v.SignValidatorRegistrationRequest(ctx, signer, req) + signedRequest, isCached, err := v.SignValidatorRegistrationRequest(ctx, signer, req) if err != nil { log.WithFields(logrus.Fields{ "pubkey": fmt.Sprintf("%#x", req.Pubkey), @@ -1368,38 +1375,20 @@ func (v *validator) buildSignedRegReqs( continue } - signedValRegRegs = append(signedValRegRegs, signedReq) - if hexutil.Encode(feeRecipient.Bytes()) == params.BeaconConfig().EthBurnAddressHex { log.WithFields(logrus.Fields{ "pubkey": fmt.Sprintf("%#x", req.Pubkey), "feeRecipient": feeRecipient, }).Warn("Fee recipient is burn address") } - } - return signedValRegRegs -} -func (v *validator) validatorIndex(ctx context.Context, pubkey [fieldparams.BLSPubkeyLength]byte) (primitives.ValidatorIndex, bool, error) { - ctx, span := trace.StartSpan(ctx, "validator.validatorIndex") - defer span.End() - - resp, err := v.validatorClient.ValidatorIndex(ctx, ðpb.ValidatorIndexRequest{PublicKey: pubkey[:]}) - switch { - case status.Code(err) == codes.NotFound: - log.Debugf("Could not find validator index for public key %#x. "+ - "Perhaps the validator is not yet active.", pubkey) - return 0, false, nil - case err != nil: - notFoundErr := &beaconapi.IndexNotFoundError{} - if errors.As(err, ¬FoundErr) { - log.Debugf("Could not find validator index for public key %#x. "+ - "Perhaps the validator is not yet active.", pubkey) - return 0, false, nil - } - return 0, false, err - } - return resp.Index, true, nil + if slots.IsEpochStart(slot) || forceFullPush || !isCached { + // if epoch start (or forced to) send all validator registrations + // otherwise if slot is not epoch start then only send new non cached values + signedValRegRequests = append(signedValRegRequests, signedRequest) + } + } + return signedValRegRequests } func (v *validator) aggregatedSelectionProofs(ctx context.Context, duties *ethpb.DutiesResponse) error { diff --git a/validator/client/validator_test.go b/validator/client/validator_test.go index 2d9eca2ff3e9..9217347d9a56 100644 --- a/validator/client/validator_test.go +++ b/validator/client/validator_test.go @@ -1,6 +1,7 @@ package client import ( + "bytes" "context" "errors" "flag" @@ -9,6 +10,7 @@ import ( "math" "os" "path/filepath" + "sort" "strings" "sync" "testing" @@ -31,7 +33,6 @@ import ( ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/testing/assert" - mock2 "github.com/prysmaticlabs/prysm/v5/testing/mock" "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/testing/util" validatormock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock" @@ -45,8 +46,6 @@ import ( logTest "github.com/sirupsen/logrus/hooks/test" "github.com/urfave/cli/v2" "go.uber.org/mock/gomock" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" ) @@ -59,6 +58,8 @@ var _ iface.Validator = (*validator)(nil) const cancelledCtx = "context has been canceled" +var unknownIndex = primitives.ValidatorIndex(^uint64(0)) + func genMockKeymanager(t *testing.T, numKeys int) *mockKeymanager { pairs := make([]keypair, numKeys) for i := 0; i < numKeys; i++ { @@ -156,19 +157,6 @@ func (*mockKeymanager) DeleteKeystores(context.Context, [][]byte, return nil, nil } -func generateMockStatusResponse(pubkeys [][]byte) *ethpb.ValidatorActivationResponse { - multipleStatus := make([]*ethpb.ValidatorActivationResponse_Status, len(pubkeys)) - for i, key := range pubkeys { - multipleStatus[i] = ðpb.ValidatorActivationResponse_Status{ - PublicKey: key, - Status: ðpb.ValidatorStatusResponse{ - Status: ethpb.ValidatorStatus_UNKNOWN_STATUS, - }, - } - } - return ðpb.ValidatorActivationResponse{Statuses: multipleStatus} -} - func TestWaitForChainStart_SetsGenesisInfo(t *testing.T) { for _, isSlashingProtectionMinimal := range [...]bool{false, true} { t.Run(fmt.Sprintf("SlashingProtectionMinimal:%v", isSlashingProtectionMinimal), func(t *testing.T) { @@ -339,45 +327,6 @@ func TestCanonicalHeadSlot_OK(t *testing.T) { assert.Equal(t, primitives.Slot(0), headSlot, "Mismatch slots") } -func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) { - ctx := context.Background() - hook := logTest.NewGlobal() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - client := validatormock.NewMockValidatorClient(ctrl) - chainClient := validatormock.NewMockChainClient(ctrl) - prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl) - - kp := randKeypair(t) - v := validator{ - validatorClient: client, - km: newMockKeymanager(t, kp), - chainClient: chainClient, - prysmChainClient: prysmChainClient, - } - - resp := generateMockStatusResponse([][]byte{kp.pub[:]}) - resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE - clientStream := mock2.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - client.EXPECT().WaitForActivation( - gomock.Any(), - ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{kp.pub[:]}, - }, - ).Return(clientStream, nil) - clientStream.EXPECT().Recv().Return( - resp, - nil, - ) - prysmChainClient.EXPECT().ValidatorCount( - gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil) - require.NoError(t, v.WaitForActivation(ctx, nil), "Could not wait for activation") - require.LogsContain(t, hook, "Validator activated") -} - func TestWaitSync_ContextCanceled(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -857,7 +806,7 @@ func TestCheckAndLogValidatorStatus_OK(t *testing.T) { PositionInActivationQueue: 30, }, }, - log: "Deposit processed, entering activation queue after finalization\" positionInActivationQueue=30 prefix=client pubkey=0x000000000000 status=DEPOSITED validatorIndex=30", + log: "Validator deposited, entering activation queue after finalization\" prefix=client pubkey=0x000000000000 status=DEPOSITED validatorIndex=30", active: false, }, { @@ -871,21 +820,7 @@ func TestCheckAndLogValidatorStatus_OK(t *testing.T) { PositionInActivationQueue: 6, }, }, - log: "Waiting to be assigned activation epoch\" expectedWaitingTime=12m48s positionInActivationQueue=6 prefix=client pubkey=0x000000000000 status=PENDING validatorIndex=50", - active: false, - }, - { - name: "PENDING", - status: &validatorStatus{ - publicKey: pubKeys[0], - index: 89, - status: ðpb.ValidatorStatusResponse{ - Status: ethpb.ValidatorStatus_PENDING, - ActivationEpoch: 60, - PositionInActivationQueue: 5, - }, - }, - log: "Waiting for activation\" activationEpoch=60 prefix=client pubkey=0x000000000000 status=PENDING validatorIndex=89", + log: "Waiting for activation... Check validator queue status in a block explorer\" prefix=client pubkey=0x000000000000 status=PENDING validatorIndex=50", active: false, }, { @@ -937,9 +872,10 @@ func TestCheckAndLogValidatorStatus_OK(t *testing.T) { }, }, }, + pubkeyToStatus: make(map[[48]byte]*validatorStatus), } - - active := v.checkAndLogValidatorStatus([]*validatorStatus{test.status}, 100) + v.pubkeyToStatus[bytesutil.ToBytes48(test.status.publicKey)] = test.status + active := v.checkAndLogValidatorStatus() require.Equal(t, test.active, active) if test.log != "" { require.LogsContain(t, hook, test.log) @@ -1453,6 +1389,40 @@ func TestValidator_WaitForKeymanagerInitialization_Interop(t *testing.T) { } } +type PrepareBeaconProposerRequestMatcher struct { + expectedRecipients []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer +} + +func (m *PrepareBeaconProposerRequestMatcher) Matches(x interface{}) bool { + req, ok := x.(*ethpb.PrepareBeaconProposerRequest) + if !ok { + return false + } + + if len(req.Recipients) != len(m.expectedRecipients) { + return false + } + + // Build maps for efficient comparison + expectedMap := make(map[primitives.ValidatorIndex][]byte) + for _, recipient := range m.expectedRecipients { + expectedMap[recipient.ValidatorIndex] = recipient.FeeRecipient + } + + // Compare the maps + for _, fc := range req.Recipients { + expectedFeeRecipient, exists := expectedMap[fc.ValidatorIndex] + if !exists || !bytes.Equal(expectedFeeRecipient, fc.FeeRecipient) { + return false + } + } + return true +} + +func (m *PrepareBeaconProposerRequestMatcher) String() string { + return fmt.Sprintf("matches PrepareBeaconProposerRequest with Recipients: %v", m.expectedRecipients) +} + func TestValidator_PushSettings(t *testing.T) { for _, isSlashingProtectionMinimal := range [...]bool{false, true} { ctrl := gomock.NewController(t) @@ -1489,7 +1459,7 @@ func TestValidator_PushSettings(t *testing.T) { validatorClient: client, nodeClient: nodeClient, db: db, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, interopKeysConfig: &local.InteropKeymanagerConfig{ @@ -1504,17 +1474,26 @@ func TestValidator_PushSettings(t *testing.T) { require.NoError(t, err) keys, err := km.FetchValidatingPublicKeys(ctx) require.NoError(t, err) - v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1) - v.pubkeyToValidatorIndex[keys[1]] = primitives.ValidatorIndex(2) + v.pubkeyToStatus[keys[0]] = &validatorStatus{ + publicKey: keys[0][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(1), + } + v.pubkeyToStatus[keys[1]] = &validatorStatus{ + publicKey: keys[1][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(2), + } client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).Return( ðpb.MultipleValidatorStatusResponse{ Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}}, PublicKeys: [][]byte{keys[0][:], keys[1][:]}, + Indices: []primitives.ValidatorIndex{1, 2}, }, nil) - client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{ - Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{ + client.EXPECT().PrepareBeaconProposer(gomock.Any(), &PrepareBeaconProposerRequestMatcher{ + expectedRecipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{ {FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1}, {FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2}, }, @@ -1571,7 +1550,7 @@ func TestValidator_PushSettings(t *testing.T) { validatorClient: client, nodeClient: nodeClient, db: db, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, interopKeysConfig: &local.InteropKeymanagerConfig{ @@ -1586,17 +1565,26 @@ func TestValidator_PushSettings(t *testing.T) { require.NoError(t, err) keys, err := km.FetchValidatingPublicKeys(ctx) require.NoError(t, err) - v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1) - v.pubkeyToValidatorIndex[keys[1]] = primitives.ValidatorIndex(2) + v.pubkeyToStatus[keys[0]] = &validatorStatus{ + publicKey: keys[0][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(1), + } + v.pubkeyToStatus[keys[1]] = &validatorStatus{ + publicKey: keys[1][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(2), + } client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).Return( ðpb.MultipleValidatorStatusResponse{ Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}}, PublicKeys: [][]byte{keys[0][:], keys[1][:]}, + Indices: []primitives.ValidatorIndex{1, 2}, }, nil) - client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{ - Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{ + client.EXPECT().PrepareBeaconProposer(gomock.Any(), &PrepareBeaconProposerRequestMatcher{ + expectedRecipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{ {FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1}, {FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2}, }, @@ -1644,12 +1632,11 @@ func TestValidator_PushSettings(t *testing.T) { { name: " Happy Path default doesn't send any validator registrations", validatorSetter: func(t *testing.T) *validator { - v := validator{ validatorClient: client, nodeClient: nodeClient, db: db, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, interopKeysConfig: &local.InteropKeymanagerConfig{ @@ -1664,17 +1651,26 @@ func TestValidator_PushSettings(t *testing.T) { require.NoError(t, err) keys, err := km.FetchValidatingPublicKeys(ctx) require.NoError(t, err) - v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1) - v.pubkeyToValidatorIndex[keys[1]] = primitives.ValidatorIndex(2) + v.pubkeyToStatus[keys[0]] = &validatorStatus{ + publicKey: keys[0][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(1), + } + v.pubkeyToStatus[keys[1]] = &validatorStatus{ + publicKey: keys[1][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(2), + } client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).Return( ðpb.MultipleValidatorStatusResponse{ Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}}, PublicKeys: [][]byte{keys[0][:], keys[1][:]}, + Indices: []primitives.ValidatorIndex{1, 2}, }, nil) - client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{ - Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{ + client.EXPECT().PrepareBeaconProposer(gomock.Any(), &PrepareBeaconProposerRequestMatcher{ + expectedRecipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{ {FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1}, {FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2}, }, @@ -1710,7 +1706,7 @@ func TestValidator_PushSettings(t *testing.T) { validatorClient: client, nodeClient: nodeClient, db: db, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, interopKeysConfig: &local.InteropKeymanagerConfig{ @@ -1740,13 +1736,18 @@ func TestValidator_PushSettings(t *testing.T) { }, }) require.NoError(t, err) - v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1) + v.pubkeyToStatus[keys[0]] = &validatorStatus{ + publicKey: keys[0][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(1), + } client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).Return( ðpb.MultipleValidatorStatusResponse{ Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}}, PublicKeys: [][]byte{keys[0][:]}, + Indices: []primitives.ValidatorIndex{1}, }, nil) client.EXPECT().SubmitValidatorRegistrations( @@ -1778,7 +1779,7 @@ func TestValidator_PushSettings(t *testing.T) { validatorClient: client, nodeClient: nodeClient, db: db, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, interopKeysConfig: &local.InteropKeymanagerConfig{ @@ -1805,13 +1806,18 @@ func TestValidator_PushSettings(t *testing.T) { require.NoError(t, err) keys, err := km.FetchValidatingPublicKeys(ctx) require.NoError(t, err) - v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1) + v.pubkeyToStatus[keys[0]] = &validatorStatus{ + publicKey: keys[0][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(1), + } client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).Return( ðpb.MultipleValidatorStatusResponse{ Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}}, PublicKeys: [][]byte{keys[0][:]}, + Indices: []primitives.ValidatorIndex{1}, }, nil) client.EXPECT().SubmitValidatorRegistrations( gomock.Any(), @@ -1842,7 +1848,7 @@ func TestValidator_PushSettings(t *testing.T) { validatorClient: client, nodeClient: nodeClient, db: db, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, interopKeysConfig: &local.InteropKeymanagerConfig{ @@ -1857,13 +1863,18 @@ func TestValidator_PushSettings(t *testing.T) { require.NoError(t, err) keys, err := km.FetchValidatingPublicKeys(ctx) require.NoError(t, err) - v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1) + v.pubkeyToStatus[keys[0]] = &validatorStatus{ + publicKey: keys[0][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(1), + } client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).Return( ðpb.MultipleValidatorStatusResponse{ Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}}, PublicKeys: [][]byte{keys[0][:]}, + Indices: []primitives.ValidatorIndex{1}, }, nil) client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.PrepareBeaconProposerRequest{ Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{ @@ -1894,7 +1905,7 @@ func TestValidator_PushSettings(t *testing.T) { v := validator{ validatorClient: client, db: db, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, interopKeysConfig: &local.InteropKeymanagerConfig{ @@ -1909,15 +1920,19 @@ func TestValidator_PushSettings(t *testing.T) { require.NoError(t, err) keys, err := km.FetchValidatingPublicKeys(ctx) require.NoError(t, err) - client.EXPECT().ValidatorIndex( - gomock.Any(), // ctx - ðpb.ValidatorIndexRequest{PublicKey: keys[0][:]}, - ).Return(nil, errors.New("could not find validator index for public key")) config[keys[0]] = &proposer.Option{ FeeRecipientConfig: &proposer.FeeRecipientConfig{ FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9"), }, } + client.EXPECT().MultipleValidatorStatus( + gomock.Any(), + gomock.Any()).Return( + ðpb.MultipleValidatorStatusResponse{ + Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}}, + PublicKeys: [][]byte{keys[0][:]}, + Indices: []primitives.ValidatorIndex{unknownIndex}, + }, nil) err = v.SetProposerSettings(context.Background(), &proposer.Settings{ ProposeConfig: config, DefaultConfig: &proposer.Option{ @@ -1937,7 +1952,7 @@ func TestValidator_PushSettings(t *testing.T) { validatorClient: client, nodeClient: nodeClient, db: db, - pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus), signedValidatorRegistrations: make(map[[fieldparams.BLSPubkeyLength]byte]*ethpb.SignedValidatorRegistrationV1), useWeb: false, interopKeysConfig: &local.InteropKeymanagerConfig{ @@ -1952,13 +1967,18 @@ func TestValidator_PushSettings(t *testing.T) { require.NoError(t, err) keys, err := km.FetchValidatingPublicKeys(ctx) require.NoError(t, err) - v.pubkeyToValidatorIndex[keys[0]] = primitives.ValidatorIndex(1) + v.pubkeyToStatus[keys[0]] = &validatorStatus{ + publicKey: keys[0][:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: primitives.ValidatorIndex(1), + } client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).Return( ðpb.MultipleValidatorStatusResponse{ Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}}, PublicKeys: [][]byte{keys[0][:]}, + Indices: []primitives.ValidatorIndex{1}, }, nil) config[keys[0]] = &proposer.Option{ @@ -2009,7 +2029,7 @@ func TestValidator_PushSettings(t *testing.T) { if tt.feeRecipientMap != nil { feeRecipients, err := v.buildPrepProposerReqs(pubkeys) require.NoError(t, err) - signedRegisterValidatorRequests := v.buildSignedRegReqs(ctx, pubkeys, km.Sign) + signedRegisterValidatorRequests := v.buildSignedRegReqs(ctx, pubkeys, km.Sign, 0, false) for _, recipient := range feeRecipients { require.Equal(t, strings.ToLower(tt.feeRecipientMap[recipient.ValidatorIndex]), strings.ToLower(hexutil.Encode(recipient.FeeRecipient))) } @@ -2027,7 +2047,7 @@ func TestValidator_PushSettings(t *testing.T) { require.Equal(t, len(tt.mockExpectedRequests), len(signedRegisterValidatorRequests)) require.Equal(t, len(signedRegisterValidatorRequests), len(v.signedValidatorRegistrations)) } - if err := v.PushProposerSettings(ctx, km, 0); tt.err != "" { + if err := v.PushProposerSettings(ctx, km, 0, false); tt.err != "" { assert.ErrorContains(t, tt.err, err) } if len(tt.logMessages) > 0 { @@ -2091,28 +2111,14 @@ func TestValidator_buildPrepProposerReqs_WithoutDefaultConfig(t *testing.T) { ctx := context.Background() client := validatormock.NewMockValidatorClient(ctrl) - client.EXPECT().ValidatorIndex( - gomock.Any(), - ðpb.ValidatorIndexRequest{ - PublicKey: pubkey2[:], - }, - ).Return(ðpb.ValidatorIndexResponse{ - Index: 2, - }, nil) - - client.EXPECT().ValidatorIndex( - gomock.Any(), - ðpb.ValidatorIndexRequest{ - PublicKey: pubkey3[:], - }, - ).Return(nil, status.Error(codes.NotFound, "NOT_FOUND")) client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).Return( ðpb.MultipleValidatorStatusResponse{ - Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}}, - PublicKeys: [][]byte{pubkey1[:], pubkey2[:], pubkey4[:]}, + Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}, {Status: ethpb.ValidatorStatus_ACTIVE}}, + PublicKeys: [][]byte{pubkey1[:], pubkey2[:], pubkey3[:], pubkey4[:]}, + Indices: []primitives.ValidatorIndex{1, 2, unknownIndex, 4}, }, nil) v := validator{ validatorClient: client, @@ -2141,9 +2147,17 @@ func TestValidator_buildPrepProposerReqs_WithoutDefaultConfig(t *testing.T) { }, }, }, - pubkeyToValidatorIndex: map[[48]byte]primitives.ValidatorIndex{ - pubkey1: 1, - pubkey4: 4, + pubkeyToStatus: map[[48]byte]*validatorStatus{ + pubkey1: { + publicKey: pubkey1[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 1, + }, + pubkey4: { + publicKey: pubkey4[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 4, + }, }, } @@ -2167,18 +2181,121 @@ func TestValidator_buildPrepProposerReqs_WithoutDefaultConfig(t *testing.T) { require.NoError(t, err) actual, err := v.buildPrepProposerReqs(filteredKeys) require.NoError(t, err) + sort.Slice(actual, func(i, j int) bool { + return actual[i].ValidatorIndex < actual[j].ValidatorIndex + }) assert.DeepEqual(t, expected, actual) } +func TestValidator_filterAndCacheActiveKeys(t *testing.T) { + // Public keys + pubkey1 := pubkeyFromString(t, "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") + pubkey2 := pubkeyFromString(t, "0x222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") + pubkey3 := pubkeyFromString(t, "0x333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333") + pubkey4 := pubkeyFromString(t, "0x444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444") + + t.Run("refetch all keys at start of epoch", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.Background() + client := validatormock.NewMockValidatorClient(ctrl) + + client.EXPECT().MultipleValidatorStatus( + gomock.Any(), + gomock.Any()).Return( + ðpb.MultipleValidatorStatusResponse{ + Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}, {Status: ethpb.ValidatorStatus_ACTIVE}}, + PublicKeys: [][]byte{pubkey1[:], pubkey2[:], pubkey3[:], pubkey4[:]}, + Indices: []primitives.ValidatorIndex{1, 2, unknownIndex, 4}, + }, nil) + v := validator{ + validatorClient: client, + pubkeyToStatus: make(map[[48]byte]*validatorStatus), + } + keys, err := v.filterAndCacheActiveKeys(ctx, [][48]byte{pubkey1, pubkey2, pubkey3, pubkey4}, 0) + require.NoError(t, err) + // one key is unknown status + require.Equal(t, 3, len(keys)) + }) + t.Run("refetch all keys at start of epoch, even with cache", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ctx := context.Background() + client := validatormock.NewMockValidatorClient(ctrl) + + client.EXPECT().MultipleValidatorStatus( + gomock.Any(), + gomock.Any()).Return( + ðpb.MultipleValidatorStatusResponse{ + Statuses: []*ethpb.ValidatorStatusResponse{{Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_ACTIVE}, {Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}, {Status: ethpb.ValidatorStatus_ACTIVE}}, + PublicKeys: [][]byte{pubkey1[:], pubkey2[:], pubkey3[:], pubkey4[:]}, + Indices: []primitives.ValidatorIndex{1, 2, unknownIndex, 4}, + }, nil) + v := validator{ + validatorClient: client, + pubkeyToStatus: map[[48]byte]*validatorStatus{ + pubkey1: { + publicKey: pubkey1[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 1, + }, + pubkey2: { + publicKey: pubkey2[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 2, + }, + pubkey3: { + publicKey: pubkey3[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, // gets overridden + index: 3, + }, + pubkey4: { + publicKey: pubkey4[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 4, + }, + }, + } + keys, err := v.filterAndCacheActiveKeys(ctx, [][48]byte{pubkey1, pubkey2, pubkey3, pubkey4}, 0) + require.NoError(t, err) + // one key is unknown status + require.Equal(t, 3, len(keys)) + }) + t.Run("cache used mid epoch, no new keys added", func(t *testing.T) { + ctx := context.Background() + v := validator{ + pubkeyToStatus: map[[48]byte]*validatorStatus{ + pubkey1: { + publicKey: pubkey1[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 1, + }, + pubkey4: { + publicKey: pubkey4[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 4, + }, + }, + } + keys, err := v.filterAndCacheActiveKeys(ctx, [][48]byte{pubkey1, pubkey4}, 5) + require.NoError(t, err) + // one key is unknown status + require.Equal(t, 2, len(keys)) + }) + +} + func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) { - // pubkey1 => feeRecipient1 - Status: active (already in `v.validatorIndex`) - // pubkey2 => feeRecipient2 - Status: active (NOT in `v.validatorIndex`, index found by beacon node) - // pubkey3 => feeRecipient3 - Status: active (NOT in `v.validatorIndex`, index NOT found by beacon node) - // pubkey4 => Nothing - Status: active (already in `v.validatorIndex`) - // pubkey5 => Nothing - Status: unknown (already in `v.validatorIndex`) - // pubkey6 => Nothing - Status: pending (already in `v.validatorIndex`) - ActivationEpoch: 35 (current slot: 641 - current epoch: 20) - // pubkey7 => Nothing - Status: pending (already in `v.validatorIndex`) - ActivationEpoch: 20 (current slot: 641 - current epoch: 20) - // pubkey8 => feeRecipient8 - Status: exiting (already in `v.validatorIndex`) + // pubkey1 => feeRecipient1 - Status: active + // pubkey2 => feeRecipient2 - Status: active + // pubkey3 => feeRecipient3 - Status: unknown + // pubkey4 => Nothing - Status: active + // pubkey5 => Nothing - Status: exited + // pubkey6 => Nothing - Status: pending - ActivationEpoch: 35 (current slot: 641 - current epoch: 20) + // pubkey7 => Nothing - Status: pending - ActivationEpoch: 20 (current slot: 641 - current epoch: 20) + // pubkey8 => feeRecipient8 - Status: exiting // Public keys pubkey1 := pubkeyFromString(t, "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") @@ -2201,9 +2318,9 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) { pubkeyToStatus := map[[fieldparams.BLSPubkeyLength]byte]ethpb.ValidatorStatus{ pubkey1: ethpb.ValidatorStatus_ACTIVE, pubkey2: ethpb.ValidatorStatus_ACTIVE, - pubkey3: ethpb.ValidatorStatus_ACTIVE, + pubkey3: ethpb.ValidatorStatus_UNKNOWN_STATUS, pubkey4: ethpb.ValidatorStatus_ACTIVE, - pubkey5: ethpb.ValidatorStatus_UNKNOWN_STATUS, + pubkey5: ethpb.ValidatorStatus_EXITED, pubkey6: ethpb.ValidatorStatus_PENDING, pubkey7: ethpb.ValidatorStatus_PENDING, pubkey8: ethpb.ValidatorStatus_EXITING, @@ -2220,28 +2337,23 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) { pubkey8: 0, } + pubkeyToIndex := map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex{ + pubkey1: 1, + pubkey2: 2, + pubkey3: unknownIndex, + pubkey4: 4, + pubkey5: 5, + pubkey6: 6, + pubkey7: 7, + pubkey8: 8, + } + ctrl := gomock.NewController(t) defer ctrl.Finish() ctx := context.Background() client := validatormock.NewMockValidatorClient(ctrl) - client.EXPECT().ValidatorIndex( - gomock.Any(), - ðpb.ValidatorIndexRequest{ - PublicKey: pubkey2[:], - }, - ).Return(ðpb.ValidatorIndexResponse{ - Index: 2, - }, nil) - - client.EXPECT().ValidatorIndex( - gomock.Any(), - ðpb.ValidatorIndexRequest{ - PublicKey: pubkey3[:], - }, - ).Return(nil, status.Error(codes.NotFound, "NOT_FOUND")) - client.EXPECT().MultipleValidatorStatus( gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, val *ethpb.MultipleValidatorStatusRequest) (*ethpb.MultipleValidatorStatusResponse, error) { @@ -2253,6 +2365,8 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) { Status: pubkeyToStatus[bytesutil.ToBytes48(k)], ActivationEpoch: pubkeyToActivationEpoch[bytesutil.ToBytes48(k)], }) + index := pubkeyToIndex[bytesutil.ToBytes48(k)] + resp.Indices = append(resp.Indices, index) } return resp, nil }) @@ -2288,13 +2402,47 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) { }, }, }, - pubkeyToValidatorIndex: map[[fieldparams.BLSPubkeyLength]byte]primitives.ValidatorIndex{ - pubkey1: 1, - pubkey4: 4, - pubkey5: 5, - pubkey6: 6, - pubkey7: 7, - pubkey8: 8, + pubkeyToStatus: map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus{ + pubkey1: { + publicKey: pubkey1[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 1, + }, + pubkey2: { + publicKey: pubkey2[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 2, + }, + pubkey3: { + publicKey: pubkey3[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_UNKNOWN_STATUS}, + index: unknownIndex, + }, + pubkey4: { + publicKey: pubkey4[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 4, + }, + pubkey5: { + publicKey: pubkey5[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 5, + }, + pubkey6: { + publicKey: pubkey6[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 6, + }, + pubkey7: { + publicKey: pubkey7[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 7, + }, + pubkey8: { + publicKey: pubkey8[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 8, + }, }, } @@ -2331,10 +2479,13 @@ func TestValidator_buildPrepProposerReqs_WithDefaultConfig(t *testing.T) { FeeRecipient: feeRecipient8[:], }, } - filteredKeys, err := v.filterAndCacheActiveKeys(ctx, pubkeys, 641) + filteredKeys, err := v.filterAndCacheActiveKeys(ctx, pubkeys, 640) require.NoError(t, err) actual, err := v.buildPrepProposerReqs(filteredKeys) require.NoError(t, err) + sort.Slice(actual, func(i, j int) bool { + return actual[i].ValidatorIndex < actual[j].ValidatorIndex + }) assert.DeepEqual(t, expected, actual) } @@ -2404,7 +2555,7 @@ func TestValidator_buildSignedRegReqs_DefaultConfigDisabled(t *testing.T) { }, }, }, - pubkeyToValidatorIndex: make(map[[48]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[48]byte]*validatorStatus), } pubkeys := [][fieldparams.BLSPubkeyLength]byte{pubkey1, pubkey2, pubkey3} @@ -2412,26 +2563,41 @@ func TestValidator_buildSignedRegReqs_DefaultConfigDisabled(t *testing.T) { var signer = func(_ context.Context, _ *validatorpb.SignRequest) (bls.Signature, error) { return signature, nil } - v.pubkeyToValidatorIndex[pubkey1] = primitives.ValidatorIndex(1) - v.pubkeyToValidatorIndex[pubkey2] = primitives.ValidatorIndex(2) - v.pubkeyToValidatorIndex[pubkey3] = primitives.ValidatorIndex(3) - actual := v.buildSignedRegReqs(ctx, pubkeys, signer) + v.pubkeyToStatus[pubkey1] = &validatorStatus{ + publicKey: pubkey1[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 1, + } + v.pubkeyToStatus[pubkey2] = &validatorStatus{ + publicKey: pubkey2[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 2, + } + v.pubkeyToStatus[pubkey3] = &validatorStatus{ + publicKey: pubkey3[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 3, + } + actual := v.buildSignedRegReqs(ctx, pubkeys, signer, 0, false) assert.Equal(t, 1, len(actual)) assert.DeepEqual(t, feeRecipient1[:], actual[0].Message.FeeRecipient) assert.Equal(t, uint64(1111), actual[0].Message.GasLimit) assert.DeepEqual(t, pubkey1[:], actual[0].Message.Pubkey) + } func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) { // pubkey1 => feeRecipient1, builder enabled // pubkey2 => feeRecipient2, builder disabled // pubkey3 => Nothing, builder enabled + // pubkey4 => added after builder requests built once, used in mid epoch test // Public keys pubkey1 := pubkeyFromString(t, "0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111") pubkey2 := pubkeyFromString(t, "0x222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222") pubkey3 := pubkeyFromString(t, "0x333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333") + pubkey4 := pubkeyFromString(t, "0x444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444") // Fee recipients feeRecipient1 := feeRecipientFromString(t, "0x0000000000000000000000000000000000000000") @@ -2446,8 +2612,7 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) { client := validatormock.NewMockValidatorClient(ctrl) signature := blsmock.NewMockSignature(ctrl) - signature.EXPECT().Marshal().Return([]byte{}).Times(2) - + signature.EXPECT().Marshal().Return([]byte{}).AnyTimes() v := validator{ signedValidatorRegistrations: map[[48]byte]*ethpb.SignedValidatorRegistrationV1{}, validatorClient: client, @@ -2489,7 +2654,7 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) { }, }, }, - pubkeyToValidatorIndex: make(map[[48]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[48]byte]*validatorStatus), } pubkeys := [][fieldparams.BLSPubkeyLength]byte{pubkey1, pubkey2, pubkey3} @@ -2497,10 +2662,22 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) { var signer = func(_ context.Context, _ *validatorpb.SignRequest) (bls.Signature, error) { return signature, nil } - v.pubkeyToValidatorIndex[pubkey1] = primitives.ValidatorIndex(1) - v.pubkeyToValidatorIndex[pubkey2] = primitives.ValidatorIndex(2) - v.pubkeyToValidatorIndex[pubkey3] = primitives.ValidatorIndex(3) - actual := v.buildSignedRegReqs(ctx, pubkeys, signer) + v.pubkeyToStatus[pubkey1] = &validatorStatus{ + publicKey: pubkey1[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 1, + } + v.pubkeyToStatus[pubkey2] = &validatorStatus{ + publicKey: pubkey2[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 2, + } + v.pubkeyToStatus[pubkey3] = &validatorStatus{ + publicKey: pubkey3[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 3, + } + actual := v.buildSignedRegReqs(ctx, pubkeys, signer, 0, false) assert.Equal(t, 2, len(actual)) @@ -2511,6 +2688,26 @@ func TestValidator_buildSignedRegReqs_DefaultConfigEnabled(t *testing.T) { assert.DeepEqual(t, defaultFeeRecipient[:], actual[1].Message.FeeRecipient) assert.Equal(t, uint64(9999), actual[1].Message.GasLimit) assert.DeepEqual(t, pubkey3[:], actual[1].Message.Pubkey) + + t.Run("mid epoch only pushes newly added key", func(t *testing.T) { + v.pubkeyToStatus[pubkey4] = &validatorStatus{ + publicKey: pubkey4[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 4, + } + pubkeys = append(pubkeys, pubkey4) + actual = v.buildSignedRegReqs(ctx, pubkeys, signer, 5, false) + assert.Equal(t, 1, len(actual)) + + assert.DeepEqual(t, defaultFeeRecipient[:], actual[0].Message.FeeRecipient) + assert.Equal(t, uint64(9999), actual[0].Message.GasLimit) + assert.DeepEqual(t, pubkey4[:], actual[0].Message.Pubkey) + }) + + t.Run("force push all keys mid epoch", func(t *testing.T) { + actual = v.buildSignedRegReqs(ctx, pubkeys, signer, 5, true) + assert.Equal(t, 3, len(actual)) + }) } func TestValidator_buildSignedRegReqs_SignerOnError(t *testing.T) { @@ -2548,7 +2745,7 @@ func TestValidator_buildSignedRegReqs_SignerOnError(t *testing.T) { return nil, errors.New("custom error") } - actual := v.buildSignedRegReqs(ctx, pubkeys, signer) + actual := v.buildSignedRegReqs(ctx, pubkeys, signer, 0, false) assert.Equal(t, 0, len(actual)) } @@ -2595,7 +2792,7 @@ func TestValidator_buildSignedRegReqs_TimestampBeforeGenesis(t *testing.T) { }, }, }, - pubkeyToValidatorIndex: make(map[[48]byte]primitives.ValidatorIndex), + pubkeyToStatus: make(map[[48]byte]*validatorStatus), } pubkeys := [][fieldparams.BLSPubkeyLength]byte{pubkey1} @@ -2603,8 +2800,12 @@ func TestValidator_buildSignedRegReqs_TimestampBeforeGenesis(t *testing.T) { var signer = func(_ context.Context, _ *validatorpb.SignRequest) (bls.Signature, error) { return signature, nil } - v.pubkeyToValidatorIndex[pubkey1] = primitives.ValidatorIndex(1) - actual := v.buildSignedRegReqs(ctx, pubkeys, signer) + v.pubkeyToStatus[pubkey1] = &validatorStatus{ + publicKey: pubkey1[:], + status: ðpb.ValidatorStatusResponse{Status: ethpb.ValidatorStatus_ACTIVE}, + index: 1, + } + actual := v.buildSignedRegReqs(ctx, pubkeys, signer, 0, false) assert.Equal(t, 0, len(actual)) } @@ -2639,3 +2840,68 @@ func TestValidator_ChangeHost(t *testing.T) { v.ChangeHost() assert.Equal(t, uint64(0), v.currentHostIndex) } + +func TestUpdateValidatorStatusCache(t *testing.T) { + ctx := context.Background() + ctrl := gomock.NewController(t) + defer ctrl.Finish() + pubkeys := [][fieldparams.BLSPubkeyLength]byte{ + {0x01}, + {0x02}, + } + statusRequestKeys := [][]byte{ + pubkeys[0][:], + pubkeys[1][:], + } + + client := validatormock.NewMockValidatorClient(ctrl) + mockResponse := ðpb.MultipleValidatorStatusResponse{ + PublicKeys: statusRequestKeys, + Statuses: []*ethpb.ValidatorStatusResponse{ + { + Status: ethpb.ValidatorStatus_ACTIVE, + }, { + Status: ethpb.ValidatorStatus_EXITING, + }}, + Indices: []primitives.ValidatorIndex{1, 2}, + } + client.EXPECT().MultipleValidatorStatus( + gomock.Any(), + gomock.Any()).Return(mockResponse, nil) + + v := &validator{ + validatorClient: client, + beaconNodeHosts: []string{"http://localhost:8080", "http://localhost:8081"}, + currentHostIndex: 0, + pubkeyToStatus: map[[fieldparams.BLSPubkeyLength]byte]*validatorStatus{ + [fieldparams.BLSPubkeyLength]byte{0x03}: &validatorStatus{ // add non existent key and status to cache, should be fully removed on update + publicKey: []byte{0x03}, + status: ðpb.ValidatorStatusResponse{ + Status: ethpb.ValidatorStatus_ACTIVE, + }, + index: 3, + }, + }, + } + + err := v.updateValidatorStatusCache(ctx, pubkeys) + assert.NoError(t, err) + + // make sure the nonexistent key is fully removed + _, ok := v.pubkeyToStatus[[fieldparams.BLSPubkeyLength]byte{0x03}] + require.Equal(t, false, ok) + // make sure we only have the added values + assert.Equal(t, 2, len(v.pubkeyToStatus)) + for i, pk := range pubkeys { + status, exists := v.pubkeyToStatus[pk] + require.Equal(t, true, exists) + require.DeepEqual(t, pk[:], status.publicKey) + require.Equal(t, mockResponse.Statuses[i], status.status) + require.Equal(t, mockResponse.Indices[i], status.index) + } + + err = v.updateValidatorStatusCache(ctx, nil) + assert.NoError(t, err) + // make sure the value is 0 + assert.Equal(t, 0, len(v.pubkeyToStatus)) +} diff --git a/validator/client/wait_for_activation.go b/validator/client/wait_for_activation.go index 0c2f6b5f417c..c40a4a0d8116 100644 --- a/validator/client/wait_for_activation.go +++ b/validator/client/wait_for_activation.go @@ -2,18 +2,15 @@ package client import ( "context" - "io" "time" "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" - validator2 "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" - "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/math" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" - ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v5/validator/client/iface" - "go.opencensus.io/trace" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" + "github.com/prysmaticlabs/prysm/v5/time/slots" + octrace "go.opentelemetry.io/otel/trace" ) // WaitForActivation checks whether the validator pubkey is in the active @@ -40,100 +37,89 @@ func (v *validator) WaitForActivation(ctx context.Context, accountsChangedChan c return v.internalWaitForActivation(ctx, accountsChangedChan) } -// internalWaitForActivation performs the following: -// 1) While the key manager is empty, subscribe to keymanager changes until some validator keys exist. -// 2) Open a server side stream for activation events against the given keys. -// 3) In another go routine, the key manager is monitored for updates and emits an update event on -// the accountsChangedChan. When an event signal is received, restart the internalWaitForActivation routine. -// 4) If the stream is reset in error, restart the routine. -// 5) If the stream returns a response indicating one or more validators are active, exit the routine. +// internalWaitForActivation recursively waits for at least one active validator key func (v *validator) internalWaitForActivation(ctx context.Context, accountsChangedChan <-chan [][fieldparams.BLSPubkeyLength]byte) error { ctx, span := trace.StartSpan(ctx, "validator.WaitForActivation") defer span.End() + + // Step 1: Fetch validating public keys. validatingKeys, err := v.km.FetchValidatingPublicKeys(ctx) if err != nil { return errors.Wrap(err, msgCouldNotFetchKeys) } - // if there are no validating keys, wait for some + + // Step 2: If no keys, wait for accounts change or context cancellation. if len(validatingKeys) == 0 { log.Warn(msgNoKeysFetched) - select { - case <-ctx.Done(): - log.Debug("Context closed, exiting fetching validating keys") - return ctx.Err() - case <-accountsChangedChan: - // if the accounts changed try it again - return v.internalWaitForActivation(ctx, accountsChangedChan) - } + return v.waitForAccountsChange(ctx, accountsChangedChan) } - stream, err := v.validatorClient.WaitForActivation(ctx, ðpb.ValidatorActivationRequest{ - PublicKeys: bytesutil.FromBytes48Array(validatingKeys), - }) - if err != nil { - tracing.AnnotateError(span, err) - attempts := streamAttempts(ctx) - log.WithError(err).WithField("attempts", attempts). - Error("Stream broken while waiting for activation. Reconnecting...") - // Reconnection attempt backoff, up to 60s. - time.Sleep(time.Second * time.Duration(math.Min(uint64(attempts), 60))) - return v.internalWaitForActivation(incrementRetries(ctx), accountsChangedChan) + // Step 3: update validator statuses in cache. + if err := v.updateValidatorStatusCache(ctx, validatingKeys); err != nil { + return v.retryWaitForActivation(ctx, span, err, "Connection broken while waiting for activation. Reconnecting...", accountsChangedChan) } - someAreActive := false - for !someAreActive { + // Step 4: Check and log validator statuses. + someAreActive := v.checkAndLogValidatorStatus() + if !someAreActive { + // Step 6: If no active validators, wait for accounts change, context cancellation, or next epoch. select { case <-ctx.Done(): - log.Debug("Context closed, exiting fetching validating keys") + log.Debug("Context closed, exiting WaitForActivation") return ctx.Err() case <-accountsChangedChan: // Accounts (keys) changed, restart the process. return v.internalWaitForActivation(ctx, accountsChangedChan) default: - res, err := (stream).Recv() // retrieve from stream one loop at a time - // If the stream is closed, we stop the loop. - if errors.Is(err, io.EOF) { - break - } - // If context is canceled we return from the function. - if errors.Is(ctx.Err(), context.Canceled) { - return errors.Wrap(ctx.Err(), "context has been canceled so shutting down the loop") - } - if err != nil { - tracing.AnnotateError(span, err) - attempts := streamAttempts(ctx) - log.WithError(err).WithField("attempts", attempts). - Error("Stream broken while waiting for activation. Reconnecting...") - // Reconnection attempt backoff, up to 60s. - time.Sleep(time.Second * time.Duration(math.Min(uint64(attempts), 60))) - return v.internalWaitForActivation(incrementRetries(ctx), accountsChangedChan) - } - - statuses := make([]*validatorStatus, len(res.Statuses)) - for i, s := range res.Statuses { - statuses[i] = &validatorStatus{ - publicKey: s.PublicKey, - status: s.Status, - index: s.Index, - } - } - - // "-1" indicates that validator count endpoint is not supported by the beacon node. - var valCount int64 = -1 - valCounts, err := v.prysmChainClient.ValidatorCount(ctx, "head", []validator2.Status{validator2.Active}) - if err != nil && !errors.Is(err, iface.ErrNotSupported) { - return errors.Wrap(err, "could not get active validator count") + if err := v.waitForNextEpoch(ctx, v.genesisTime, accountsChangedChan); err != nil { + return v.retryWaitForActivation(ctx, span, err, "Failed to wait for next epoch. Reconnecting...", accountsChangedChan) } + return v.internalWaitForActivation(incrementRetries(ctx), accountsChangedChan) + } + } + return nil +} - if len(valCounts) > 0 { - valCount = int64(valCounts[0].Count) - } +func (v *validator) retryWaitForActivation(ctx context.Context, span octrace.Span, err error, message string, accountsChangedChan <-chan [][fieldparams.BLSPubkeyLength]byte) error { + tracing.AnnotateError(span, err) + attempts := activationAttempts(ctx) + log.WithError(err).WithField("attempts", attempts).Error(message) + // Reconnection attempt backoff, up to 60s. + time.Sleep(time.Second * time.Duration(math.Min(uint64(attempts), 60))) + // TODO: refactor this to use the health tracker instead for reattempt + return v.internalWaitForActivation(incrementRetries(ctx), accountsChangedChan) +} - someAreActive = v.checkAndLogValidatorStatus(statuses, valCount) - } +func (v *validator) waitForAccountsChange(ctx context.Context, accountsChangedChan <-chan [][fieldparams.BLSPubkeyLength]byte) error { + select { + case <-ctx.Done(): + log.Debug("Context closed, exiting waitForAccountsChange") + return ctx.Err() + case <-accountsChangedChan: + // If the accounts changed, try again. + return v.internalWaitForActivation(ctx, accountsChangedChan) } +} - return nil +// waitForNextEpoch creates a blocking function to wait until the next epoch start given the current slot +func (v *validator) waitForNextEpoch(ctx context.Context, genesisTimeSec uint64, accountsChangedChan <-chan [][fieldparams.BLSPubkeyLength]byte) error { + waitTime, err := slots.SecondsUntilNextEpochStart(genesisTimeSec) + if err != nil { + return err + } + log.WithField("seconds_until_next_epoch", waitTime).Warn("No active validator keys provided. Waiting until next epoch to check again...") + select { + case <-ctx.Done(): + log.Debug("Context closed, exiting waitForNextEpoch") + return ctx.Err() + case <-accountsChangedChan: + // Accounts (keys) changed, restart the process. + return v.internalWaitForActivation(ctx, accountsChangedChan) + case <-time.After(time.Duration(waitTime) * time.Second): + log.Debug("Done waiting for epoch start") + // The ticker has ticked, indicating we've reached the next epoch + return nil + } } // Preferred way to use context keys is with a non built-in type. See: RVV-B0003 @@ -141,7 +127,7 @@ type waitForActivationContextKey string const waitForActivationAttemptsContextKey = waitForActivationContextKey("WaitForActivation-attempts") -func streamAttempts(ctx context.Context) int { +func activationAttempts(ctx context.Context) int { attempts, ok := ctx.Value(waitForActivationAttemptsContextKey).(int) if !ok { return 1 @@ -150,6 +136,6 @@ func streamAttempts(ctx context.Context) int { } func incrementRetries(ctx context.Context) context.Context { - attempts := streamAttempts(ctx) + attempts := activationAttempts(ctx) return context.WithValue(ctx, waitForActivationAttemptsContextKey, attempts+1) } diff --git a/validator/client/wait_for_activation_test.go b/validator/client/wait_for_activation_test.go index e3e5f3392198..05e67eb917b8 100644 --- a/validator/client/wait_for_activation_test.go +++ b/validator/client/wait_for_activation_test.go @@ -1,7 +1,6 @@ package client import ( - "bytes" "context" "fmt" "testing" @@ -10,50 +9,21 @@ import ( "github.com/pkg/errors" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" - validatorType "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/assert" - "github.com/prysmaticlabs/prysm/v5/testing/mock" "github.com/prysmaticlabs/prysm/v5/testing/require" validatormock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock" walletMock "github.com/prysmaticlabs/prysm/v5/validator/accounts/testing" - "github.com/prysmaticlabs/prysm/v5/validator/client/iface" + "github.com/prysmaticlabs/prysm/v5/validator/client/testutil" "github.com/prysmaticlabs/prysm/v5/validator/keymanager/derived" constant "github.com/prysmaticlabs/prysm/v5/validator/testing" logTest "github.com/sirupsen/logrus/hooks/test" - mock2 "github.com/stretchr/testify/mock" "github.com/tyler-smith/go-bip39" util "github.com/wealdtech/go-eth2-util" "go.uber.org/mock/gomock" ) -func TestWaitActivation_ContextCanceled(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - validatorClient := validatormock.NewMockValidatorClient(ctrl) - chainClient := validatormock.NewMockChainClient(ctrl) - kp := randKeypair(t) - v := validator{ - validatorClient: validatorClient, - km: newMockKeymanager(t, kp), - chainClient: chainClient, - } - clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - ctx, cancel := context.WithCancel(context.Background()) - validatorClient.EXPECT().WaitForActivation( - gomock.Any(), - ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{kp.pub[:]}, - }, - ).Return(clientStream, nil) - clientStream.EXPECT().Recv().Return( - ðpb.ValidatorActivationResponse{}, - nil, - ).Do(func() { cancel() }) - assert.ErrorContains(t, cancelledCtx, v.WaitForActivation(ctx, nil)) -} - -func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) { +func TestWaitActivation_Exiting_OK(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) @@ -66,128 +36,18 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) { chainClient: chainClient, prysmChainClient: prysmChainClient, } - clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( + ctx := context.Background() + resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]}) + resp.Statuses[0].Status = ethpb.ValidatorStatus_EXITING + validatorClient.EXPECT().MultipleValidatorStatus( gomock.Any(), - ðpb.ValidatorActivationRequest{ + ðpb.MultipleValidatorStatusRequest{ PublicKeys: [][]byte{kp.pub[:]}, }, - ).Return(clientStream, errors.New("failed stream")).Return(clientStream, nil) - prysmChainClient.EXPECT().ValidatorCount( - gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil) - resp := generateMockStatusResponse([][]byte{kp.pub[:]}) - resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE - clientStream.EXPECT().Recv().Return(resp, nil) - assert.NoError(t, v.WaitForActivation(context.Background(), nil)) -} - -func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - validatorClient := validatormock.NewMockValidatorClient(ctrl) - chainClient := validatormock.NewMockChainClient(ctrl) - prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl) - kp := randKeypair(t) - v := validator{ - validatorClient: validatorClient, - km: newMockKeymanager(t, kp), - chainClient: chainClient, - prysmChainClient: prysmChainClient, - } - clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( - gomock.Any(), - ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{kp.pub[:]}, - }, - ).Return(clientStream, nil) - prysmChainClient.EXPECT().ValidatorCount( - gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil) - // A stream fails the first time, but succeeds the second time. - resp := generateMockStatusResponse([][]byte{kp.pub[:]}) - resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE - clientStream.EXPECT().Recv().Return( - nil, - errors.New("fails"), ).Return(resp, nil) - assert.NoError(t, v.WaitForActivation(context.Background(), nil)) -} -func TestWaitActivation_LogsActivationEpochOK(t *testing.T) { - hook := logTest.NewGlobal() - ctrl := gomock.NewController(t) - defer ctrl.Finish() - validatorClient := validatormock.NewMockValidatorClient(ctrl) - chainClient := validatormock.NewMockChainClient(ctrl) - prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl) - kp := randKeypair(t) - v := validator{ - validatorClient: validatorClient, - km: newMockKeymanager(t, kp), - genesisTime: 1, - chainClient: chainClient, - prysmChainClient: prysmChainClient, - } - resp := generateMockStatusResponse([][]byte{kp.pub[:]}) - resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE - clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( - gomock.Any(), - ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{kp.pub[:]}, - }, - ).Return(clientStream, nil) - prysmChainClient.EXPECT().ValidatorCount( - gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil) - clientStream.EXPECT().Recv().Return( - resp, - nil, - ) - assert.NoError(t, v.WaitForActivation(context.Background(), nil), "Could not wait for activation") - assert.LogsContain(t, hook, "Validator activated") -} - -func TestWaitForActivation_Exiting(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - validatorClient := validatormock.NewMockValidatorClient(ctrl) - chainClient := validatormock.NewMockChainClient(ctrl) - prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl) - kp := randKeypair(t) - v := validator{ - validatorClient: validatorClient, - km: newMockKeymanager(t, kp), - chainClient: chainClient, - prysmChainClient: prysmChainClient, - } - resp := generateMockStatusResponse([][]byte{kp.pub[:]}) - resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_EXITING - clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( - gomock.Any(), - ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{kp.pub[:]}, - }, - ).Return(clientStream, nil) - prysmChainClient.EXPECT().ValidatorCount( - gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil) - clientStream.EXPECT().Recv().Return( - resp, - nil, - ) - assert.NoError(t, v.WaitForActivation(context.Background(), nil)) + require.NoError(t, v.WaitForActivation(ctx, nil)) + require.Equal(t, 1, len(v.pubkeyToStatus)) } func TestWaitForActivation_RefetchKeys(t *testing.T) { @@ -211,33 +71,27 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) { km: km, chainClient: chainClient, prysmChainClient: prysmChainClient, + pubkeyToStatus: make(map[[48]byte]*validatorStatus), } - resp := generateMockStatusResponse([][]byte{kp.pub[:]}) - resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE - clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( + resp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{kp.pub[:]}) + resp.Statuses[0].Status = ethpb.ValidatorStatus_ACTIVE + + validatorClient.EXPECT().MultipleValidatorStatus( gomock.Any(), - ðpb.ValidatorActivationRequest{ + ðpb.MultipleValidatorStatusRequest{ PublicKeys: [][]byte{kp.pub[:]}, }, - ).Return(clientStream, nil) - prysmChainClient.EXPECT().ValidatorCount( - gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil) - clientStream.EXPECT().Recv().Return( - resp, - nil) + ).Return(resp, nil) + accountChan := make(chan [][fieldparams.BLSPubkeyLength]byte) sub := km.SubscribeAccountChanges(accountChan) defer func() { sub.Unsubscribe() close(accountChan) }() - // update the accounts after a delay + // update the accounts from 0 to 1 after a delay go func() { - time.Sleep(2 * time.Second) + time.Sleep(1 * time.Second) require.NoError(t, km.add(kp)) km.SimulateAccountChanges([][48]byte{kp.pub}) }() @@ -246,12 +100,11 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) { assert.LogsContain(t, hook, "Validator activated") } -// Regression test for a scenario where you start with an inactive key and then import an active key. func TestWaitForActivation_AccountsChanged(t *testing.T) { + params.SetupTestConfigCleanup(t) hook := logTest.NewGlobal() ctrl := gomock.NewController(t) defer ctrl.Finish() - t.Run("Imported keymanager", func(t *testing.T) { inactive := randKeypair(t) active := randKeypair(t) @@ -264,58 +117,38 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) { km: km, chainClient: chainClient, prysmChainClient: prysmChainClient, + pubkeyToStatus: make(map[[48]byte]*validatorStatus), } - inactiveResp := generateMockStatusResponse([][]byte{inactive.pub[:]}) - inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS - inactiveClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( + inactiveResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:]}) + inactiveResp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS + + activeResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactive.pub[:], active.pub[:]}) + activeResp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS + activeResp.Statuses[1].Status = ethpb.ValidatorStatus_ACTIVE + gomock.InOrder( + validatorClient.EXPECT().MultipleValidatorStatus( + gomock.Any(), + ðpb.MultipleValidatorStatusRequest{ + PublicKeys: [][]byte{inactive.pub[:]}, + }, + ).Return(inactiveResp, nil).Do(func(arg0, arg1 interface{}) { + require.NoError(t, km.add(active)) + km.SimulateAccountChanges([][fieldparams.BLSPubkeyLength]byte{inactive.pub, active.pub}) + }), + validatorClient.EXPECT().MultipleValidatorStatus( + gomock.Any(), + ðpb.MultipleValidatorStatusRequest{ + PublicKeys: [][]byte{inactive.pub[:], active.pub[:]}, + }, + ).Return(activeResp, nil)) + + chainClient.EXPECT().ChainHead( gomock.Any(), - ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{inactive.pub[:]}, - }, - ).DoAndReturn(func(ctx context.Context, in *ethpb.ValidatorActivationRequest) (*mock.MockBeaconNodeValidator_WaitForActivationClient, error) { - //delay a bit so that other key can be added - time.Sleep(time.Second * 2) - return inactiveClientStream, nil - }) - prysmChainClient.EXPECT().ValidatorCount( gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil).AnyTimes() - inactiveClientStream.EXPECT().Recv().Return( - inactiveResp, + ).Return( + ðpb.ChainHead{HeadEpoch: 0}, nil, ).AnyTimes() - - activeResp := generateMockStatusResponse([][]byte{inactive.pub[:], active.pub[:]}) - activeResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS - activeResp.Statuses[1].Status.Status = ethpb.ValidatorStatus_ACTIVE - activeClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( - gomock.Any(), - mock2.MatchedBy(func(req *ethpb.ValidatorActivationRequest) bool { - found := 0 - for _, pk := range req.PublicKeys { - if bytes.Equal(pk, active.pub[:]) || bytes.Equal(pk, inactive.pub[:]) { - found++ - } - } - return found == 2 - }), - ).Return(activeClientStream, nil) - activeClientStream.EXPECT().Recv().Return( - activeResp, - nil, - ) - - go func() { - // We add the active key into the keymanager and simulate a key refresh. - time.Sleep(time.Second * 1) - require.NoError(t, km.add(active)) - km.SimulateAccountChanges(make([][fieldparams.BLSPubkeyLength]byte, 0)) - }() - assert.NoError(t, v.WaitForActivation(context.Background(), nil)) assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node") assert.LogsContain(t, hook, "Validator activated") @@ -355,94 +188,88 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) { genesisTime: 1, chainClient: chainClient, prysmChainClient: prysmChainClient, + pubkeyToStatus: make(map[[48]byte]*validatorStatus), } - inactiveResp := generateMockStatusResponse([][]byte{inactivePubKey[:]}) - inactiveResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS - inactiveClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( + inactiveResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactivePubKey[:]}) + inactiveResp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS + + activeResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{inactivePubKey[:], activePubKey[:]}) + activeResp.Statuses[0].Status = ethpb.ValidatorStatus_UNKNOWN_STATUS + activeResp.Statuses[1].Status = ethpb.ValidatorStatus_ACTIVE + channel := make(chan [][fieldparams.BLSPubkeyLength]byte, 1) + km.SubscribeAccountChanges(channel) + gomock.InOrder( + validatorClient.EXPECT().MultipleValidatorStatus( + gomock.Any(), + ðpb.MultipleValidatorStatusRequest{ + PublicKeys: [][]byte{inactivePubKey[:]}, + }, + ).Return(inactiveResp, nil).Do(func(arg0, arg1 interface{}) { + err = km.RecoverAccountsFromMnemonic(ctx, constant.TestMnemonic, derived.DefaultMnemonicLanguage, "", 2) + require.NoError(t, err) + pks, err := km.FetchValidatingPublicKeys(ctx) + require.NoError(t, err) + require.DeepEqual(t, pks, [][fieldparams.BLSPubkeyLength]byte{inactivePubKey, activePubKey}) + channel <- [][fieldparams.BLSPubkeyLength]byte{inactivePubKey, activePubKey} + }), + validatorClient.EXPECT().MultipleValidatorStatus( + gomock.Any(), + ðpb.MultipleValidatorStatusRequest{ + PublicKeys: [][]byte{inactivePubKey[:], activePubKey[:]}, + }, + ).Return(activeResp, nil)) + + chainClient.EXPECT().ChainHead( gomock.Any(), - ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{inactivePubKey[:]}, - }, - ).DoAndReturn(func(ctx context.Context, in *ethpb.ValidatorActivationRequest) (*mock.MockBeaconNodeValidator_WaitForActivationClient, error) { - //delay a bit so that other key can be added - time.Sleep(time.Second * 2) - return inactiveClientStream, nil - }) - prysmChainClient.EXPECT().ValidatorCount( gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil).AnyTimes() - inactiveClientStream.EXPECT().Recv().Return( - inactiveResp, + ).Return( + ðpb.ChainHead{HeadEpoch: 0}, nil, ).AnyTimes() - - activeResp := generateMockStatusResponse([][]byte{inactivePubKey[:], activePubKey[:]}) - activeResp.Statuses[0].Status.Status = ethpb.ValidatorStatus_UNKNOWN_STATUS - activeResp.Statuses[1].Status.Status = ethpb.ValidatorStatus_ACTIVE - activeClientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( - gomock.Any(), - ðpb.ValidatorActivationRequest{ - PublicKeys: [][]byte{inactivePubKey[:], activePubKey[:]}, - }, - ).Return(activeClientStream, nil) - activeClientStream.EXPECT().Recv().Return( - activeResp, - nil, - ) - - channel := make(chan [][fieldparams.BLSPubkeyLength]byte) - go func() { - // We add the active key into the keymanager and simulate a key refresh. - time.Sleep(time.Second * 1) - err = km.RecoverAccountsFromMnemonic(ctx, constant.TestMnemonic, derived.DefaultMnemonicLanguage, "", 2) - require.NoError(t, err) - channel <- [][fieldparams.BLSPubkeyLength]byte{} - }() - assert.NoError(t, v.internalWaitForActivation(context.Background(), channel)) assert.LogsContain(t, hook, "Waiting for deposit to be observed by beacon node") assert.LogsContain(t, hook, "Validator activated") }) } -func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) { +func TestWaitForActivation_AttemptsReconnectionOnFailure(t *testing.T) { + params.SetupTestConfigCleanup(t) + cfg := params.MainnetConfig().Copy() + cfg.ConfigName = "test" + cfg.SecondsPerSlot = 1 + params.OverrideBeaconConfig(cfg) ctrl := gomock.NewController(t) defer ctrl.Finish() validatorClient := validatormock.NewMockValidatorClient(ctrl) chainClient := validatormock.NewMockChainClient(ctrl) prysmChainClient := validatormock.NewMockPrysmChainClient(ctrl) - kp := randKeypair(t) v := validator{ validatorClient: validatorClient, km: newMockKeymanager(t, kp), chainClient: chainClient, prysmChainClient: prysmChainClient, + pubkeyToStatus: make(map[[48]byte]*validatorStatus), } - resp := generateMockStatusResponse([][]byte{kp.pub[:]}) - resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE - clientStream := mock.NewMockBeaconNodeValidator_WaitForActivationClient(ctrl) - validatorClient.EXPECT().WaitForActivation( - gomock.Any(), + active := randKeypair(t) + activeResp := testutil.GenerateMultipleValidatorStatusResponse([][]byte{active.pub[:]}) + activeResp.Statuses[0].Status = ethpb.ValidatorStatus_ACTIVE + gomock.InOrder( + validatorClient.EXPECT().MultipleValidatorStatus( + gomock.Any(), + gomock.Any(), + ).Return(nil, errors.New("some random connection error")), + validatorClient.EXPECT().MultipleValidatorStatus( + gomock.Any(), + gomock.Any(), + ).Return(activeResp, nil)) + chainClient.EXPECT().ChainHead( gomock.Any(), - ).Return(clientStream, nil) - prysmChainClient.EXPECT().ValidatorCount( gomock.Any(), - "head", - []validatorType.Status{validatorType.Active}, - ).Return([]iface.ValidatorCount{}, nil).Times(2) - clientStream.EXPECT().Recv().Return( - ðpb.ValidatorActivationResponse{}, - nil, - ) - clientStream.EXPECT().Recv().Return( - resp, + ).Return( + ðpb.ChainHead{HeadEpoch: 0}, nil, - ) - assert.NoError(t, v.WaitForActivation(context.Background(), nil), "Could not wait for activation") + ).AnyTimes() + assert.NoError(t, v.WaitForActivation(context.Background(), nil)) } diff --git a/validator/db/filesystem/BUILD.bazel b/validator/db/filesystem/BUILD.bazel index f61ff14cf3b3..39810f59da9a 100644 --- a/validator/db/filesystem/BUILD.bazel +++ b/validator/db/filesystem/BUILD.bazel @@ -20,6 +20,7 @@ go_library( "//consensus-types/interfaces:go_default_library", "//consensus-types/primitives:go_default_library", "//io/file:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", "//validator/db/common:go_default_library", @@ -31,7 +32,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@in_gopkg_yaml_v3//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/validator/db/filesystem/attester_protection.go b/validator/db/filesystem/attester_protection.go index 996538e0137d..5a48e7f78fdb 100644 --- a/validator/db/filesystem/attester_protection.go +++ b/validator/db/filesystem/attester_protection.go @@ -8,9 +8,9 @@ import ( "github.com/prometheus/client_golang/prometheus" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/validator/db/common" - "go.opencensus.io/trace" ) const failedAttLocalProtectionErr = "attempted to make slashable attestation, rejected by local slashing protection" @@ -131,10 +131,9 @@ func (s *Store) SaveAttestationForPubKey( att ethpb.IndexedAtt, ) error { // If there is no attestation, return on error. - if att == nil || att.GetData() == nil || att.GetData().Source == nil || att.GetData().Target == nil { + if att == nil || att.IsNil() || att.GetData().Source == nil || att.GetData().Target == nil { return errors.New("incoming attestation does not contain source and/or target epoch") } - // Get validator slashing protection. validatorSlashingProtection, err := s.validatorSlashingProtection(pubkey) if err != nil { diff --git a/validator/db/kv/BUILD.bazel b/validator/db/kv/BUILD.bazel index 1df227591d2d..38e61170b651 100644 --- a/validator/db/kv/BUILD.bazel +++ b/validator/db/kv/BUILD.bazel @@ -38,6 +38,7 @@ go_library( "//io/file:go_default_library", "//monitoring/progress:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/slashings:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", @@ -51,7 +52,6 @@ go_library( "@com_github_prysmaticlabs_prombbolt//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@io_etcd_go_bbolt//:go_default_library", - "@io_opencensus_go//trace:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/validator/db/kv/attester_protection.go b/validator/db/kv/attester_protection.go index 5187b2f30f74..89a2bdb189f9 100644 --- a/validator/db/kv/attester_protection.go +++ b/validator/db/kv/attester_protection.go @@ -13,11 +13,11 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/slashings" "github.com/prysmaticlabs/prysm/v5/validator/db/common" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // SlashingKind used for helpful information upon detection. @@ -419,7 +419,7 @@ func (s *Store) batchAttestationWrites(ctx context.Context) { _, span := trace.StartSpan(v.ctx, "batchAttestationWrites.handleBatchedAttestationSaveRequest") s.batchedAttestations.Append(v.record) - span.AddAttributes(trace.Int64Attribute("num_records", int64(s.batchedAttestations.Len()))) + span.SetAttributes(trace.Int64Attribute("num_records", int64(s.batchedAttestations.Len()))) if numRecords := s.batchedAttestations.Len(); numRecords >= attestationBatchCapacity { log.WithField("recordCount", numRecords).Debug( diff --git a/validator/db/kv/backup.go b/validator/db/kv/backup.go index afbe122a964b..20a4fba678eb 100644 --- a/validator/db/kv/backup.go +++ b/validator/db/kv/backup.go @@ -8,8 +8,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/io/file" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) const backupsDirectoryName = "backups" diff --git a/validator/db/kv/deprecated_attester_protection.go b/validator/db/kv/deprecated_attester_protection.go index 1dcaa6c497dc..7a0343df021c 100644 --- a/validator/db/kv/deprecated_attester_protection.go +++ b/validator/db/kv/deprecated_attester_protection.go @@ -31,7 +31,7 @@ type deprecatedHistoryData struct { type deprecatedEncodedAttestingHistory []byte func (dh deprecatedEncodedAttestingHistory) assertSize() error { - if dh == nil || len(dh) < minimalSize { + if len(dh) < minimalSize { return fmt.Errorf("encapsulated data size: %d is smaller then minimal size: %d", len(dh), minimalSize) } if (len(dh)-minimalSize)%historySize != 0 { diff --git a/validator/db/kv/eip_blacklisted_keys.go b/validator/db/kv/eip_blacklisted_keys.go index db3921d42b83..618d43849f01 100644 --- a/validator/db/kv/eip_blacklisted_keys.go +++ b/validator/db/kv/eip_blacklisted_keys.go @@ -4,8 +4,8 @@ import ( "context" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // EIPImportBlacklistedPublicKeys returns keys that were marked as blacklisted during EIP-3076 slashing diff --git a/validator/db/kv/kv_test.go b/validator/db/kv/kv_test.go index 12ef8d34f928..877fb64fd6cf 100644 --- a/validator/db/kv/kv_test.go +++ b/validator/db/kv/kv_test.go @@ -3,6 +3,7 @@ package kv import ( "context" "io" + "os" "testing" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" @@ -14,7 +15,7 @@ func TestMain(m *testing.M) { logrus.SetLevel(logrus.DebugLevel) logrus.SetOutput(io.Discard) - m.Run() + os.Exit(m.Run()) } // setupDB instantiates and returns a DB instance for the validator client. diff --git a/validator/db/kv/proposer_protection.go b/validator/db/kv/proposer_protection.go index eb1ebfefdb84..4dd1d622faa2 100644 --- a/validator/db/kv/proposer_protection.go +++ b/validator/db/kv/proposer_protection.go @@ -11,10 +11,10 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/time/slots" "github.com/prysmaticlabs/prysm/v5/validator/db/common" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // ProposedPublicKeys retrieves all public keys in our proposals history bucket. diff --git a/validator/db/kv/proposer_settings.go b/validator/db/kv/proposer_settings.go index 6b573dbc2796..1cb7ffd4dae6 100644 --- a/validator/db/kv/proposer_settings.go +++ b/validator/db/kv/proposer_settings.go @@ -5,9 +5,9 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/config/proposer" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" "google.golang.org/protobuf/proto" ) diff --git a/validator/db/kv/prune_attester_protection.go b/validator/db/kv/prune_attester_protection.go index ef73cb68e4cd..1b3ec2f109cc 100644 --- a/validator/db/kv/prune_attester_protection.go +++ b/validator/db/kv/prune_attester_protection.go @@ -6,8 +6,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/params" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" bolt "go.etcd.io/bbolt" - "go.opencensus.io/trace" ) // PruneAttestations loops through every public key in the public keys bucket diff --git a/validator/db/testing/setup_db.go b/validator/db/testing/setup_db.go index 288fbb4d6f62..72aeb1222693 100644 --- a/validator/db/testing/setup_db.go +++ b/validator/db/testing/setup_db.go @@ -13,14 +13,14 @@ import ( // SetupDB instantiates and returns a DB instance for the validator client. // The `minimal` flag indicates whether the DB should be instantiated with minimal, filesystem // slashing protection database. -func SetupDB(t testing.TB, pubkeys [][fieldparams.BLSPubkeyLength]byte, mimimal bool) iface.ValidatorDB { +func SetupDB(t testing.TB, pubkeys [][fieldparams.BLSPubkeyLength]byte, minimal bool) iface.ValidatorDB { var ( db iface.ValidatorDB err error ) // Create a new DB instance. - if mimimal { + if minimal { config := &filesystem.Config{PubKeys: pubkeys} db, err = filesystem.NewStore(t.TempDir(), config) } else { diff --git a/validator/keymanager/local/BUILD.bazel b/validator/keymanager/local/BUILD.bazel index cd44564f44a8..5b21621c6be8 100644 --- a/validator/keymanager/local/BUILD.bazel +++ b/validator/keymanager/local/BUILD.bazel @@ -27,6 +27,7 @@ go_library( "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", "//runtime/interop:go_default_library", "//validator/accounts/iface:go_default_library", @@ -40,7 +41,6 @@ go_library( "@com_github_schollz_progressbar_v3//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_wealdtech_go_eth2_wallet_encryptor_keystorev4//:go_default_library", - "@io_opencensus_go//trace:go_default_library", ], ) diff --git a/validator/keymanager/local/keymanager.go b/validator/keymanager/local/keymanager.go index 5346a11078f7..241610c13e92 100644 --- a/validator/keymanager/local/keymanager.go +++ b/validator/keymanager/local/keymanager.go @@ -15,13 +15,13 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/runtime/interop" "github.com/prysmaticlabs/prysm/v5/validator/accounts/iface" "github.com/prysmaticlabs/prysm/v5/validator/accounts/petnames" "github.com/prysmaticlabs/prysm/v5/validator/keymanager" keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4" - "go.opencensus.io/trace" ) var ( diff --git a/validator/keymanager/remote-web3signer/BUILD.bazel b/validator/keymanager/remote-web3signer/BUILD.bazel index d3cc832bb8c6..1e7742a35eea 100644 --- a/validator/keymanager/remote-web3signer/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/BUILD.bazel @@ -18,11 +18,13 @@ go_library( "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", + "//runtime/version:go_default_library", "//validator/accounts/petnames:go_default_library", "//validator/keymanager:go_default_library", "//validator/keymanager/remote-web3signer/internal:go_default_library", - "//validator/keymanager/remote-web3signer/v1:go_default_library", + "//validator/keymanager/remote-web3signer/types:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_fsnotify_fsnotify//:go_default_library", "@com_github_go_playground_validator_v10//:go_default_library", @@ -31,8 +33,6 @@ go_library( "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", - "@org_golang_x_exp//maps:go_default_library", ], ) @@ -48,7 +48,7 @@ go_test( "//testing/require:go_default_library", "//validator/keymanager:go_default_library", "//validator/keymanager/remote-web3signer/internal:go_default_library", - "//validator/keymanager/remote-web3signer/v1/mock:go_default_library", + "//validator/keymanager/remote-web3signer/types/mock:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", "@com_github_stretchr_testify//assert:go_default_library", diff --git a/validator/keymanager/remote-web3signer/internal/BUILD.bazel b/validator/keymanager/remote-web3signer/internal/BUILD.bazel index 8b9e49daf3a9..571d23408e49 100644 --- a/validator/keymanager/remote-web3signer/internal/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/internal/BUILD.bazel @@ -13,12 +13,13 @@ go_library( "//config/fieldparams:go_default_library", "//crypto/bls:go_default_library", "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp//:go_default_library", ], ) diff --git a/validator/keymanager/remote-web3signer/internal/client.go b/validator/keymanager/remote-web3signer/internal/client.go index 9c9c9fc0646f..c84f6015e672 100644 --- a/validator/keymanager/remote-web3signer/internal/client.go +++ b/validator/keymanager/remote-web3signer/internal/client.go @@ -18,8 +18,9 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) const ( @@ -56,7 +57,7 @@ func NewApiClient(baseEndpoint string) (*ApiClient, error) { } return &ApiClient{ BaseURL: u, - RestClient: &http.Client{}, + RestClient: &http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}, }, nil } @@ -138,7 +139,7 @@ func (client *ApiClient) doRequest(ctx context.Context, httpMethod, fullPath str var requestDump []byte ctx, span := trace.StartSpan(ctx, "remote_web3signer.Client.doRequest") defer span.End() - span.AddAttributes( + span.SetAttributes( trace.StringAttribute("httpMethod", httpMethod), trace.StringAttribute("fullPath", fullPath), trace.BoolAttribute("hasBody", body != nil), diff --git a/validator/keymanager/remote-web3signer/keymanager.go b/validator/keymanager/remote-web3signer/keymanager.go index 0da752d72806..1d050858343c 100644 --- a/validator/keymanager/remote-web3signer/keymanager.go +++ b/validator/keymanager/remote-web3signer/keymanager.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "maps" "os" "path/filepath" "slices" @@ -22,14 +23,14 @@ import ( "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" "github.com/prysmaticlabs/prysm/v5/io/file" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" + "github.com/prysmaticlabs/prysm/v5/runtime/version" "github.com/prysmaticlabs/prysm/v5/validator/accounts/petnames" "github.com/prysmaticlabs/prysm/v5/validator/keymanager" "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/internal" - web3signerv1 "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types" "github.com/sirupsen/logrus" - "go.opencensus.io/trace" - "golang.org/x/exp/maps" ) const ( @@ -145,7 +146,7 @@ func NewKeymanager(ctx context.Context, cfg *SetupConfig) (*Keymanager, error) { } } km.lock.Lock() - km.providedPublicKeys = maps.Values(fileKeys) + km.providedPublicKeys = slices.Collect(maps.Values(fileKeys)) km.lock.Unlock() // create a file watcher go func() { @@ -156,7 +157,7 @@ func NewKeymanager(ctx context.Context, cfg *SetupConfig) (*Keymanager, error) { }() } else { km.lock.Lock() - km.providedPublicKeys = maps.Values(flagLoadedKeys) + km.providedPublicKeys = slices.Collect(maps.Values(flagLoadedKeys)) km.lock.Unlock() } @@ -172,7 +173,7 @@ func (km *Keymanager) refreshRemoteKeysFromFileChangesWithRetry(ctx context.Cont } err := km.refreshRemoteKeysFromFileChanges(ctx) if err != nil { - km.updatePublicKeys(maps.Values(km.flagLoadedKeysMap)) // update the keys to flag provided defaults + km.updatePublicKeys(slices.Collect(maps.Values(km.flagLoadedKeysMap))) // update the keys to flag provided defaults km.retriesRemaining-- log.WithError(err).Debug("Error occurred on key refresh") log.WithFields(logrus.Fields{"path": km.keyFilePath, "retriesRemaining": km.retriesRemaining, "retryDelay": retryDelay}).Warnf("Could not refresh keys. Retrying...") @@ -305,7 +306,7 @@ func (km *Keymanager) refreshRemoteKeysFromFileChanges(ctx context.Context) erro if err = km.savePublicKeysToFile(fk); err != nil { return errors.Wrap(err, "could not save public keys to file") } - km.updatePublicKeys(maps.Values(fk)) + km.updatePublicKeys(slices.Collect(maps.Values(fk))) } for { select { @@ -334,7 +335,7 @@ func (km *Keymanager) refreshRemoteKeysFromFileChanges(ctx context.Context) erro // prioritize file keys over flag keys if len(fileKeys) == 0 { log.Warnln("Remote signer key file no longer has keys, defaulting to flag provided keys") - fileKeys = maps.Values(km.flagLoadedKeysMap) + fileKeys = slices.Collect(maps.Values(km.flagLoadedKeysMap)) } currentKeys, err := km.FetchValidatingPublicKeys(ctx) if err != nil { @@ -405,7 +406,10 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ case *validatorpb.SignRequest_AttestationData: return handleAttestationData(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_AggregateAttestationAndProof: + // TODO: update to V2 sometime after release return handleAggregateAttestationAndProof(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_AggregateAttestationAndProofElectra: + return handleAggregateAttestationAndProofV2(ctx, version.Electra, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_Slot: return handleAggregationSlot(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlockAltair: @@ -422,6 +426,10 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ return handleBlockDeneb(ctx, validator, request, genesisValidatorsRoot) case *validatorpb.SignRequest_BlindedBlockDeneb: return handleBlindedBlockDeneb(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_BlockElectra: + return handleBlockElectra(ctx, validator, request, genesisValidatorsRoot) + case *validatorpb.SignRequest_BlindedBlockElectra: + return handleBlindedBlockElectra(ctx, validator, request, genesisValidatorsRoot) // We do not support "DEPOSIT" type. /* case *validatorpb.: @@ -447,7 +455,7 @@ func getSignRequestJson(ctx context.Context, validator *validator.Validate, requ } func handleBlock(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - bockSignRequest, err := web3signerv1.GetBlockSignRequest(request, genesisValidatorsRoot) + bockSignRequest, err := types.GetBlockSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -459,7 +467,7 @@ func handleBlock(ctx context.Context, validator *validator.Validate, request *va } func handleAttestationData(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - attestationSignRequest, err := web3signerv1.GetAttestationSignRequest(request, genesisValidatorsRoot) + attestationSignRequest, err := types.GetAttestationSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -471,7 +479,7 @@ func handleAttestationData(ctx context.Context, validator *validator.Validate, r } func handleAggregateAttestationAndProof(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - aggregateAndProofSignRequest, err := web3signerv1.GetAggregateAndProofSignRequest(request, genesisValidatorsRoot) + aggregateAndProofSignRequest, err := types.GetAggregateAndProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -482,8 +490,20 @@ func handleAggregateAttestationAndProof(ctx context.Context, validator *validato return json.Marshal(aggregateAndProofSignRequest) } +func handleAggregateAttestationAndProofV2(ctx context.Context, fork int, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + aggregateAndProofSignRequestV2, err := types.GetAggregateAndProofV2SignRequest(fork, request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, aggregateAndProofSignRequestV2); err != nil { + return nil, err + } + aggregateAndProofSignRequestsTotal.Inc() + return json.Marshal(aggregateAndProofSignRequestV2) +} + func handleAggregationSlot(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - aggregationSlotSignRequest, err := web3signerv1.GetAggregationSlotSignRequest(request, genesisValidatorsRoot) + aggregationSlotSignRequest, err := types.GetAggregationSlotSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -495,7 +515,7 @@ func handleAggregationSlot(ctx context.Context, validator *validator.Validate, r } func handleBlockAltair(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blockv2AltairSignRequest, err := web3signerv1.GetBlockAltairSignRequest(request, genesisValidatorsRoot) + blockv2AltairSignRequest, err := types.GetBlockAltairSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -507,7 +527,7 @@ func handleBlockAltair(ctx context.Context, validator *validator.Validate, reque } func handleBlockBellatrix(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blockv2BellatrixSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blockv2BellatrixSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -519,7 +539,7 @@ func handleBlockBellatrix(ctx context.Context, validator *validator.Validate, re } func handleBlindedBlockBellatrix(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blindedBlockv2SignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blindedBlockv2SignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -531,7 +551,7 @@ func handleBlindedBlockBellatrix(ctx context.Context, validator *validator.Valid } func handleBlockCapella(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blockv2CapellaSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blockv2CapellaSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -543,7 +563,7 @@ func handleBlockCapella(ctx context.Context, validator *validator.Validate, requ } func handleBlindedBlockCapella(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blindedBlockv2CapellaSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blindedBlockv2CapellaSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -555,7 +575,7 @@ func handleBlindedBlockCapella(ctx context.Context, validator *validator.Validat } func handleBlockDeneb(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blockv2DenebSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blockv2DenebSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -567,7 +587,7 @@ func handleBlockDeneb(ctx context.Context, validator *validator.Validate, reques } func handleBlindedBlockDeneb(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - blindedBlockv2DenebSignRequest, err := web3signerv1.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + blindedBlockv2DenebSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -578,8 +598,32 @@ func handleBlindedBlockDeneb(ctx context.Context, validator *validator.Validate, return json.Marshal(blindedBlockv2DenebSignRequest) } +func handleBlockElectra(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blockv2ElectraSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blockv2ElectraSignRequest); err != nil { + return nil, err + } + remoteBlockSignRequestsTotal.WithLabelValues("electra", "false").Inc() + return json.Marshal(blockv2ElectraSignRequest) +} + +func handleBlindedBlockElectra(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { + blindedBlockv2ElectraSignRequest, err := types.GetBlockV2BlindedSignRequest(request, genesisValidatorsRoot) + if err != nil { + return nil, err + } + if err = validator.StructCtx(ctx, blindedBlockv2ElectraSignRequest); err != nil { + return nil, err + } + remoteBlockSignRequestsTotal.WithLabelValues("electra", "true").Inc() + return json.Marshal(blindedBlockv2ElectraSignRequest) +} + func handleRandaoReveal(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - randaoRevealSignRequest, err := web3signerv1.GetRandaoRevealSignRequest(request, genesisValidatorsRoot) + randaoRevealSignRequest, err := types.GetRandaoRevealSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -591,7 +635,7 @@ func handleRandaoReveal(ctx context.Context, validator *validator.Validate, requ } func handleVoluntaryExit(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - voluntaryExitRequest, err := web3signerv1.GetVoluntaryExitSignRequest(request, genesisValidatorsRoot) + voluntaryExitRequest, err := types.GetVoluntaryExitSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -603,7 +647,7 @@ func handleVoluntaryExit(ctx context.Context, validator *validator.Validate, req } func handleSyncMessageBlockRoot(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - syncCommitteeMessageRequest, err := web3signerv1.GetSyncCommitteeMessageSignRequest(request, genesisValidatorsRoot) + syncCommitteeMessageRequest, err := types.GetSyncCommitteeMessageSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -615,7 +659,7 @@ func handleSyncMessageBlockRoot(ctx context.Context, validator *validator.Valida } func handleSyncAggregatorSelectionData(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - syncCommitteeSelectionProofRequest, err := web3signerv1.GetSyncCommitteeSelectionProofSignRequest(request, genesisValidatorsRoot) + syncCommitteeSelectionProofRequest, err := types.GetSyncCommitteeSelectionProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -627,7 +671,7 @@ func handleSyncAggregatorSelectionData(ctx context.Context, validator *validator } func handleContributionAndProof(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) ([]byte, error) { - contributionAndProofRequest, err := web3signerv1.GetSyncCommitteeContributionAndProofSignRequest(request, genesisValidatorsRoot) + contributionAndProofRequest, err := types.GetSyncCommitteeContributionAndProofSignRequest(request, genesisValidatorsRoot) if err != nil { return nil, err } @@ -639,7 +683,7 @@ func handleContributionAndProof(ctx context.Context, validator *validator.Valida } func handleRegistration(ctx context.Context, validator *validator.Validate, request *validatorpb.SignRequest) ([]byte, error) { - validatorRegistrationRequest, err := web3signerv1.GetValidatorRegistrationSignRequest(request) + validatorRegistrationRequest, err := types.GetValidatorRegistrationSignRequest(request) if err != nil { return nil, err } @@ -764,7 +808,7 @@ func (km *Keymanager) AddPublicKeys(pubKeys []string) ([]*keymanager.KeyStatus, return nil, err } } else { - km.updatePublicKeys(maps.Values(combinedKeys)) + km.updatePublicKeys(slices.Collect(maps.Values(combinedKeys))) } } @@ -833,7 +877,7 @@ func (km *Keymanager) DeletePublicKeys(publicKeys []string) ([]*keymanager.KeySt return nil, err } } else { - km.updatePublicKeys(maps.Values(combinedKeys)) + km.updatePublicKeys(slices.Collect(maps.Values(combinedKeys))) } } diff --git a/validator/keymanager/remote-web3signer/keymanager_test.go b/validator/keymanager/remote-web3signer/keymanager_test.go index 9d47eda75359..adeffb4a81e2 100644 --- a/validator/keymanager/remote-web3signer/keymanager_test.go +++ b/validator/keymanager/remote-web3signer/keymanager_test.go @@ -22,7 +22,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/testing/require" "github.com/prysmaticlabs/prysm/v5/validator/keymanager" "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/internal" - "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1/mock" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types/mock" logTest "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/assert" ) @@ -407,6 +407,14 @@ func TestKeymanager_Sign(t *testing.T) { want: desiredSig, wantErr: false, }, + { + name: "AGGREGATE_AND_PROOF_V2", + args: args{ + request: mock.GetMockSignRequest("AGGREGATE_AND_PROOF_V2"), + }, + want: desiredSig, + wantErr: false, + }, { name: "ATTESTATION", args: args{ diff --git a/validator/keymanager/remote-web3signer/metrics.go b/validator/keymanager/remote-web3signer/metrics.go index 0e6b23974e5d..e40a131d93ca 100644 --- a/validator/keymanager/remote-web3signer/metrics.go +++ b/validator/keymanager/remote-web3signer/metrics.go @@ -14,10 +14,7 @@ var ( Name: "remote_web3signer_errored_responses_total", Help: "Total number of errored responses when calling web3signer", }) - blockSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ - Name: "remote_web3signer_block_sign_requests_total", - Help: "Total number of block sign requests", - }) + aggregationSlotSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ Name: "remote_web3signer_aggregation_slot_requests_total", Help: "Total number of aggregation slot requests", @@ -30,6 +27,11 @@ var ( Name: "remote_web3signer_attestation_sign_requests_total", Help: "Total number of attestation sign requests", }) + //TODO: deprecate these fork specific counters in prysm v6... + blockSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ + Name: "remote_web3signer_block_sign_requests_total", + Help: "Total number of block sign requests", + }) blockAltairSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ Name: "remote_web3signer_block_altair_sign_requests_total", Help: "Total number of block altair sign requests", @@ -58,6 +60,13 @@ var ( Name: "remote_web3signer_blinded_block_deneb_sign_requests_total", Help: "Total number of blinded block deneb sign requests", }) + ///// + + remoteBlockSignRequestsTotal = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "remote_block_sign_requests_total", + Help: "Total number of block sign requests with fork and blinded block check", + }, []string{"fork", "isBlinded"}) + randaoRevealSignRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{ Name: "remote_web3signer_randao_reveal_sign_requests_total", Help: "Total number of randao reveal sign requests", diff --git a/validator/keymanager/remote-web3signer/v1/BUILD.bazel b/validator/keymanager/remote-web3signer/types/BUILD.bazel similarity index 89% rename from validator/keymanager/remote-web3signer/v1/BUILD.bazel rename to validator/keymanager/remote-web3signer/types/BUILD.bazel index ebc1a0fcae58..980d432ac2f7 100644 --- a/validator/keymanager/remote-web3signer/v1/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/types/BUILD.bazel @@ -7,7 +7,7 @@ go_library( "requests.go", "web3signer_types.go", ], - importpath = "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1", + importpath = "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types", visibility = ["//visibility:public"], deps = [ "//consensus-types/blocks:go_default_library", @@ -16,6 +16,7 @@ go_library( "//network/forks:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", + "//runtime/version:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_pkg_errors//:go_default_library", @@ -35,7 +36,7 @@ go_test( "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", "//testing/require:go_default_library", - "//validator/keymanager/remote-web3signer/v1/mock:go_default_library", + "//validator/keymanager/remote-web3signer/types/mock:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], diff --git a/validator/keymanager/remote-web3signer/v1/custom_mappers.go b/validator/keymanager/remote-web3signer/types/custom_mappers.go similarity index 91% rename from validator/keymanager/remote-web3signer/v1/custom_mappers.go rename to validator/keymanager/remote-web3signer/types/custom_mappers.go index 69581fb5b00a..b36796ad9c6d 100644 --- a/validator/keymanager/remote-web3signer/v1/custom_mappers.go +++ b/validator/keymanager/remote-web3signer/types/custom_mappers.go @@ -1,4 +1,4 @@ -package v1 +package types import ( "fmt" @@ -44,6 +44,22 @@ func MapAggregateAndProof(from *ethpb.AggregateAttestationAndProof) (*AggregateA }, nil } +// MapAggregateAndProofElectra maps the eth2.AggregateAndProofElectra proto to the Web3Signer spec. +func MapAggregateAndProofElectra(from *ethpb.AggregateAttestationAndProofElectra) (*AggregateAndProofElectra, error) { + if from == nil { + return nil, fmt.Errorf("AggregateAttestationAndProof is nil") + } + aggregate, err := MapAttestationElectra(from.Aggregate) + if err != nil { + return nil, err + } + return &AggregateAndProofElectra{ + AggregatorIndex: fmt.Sprint(from.AggregatorIndex), + Aggregate: aggregate, + SelectionProof: from.SelectionProof, + }, nil +} + // MapAttestation maps the eth2.Attestation proto to the Web3Signer spec. func MapAttestation(attestation *ethpb.Attestation) (*Attestation, error) { if attestation == nil { @@ -63,6 +79,29 @@ func MapAttestation(attestation *ethpb.Attestation) (*Attestation, error) { }, nil } +// MapAttestationElectra maps the eth2.Attestation proto to the Web3Signer spec. +func MapAttestationElectra(attestation *ethpb.AttestationElectra) (*AttestationElectra, error) { + if attestation == nil { + return nil, fmt.Errorf("attestation is nil") + } + if attestation.AggregationBits == nil { + return nil, fmt.Errorf("aggregation bits in attestation is nil") + } + if attestation.CommitteeBits == nil { + return nil, fmt.Errorf("committee bits in attestation is nil") + } + data, err := MapAttestationData(attestation.Data) + if err != nil { + return nil, err + } + return &AttestationElectra{ + AggregationBits: []byte(attestation.AggregationBits), + Data: data, + Signature: attestation.Signature, + CommitteeBits: attestation.CommitteeBits.Bytes(), + }, nil +} + // MapAttestationData maps the eth2.AttestationData proto to the Web3Signer spec. func MapAttestationData(data *ethpb.AttestationData) (*AttestationData, error) { if data == nil { diff --git a/validator/keymanager/remote-web3signer/v1/custom_mappers_test.go b/validator/keymanager/remote-web3signer/types/custom_mappers_test.go similarity index 79% rename from validator/keymanager/remote-web3signer/v1/custom_mappers_test.go rename to validator/keymanager/remote-web3signer/types/custom_mappers_test.go index 3088f84f32a3..fa189d11d947 100644 --- a/validator/keymanager/remote-web3signer/v1/custom_mappers_test.go +++ b/validator/keymanager/remote-web3signer/types/custom_mappers_test.go @@ -1,4 +1,4 @@ -package v1_test +package types_test import ( "reflect" @@ -8,8 +8,8 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - v1 "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1" - "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1/mock" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types/mock" ) func TestMapAggregateAndProof(t *testing.T) { @@ -19,7 +19,7 @@ func TestMapAggregateAndProof(t *testing.T) { tests := []struct { name string args args - want *v1.AggregateAndProof + want *types.AggregateAndProof wantErr bool }{ { @@ -43,7 +43,7 @@ func TestMapAggregateAndProof(t *testing.T) { SelectionProof: make([]byte, fieldparams.BLSSignatureLength), }, }, - want: &v1.AggregateAndProof{ + want: &types.AggregateAndProof{ AggregatorIndex: "0", Aggregate: mock.Attestation(), SelectionProof: make([]byte, fieldparams.BLSSignatureLength), @@ -53,7 +53,65 @@ func TestMapAggregateAndProof(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapAggregateAndProof(tt.args.from) + got, err := types.MapAggregateAndProof(tt.args.from) + if (err != nil) != tt.wantErr { + t.Errorf("MapAggregateAndProof() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got.Aggregate, tt.want.Aggregate) { + t.Errorf("MapAggregateAndProof() got = %v, want %v", got.Aggregate, tt.want.Aggregate) + } + }) + } +} + +func TestMapAggregateAndProofElectra(t *testing.T) { + type args struct { + from *ethpb.AggregateAttestationAndProofElectra + } + tests := []struct { + name string + args args + want *types.AggregateAndProofElectra + wantErr bool + }{ + { + name: "HappyPathTest", + args: args{ + from: ðpb.AggregateAttestationAndProofElectra{ + AggregatorIndex: 0, + Aggregate: ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1101}, + Data: ðpb.AttestationData{ + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ðpb.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + Target: ðpb.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + }, + Signature: make([]byte, 96), + CommitteeBits: func() bitfield.Bitvector64 { + committeeBits := bitfield.NewBitvector64() + committeeBits.SetBitAt(0, true) + return committeeBits + }(), + }, + SelectionProof: make([]byte, fieldparams.BLSSignatureLength), + }, + }, + want: &types.AggregateAndProofElectra{ + AggregatorIndex: "0", + Aggregate: mock.AttestationElectra(), + SelectionProof: make([]byte, fieldparams.BLSSignatureLength), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := types.MapAggregateAndProofElectra(tt.args.from) if (err != nil) != tt.wantErr { t.Errorf("MapAggregateAndProof() error = %v, wantErr %v", err, tt.wantErr) return @@ -72,7 +130,7 @@ func TestMapAttestation(t *testing.T) { tests := []struct { name string args args - want *v1.Attestation + want *types.Attestation wantErr bool }{ { @@ -98,7 +156,57 @@ func TestMapAttestation(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapAttestation(tt.args.attestation) + got, err := types.MapAttestation(tt.args.attestation) + if (err != nil) != tt.wantErr { + t.Errorf("MapAttestation() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("MapAttestation() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestMapAttestationElectra(t *testing.T) { + type args struct { + attestation *ethpb.AttestationElectra + } + tests := []struct { + name string + args args + want *types.AttestationElectra + wantErr bool + }{ + { + name: "HappyPathTest", + args: args{ + attestation: ðpb.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1101}, + Data: ðpb.AttestationData{ + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ðpb.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + Target: ðpb.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + }, + CommitteeBits: func() bitfield.Bitvector64 { + committeeBits := bitfield.NewBitvector64() + committeeBits.SetBitAt(0, true) + return committeeBits + }(), + Signature: make([]byte, 96), + }, + }, + want: mock.AttestationElectra(), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := types.MapAttestationElectra(tt.args.attestation) if (err != nil) != tt.wantErr { t.Errorf("MapAttestation() error = %v, wantErr %v", err, tt.wantErr) return @@ -117,7 +225,7 @@ func TestMapAttestationData(t *testing.T) { tests := []struct { name string args args - want *v1.AttestationData + want *types.AttestationData wantErr bool }{ { @@ -139,7 +247,7 @@ func TestMapAttestationData(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapAttestationData(tt.args.data) + got, err := types.MapAttestationData(tt.args.data) if (err != nil) != tt.wantErr { t.Errorf("MapAttestationData() error = %v, wantErr %v", err, tt.wantErr) return @@ -158,7 +266,7 @@ func TestMapAttesterSlashing(t *testing.T) { tests := []struct { name string args args - want *v1.AttesterSlashing + want *types.AttesterSlashing wantErr bool }{ { @@ -193,7 +301,7 @@ func TestMapAttesterSlashing(t *testing.T) { }, }, }, - want: &v1.AttesterSlashing{ + want: &types.AttesterSlashing{ Attestation1: mock.IndexedAttestation(), Attestation2: mock.IndexedAttestation(), }, @@ -202,7 +310,7 @@ func TestMapAttesterSlashing(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapAttesterSlashing(tt.args.slashing) + got, err := types.MapAttesterSlashing(tt.args.slashing) if (err != nil) != tt.wantErr { t.Errorf("MapAttesterSlashing() error = %v, wantErr %v", err, tt.wantErr) return @@ -221,7 +329,7 @@ func TestMapBeaconBlockAltair(t *testing.T) { tests := []struct { name string args args - want *v1.BeaconBlockAltair + want *types.BeaconBlockAltair wantErr bool }{ { @@ -342,7 +450,7 @@ func TestMapBeaconBlockAltair(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapBeaconBlockAltair(tt.args.block) + got, err := types.MapBeaconBlockAltair(tt.args.block) if (err != nil) != tt.wantErr { t.Errorf("MapBeaconBlockAltair() error = %v, wantErr %v", err, tt.wantErr) return @@ -361,7 +469,7 @@ func TestMapBeaconBlockBody(t *testing.T) { tests := []struct { name string args args - want *v1.BeaconBlockBody + want *types.BeaconBlockBody wantErr bool }{ { @@ -472,7 +580,7 @@ func TestMapBeaconBlockBody(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapBeaconBlockBody(tt.args.body) + got, err := types.MapBeaconBlockBody(tt.args.body) if (err != nil) != tt.wantErr { t.Errorf("MapBeaconBlockBody() error = %v, wantErr %v", err, tt.wantErr) return @@ -491,7 +599,7 @@ func TestMapContributionAndProof(t *testing.T) { tests := []struct { name string args args - want *v1.ContributionAndProof + want *types.ContributionAndProof wantErr bool }{ { @@ -514,7 +622,7 @@ func TestMapContributionAndProof(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapContributionAndProof(tt.args.contribution) + got, err := types.MapContributionAndProof(tt.args.contribution) if (err != nil) != tt.wantErr { t.Errorf("MapContributionAndProof() error = %v, wantErr %v", err, tt.wantErr) return @@ -535,7 +643,7 @@ func TestMapForkInfo(t *testing.T) { tests := []struct { name string args args - want *v1.ForkInfo + want *types.ForkInfo wantErr bool }{ { @@ -550,7 +658,7 @@ func TestMapForkInfo(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapForkInfo(tt.args.slot, tt.args.genesisValidatorsRoot) + got, err := types.MapForkInfo(tt.args.slot, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("MapForkInfo() error = %v, wantErr %v", err, tt.wantErr) return @@ -569,7 +677,7 @@ func TestMapSyncAggregatorSelectionData(t *testing.T) { tests := []struct { name string args args - want *v1.SyncAggregatorSelectionData + want *types.SyncAggregatorSelectionData wantErr bool }{ { @@ -580,7 +688,7 @@ func TestMapSyncAggregatorSelectionData(t *testing.T) { SubcommitteeIndex: 0, }, }, - want: &v1.SyncAggregatorSelectionData{ + want: &types.SyncAggregatorSelectionData{ Slot: "0", SubcommitteeIndex: "0", }, @@ -589,7 +697,7 @@ func TestMapSyncAggregatorSelectionData(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.MapSyncAggregatorSelectionData(tt.args.data) + got, err := types.MapSyncAggregatorSelectionData(tt.args.data) if (err != nil) != tt.wantErr { t.Errorf("MapSyncAggregatorSelectionData() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel b/validator/keymanager/remote-web3signer/types/mock/BUILD.bazel similarity index 84% rename from validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel rename to validator/keymanager/remote-web3signer/types/mock/BUILD.bazel index 6c09a88be40b..87d535c95c46 100644 --- a/validator/keymanager/remote-web3signer/v1/mock/BUILD.bazel +++ b/validator/keymanager/remote-web3signer/types/mock/BUILD.bazel @@ -4,14 +4,14 @@ go_library( name = "go_default_library", testonly = True, srcs = ["mocks.go"], - importpath = "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1/mock", + importpath = "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types/mock", visibility = ["//visibility:public"], deps = [ "//config/fieldparams:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//proto/prysm/v1alpha1/validator-client:go_default_library", "//testing/util:go_default_library", - "//validator/keymanager/remote-web3signer/v1:go_default_library", + "//validator/keymanager/remote-web3signer/types:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], diff --git a/validator/keymanager/remote-web3signer/v1/mock/mocks.go b/validator/keymanager/remote-web3signer/types/mock/mocks.go similarity index 79% rename from validator/keymanager/remote-web3signer/v1/mock/mocks.go rename to validator/keymanager/remote-web3signer/types/mock/mocks.go index fdd7c3dc5a76..13d911a3f7da 100644 --- a/validator/keymanager/remote-web3signer/v1/mock/mocks.go +++ b/validator/keymanager/remote-web3signer/types/mock/mocks.go @@ -9,7 +9,7 @@ import ( eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/testing/util" - v1 "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types" ) ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -79,6 +79,33 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { }, SigningSlot: 0, } + case "AGGREGATE_AND_PROOF_V2": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_AggregateAttestationAndProofElectra{ + AggregateAttestationAndProofElectra: ð.AggregateAttestationAndProofElectra{ + AggregatorIndex: 0, + Aggregate: ð.AttestationElectra{ + AggregationBits: bitfield.Bitlist{0b1101}, + Data: ð.AttestationData{ + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: ð.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + Target: ð.Checkpoint{ + Root: make([]byte, fieldparams.RootLength), + }, + }, + Signature: make([]byte, 96), + CommitteeBits: bitfield.Bitvector64{0x01}, + }, + SelectionProof: make([]byte, fieldparams.BLSSignatureLength), + }, + }, + SigningSlot: 0, + } case "ATTESTATION": return &validatorpb.SignRequest{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), @@ -381,6 +408,24 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { BlindedBlockDeneb: util.HydrateBlindedBeaconBlockDeneb(ð.BlindedBeaconBlockDeneb{}), }, } + case "BLOCK_V2_ELECTRA": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlockElectra{ + BlockElectra: util.HydrateBeaconBlockElectra(ð.BeaconBlockElectra{}), + }, + } + case "BLOCK_V2_BLINDED_ELECTRA": + return &validatorpb.SignRequest{ + PublicKey: make([]byte, fieldparams.BLSPubkeyLength), + SigningRoot: make([]byte, fieldparams.RootLength), + SignatureDomain: make([]byte, 4), + Object: &validatorpb.SignRequest_BlindedBlockElectra{ + BlindedBlockElectra: util.HydrateBlindedBeaconBlockElectra(ð.BlindedBeaconBlockElectra{}), + }, + } case "RANDAO_REVEAL": return &validatorpb.SignRequest{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), @@ -469,22 +514,22 @@ func GetMockSignRequest(t string) *validatorpb.SignRequest { } // AggregationSlotSignRequest is a mock implementation of the AggregationSlotSignRequest. -func AggregationSlotSignRequest() *v1.AggregationSlotSignRequest { - return &v1.AggregationSlotSignRequest{ +func AggregationSlotSignRequest() *types.AggregationSlotSignRequest { + return &types.AggregationSlotSignRequest{ Type: "AGGREGATION_SLOT", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - AggregationSlot: &v1.AggregationSlot{Slot: "0"}, + AggregationSlot: &types.AggregationSlot{Slot: "0"}, } } // AggregateAndProofSignRequest is a mock implementation of the AggregateAndProofSignRequest. -func AggregateAndProofSignRequest() *v1.AggregateAndProofSignRequest { - return &v1.AggregateAndProofSignRequest{ +func AggregateAndProofSignRequest() *types.AggregateAndProofSignRequest { + return &types.AggregateAndProofSignRequest{ Type: "AGGREGATE_AND_PROOF", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - AggregateAndProof: &v1.AggregateAndProof{ + AggregateAndProof: &types.AggregateAndProof{ AggregatorIndex: "0", Aggregate: Attestation(), SelectionProof: make([]byte, fieldparams.BLSSignatureLength), @@ -493,8 +538,8 @@ func AggregateAndProofSignRequest() *v1.AggregateAndProofSignRequest { } // AttestationSignRequest is a mock implementation of the AttestationSignRequest. -func AttestationSignRequest() *v1.AttestationSignRequest { - return &v1.AttestationSignRequest{ +func AttestationSignRequest() *types.AttestationSignRequest { + return &types.AttestationSignRequest{ Type: "ATTESTATION", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), @@ -503,12 +548,12 @@ func AttestationSignRequest() *v1.AttestationSignRequest { } // BlockSignRequest is a mock implementation of the BlockSignRequest. -func BlockSignRequest() *v1.BlockSignRequest { - return &v1.BlockSignRequest{ +func BlockSignRequest() *types.BlockSignRequest { + return &types.BlockSignRequest{ Type: "BLOCK", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - Block: &v1.BeaconBlock{ + Block: &types.BeaconBlock{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -519,26 +564,26 @@ func BlockSignRequest() *v1.BlockSignRequest { } // BlockV2AltairSignRequest is a mock implementation of the BlockAltairSignRequest. -func BlockV2AltairSignRequest() *v1.BlockAltairSignRequest { - return &v1.BlockAltairSignRequest{ +func BlockV2AltairSignRequest() *types.BlockAltairSignRequest { + return &types.BlockAltairSignRequest{ Type: "BLOCK_V2", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - BeaconBlock: &v1.BeaconBlockAltairBlockV2{ + BeaconBlock: &types.BeaconBlockAltairBlockV2{ Version: "ALTAIR", Block: BeaconBlockAltair(), }, } } -func BlockV2BlindedSignRequest(bodyRoot []byte, version string) *v1.BlockV2BlindedSignRequest { - return &v1.BlockV2BlindedSignRequest{ +func BlockV2BlindedSignRequest(bodyRoot []byte, version string) *types.BlockV2BlindedSignRequest { + return &types.BlockV2BlindedSignRequest{ Type: "BLOCK_V2", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - BeaconBlock: &v1.BeaconBlockV2Blinded{ + BeaconBlock: &types.BeaconBlockV2Blinded{ Version: version, - BlockHeader: &v1.BeaconBlockHeader{ + BlockHeader: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -550,20 +595,20 @@ func BlockV2BlindedSignRequest(bodyRoot []byte, version string) *v1.BlockV2Blind } // RandaoRevealSignRequest is a mock implementation of the RandaoRevealSignRequest. -func RandaoRevealSignRequest() *v1.RandaoRevealSignRequest { - return &v1.RandaoRevealSignRequest{ +func RandaoRevealSignRequest() *types.RandaoRevealSignRequest { + return &types.RandaoRevealSignRequest{ Type: "RANDAO_REVEAL", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - RandaoReveal: &v1.RandaoReveal{ + RandaoReveal: &types.RandaoReveal{ Epoch: "0", }, } } // SyncCommitteeContributionAndProofSignRequest is a mock implementation of the SyncCommitteeContributionAndProofSignRequest. -func SyncCommitteeContributionAndProofSignRequest() *v1.SyncCommitteeContributionAndProofSignRequest { - return &v1.SyncCommitteeContributionAndProofSignRequest{ +func SyncCommitteeContributionAndProofSignRequest() *types.SyncCommitteeContributionAndProofSignRequest { + return &types.SyncCommitteeContributionAndProofSignRequest{ Type: "SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), @@ -572,12 +617,12 @@ func SyncCommitteeContributionAndProofSignRequest() *v1.SyncCommitteeContributio } // SyncCommitteeMessageSignRequest is a mock implementation of the SyncCommitteeMessageSignRequest. -func SyncCommitteeMessageSignRequest() *v1.SyncCommitteeMessageSignRequest { - return &v1.SyncCommitteeMessageSignRequest{ +func SyncCommitteeMessageSignRequest() *types.SyncCommitteeMessageSignRequest { + return &types.SyncCommitteeMessageSignRequest{ Type: "SYNC_COMMITTEE_MESSAGE", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - SyncCommitteeMessage: &v1.SyncCommitteeMessage{ + SyncCommitteeMessage: &types.SyncCommitteeMessage{ BeaconBlockRoot: make([]byte, fieldparams.RootLength), Slot: "0", }, @@ -585,12 +630,12 @@ func SyncCommitteeMessageSignRequest() *v1.SyncCommitteeMessageSignRequest { } // SyncCommitteeSelectionProofSignRequest is a mock implementation of the SyncCommitteeSelectionProofSignRequest. -func SyncCommitteeSelectionProofSignRequest() *v1.SyncCommitteeSelectionProofSignRequest { - return &v1.SyncCommitteeSelectionProofSignRequest{ +func SyncCommitteeSelectionProofSignRequest() *types.SyncCommitteeSelectionProofSignRequest { + return &types.SyncCommitteeSelectionProofSignRequest{ Type: "SYNC_COMMITTEE_SELECTION_PROOF", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - SyncAggregatorSelectionData: &v1.SyncAggregatorSelectionData{ + SyncAggregatorSelectionData: &types.SyncAggregatorSelectionData{ Slot: "0", SubcommitteeIndex: "0", }, @@ -598,12 +643,12 @@ func SyncCommitteeSelectionProofSignRequest() *v1.SyncCommitteeSelectionProofSig } // VoluntaryExitSignRequest is a mock implementation of the VoluntaryExitSignRequest. -func VoluntaryExitSignRequest() *v1.VoluntaryExitSignRequest { - return &v1.VoluntaryExitSignRequest{ +func VoluntaryExitSignRequest() *types.VoluntaryExitSignRequest { + return &types.VoluntaryExitSignRequest{ Type: "VOLUNTARY_EXIT", ForkInfo: ForkInfo(), SigningRoot: make([]byte, fieldparams.RootLength), - VoluntaryExit: &v1.VoluntaryExit{ + VoluntaryExit: &types.VoluntaryExit{ Epoch: "0", ValidatorIndex: "0", }, @@ -611,11 +656,11 @@ func VoluntaryExitSignRequest() *v1.VoluntaryExitSignRequest { } // ValidatorRegistrationSignRequest is a mock implementation of the ValidatorRegistrationSignRequest. -func ValidatorRegistrationSignRequest() *v1.ValidatorRegistrationSignRequest { - return &v1.ValidatorRegistrationSignRequest{ +func ValidatorRegistrationSignRequest() *types.ValidatorRegistrationSignRequest { + return &types.ValidatorRegistrationSignRequest{ Type: "VALIDATOR_REGISTRATION", SigningRoot: make([]byte, fieldparams.RootLength), - ValidatorRegistration: &v1.ValidatorRegistration{ + ValidatorRegistration: &types.ValidatorRegistration{ FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), GasLimit: fmt.Sprint(0), Timestamp: fmt.Sprint(0), @@ -629,9 +674,9 @@ func ValidatorRegistrationSignRequest() *v1.ValidatorRegistrationSignRequest { ///////////////////////////////////////////////////////////////////////////////////////////////// // ForkInfo is a mock implementation of the ForkInfo. -func ForkInfo() *v1.ForkInfo { - return &v1.ForkInfo{ - Fork: &v1.Fork{ +func ForkInfo() *types.ForkInfo { + return &types.ForkInfo{ + Fork: &types.Fork{ PreviousVersion: make([]byte, 4), CurrentVersion: make([]byte, 4), Epoch: "0", @@ -641,18 +686,18 @@ func ForkInfo() *v1.ForkInfo { } // Attestation is a mock implementation of the Attestation. -func Attestation() *v1.Attestation { - return &v1.Attestation{ +func Attestation() *types.Attestation { + return &types.Attestation{ AggregationBits: []byte(bitfield.Bitlist{0b1101}), - Data: &v1.AttestationData{ + Data: &types.AttestationData{ Slot: "0", Index: "0", BeaconBlockRoot: make([]byte, fieldparams.RootLength), - Source: &v1.Checkpoint{ + Source: &types.Checkpoint{ Epoch: "0", Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), }, - Target: &v1.Checkpoint{ + Target: &types.Checkpoint{ Epoch: "0", Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), }, @@ -661,18 +706,42 @@ func Attestation() *v1.Attestation { } } -func IndexedAttestation() *v1.IndexedAttestation { - return &v1.IndexedAttestation{ +// AttestationElectra is a mock implementation of the AttestationElectra. +func AttestationElectra() *types.AttestationElectra { + committeeBits := bitfield.NewBitvector64() + committeeBits.SetBitAt(0, true) + return &types.AttestationElectra{ + AggregationBits: []byte(bitfield.Bitlist{0b1101}), + Data: &types.AttestationData{ + Slot: "0", + Index: "0", + BeaconBlockRoot: make([]byte, fieldparams.RootLength), + Source: &types.Checkpoint{ + Epoch: "0", + Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), + }, + Target: &types.Checkpoint{ + Epoch: "0", + Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), + }, + }, + Signature: make([]byte, fieldparams.BLSSignatureLength), + CommitteeBits: []byte(committeeBits), + } +} + +func IndexedAttestation() *types.IndexedAttestation { + return &types.IndexedAttestation{ AttestingIndices: []string{"0", "1", "2"}, - Data: &v1.AttestationData{ + Data: &types.AttestationData{ Slot: "0", Index: "0", BeaconBlockRoot: make([]byte, fieldparams.RootLength), - Source: &v1.Checkpoint{ + Source: &types.Checkpoint{ Epoch: "0", Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), }, - Target: &v1.Checkpoint{ + Target: &types.Checkpoint{ Epoch: "0", Root: hexutil.Encode(make([]byte, fieldparams.RootLength)), }, @@ -681,24 +750,24 @@ func IndexedAttestation() *v1.IndexedAttestation { } } -func BeaconBlockAltair() *v1.BeaconBlockAltair { - return &v1.BeaconBlockAltair{ +func BeaconBlockAltair() *types.BeaconBlockAltair { + return &types.BeaconBlockAltair{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), StateRoot: make([]byte, fieldparams.RootLength), - Body: &v1.BeaconBlockBodyAltair{ + Body: &types.BeaconBlockBodyAltair{ RandaoReveal: make([]byte, 32), - Eth1Data: &v1.Eth1Data{ + Eth1Data: &types.Eth1Data{ DepositRoot: make([]byte, fieldparams.RootLength), DepositCount: "0", BlockHash: make([]byte, 32), }, Graffiti: make([]byte, 32), - ProposerSlashings: []*v1.ProposerSlashing{ + ProposerSlashings: []*types.ProposerSlashing{ { - Signedheader1: &v1.SignedBeaconBlockHeader{ - Message: &v1.BeaconBlockHeader{ + Signedheader1: &types.SignedBeaconBlockHeader{ + Message: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -707,8 +776,8 @@ func BeaconBlockAltair() *v1.BeaconBlockAltair { }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, - Signedheader2: &v1.SignedBeaconBlockHeader{ - Message: &v1.BeaconBlockHeader{ + Signedheader2: &types.SignedBeaconBlockHeader{ + Message: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -719,19 +788,19 @@ func BeaconBlockAltair() *v1.BeaconBlockAltair { }, }, }, - AttesterSlashings: []*v1.AttesterSlashing{ + AttesterSlashings: []*types.AttesterSlashing{ { Attestation1: IndexedAttestation(), Attestation2: IndexedAttestation(), }, }, - Attestations: []*v1.Attestation{ + Attestations: []*types.Attestation{ Attestation(), }, - Deposits: []*v1.Deposit{ + Deposits: []*types.Deposit{ { Proof: []string{"0x41"}, - Data: &v1.DepositData{ + Data: &types.DepositData{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), WithdrawalCredentials: make([]byte, 32), Amount: "0", @@ -739,16 +808,16 @@ func BeaconBlockAltair() *v1.BeaconBlockAltair { }, }, }, - VoluntaryExits: []*v1.SignedVoluntaryExit{ + VoluntaryExits: []*types.SignedVoluntaryExit{ { - Message: &v1.VoluntaryExit{ + Message: &types.VoluntaryExit{ Epoch: "0", ValidatorIndex: "0", }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, }, - SyncAggregate: &v1.SyncAggregate{ + SyncAggregate: &types.SyncAggregate{ SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), SyncCommitteeBits: SyncComitteeBits(), }, @@ -756,19 +825,19 @@ func BeaconBlockAltair() *v1.BeaconBlockAltair { } } -func BeaconBlockBody() *v1.BeaconBlockBody { - return &v1.BeaconBlockBody{ +func BeaconBlockBody() *types.BeaconBlockBody { + return &types.BeaconBlockBody{ RandaoReveal: make([]byte, 32), - Eth1Data: &v1.Eth1Data{ + Eth1Data: &types.Eth1Data{ DepositRoot: make([]byte, fieldparams.RootLength), DepositCount: "0", BlockHash: make([]byte, 32), }, Graffiti: make([]byte, 32), - ProposerSlashings: []*v1.ProposerSlashing{ + ProposerSlashings: []*types.ProposerSlashing{ { - Signedheader1: &v1.SignedBeaconBlockHeader{ - Message: &v1.BeaconBlockHeader{ + Signedheader1: &types.SignedBeaconBlockHeader{ + Message: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -777,8 +846,8 @@ func BeaconBlockBody() *v1.BeaconBlockBody { }, Signature: make([]byte, fieldparams.BLSSignatureLength), }, - Signedheader2: &v1.SignedBeaconBlockHeader{ - Message: &v1.BeaconBlockHeader{ + Signedheader2: &types.SignedBeaconBlockHeader{ + Message: &types.BeaconBlockHeader{ Slot: "0", ProposerIndex: "0", ParentRoot: make([]byte, fieldparams.RootLength), @@ -789,19 +858,19 @@ func BeaconBlockBody() *v1.BeaconBlockBody { }, }, }, - AttesterSlashings: []*v1.AttesterSlashing{ + AttesterSlashings: []*types.AttesterSlashing{ { Attestation1: IndexedAttestation(), Attestation2: IndexedAttestation(), }, }, - Attestations: []*v1.Attestation{ + Attestations: []*types.Attestation{ Attestation(), }, - Deposits: []*v1.Deposit{ + Deposits: []*types.Deposit{ { Proof: []string{"0x41"}, - Data: &v1.DepositData{ + Data: &types.DepositData{ PublicKey: make([]byte, fieldparams.BLSPubkeyLength), WithdrawalCredentials: make([]byte, 32), Amount: "0", @@ -809,9 +878,9 @@ func BeaconBlockBody() *v1.BeaconBlockBody { }, }, }, - VoluntaryExits: []*v1.SignedVoluntaryExit{ + VoluntaryExits: []*types.SignedVoluntaryExit{ { - Message: &v1.VoluntaryExit{ + Message: &types.VoluntaryExit{ Epoch: "0", ValidatorIndex: "0", }, @@ -821,10 +890,10 @@ func BeaconBlockBody() *v1.BeaconBlockBody { } } -func ContributionAndProof() *v1.ContributionAndProof { - return &v1.ContributionAndProof{ +func ContributionAndProof() *types.ContributionAndProof { + return &types.ContributionAndProof{ AggregatorIndex: "0", - Contribution: &v1.SyncCommitteeContribution{ + Contribution: &types.SyncCommitteeContribution{ Slot: "0", BeaconBlockRoot: make([]byte, fieldparams.RootLength), SubcommitteeIndex: "0", diff --git a/validator/keymanager/remote-web3signer/v1/requests.go b/validator/keymanager/remote-web3signer/types/requests.go similarity index 87% rename from validator/keymanager/remote-web3signer/v1/requests.go rename to validator/keymanager/remote-web3signer/types/requests.go index c78fcf08dc68..f04b65e8dec9 100644 --- a/validator/keymanager/remote-web3signer/v1/requests.go +++ b/validator/keymanager/remote-web3signer/types/requests.go @@ -1,12 +1,14 @@ -package v1 +package types import ( "fmt" + "strings" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks" "github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" + "github.com/prysmaticlabs/prysm/v5/runtime/version" ) // GetBlockSignRequest maps the request for signing type BLOCK. @@ -88,6 +90,34 @@ func GetAggregateAndProofSignRequest(request *validatorpb.SignRequest, genesisVa }, nil } +// GetAggregateAndProofV2SignRequest maps the request for signing type AGGREGATE_AND_PROOF_V2 on Electra changes. +func GetAggregateAndProofV2SignRequest(v int, request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*AggregateAndProofV2SignRequest, error) { + aggregateAttestationAndProof, ok := request.Object.(*validatorpb.SignRequest_AggregateAttestationAndProofElectra) + if !ok { + return nil, errors.New("failed to cast request object to aggregate attestation and proof") + } + if aggregateAttestationAndProof == nil { + return nil, errors.New("invalid sign request: AggregateAndProof is nil") + } + fork, err := MapForkInfo(request.SigningSlot, genesisValidatorsRoot) + if err != nil { + return nil, err + } + aggregateAndProof, err := MapAggregateAndProofElectra(aggregateAttestationAndProof.AggregateAttestationAndProofElectra) + if err != nil { + return nil, err + } + return &AggregateAndProofV2SignRequest{ + Type: "AGGREGATE_AND_PROOF_V2", + ForkInfo: fork, + SigningRoot: request.SigningRoot, + AggregateAndProof: &AggregateAndProofV2{ + Version: strings.ToUpper(version.String(v)), + Data: aggregateAndProof, + }, + }, nil +} + // GetAttestationSignRequest maps the request for signing type ATTESTATION. func GetAttestationSignRequest(request *validatorpb.SignRequest, genesisValidatorsRoot []byte) (*AttestationSignRequest, error) { attestation, ok := request.Object.(*validatorpb.SignRequest_AttestationData) @@ -365,6 +395,34 @@ func GetBlockV2BlindedSignRequest(request *validatorpb.SignRequest, genesisValid return nil, err } b = beaconBlock + case *validatorpb.SignRequest_BlockElectra: + version = "ELECTRA" + blockElectra, ok := request.Object.(*validatorpb.SignRequest_BlockElectra) + if !ok { + return nil, errors.New("failed to cast request object to electra block") + } + if blockElectra == nil { + return nil, errors.New("invalid sign request: electra block is nil") + } + beaconBlock, err := blocks.NewBeaconBlock(blockElectra.BlockElectra) + if err != nil { + return nil, err + } + b = beaconBlock + case *validatorpb.SignRequest_BlindedBlockElectra: + version = "ELECTRA" + blindedBlockElectra, ok := request.Object.(*validatorpb.SignRequest_BlindedBlockElectra) + if !ok { + return nil, errors.New("failed to cast request object to blinded electra block") + } + if blindedBlockElectra == nil { + return nil, errors.New("invalid sign request: blinded electra block is nil") + } + beaconBlock, err := blocks.NewBeaconBlock(blindedBlockElectra.BlindedBlockElectra) + if err != nil { + return nil, err + } + b = beaconBlock default: return nil, errors.New("invalid sign request - invalid object type") } diff --git a/validator/keymanager/remote-web3signer/v1/requests_test.go b/validator/keymanager/remote-web3signer/types/requests_test.go similarity index 83% rename from validator/keymanager/remote-web3signer/v1/requests_test.go rename to validator/keymanager/remote-web3signer/types/requests_test.go index b5562043c665..dabe6cdbcac0 100644 --- a/validator/keymanager/remote-web3signer/v1/requests_test.go +++ b/validator/keymanager/remote-web3signer/types/requests_test.go @@ -1,4 +1,4 @@ -package v1_test +package types_test import ( "reflect" @@ -8,8 +8,8 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client" "github.com/prysmaticlabs/prysm/v5/testing/require" - v1 "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1" - "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/v1/mock" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types" + "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer/types/mock" ) func TestGetAggregateAndProofSignRequest(t *testing.T) { @@ -20,7 +20,7 @@ func TestGetAggregateAndProofSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.AggregateAndProofSignRequest + want *types.AggregateAndProofSignRequest wantErr bool }{ { @@ -35,7 +35,7 @@ func TestGetAggregateAndProofSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetAggregateAndProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetAggregateAndProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetAggregateAndProofSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -55,7 +55,7 @@ func TestGetAggregationSlotSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.AggregationSlotSignRequest + want *types.AggregationSlotSignRequest wantErr bool }{ { @@ -70,7 +70,7 @@ func TestGetAggregationSlotSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetAggregationSlotSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetAggregationSlotSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetAggregationSlotSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -90,7 +90,7 @@ func TestGetAttestationSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.AttestationSignRequest + want *types.AttestationSignRequest wantErr bool }{ { @@ -104,7 +104,7 @@ func TestGetAttestationSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetAttestationSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetAttestationSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetAttestationSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -124,7 +124,7 @@ func TestGetBlockSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.BlockSignRequest + want *types.BlockSignRequest wantErr bool }{ { @@ -139,7 +139,7 @@ func TestGetBlockSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetBlockSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetBlockSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetBlockSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -159,7 +159,7 @@ func TestGetBlockV2AltairSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.BlockAltairSignRequest + want *types.BlockAltairSignRequest wantErr bool }{ { @@ -174,7 +174,7 @@ func TestGetBlockV2AltairSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetBlockAltairSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetBlockAltairSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetBlockAltairSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -194,7 +194,7 @@ func TestGetRandaoRevealSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.RandaoRevealSignRequest + want *types.RandaoRevealSignRequest wantErr bool }{ { @@ -209,7 +209,7 @@ func TestGetRandaoRevealSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetRandaoRevealSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetRandaoRevealSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetRandaoRevealSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -229,7 +229,7 @@ func TestGetSyncCommitteeContributionAndProofSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.SyncCommitteeContributionAndProofSignRequest + want *types.SyncCommitteeContributionAndProofSignRequest wantErr bool }{ { @@ -244,7 +244,7 @@ func TestGetSyncCommitteeContributionAndProofSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetSyncCommitteeContributionAndProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetSyncCommitteeContributionAndProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetSyncCommitteeContributionAndProofSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -264,7 +264,7 @@ func TestGetSyncCommitteeMessageSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.SyncCommitteeMessageSignRequest + want *types.SyncCommitteeMessageSignRequest wantErr bool }{ { @@ -279,7 +279,7 @@ func TestGetSyncCommitteeMessageSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetSyncCommitteeMessageSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetSyncCommitteeMessageSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetSyncCommitteeMessageSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -299,7 +299,7 @@ func TestGetSyncCommitteeSelectionProofSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.SyncCommitteeSelectionProofSignRequest + want *types.SyncCommitteeSelectionProofSignRequest wantErr bool }{ { @@ -314,7 +314,7 @@ func TestGetSyncCommitteeSelectionProofSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetSyncCommitteeSelectionProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetSyncCommitteeSelectionProofSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetSyncCommitteeSelectionProofSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -334,7 +334,7 @@ func TestGetVoluntaryExitSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.VoluntaryExitSignRequest + want *types.VoluntaryExitSignRequest wantErr bool }{ { @@ -349,7 +349,7 @@ func TestGetVoluntaryExitSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetVoluntaryExitSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetVoluntaryExitSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetVoluntaryExitSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -369,7 +369,7 @@ func TestGetBlockV2BlindedSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.BlockV2BlindedSignRequest + want *types.BlockV2BlindedSignRequest wantErr bool }{ { @@ -450,10 +450,36 @@ func TestGetBlockV2BlindedSignRequest(t *testing.T) { }(t), "DENEB"), wantErr: false, }, + { + name: "Happy Path Test non blinded Electra", + args: args{ + request: mock.GetMockSignRequest("BLOCK_V2_ELECTRA"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.BlockV2BlindedSignRequest(func(t *testing.T) []byte { + bytevalue, err := hexutil.Decode("0xca4f98890bc98a59f015d06375a5e00546b8f2ac1e88d31b1774ea28d4b3e7d1") + require.NoError(t, err) + return bytevalue + }(t), "ELECTRA"), + wantErr: false, + }, + { + name: "Happy Path Test blinded Electra", + args: args{ + request: mock.GetMockSignRequest("BLOCK_V2_BLINDED_ELECTRA"), + genesisValidatorsRoot: make([]byte, fieldparams.RootLength), + }, + want: mock.BlockV2BlindedSignRequest(func(t *testing.T) []byte { + bytevalue, err := hexutil.Decode("0x60cd4e8a557e64d00f63777b53f18c10cc122997c55f40a37cb19dc2edd3b0c7") + require.NoError(t, err) + return bytevalue + }(t), "ELECTRA"), + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetBlockV2BlindedSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) + got, err := types.GetBlockV2BlindedSignRequest(tt.args.request, tt.args.genesisValidatorsRoot) if (err != nil) != tt.wantErr { t.Errorf("GetBlockV2BlindedSignRequest() error = %v, wantErr %v", err, tt.wantErr) return @@ -472,7 +498,7 @@ func TestGetValidatorRegistrationSignRequest(t *testing.T) { tests := []struct { name string args args - want *v1.ValidatorRegistrationSignRequest + want *types.ValidatorRegistrationSignRequest wantErr bool }{ { @@ -486,7 +512,7 @@ func TestGetValidatorRegistrationSignRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := v1.GetValidatorRegistrationSignRequest(tt.args.request) + got, err := types.GetValidatorRegistrationSignRequest(tt.args.request) if (err != nil) != tt.wantErr { t.Errorf("GetValidatorRegistrationSignRequest() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/validator/keymanager/remote-web3signer/v1/web3signer_types.go b/validator/keymanager/remote-web3signer/types/web3signer_types.go similarity index 91% rename from validator/keymanager/remote-web3signer/v1/web3signer_types.go rename to validator/keymanager/remote-web3signer/types/web3signer_types.go index 075204677384..49a7028320bc 100644 --- a/validator/keymanager/remote-web3signer/v1/web3signer_types.go +++ b/validator/keymanager/remote-web3signer/types/web3signer_types.go @@ -1,6 +1,6 @@ // Package v1 defines mappings of types as defined by the web3signer official specification for its v1 version i.e. /api/v1/eth2 /* Web3Signer Specs are found by searching Consensys' Web3Signer API specification*/ -package v1 +package types import ( "github.com/ethereum/go-ethereum/common/hexutil" @@ -22,6 +22,20 @@ type AggregateAndProofSignRequest struct { AggregateAndProof *AggregateAndProof `json:"aggregate_and_proof" validate:"required"` } +// AggregateAndProofV2SignRequest is a request object for web3signer sign api. +type AggregateAndProofV2SignRequest struct { + Type string `json:"type" validate:"required"` + ForkInfo *ForkInfo `json:"fork_info" validate:"required"` + SigningRoot hexutil.Bytes `json:"signingRoot"` + AggregateAndProof *AggregateAndProofV2 `json:"aggregate_and_proof" validate:"required"` +} + +// AggregateAndProofV2 is a wrapper object for AggregateAndProofV2SignRequest +type AggregateAndProofV2 struct { + Version string `json:"version" validate:"required"` + Data *AggregateAndProofElectra `json:"data" validate:"required"` // specifies Electra for now +} + // AttestationSignRequest is a request object for web3signer sign api. type AttestationSignRequest struct { Type string `json:"type" validate:"required"` @@ -134,6 +148,13 @@ type AggregateAndProof struct { SelectionProof hexutil.Bytes `json:"selection_proof"` /* 96 bytes */ } +// AggregateAndProofElectra a sub property of AggregateAndProofV2ElectraSignRequest. +type AggregateAndProofElectra struct { + AggregatorIndex string `json:"aggregator_index"` /* uint64 */ + Aggregate *AttestationElectra `json:"aggregate"` + SelectionProof hexutil.Bytes `json:"selection_proof"` /* 96 bytes */ +} + // Attestation a sub property of AggregateAndProofSignRequest. type Attestation struct { AggregationBits hexutil.Bytes `json:"aggregation_bits"` /*hex bitlist*/ @@ -141,6 +162,14 @@ type Attestation struct { Signature hexutil.Bytes `json:"signature"` } +// AttestationElectra a sub property of AggregateAndProofElectra. +type AttestationElectra struct { + AggregationBits hexutil.Bytes `json:"aggregation_bits"` /*hex bitlist*/ + Data *AttestationData `json:"data"` + Signature hexutil.Bytes `json:"signature"` + CommitteeBits hexutil.Bytes `json:"committee_bits"` /* SSZ hexadecimal string */ +} + // AttestationData a sub property of Attestation. type AttestationData struct { Slot string `json:"slot"` /* uint64 */ diff --git a/validator/node/BUILD.bazel b/validator/node/BUILD.bazel index 253255212ab8..8a27ab47fa31 100644 --- a/validator/node/BUILD.bazel +++ b/validator/node/BUILD.bazel @@ -34,7 +34,6 @@ go_library( ], deps = [ "//api:go_default_library", - "//api/gateway:go_default_library", "//api/server/middleware:go_default_library", "//async/event:go_default_library", "//cmd:go_default_library", @@ -47,7 +46,6 @@ go_library( "//monitoring/backup:go_default_library", "//monitoring/prometheus:go_default_library", "//monitoring/tracing:go_default_library", - "//proto/prysm/v1alpha1:go_default_library", "//runtime:go_default_library", "//runtime/debug:go_default_library", "//runtime/prereqs:go_default_library", @@ -62,12 +60,8 @@ go_library( "//validator/keymanager/local:go_default_library", "//validator/keymanager/remote-web3signer:go_default_library", "//validator/rpc:go_default_library", - "//validator/web:go_default_library", - "@com_github_gorilla_mux//:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", "@com_github_urfave_cli_v2//:go_default_library", - "@org_golang_google_protobuf//encoding/protojson:go_default_library", ], ) diff --git a/validator/node/node.go b/validator/node/node.go index ed80038020c7..383688dba7e3 100644 --- a/validator/node/node.go +++ b/validator/node/node.go @@ -6,7 +6,6 @@ package node import ( "context" "fmt" - "net" "net/http" "net/url" "os" @@ -18,11 +17,8 @@ import ( "syscall" "time" - "github.com/gorilla/mux" - gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api" - "github.com/prysmaticlabs/prysm/v5/api/gateway" "github.com/prysmaticlabs/prysm/v5/api/server/middleware" "github.com/prysmaticlabs/prysm/v5/async/event" "github.com/prysmaticlabs/prysm/v5/cmd" @@ -34,8 +30,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/io/file" "github.com/prysmaticlabs/prysm/v5/monitoring/backup" "github.com/prysmaticlabs/prysm/v5/monitoring/prometheus" - tracing2 "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" - pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" "github.com/prysmaticlabs/prysm/v5/runtime" "github.com/prysmaticlabs/prysm/v5/runtime/debug" "github.com/prysmaticlabs/prysm/v5/runtime/prereqs" @@ -50,10 +45,8 @@ import ( "github.com/prysmaticlabs/prysm/v5/validator/keymanager/local" remoteweb3signer "github.com/prysmaticlabs/prysm/v5/validator/keymanager/remote-web3signer" "github.com/prysmaticlabs/prysm/v5/validator/rpc" - "github.com/prysmaticlabs/prysm/v5/validator/web" "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" - "google.golang.org/protobuf/encoding/protojson" ) // ValidatorClient defines an instance of an Ethereum validator that manages @@ -73,7 +66,8 @@ type ValidatorClient struct { // NewValidatorClient creates a new instance of the Prysm validator client. func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) { // TODO(#9883) - Maybe we can pass in a new validator client config instead of the cliCTX to abstract away the use of flags here . - if err := tracing2.Setup( + if err := tracing.Setup( + cliCtx.Context, "validator", // service name cliCtx.String(cmd.TracingProcessNameFlag.Name), cliCtx.String(cmd.TracingEndpointFlag.Name), @@ -119,7 +113,7 @@ func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) { } // initialize router used for endpoints - router := newRouter(cliCtx) + router := http.NewServeMux() // If the --web flag is enabled to administer the validator // client via a web portal, we start the validator client in a different way. // Change Web flag name to enable keymanager API, look at merging initializeFromCLI and initializeForWeb maybe after WebUI DEPRECATED. @@ -141,19 +135,6 @@ func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) { return validatorClient, nil } -func newRouter(cliCtx *cli.Context) *mux.Router { - var allowedOrigins []string - if cliCtx.IsSet(flags.GRPCGatewayCorsDomain.Name) { - allowedOrigins = strings.Split(cliCtx.String(flags.GRPCGatewayCorsDomain.Name), ",") - } else { - allowedOrigins = strings.Split(flags.GRPCGatewayCorsDomain.Value, ",") - } - r := mux.NewRouter() - r.Use(middleware.NormalizeQueryValuesHandler) - r.Use(middleware.CorsHandler(allowedOrigins)) - return r -} - // Start every service in the validator client. func (c *ValidatorClient) Start() { c.lock.Lock() @@ -249,7 +230,7 @@ func (c *ValidatorClient) getLegacyDatabaseLocation( return dataDir, dataFile, nil } -func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context, router *mux.Router) error { +func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context, router *http.ServeMux) error { isInteropNumValidatorsSet := cliCtx.IsSet(flags.InteropNumValidators.Name) isWeb3SignerURLFlagSet := cliCtx.IsSet(flags.Web3SignerURLFlag.Name) @@ -289,14 +270,11 @@ func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context, router *mux.Rou if err := c.registerRPCService(router); err != nil { return err } - if err := c.registerRPCGatewayService(router); err != nil { - return err - } } return nil } -func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context, router *mux.Router) error { +func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context, router *http.ServeMux) error { if cliCtx.IsSet(flags.Web3SignerURLFlag.Name) { // Custom Check For Web3Signer c.wallet = wallet.NewWalletForWeb3Signer(cliCtx) @@ -332,12 +310,10 @@ func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context, router *mux.Rout if err := c.registerRPCService(router); err != nil { return err } - if err := c.registerRPCGatewayService(router); err != nil { - return err - } - gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name) - gatewayPort := cliCtx.Int(flags.GRPCGatewayPort.Name) - webAddress := fmt.Sprintf("http://%s:%d", gatewayHost, gatewayPort) + + host := cliCtx.String(flags.HTTPServerHost.Name) + port := cliCtx.Int(flags.HTTPServerPort.Name) + webAddress := fmt.Sprintf("http://%s:%d", host, port) log.WithField("address", webAddress).Info( "Starting Prysm web UI on address, open in browser to access", ) @@ -560,8 +536,8 @@ func Web3SignerConfig(cliCtx *cli.Context) (*remoteweb3signer.SetupConfig, error if cliCtx.IsSet(flags.WalletPasswordFileFlag.Name) { log.Warnf("%s was provided while using web3signer and will be ignored", flags.WalletPasswordFileFlag.Name) } - - if publicKeysSlice := cliCtx.StringSlice(flags.Web3SignerPublicValidatorKeysFlag.Name); len(publicKeysSlice) > 0 { + if cliCtx.IsSet(flags.Web3SignerPublicValidatorKeysFlag.Name) { + publicKeysSlice := cliCtx.StringSlice(flags.Web3SignerPublicValidatorKeysFlag.Name) if len(publicKeysSlice) == 1 { pURL, err := url.ParseRequestURI(publicKeysSlice[0]) if err == nil && pURL.Scheme != "" && pURL.Host != "" { @@ -593,7 +569,7 @@ func proposerSettings(cliCtx *cli.Context, db iface.ValidatorDB) (*proposer.Sett return l.Load(cliCtx) } -func (c *ValidatorClient) registerRPCService(router *mux.Router) error { +func (c *ValidatorClient) registerRPCService(router *http.ServeMux) error { var vs *client.ValidatorService if err := c.services.FetchService(&vs); err != nil { return err @@ -608,11 +584,28 @@ func (c *ValidatorClient) registerRPCService(router *mux.Router) error { authTokenPath = filepath.Join(walletDir, api.AuthTokenFileName) } } + host := c.cliCtx.String(flags.HTTPServerHost.Name) + if host != flags.DefaultHTTPServerHost { + log.WithField("webHost", host).Warn( + "You are using a non-default web host. Web traffic is served by HTTP, so be wary of " + + "changing this parameter if you are exposing this host to the Internet!", + ) + } + port := c.cliCtx.Int(flags.HTTPServerPort.Name) + var allowedOrigins []string + if c.cliCtx.IsSet(flags.HTTPServerCorsDomain.Name) { + allowedOrigins = strings.Split(c.cliCtx.String(flags.HTTPServerCorsDomain.Name), ",") + } else { + allowedOrigins = strings.Split(flags.HTTPServerCorsDomain.Value, ",") + } + + middlewares := []middleware.Middleware{ + middleware.NormalizeQueryValuesHandler, + middleware.CorsHandler(allowedOrigins), + } s := rpc.NewServer(c.cliCtx.Context, &rpc.Config{ - Host: c.cliCtx.String(flags.RPCHost.Name), - Port: fmt.Sprintf("%d", c.cliCtx.Int(flags.RPCPort.Name)), - GRPCGatewayHost: c.cliCtx.String(flags.GRPCGatewayHost.Name), - GRPCGatewayPort: c.cliCtx.Int(flags.GRPCGatewayPort.Name), + HTTPHost: host, + HTTPPort: port, GRPCMaxCallRecvMsgSize: c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name), GRPCRetries: c.cliCtx.Uint(flags.GRPCRetriesFlag.Name), GRPCRetryDelay: c.cliCtx.Duration(flags.GRPCRetryDelayFlag.Name), @@ -627,87 +620,12 @@ func (c *ValidatorClient) registerRPCService(router *mux.Router) error { WalletInitializedFeed: c.walletInitializedFeed, ValidatorService: vs, AuthTokenPath: authTokenPath, + Middlewares: middlewares, Router: router, }) return c.services.RegisterService(s) } -func (c *ValidatorClient) registerRPCGatewayService(router *mux.Router) error { - gatewayHost := c.cliCtx.String(flags.GRPCGatewayHost.Name) - if gatewayHost != flags.DefaultGatewayHost { - log.WithField("webHost", gatewayHost).Warn( - "You are using a non-default web host. Web traffic is served by HTTP, so be wary of " + - "changing this parameter if you are exposing this host to the Internet!", - ) - } - gatewayPort := c.cliCtx.Int(flags.GRPCGatewayPort.Name) - rpcHost := c.cliCtx.String(flags.RPCHost.Name) - rpcPort := c.cliCtx.Int(flags.RPCPort.Name) - rpcAddr := net.JoinHostPort(rpcHost, fmt.Sprintf("%d", rpcPort)) - gatewayAddress := net.JoinHostPort(gatewayHost, fmt.Sprintf("%d", gatewayPort)) - timeout := c.cliCtx.Int(cmd.ApiTimeoutFlag.Name) - var allowedOrigins []string - if c.cliCtx.IsSet(flags.GRPCGatewayCorsDomain.Name) { - allowedOrigins = strings.Split(c.cliCtx.String(flags.GRPCGatewayCorsDomain.Name), ",") - } else { - allowedOrigins = strings.Split(flags.GRPCGatewayCorsDomain.Value, ",") - } - maxCallSize := c.cliCtx.Uint64(cmd.GrpcMaxCallRecvMsgSizeFlag.Name) - - registrations := []gateway.PbHandlerRegistration{ - pb.RegisterHealthHandler, - } - gwmux := gwruntime.NewServeMux( - gwruntime.WithMarshalerOption(gwruntime.MIMEWildcard, &gwruntime.HTTPBodyMarshaler{ - Marshaler: &gwruntime.JSONPb{ - MarshalOptions: protojson.MarshalOptions{ - EmitUnpopulated: true, - UseProtoNames: true, - }, - UnmarshalOptions: protojson.UnmarshalOptions{ - DiscardUnknown: true, - }, - }, - }), - gwruntime.WithMarshalerOption( - api.EventStreamMediaType, &gwruntime.EventSourceJSONPb{}, // TODO: remove this - ), - gwruntime.WithForwardResponseOption(gateway.HttpResponseModifier), - ) - - muxHandler := func(h http.HandlerFunc, w http.ResponseWriter, req *http.Request) { - // The validator gateway handler requires this special logic as it serves the web APIs and the web UI. - if strings.HasPrefix(req.URL.Path, "/api") { - req.URL.Path = strings.Replace(req.URL.Path, "/api", "", 1) - // Else, we handle with the Prysm API gateway without a middleware. - h(w, req) - } else { - // Finally, we handle with the web server. - web.Handler(w, req) - } - } - - pbHandler := &gateway.PbMux{ - Registrations: registrations, - Mux: gwmux, - } - opts := []gateway.Option{ - gateway.WithMuxHandler(muxHandler), - gateway.WithRouter(router), // note some routes are registered in server.go - gateway.WithRemoteAddr(rpcAddr), - gateway.WithGatewayAddr(gatewayAddress), - gateway.WithMaxCallRecvMsgSize(maxCallSize), - gateway.WithPbHandlers([]*gateway.PbMux{pbHandler}), - gateway.WithAllowedOrigins(allowedOrigins), - gateway.WithTimeout(uint64(timeout)), - } - gw, err := gateway.New(c.cliCtx.Context, opts...) - if err != nil { - return err - } - return c.services.RegisterService(gw) -} - func setWalletPasswordFilePath(cliCtx *cli.Context) error { walletDir := cliCtx.String(flags.WalletDirFlag.Name) defaultWalletPasswordFilePath := filepath.Join(walletDir, wallet.DefaultWalletPasswordFile) diff --git a/validator/package/validator.yaml b/validator/package/validator.yaml index 4cee5808a874..4cf7e716629e 100644 --- a/validator/package/validator.yaml +++ b/validator/package/validator.yaml @@ -15,7 +15,7 @@ wallet-dir: /var/lib/prysm/validator # beacon-rpc-provider: Beacon node RPC provider endpoint. Default: localhost:4000 # rpc-host: Specify the RPC host exposed by the validator. Default: localhost # rpc-port: Specify the RPC port exposed by the validator. Default: 7000 -# grpc-gateway-host: Specify the gRPC gateway port exposed by the validator. Default: localhost -# grpc-gateway-port: Specify the gRPC gateway port exposed by the validator. Default: 7500 +# http-host: Specify the HTTP host exposed by the validator. Default: localhost +# http-port: Specify the HTTP port exposed by the validator. Default: 7500 # graffiti: A string to include in proposed block. # graffiti-file: Path to Yaml file containing advanced graffiti settings. See https://docs.prylabs.network/docs/prysm-usage/graffiti-file \ No newline at end of file diff --git a/validator/rpc/BUILD.bazel b/validator/rpc/BUILD.bazel index 96701e719c63..04300c0dba0d 100644 --- a/validator/rpc/BUILD.bazel +++ b/validator/rpc/BUILD.bazel @@ -26,6 +26,8 @@ go_library( "//api/grpc:go_default_library", "//api/pagination:go_default_library", "//api/server:go_default_library", + "//api/server/httprest:go_default_library", + "//api/server/middleware:go_default_library", "//api/server/structs:go_default_library", "//async/event:go_default_library", "//beacon-chain/rpc/eth/shared:go_default_library", @@ -42,7 +44,7 @@ go_library( "//io/file:go_default_library", "//io/logs:go_default_library", "//io/prompt:go_default_library", - "//monitoring/tracing:go_default_library", + "//monitoring/tracing/trace:go_default_library", "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", @@ -62,13 +64,12 @@ go_library( "//validator/keymanager/local:go_default_library", "//validator/slashing-protection-history:go_default_library", "//validator/slashing-protection-history/format:go_default_library", + "//validator/web:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", "@com_github_fsnotify_fsnotify//:go_default_library", "@com_github_golang_jwt_jwt_v4//:go_default_library", - "@com_github_gorilla_mux//:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library", - "@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//retry:go_default_library", "@com_github_grpc_ecosystem_go_grpc_middleware//tracing/opentracing:go_default_library", "@com_github_grpc_ecosystem_go_grpc_prometheus//:go_default_library", @@ -77,12 +78,10 @@ go_library( "@com_github_tyler_smith_go_bip39//:go_default_library", "@com_github_tyler_smith_go_bip39//wordlists:go_default_library", "@com_github_wealdtech_go_eth2_wallet_encryptor_keystorev4//:go_default_library", - "@io_opencensus_go//plugin/ocgrpc:go_default_library", - "@io_opencensus_go//trace:go_default_library", + "@io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp//:go_default_library", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//codes:go_default_library", "@org_golang_google_grpc//metadata:go_default_library", - "@org_golang_google_grpc//reflection:go_default_library", "@org_golang_google_grpc//status:go_default_library", "@org_golang_google_protobuf//types/known/emptypb:go_default_library", ], @@ -119,6 +118,7 @@ go_test( "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", "//io/logs/mock:go_default_library", + "//network/httputil:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", @@ -143,8 +143,6 @@ go_test( "@com_github_golang_jwt_jwt_v4//:go_default_library", "@com_github_golang_protobuf//ptypes/empty", "@com_github_google_uuid//:go_default_library", - "@com_github_gorilla_mux//:go_default_library", - "@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_sirupsen_logrus//hooks/test:go_default_library", "@com_github_tyler_smith_go_bip39//:go_default_library", diff --git a/validator/rpc/auth_token.go b/validator/rpc/auth_token.go index ecff1019b570..df67fae07965 100644 --- a/validator/rpc/auth_token.go +++ b/validator/rpc/auth_token.go @@ -104,7 +104,7 @@ func (s *Server) refreshAuthTokenFromFileChanges(ctx context.Context, authTokenP log.WithError(err).Errorf("Could not watch for file changes for: %s", authTokenPath) continue } - validatorWebAddr := fmt.Sprintf("%s:%d", s.grpcGatewayHost, s.grpcGatewayPort) + validatorWebAddr := fmt.Sprintf("%s:%d", s.httpHost, s.httpPort) logValidatorWebAuth(validatorWebAddr, s.authToken, authTokenPath) case err := <-watcher.Errors: log.WithError(err).Errorf("Could not watch for file changes for: %s", authTokenPath) diff --git a/validator/rpc/beacon.go b/validator/rpc/beacon.go index 5ae024d3011a..809e9d9ca0e2 100644 --- a/validator/rpc/beacon.go +++ b/validator/rpc/beacon.go @@ -16,10 +16,11 @@ import ( nodeClientFactory "github.com/prysmaticlabs/prysm/v5/validator/client/node-client-factory" validatorClientFactory "github.com/prysmaticlabs/prysm/v5/validator/client/validator-client-factory" validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "google.golang.org/grpc" ) -// Initialize a client connect to a beacon node gRPC endpoint. +// Initialize a client connect to a beacon node gRPC or HTTP endpoint. func (s *Server) registerBeaconClient() error { streamInterceptor := grpc.WithStreamInterceptor(middleware.ChainStreamClient( grpcopentracing.StreamClientInterceptor(), @@ -55,13 +56,12 @@ func (s *Server) registerBeaconClient() error { ) restHandler := beaconApi.NewBeaconApiJsonRestHandler( - http.Client{Timeout: s.beaconApiTimeout}, + http.Client{Timeout: s.beaconApiTimeout, Transport: otelhttp.NewTransport(http.DefaultTransport)}, s.beaconApiEndpoint, ) s.chainClient = beaconChainClientFactory.NewChainClient(conn, restHandler) s.nodeClient = nodeClientFactory.NewNodeClient(conn, restHandler) s.beaconNodeValidatorClient = validatorClientFactory.NewValidatorClient(conn, restHandler) - return nil } diff --git a/validator/rpc/handler_wallet.go b/validator/rpc/handler_wallet.go index d100d6ce0e3d..eaaa0c1bea98 100644 --- a/validator/rpc/handler_wallet.go +++ b/validator/rpc/handler_wallet.go @@ -13,6 +13,7 @@ import ( "github.com/prysmaticlabs/prysm/v5/config/features" "github.com/prysmaticlabs/prysm/v5/io/file" "github.com/prysmaticlabs/prysm/v5/io/prompt" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/validator/accounts" "github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet" @@ -20,7 +21,6 @@ import ( "github.com/tyler-smith/go-bip39" "github.com/tyler-smith/go-bip39/wordlists" keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4" - "go.opencensus.io/trace" ) // CreateWallet via an API request, allowing a user to save a new wallet. @@ -291,7 +291,7 @@ func (*Server) ValidateKeystores(w http.ResponseWriter, r *http.Request) { return } // Needs to unmarshal the keystores from the requests. - if req.Keystores == nil || len(req.Keystores) < 1 { + if len(req.Keystores) < 1 { httputil.HandleError(w, "No keystores included in request", http.StatusBadRequest) return } diff --git a/validator/rpc/handlers_accounts.go b/validator/rpc/handlers_accounts.go index 724c0353b77c..769f1c62d972 100644 --- a/validator/rpc/handlers_accounts.go +++ b/validator/rpc/handlers_accounts.go @@ -18,13 +18,13 @@ import ( fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/crypto/bls" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/validator/accounts" "github.com/prysmaticlabs/prysm/v5/validator/accounts/petnames" "github.com/prysmaticlabs/prysm/v5/validator/keymanager" "github.com/prysmaticlabs/prysm/v5/validator/keymanager/derived" "github.com/prysmaticlabs/prysm/v5/validator/keymanager/local" - "go.opencensus.io/trace" ) // ListAccounts allows retrieval of validating keys and their petnames @@ -131,7 +131,7 @@ func (s *Server) BackupAccounts(w http.ResponseWriter, r *http.Request) { return } - if req.PublicKeys == nil || len(req.PublicKeys) < 1 { + if len(req.PublicKeys) < 1 { httputil.HandleError(w, "No public keys specified to backup", http.StatusBadRequest) return } diff --git a/validator/rpc/handlers_auth.go b/validator/rpc/handlers_auth.go index 24c29491945a..52a4b8986df5 100644 --- a/validator/rpc/handlers_auth.go +++ b/validator/rpc/handlers_auth.go @@ -5,9 +5,9 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/io/file" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet" - "go.opencensus.io/trace" ) // Initialize returns metadata regarding whether the caller has authenticated and has a wallet. diff --git a/validator/rpc/handlers_beacon.go b/validator/rpc/handlers_beacon.go index 345d36a1bf80..b69a0dfc47ae 100644 --- a/validator/rpc/handlers_beacon.go +++ b/validator/rpc/handlers_beacon.go @@ -13,9 +13,9 @@ import ( "github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/shared" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" - "go.opencensus.io/trace" "google.golang.org/protobuf/types/known/emptypb" ) @@ -42,6 +42,7 @@ func (s *Server) GetBeaconStatus(w http.ResponseWriter, r *http.Request) { } genesisTime := uint64(time.Unix(genesis.GenesisTime.Seconds, 0).Unix()) address := genesis.DepositContractAddress + chainHead, err := s.chainClient.ChainHead(ctx, &emptypb.Empty{}) if err != nil { httputil.HandleError(w, errors.Wrap(err, "ChainHead").Error(), http.StatusInternalServerError) diff --git a/validator/rpc/handlers_health.go b/validator/rpc/handlers_health.go index 7c65ea81d268..b84ac98ce8bd 100644 --- a/validator/rpc/handlers_health.go +++ b/validator/rpc/handlers_health.go @@ -6,10 +6,10 @@ import ( "net/http" "github.com/prysmaticlabs/prysm/v5/api" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/runtime/version" - "go.opencensus.io/trace" "google.golang.org/protobuf/types/known/emptypb" ) diff --git a/validator/rpc/handlers_health_test.go b/validator/rpc/handlers_health_test.go index ac46c31221a1..7f334c8e1361 100644 --- a/validator/rpc/handlers_health_test.go +++ b/validator/rpc/handlers_health_test.go @@ -12,7 +12,6 @@ import ( "github.com/golang/protobuf/ptypes/empty" "github.com/prysmaticlabs/prysm/v5/api" "github.com/prysmaticlabs/prysm/v5/io/logs/mock" - eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/testing/require" validatormock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock" @@ -26,11 +25,11 @@ type MockBeaconNodeHealthClient struct { err error } -func (m *MockBeaconNodeHealthClient) StreamBeaconLogs(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (eth.Health_StreamBeaconLogsClient, error) { +func (m *MockBeaconNodeHealthClient) StreamBeaconLogs(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (pb.Health_StreamBeaconLogsClient, error) { return m, m.err } -func (m *MockBeaconNodeHealthClient) Recv() (*eth.LogsResponse, error) { +func (m *MockBeaconNodeHealthClient) Recv() (*pb.LogsResponse, error) { if len(m.logs) == 0 { return nil, io.EOF } @@ -173,7 +172,7 @@ func TestServer_GetVersion(t *testing.T) { ctx: ctx, nodeClient: mockNodeClient, } - mockNodeClient.EXPECT().Version(gomock.Any(), gomock.Any()).Return(ð.Version{ + mockNodeClient.EXPECT().Version(gomock.Any(), gomock.Any()).Return(&pb.Version{ Version: "4.10.1", Metadata: "beacon node", }, nil) diff --git a/validator/rpc/handlers_keymanager.go b/validator/rpc/handlers_keymanager.go index d45dc17ce355..9a178a7ccf71 100644 --- a/validator/rpc/handlers_keymanager.go +++ b/validator/rpc/handlers_keymanager.go @@ -21,13 +21,13 @@ import ( "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" "github.com/prysmaticlabs/prysm/v5/consensus-types/validator" "github.com/prysmaticlabs/prysm/v5/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/validator/client" "github.com/prysmaticlabs/prysm/v5/validator/keymanager" "github.com/prysmaticlabs/prysm/v5/validator/keymanager/derived" slashingprotection "github.com/prysmaticlabs/prysm/v5/validator/slashing-protection-history" "github.com/prysmaticlabs/prysm/v5/validator/slashing-protection-history/format" - "go.opencensus.io/trace" "google.golang.org/protobuf/types/known/emptypb" ) @@ -50,7 +50,11 @@ func (s *Server) ListKeystores(w http.ResponseWriter, r *http.Request) { return } if s.wallet.KeymanagerKind() != keymanager.Derived && s.wallet.KeymanagerKind() != keymanager.Local { - httputil.HandleError(w, errors.Wrap(err, "Prysm validator keys are not stored locally with this keymanager type").Error(), http.StatusInternalServerError) + log.Debugf("List keystores keymanager api expected wallet type %s but got %s", s.wallet.KeymanagerKind().String(), keymanager.Local.String()) + response := &ListKeystoresResponse{ + Data: make([]*Keystore, 0), + } + httputil.WriteJson(w, response) return } pubKeys, err := km.FetchValidatingPublicKeys(ctx) @@ -402,7 +406,11 @@ func (s *Server) ListRemoteKeys(w http.ResponseWriter, r *http.Request) { return } if s.wallet.KeymanagerKind() != keymanager.Web3Signer { - httputil.HandleError(w, "Prysm Wallet is not of type Web3Signer. Please execute validator client with web3signer flags.", http.StatusInternalServerError) + log.Debugf("List remote keys keymanager api expected wallet type %s but got %s", s.wallet.KeymanagerKind().String(), keymanager.Web3Signer.String()) + response := &ListKeystoresResponse{ + Data: make([]*Keystore, 0), + } + httputil.WriteJson(w, response) return } pubKeys, err := km.FetchValidatingPublicKeys(ctx) diff --git a/validator/rpc/handlers_keymanager_test.go b/validator/rpc/handlers_keymanager_test.go index 4cb58217df26..0614db2cc0b6 100644 --- a/validator/rpc/handlers_keymanager_test.go +++ b/validator/rpc/handlers_keymanager_test.go @@ -16,8 +16,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/gorilla/mux" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/prysmaticlabs/prysm/v5/cmd/validator/flags" fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" "github.com/prysmaticlabs/prysm/v5/config/params" @@ -46,7 +44,6 @@ import ( mocks "github.com/prysmaticlabs/prysm/v5/validator/testing" "github.com/urfave/cli/v2" "go.uber.org/mock/gomock" - "google.golang.org/grpc" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -122,6 +119,16 @@ func TestServer_ListKeystores(t *testing.T) { ) } }) + t.Run("calling list remote while using a local wallet returns empty", func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/remotekeys"), nil) + wr := httptest.NewRecorder() + wr.Body = &bytes.Buffer{} + s.ListRemoteKeys(wr, req) + require.Equal(t, http.StatusOK, wr.Code) + resp := &ListRemoteKeysResponse{} + require.NoError(t, json.Unmarshal(wr.Body.Bytes(), resp)) + require.Equal(t, 0, len(resp.Data)) + }) } func TestServer_ImportKeystores(t *testing.T) { @@ -707,7 +714,7 @@ func TestServer_SetVoluntaryExit(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) + ctx := context.Background() defaultWalletPath = setupWalletDir(t) opts := []accounts.Option{ accounts.WithWalletDir(defaultWalletPath), @@ -841,7 +848,7 @@ func TestServer_SetVoluntaryExit(t *testing.T) { require.NoError(t, tt.mockSetup(s)) } req := httptest.NewRequest("POST", fmt.Sprintf("/eth/v1/validator/{pubkey}/voluntary_exit?epoch=%s", tt.epoch), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": tt.pubkey}) + req.SetPathValue("pubkey", tt.pubkey) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} @@ -861,7 +868,7 @@ func TestServer_SetVoluntaryExit(t *testing.T) { tt.w.epoch, err = client.CurrentEpoch(genesisResponse.GenesisTime) require.NoError(t, err) req2 := httptest.NewRequest("POST", fmt.Sprintf("/eth/v1/validator/{pubkey}/voluntary_exit?epoch=%s", tt.epoch), nil) - req2 = mux.SetURLVars(req2, map[string]string{"pubkey": hexutil.Encode(pubKeys[0][:])}) + req2.SetPathValue("pubkey", hexutil.Encode(pubKeys[0][:])) w2 := httptest.NewRecorder() w2.Body = &bytes.Buffer{} s.SetVoluntaryExit(w2, req2) @@ -954,7 +961,7 @@ func TestServer_GetGasLimit(t *testing.T) { validatorService: vs, } req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/validator/{pubkey}/gas_limit"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": hexutil.Encode(tt.pubkey[:])}) + req.SetPathValue("pubkey", hexutil.Encode(tt.pubkey[:])) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.GetGasLimit(w, req) @@ -970,7 +977,7 @@ func TestServer_SetGasLimit(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() beaconClient := validatormock.NewMockValidatorClient(ctrl) - ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) + ctx := context.Background() pubkey1, err := hexutil.Decode("0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493") pubkey2, err2 := hexutil.Decode("0xbedefeaa94e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2cdddddddddddddddddddddddd") @@ -1132,7 +1139,7 @@ func TestServer_SetGasLimit(t *testing.T) { require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/eth/v1/validator/{pubkey}/gas_limit"), &buf) - req = mux.SetURLVars(req, map[string]string{"pubkey": hexutil.Encode(tt.pubkey)}) + req.SetPathValue("pubkey", hexutil.Encode(tt.pubkey)) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} @@ -1168,7 +1175,7 @@ func TestServer_SetGasLimit_InvalidPubKey(t *testing.T) { validatorService: &client.ValidatorService{}, } req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/validator/{pubkey}/gas_limit"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": "0x00"}) + req.SetPathValue("pubkey", "0x00") w := httptest.NewRecorder() w.Body = &bytes.Buffer{} @@ -1178,7 +1185,7 @@ func TestServer_SetGasLimit_InvalidPubKey(t *testing.T) { } func TestServer_DeleteGasLimit(t *testing.T) { - ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) + ctx := context.Background() pubkey1, err := hexutil.Decode("0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493") pubkey2, err2 := hexutil.Decode("0xbedefeaa94e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2cdddddddddddddddddddddddd") require.NoError(t, err) @@ -1306,7 +1313,7 @@ func TestServer_DeleteGasLimit(t *testing.T) { params.BeaconConfig().DefaultBuilderGasLimit = uint64(globalDefaultGasLimit) req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/eth/v1/validator/{pubkey}/gas_limit"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": hexutil.Encode(tt.pubkey)}) + req.SetPathValue("pubkey", hexutil.Encode(tt.pubkey)) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} @@ -1369,6 +1376,16 @@ func TestServer_ListRemoteKeys(t *testing.T) { require.DeepEqual(t, hexutil.Encode(expectedKeys[i][:]), resp.Data[i].Pubkey) } }) + t.Run("calling list keystores while using a remote wallet returns empty", func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/keystores"), nil) + wr := httptest.NewRecorder() + wr.Body = &bytes.Buffer{} + s.ListKeystores(wr, req) + require.Equal(t, http.StatusOK, wr.Code) + resp := &ListKeystoresResponse{} + require.NoError(t, json.Unmarshal(wr.Body.Bytes(), resp)) + require.Equal(t, 0, len(resp.Data)) + }) } func TestServer_ImportRemoteKeys(t *testing.T) { @@ -1559,7 +1576,7 @@ func TestServer_ListFeeRecipientByPubkey(t *testing.T) { validatorService: vs, } req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey}) + req.SetPathValue("pubkey", pubkey) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.ListFeeRecipientByPubkey(w, req) @@ -1583,7 +1600,7 @@ func TestServer_ListFeeRecipientByPubKey_NoFeeRecipientSet(t *testing.T) { validatorService: vs, } req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": "0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493"}) + req.SetPathValue("pubkey", "0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493") w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.ListFeeRecipientByPubkey(w, req) @@ -1594,7 +1611,7 @@ func TestServer_ListFeeRecipientByPubKey_NoFeeRecipientSet(t *testing.T) { func TestServer_ListFeeRecipientByPubkey_ValidatorServiceNil(t *testing.T) { s := &Server{} req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": "0x00"}) + req.SetPathValue("pubkey", "0x00") w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.SetFeeRecipientByPubkey(w, req) @@ -1608,7 +1625,7 @@ func TestServer_ListFeeRecipientByPubkey_InvalidPubKey(t *testing.T) { } req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": "0x00"}) + req.SetPathValue("pubkey", "0x00") w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.SetFeeRecipientByPubkey(w, req) @@ -1621,7 +1638,7 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) { defer ctrl.Finish() beaconClient := validatormock.NewMockValidatorClient(ctrl) - ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) + ctx := context.Background() pubkey := "0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493" byteval, err := hexutil.Decode(pubkey) require.NoError(t, err) @@ -1782,7 +1799,7 @@ func TestServer_FeeRecipientByPubkey(t *testing.T) { require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), &buf) - req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey}) + req.SetPathValue("pubkey", pubkey) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.SetFeeRecipientByPubkey(w, req) @@ -1799,7 +1816,7 @@ func TestServer_SetFeeRecipientByPubkey_InvalidPubKey(t *testing.T) { validatorService: &client.ValidatorService{}, } req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": "0x00"}) + req.SetPathValue("pubkey", "0x00") w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.SetFeeRecipientByPubkey(w, req) @@ -1821,7 +1838,7 @@ func TestServer_SetFeeRecipientByPubkey_InvalidFeeRecipient(t *testing.T) { err := json.NewEncoder(&buf).Encode(request) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), &buf) - req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey}) + req.SetPathValue("pubkey", pubkey) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.SetFeeRecipientByPubkey(w, req) @@ -1831,7 +1848,7 @@ func TestServer_SetFeeRecipientByPubkey_InvalidFeeRecipient(t *testing.T) { } func TestServer_DeleteFeeRecipientByPubkey(t *testing.T) { - ctx := grpc.NewContextWithServerTransportStream(context.Background(), &runtime.ServerTransportStream{}) + ctx := context.Background() pubkey := "0xaf2e7ba294e03438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493" byteval, err := hexutil.Decode(pubkey) require.NoError(t, err) @@ -1883,7 +1900,7 @@ func TestServer_DeleteFeeRecipientByPubkey(t *testing.T) { db: validatorDB, } req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey}) + req.SetPathValue("pubkey", pubkey) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.DeleteFeeRecipientByPubkey(w, req) @@ -1897,7 +1914,7 @@ func TestServer_DeleteFeeRecipientByPubkey(t *testing.T) { func TestServer_DeleteFeeRecipientByPubkey_ValidatorServiceNil(t *testing.T) { s := &Server{} req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": "0x1234567878903438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493"}) + req.SetPathValue("pubkey", "0x1234567878903438ea819bd4033c6c1bf6b04320ee2075b77273c08d02f8a61bcc303c2c06bd3713cb442072ae591493") w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.DeleteFeeRecipientByPubkey(w, req) @@ -1911,7 +1928,7 @@ func TestServer_DeleteFeeRecipientByPubkey_InvalidPubKey(t *testing.T) { } req := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/eth/v1/validator/{pubkey}/feerecipient"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": "0x123"}) + req.SetPathValue("pubkey", "0x123") w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.DeleteFeeRecipientByPubkey(w, req) @@ -1940,14 +1957,14 @@ func TestServer_Graffiti(t *testing.T) { err = json.NewEncoder(&buf).Encode(request) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/eth/v1/validator/{pubkey}/graffiti"), &buf) - req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey}) + req.SetPathValue("pubkey", pubkey) w := httptest.NewRecorder() w.Body = &bytes.Buffer{} s.SetGraffiti(w, req) require.Equal(t, http.StatusOK, w.Code) req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("/eth/v1/validator/{pubkey}/graffiti"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey}) + req.SetPathValue("pubkey", pubkey) w = httptest.NewRecorder() w.Body = &bytes.Buffer{} s.GetGraffiti(w, req) @@ -1958,7 +1975,7 @@ func TestServer_Graffiti(t *testing.T) { assert.Equal(t, resp.Data.Pubkey, pubkey) req = httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/eth/v1/validator/{pubkey}/graffiti"), nil) - req = mux.SetURLVars(req, map[string]string{"pubkey": pubkey}) + req.SetPathValue("pubkey", pubkey) w = httptest.NewRecorder() w.Body = &bytes.Buffer{} s.DeleteGraffiti(w, req) diff --git a/validator/rpc/handlers_slashing.go b/validator/rpc/handlers_slashing.go index 595047e2f25a..97439cec9d36 100644 --- a/validator/rpc/handlers_slashing.go +++ b/validator/rpc/handlers_slashing.go @@ -7,9 +7,9 @@ import ( "net/http" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" "github.com/prysmaticlabs/prysm/v5/network/httputil" slashing "github.com/prysmaticlabs/prysm/v5/validator/slashing-protection-history" - "go.opencensus.io/trace" ) // ExportSlashingProtection handles the rpc call returning the json slashing history. diff --git a/validator/rpc/intercepter.go b/validator/rpc/intercepter.go index 1f574a433ead..eb42755237c0 100644 --- a/validator/rpc/intercepter.go +++ b/validator/rpc/intercepter.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/prysmaticlabs/prysm/v5/api" + "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -41,18 +42,18 @@ func (s *Server) AuthTokenHandler(next http.Handler) http.Handler { // ignore some routes reqToken := r.Header.Get("Authorization") if reqToken == "" { - http.Error(w, "unauthorized: no Authorization header passed. Please use an Authorization header with the jwt created in the prysm wallet", http.StatusUnauthorized) + httputil.HandleError(w, "Unauthorized: no Authorization header passed. Please use an Authorization header with the jwt created in the prysm wallet", http.StatusUnauthorized) return } tokenParts := strings.Split(reqToken, "Bearer ") if len(tokenParts) != 2 { - http.Error(w, "Invalid token format", http.StatusBadRequest) + httputil.HandleError(w, "Invalid token format", http.StatusBadRequest) return } token := tokenParts[1] if strings.TrimSpace(token) != s.authToken || strings.TrimSpace(s.authToken) == "" { - http.Error(w, "Forbidden: token value is invalid", http.StatusForbidden) + httputil.HandleError(w, "Forbidden: token value is invalid", http.StatusForbidden) return } } diff --git a/validator/rpc/intercepter_test.go b/validator/rpc/intercepter_test.go index 94a0461da476..85b7c7a5655e 100644 --- a/validator/rpc/intercepter_test.go +++ b/validator/rpc/intercepter_test.go @@ -2,11 +2,13 @@ package rpc import ( "context" + "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/prysmaticlabs/prysm/v5/api" + "github.com/prysmaticlabs/prysm/v5/network/httputil" "github.com/prysmaticlabs/prysm/v5/testing/require" "google.golang.org/grpc" "google.golang.org/grpc/metadata" @@ -72,6 +74,9 @@ func TestServer_AuthTokenHandler(t *testing.T) { require.NoError(t, err) testHandler.ServeHTTP(rr, req) require.Equal(t, http.StatusUnauthorized, rr.Code) + errJson := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), errJson)) + require.StringContains(t, "Unauthorized", errJson.Message) }) t.Run("wrong auth token was sent", func(t *testing.T) { rr := httptest.NewRecorder() @@ -80,6 +85,9 @@ func TestServer_AuthTokenHandler(t *testing.T) { req.Header.Set("Authorization", "Bearer YOUR_JWT_TOKEN") // Replace with a valid JWT token testHandler.ServeHTTP(rr, req) require.Equal(t, http.StatusForbidden, rr.Code) + errJson := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), errJson)) + require.StringContains(t, "token value is invalid", errJson.Message) }) t.Run("good auth token was sent", func(t *testing.T) { rr := httptest.NewRecorder() @@ -95,6 +103,9 @@ func TestServer_AuthTokenHandler(t *testing.T) { require.NoError(t, err) testHandler.ServeHTTP(rr, req) require.Equal(t, http.StatusUnauthorized, rr.Code) + errJson := &httputil.DefaultJsonError{} + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), errJson)) + require.StringContains(t, "Unauthorized", errJson.Message) }) t.Run("initialize does not need auth", func(t *testing.T) { rr := httptest.NewRecorder() diff --git a/validator/rpc/server.go b/validator/rpc/server.go index 6120e5ccfd08..f623faf06fb9 100644 --- a/validator/rpc/server.go +++ b/validator/rpc/server.go @@ -6,34 +6,27 @@ import ( "net" "net/http" "path/filepath" + "strings" "time" - "github.com/gorilla/mux" - middleware "github.com/grpc-ecosystem/go-grpc-middleware" - recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" - grpcopentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing" - grpcprometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v5/api" + "github.com/prysmaticlabs/prysm/v5/api/server/httprest" + "github.com/prysmaticlabs/prysm/v5/api/server/middleware" "github.com/prysmaticlabs/prysm/v5/async/event" "github.com/prysmaticlabs/prysm/v5/io/logs" - "github.com/prysmaticlabs/prysm/v5/monitoring/tracing" ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/v5/validator/accounts/wallet" "github.com/prysmaticlabs/prysm/v5/validator/client" iface "github.com/prysmaticlabs/prysm/v5/validator/client/iface" "github.com/prysmaticlabs/prysm/v5/validator/db" - "go.opencensus.io/plugin/ocgrpc" - "google.golang.org/grpc" - "google.golang.org/grpc/reflection" + "github.com/prysmaticlabs/prysm/v5/validator/web" ) -// Config options for the gRPC server. +// Config options for the HTTP server. type Config struct { - Host string - Port string - GRPCGatewayHost string - GRPCGatewayPort int + HTTPHost string + HTTPPort int GRPCMaxCallRecvMsgSize int GRPCRetries uint GRPCRetryDelay time.Duration @@ -48,23 +41,21 @@ type Config struct { WalletInitializedFeed *event.Feed ValidatorService *client.ValidatorService AuthTokenPath string - Router *mux.Router + Middlewares []middleware.Middleware + Router *http.ServeMux } -// Server defining a gRPC server for the remote signer API. +// Server defining a HTTP server for the remote signer API and registering clients type Server struct { ctx context.Context cancel context.CancelFunc - host string - port string - grpcGatewayHost string - grpcGatewayPort int - listener net.Listener + httpHost string + httpPort int + server *httprest.Server grpcMaxCallRecvMsgSize int grpcRetries uint grpcRetryDelay time.Duration grpcHeaders []string - grpcServer *grpc.Server beaconNodeValidatorClient iface.ValidatorClient chainClient iface.ChainClient nodeClient iface.NodeClient @@ -82,12 +73,13 @@ type Server struct { walletInitializedFeed *event.Feed walletInitialized bool validatorService *client.ValidatorService - router *mux.Router + router *http.ServeMux logStreamer logs.Streamer logStreamerBufferSize int + startFailure error } -// NewServer instantiates a new gRPC server. +// NewServer instantiates a new HTTP server. func NewServer(ctx context.Context, cfg *Config) *Server { ctx, cancel := context.WithCancel(ctx) server := &Server{ @@ -95,10 +87,8 @@ func NewServer(ctx context.Context, cfg *Config) *Server { cancel: cancel, logStreamer: logs.NewStreamServer(), logStreamerBufferSize: 1000, // Enough to handle most bursts of logs in the validator client. - host: cfg.Host, - port: cfg.Port, - grpcGatewayHost: cfg.GRPCGatewayHost, - grpcGatewayPort: cfg.GRPCGatewayPort, + httpHost: cfg.HTTPHost, + httpPort: cfg.HTTPPort, grpcMaxCallRecvMsgSize: cfg.GRPCMaxCallRecvMsgSize, grpcRetries: cfg.GRPCRetries, grpcRetryDelay: cfg.GRPCRetryDelay, @@ -124,62 +114,57 @@ func NewServer(ctx context.Context, cfg *Config) *Server { if err := server.initializeAuthToken(); err != nil { log.WithError(err).Error("Could not initialize web auth token") } - validatorWebAddr := fmt.Sprintf("%s:%d", server.grpcGatewayHost, server.grpcGatewayPort) + validatorWebAddr := fmt.Sprintf("%s:%d", server.httpHost, server.httpPort) logValidatorWebAuth(validatorWebAddr, server.authToken, server.authTokenPath) go server.refreshAuthTokenFromFileChanges(server.ctx, server.authTokenPath) } - // immediately register routes to override any catchalls - if err := server.InitializeRoutes(); err != nil { - log.WithError(err).Fatal("Could not initialize routes") + // Register a gRPC or HTTP client to the beacon node. + // Used for proxy calls to beacon node from validator REST handlers + if err := server.registerBeaconClient(); err != nil { + log.WithError(err).Fatal("Could not register beacon chain gRPC or HTTP client") } - return server -} -// Start the gRPC server. -func (s *Server) Start() { - // Setup the gRPC server options and TLS configuration. - address := net.JoinHostPort(s.host, s.port) - lis, err := net.Listen("tcp", address) - if err != nil { - log.WithError(err).Errorf("Could not listen to port in Start() %s", address) - } - s.listener = lis - - // Register interceptors for metrics gathering as well as our - // own, custom JWT unary interceptor. - opts := []grpc.ServerOption{ - grpc.StatsHandler(&ocgrpc.ServerHandler{}), - grpc.UnaryInterceptor(middleware.ChainUnaryServer( - recovery.UnaryServerInterceptor( - recovery.WithRecoveryHandlerContext(tracing.RecoveryHandlerFunc), - ), - grpcprometheus.UnaryServerInterceptor, - grpcopentracing.UnaryServerInterceptor(), - s.AuthTokenInterceptor(), - )), + // Adding AuthTokenHandler to the list of middlewares + cfg.Middlewares = append(cfg.Middlewares, server.AuthTokenHandler) + opts := []httprest.Option{ + httprest.WithRouter(cfg.Router), + httprest.WithHTTPAddr(net.JoinHostPort(server.httpHost, fmt.Sprintf("%d", server.httpPort))), + httprest.WithMiddlewares(cfg.Middlewares), } - grpcprometheus.EnableHandlingTimeHistogram() - s.grpcServer = grpc.NewServer(opts...) - - // Register a gRPC client to the beacon node. - if err := s.registerBeaconClient(); err != nil { - log.WithError(err).Fatal("Could not register beacon chain gRPC client") + if err := server.InitializeRoutesWithWebHandler(); err != nil { + log.WithError(err).Fatal("Could not initialize routes with web handler") + } + // create and set a new http server + s, err := httprest.New(server.ctx, opts...) + if err != nil { + log.WithError(err).Fatal("Failed to create HTTP server") } + server.server = s + + return server +} - // Register services available for the gRPC server. - reflection.Register(s.grpcServer) +// Start the HTTP server and registers clients that can communicate via HTTP or gRPC. +func (s *Server) Start() { + s.server.Start() +} - // routes needs to be set before the server calls the server function - go func() { - if s.listener != nil { - if err := s.grpcServer.Serve(s.listener); err != nil { - log.WithError(err).Error("Could not serve") - } +// InitializeRoutesWithWebHandler adds a catchall wrapper for web handling +func (s *Server) InitializeRoutesWithWebHandler() error { + if err := s.InitializeRoutes(); err != nil { + return err + } + s.router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if strings.HasPrefix(r.URL.Path, "/api") { + r.URL.Path = strings.Replace(r.URL.Path, "/api", "", 1) // used to redirect apis to standard rest APIs + s.router.ServeHTTP(w, r) + } else { + // Finally, we handle with the web server. + web.Handler(w, r) } - }() - - log.WithField("address", address).Info("gRPC server listening on address") + }) + return nil } // InitializeRoutes initializes pure HTTP REST endpoints for the validator client. @@ -188,66 +173,63 @@ func (s *Server) InitializeRoutes() error { if s.router == nil { return errors.New("no router found on server") } - // Adding Auth Interceptor for the routes below - s.router.Use(s.AuthTokenHandler) // Register all services, HandleFunc calls, etc. // ... - s.router.HandleFunc("/eth/v1/keystores", s.ListKeystores).Methods(http.MethodGet) - s.router.HandleFunc("/eth/v1/keystores", s.ImportKeystores).Methods(http.MethodPost) - s.router.HandleFunc("/eth/v1/keystores", s.DeleteKeystores).Methods(http.MethodDelete) - s.router.HandleFunc("/eth/v1/remotekeys", s.ListRemoteKeys).Methods(http.MethodGet) - s.router.HandleFunc("/eth/v1/remotekeys", s.ImportRemoteKeys).Methods(http.MethodPost) - s.router.HandleFunc("/eth/v1/remotekeys", s.DeleteRemoteKeys).Methods(http.MethodDelete) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/gas_limit", s.GetGasLimit).Methods(http.MethodGet) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/gas_limit", s.SetGasLimit).Methods(http.MethodPost) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/gas_limit", s.DeleteGasLimit).Methods(http.MethodDelete) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/feerecipient", s.ListFeeRecipientByPubkey).Methods(http.MethodGet) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/feerecipient", s.SetFeeRecipientByPubkey).Methods(http.MethodPost) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/feerecipient", s.DeleteFeeRecipientByPubkey).Methods(http.MethodDelete) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/voluntary_exit", s.SetVoluntaryExit).Methods(http.MethodPost) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/graffiti", s.GetGraffiti).Methods(http.MethodGet) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/graffiti", s.SetGraffiti).Methods(http.MethodPost) - s.router.HandleFunc("/eth/v1/validator/{pubkey}/graffiti", s.DeleteGraffiti).Methods(http.MethodDelete) + s.router.HandleFunc("GET /eth/v1/keystores", s.ListKeystores) + s.router.HandleFunc("POST /eth/v1/keystores", s.ImportKeystores) + s.router.HandleFunc("DELETE /eth/v1/keystores", s.DeleteKeystores) + s.router.HandleFunc("GET /eth/v1/remotekeys", s.ListRemoteKeys) + s.router.HandleFunc("POST /eth/v1/remotekeys", s.ImportRemoteKeys) + s.router.HandleFunc("DELETE /eth/v1/remotekeys", s.DeleteRemoteKeys) + s.router.HandleFunc("GET /eth/v1/validator/{pubkey}/gas_limit", s.GetGasLimit) + s.router.HandleFunc("POST /eth/v1/validator/{pubkey}/gas_limit", s.SetGasLimit) + s.router.HandleFunc("DELETE /eth/v1/validator/{pubkey}/gas_limit", s.DeleteGasLimit) + s.router.HandleFunc("GET /eth/v1/validator/{pubkey}/feerecipient", s.ListFeeRecipientByPubkey) + s.router.HandleFunc("POST /eth/v1/validator/{pubkey}/feerecipient", s.SetFeeRecipientByPubkey) + s.router.HandleFunc("DELETE /eth/v1/validator/{pubkey}/feerecipient", s.DeleteFeeRecipientByPubkey) + s.router.HandleFunc("POST /eth/v1/validator/{pubkey}/voluntary_exit", s.SetVoluntaryExit) + s.router.HandleFunc("GET /eth/v1/validator/{pubkey}/graffiti", s.GetGraffiti) + s.router.HandleFunc("POST /eth/v1/validator/{pubkey}/graffiti", s.SetGraffiti) + s.router.HandleFunc("DELETE /eth/v1/validator/{pubkey}/graffiti", s.DeleteGraffiti) // auth endpoint - s.router.HandleFunc(api.WebUrlPrefix+"initialize", s.Initialize).Methods(http.MethodGet) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"initialize", s.Initialize) // accounts endpoints - s.router.HandleFunc(api.WebUrlPrefix+"accounts", s.ListAccounts).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"accounts/backup", s.BackupAccounts).Methods(http.MethodPost) - s.router.HandleFunc(api.WebUrlPrefix+"accounts/voluntary-exit", s.VoluntaryExit).Methods(http.MethodPost) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"accounts", s.ListAccounts) + s.router.HandleFunc("POST "+api.WebUrlPrefix+"accounts/backup", s.BackupAccounts) + s.router.HandleFunc("POST "+api.WebUrlPrefix+"accounts/voluntary-exit", s.VoluntaryExit) // web health endpoints - s.router.HandleFunc(api.WebUrlPrefix+"health/version", s.GetVersion).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"health/logs/validator/stream", s.StreamValidatorLogs).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"health/logs/beacon/stream", s.StreamBeaconLogs).Methods(http.MethodGet) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"health/version", s.GetVersion) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"health/logs/validator/stream", s.StreamValidatorLogs) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"health/logs/beacon/stream", s.StreamBeaconLogs) // Beacon calls - s.router.HandleFunc(api.WebUrlPrefix+"beacon/status", s.GetBeaconStatus).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"beacon/summary", s.GetValidatorPerformance).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"beacon/validators", s.GetValidators).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"beacon/balances", s.GetValidatorBalances).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"beacon/peers", s.GetPeers).Methods(http.MethodGet) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"beacon/status", s.GetBeaconStatus) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"beacon/summary", s.GetValidatorPerformance) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"beacon/validators", s.GetValidators) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"beacon/balances", s.GetValidatorBalances) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"beacon/peers", s.GetPeers) // web wallet endpoints - s.router.HandleFunc(api.WebUrlPrefix+"wallet", s.WalletConfig).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"wallet/create", s.CreateWallet).Methods(http.MethodPost) - s.router.HandleFunc(api.WebUrlPrefix+"wallet/keystores/validate", s.ValidateKeystores).Methods(http.MethodPost) - s.router.HandleFunc(api.WebUrlPrefix+"wallet/recover", s.RecoverWallet).Methods(http.MethodPost) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"wallet", s.WalletConfig) + s.router.HandleFunc("POST "+api.WebUrlPrefix+"wallet/create", s.CreateWallet) + s.router.HandleFunc("POST "+api.WebUrlPrefix+"wallet/keystores/validate", s.ValidateKeystores) + s.router.HandleFunc("POST "+api.WebUrlPrefix+"wallet/recover", s.RecoverWallet) // slashing protection endpoints - s.router.HandleFunc(api.WebUrlPrefix+"slashing-protection/export", s.ExportSlashingProtection).Methods(http.MethodGet) - s.router.HandleFunc(api.WebUrlPrefix+"slashing-protection/import", s.ImportSlashingProtection).Methods(http.MethodPost) + s.router.HandleFunc("GET "+api.WebUrlPrefix+"slashing-protection/export", s.ExportSlashingProtection) + s.router.HandleFunc("POST "+api.WebUrlPrefix+"slashing-protection/import", s.ImportSlashingProtection) + log.Info("Initialized REST API routes") return nil } -// Stop the gRPC server. +// Stop the HTTP server. func (s *Server) Stop() error { - s.cancel() - if s.listener != nil { - s.grpcServer.GracefulStop() - log.Debug("Initiated graceful stop of server") - } - return nil + return s.server.Stop() } // Status returns an error if the service is unhealthy. func (s *Server) Status() error { + if s.startFailure != nil { + return s.startFailure + } return nil } diff --git a/validator/rpc/server_test.go b/validator/rpc/server_test.go index f285fc823068..fb97e2133c60 100644 --- a/validator/rpc/server_test.go +++ b/validator/rpc/server_test.go @@ -4,13 +4,12 @@ import ( "net/http" "testing" - "github.com/gorilla/mux" "github.com/prysmaticlabs/prysm/v5/testing/require" ) func TestServer_InitializeRoutes(t *testing.T) { s := Server{ - router: mux.NewRouter(), + router: http.NewServeMux(), } err := s.InitializeRoutes() require.NoError(t, err) @@ -41,20 +40,23 @@ func TestServer_InitializeRoutes(t *testing.T) { "/v2/validator/beacon/validators": {http.MethodGet}, "/v2/validator/initialize": {http.MethodGet}, } - gotRouteList := make(map[string][]string) - err = s.router.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { - tpl, err1 := route.GetPathTemplate() - require.NoError(t, err1) - met, err2 := route.GetMethods() - require.NoError(t, err2) - methods, ok := gotRouteList[tpl] - if !ok { - gotRouteList[tpl] = []string{met[0]} - } else { - gotRouteList[tpl] = append(methods, met[0]) + for route, methods := range wantRouteList { + for _, method := range methods { + r, err := http.NewRequest(method, route, nil) + require.NoError(t, err) + if method == http.MethodGet { + _, path := s.router.Handler(r) + require.Equal(t, "GET "+route, path) + } else if method == http.MethodPost { + _, path := s.router.Handler(r) + require.Equal(t, "POST "+route, path) + } else if method == http.MethodDelete { + _, path := s.router.Handler(r) + require.Equal(t, "DELETE "+route, path) + } else { + t.Errorf("Unsupported method %v", method) + } } - return nil - }) - require.NoError(t, err) - require.DeepEqual(t, wantRouteList, gotRouteList) + } + } diff --git a/validator/web/BUILD.bazel b/validator/web/BUILD.bazel index f9a4a63935fa..63a3d714541a 100644 --- a/validator/web/BUILD.bazel +++ b/validator/web/BUILD.bazel @@ -11,7 +11,6 @@ go_library( ], importpath = "github.com/prysmaticlabs/prysm/v5/validator/web", visibility = [ - "//api/gateway:__pkg__", "//validator:__subpackages__", ], deps = ["@com_github_sirupsen_logrus//:go_default_library"], diff --git a/validator/web/handler.go b/validator/web/handler.go index ac9ad89d3083..c5f5f46199c1 100644 --- a/validator/web/handler.go +++ b/validator/web/handler.go @@ -10,7 +10,6 @@ import ( const prefix = "prysm-web-ui" // Handler serves web requests from the bundled site data. -// DEPRECATED: Prysm Web UI and associated endpoints will be fully removed in a future hard fork. var Handler = func(res http.ResponseWriter, req *http.Request) { addSecurityHeaders(res) u, err := url.ParseRequestURI(req.RequestURI)